Files
ttstd-infinite-canvas/web/test/floating-dock-pointer-guard.test.tsx
AetherNo2332 22d65d0192 fix(web): 基础控件 FloatingDock - 宿主没有 matchMedia 时不再渲染失败 (#563)
Original-Commit: 3da77b3931a675de06b02c1bba93f112d253041b
fix(web): 基础控件 FloatingDock - 宿主没有 matchMedia 时不再渲染失败

`window` 存在不代表 `matchMedia` 存在(SSR 垫片、嵌入式 webview、部分 DOM polyfill),
而 FloatingDock 在渲染期直接取 `window.matchMedia("(pointer: coarse)").matches`,
取不到就抛 TypeError,整个 dock(画布工具栏/素材托盘/缩放控件)渲染失败。
仓库里同一模式已有先例:canvas-workspace-tool-panel 用 typeof 守卫。

抽 coarsePointerQuery():两个都探测,取不到按"非触屏"处理,useEffect 也提前返回;
能取到时行为不变。新增源码级守卫用例(上游原态失败、补丁后通过)。
2026-09-21 09:37:19 +08:00

19 lines
1.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test } from "bun:test";
import { readFileSync } from "node:fs";
// 指针能力探测是纯增强:`window` 存在不代表 `matchMedia` 存在(SSR 垫片、嵌入式 webview、
// 部分 DOM polyfill 下它是 undefined),而 FloatingDock 在**渲染期**就取
// `window.matchMedia("(pointer: coarse)")`,取不到会直接抛 TypeError 让整个 dock 渲染失败。
// 仓库里同一模式已有先例:canvas-workspace-tool-panel.tsx 用 `typeof window.matchMedia === "function"` 守卫。
describe("floating dock pointer capability probe", () => {
const source = readFileSync(new URL("../src/components/ui/aceternity/floating-dock.tsx", import.meta.url), "utf8");
test("probes matchMedia through a guarded helper", () => {
expect(source).toContain('typeof window.matchMedia !== "function"');
expect(source).toContain("function coarsePointerQuery()");
// 不允许再出现"直接取用 matchMedia 结果"的写法(初始化与 useEffect 都不得裸取)
expect(source).not.toMatch(/window\.matchMedia\("\(pointer: coarse\)"\)\.matches/);
expect(source).not.toMatch(/const media = window\.matchMedia/);
});
});