/** * 测试用 Tauri 全局桥替身:全仓唯一的 `window.__TAURI__` 安装点与类型转换点。 * * `Window['__TAURI__']` 声明的是泛型签名(`core.invoke` / `event.listen` 都是泛型函数), * 而各套件的替身是 `vi.fn` 或具体签名的 mock,二者结构上不兼容。若在每个用例里直接赋值, * 就得反复写 `as never` / `as unknown as`,类型检查形同虚设;这里把转换收敛到一处, * 调用方只声明自己真正装了哪些能力。 * * 参数用「可调用」下界而不是 `unknown`:非函数的误装(字符串、`undefined`)会在编译期被挡下, * 同时不与各夹具更具体的 mock 签名冲突;`core` / `event` 都可缺省。 */ export type TauriRuntimeInstall = { core?: { invoke?: ( command: string, args?: Record, ) => Promise; }; event?: { listen?: ( event: string, handler: (event: { payload: unknown }) => void, ) => Promise<() => void>; }; }; export function installTauriRuntime(runtime: TauriRuntimeInstall) { window.__TAURI__ = runtime as unknown as Window['__TAURI__']; } /** 清掉替身,供 `afterEach` / `beforeEach` 复位(等价于仓库既有的 `delete window.__TAURI__`)。 */ export function resetTauriRuntime() { delete window.__TAURI__; } /** * 测试用 Tauri 事件注册表:只登记 `event.listen` 的回调并按事件名派发。 * * 不碰 `window.__TAURI__`、不做类型转换;安装由 `installTauriRuntime` 负责,需要事件桥的 * 用例把 `bridge.listen` 交给它即可。 */ export function createTauriEventBridge() { const listeners = new Map void>(); return { listen: async ( event: string, handler: (event: { payload: unknown }) => void, ) => { listeners.set(event, handler); return () => { listeners.delete(event); }; }, emit: (event: string, payload: unknown) => { listeners.get(event)?.({ payload }); }, }; }