/* @vitest-environment jsdom */ import { afterEach, describe, expect, test, vi } from 'vitest'; import type { HostBridgeCapability, HostBridgeRequest, } from '../../../packages/shared/src/contracts/hostBridge'; import { resetHostRuntimeCacheForTest } from '../../services/host-bridge/hostBridge'; import { resetNativeAppHostBridgeForTest } from '../../services/host-bridge/nativeAppHostBridge'; import { sendPlatformHostDraftNotificationToHost, syncPlatformHostDraftBadgeCountToHost, } from './platformHostBridgeSync'; function asTauriInvoke( invoke: (command: string, args?: Record) => Promise, ) { return async function tauriInvoke( command: string, args?: Record, ) { return (await invoke(command, args)) as Result; }; } function nativeAppPath(capabilities: HostBridgeCapability[] = []) { const params = new URLSearchParams({ clientRuntime: 'native_app', hostShell: 'tauri_desktop', }); if (capabilities.length > 0) { params.set('hostCapabilities', capabilities.join(',')); } return `/?${params.toString()}`; } function installTauriHostBridgeRecorder() { const requests: HostBridgeRequest[] = []; const invoke = vi.fn(async (_command: string, args?: Record) => { const request = (args as { request: HostBridgeRequest }).request; requests.push(request); return { bridge: 'GenarrativeHostBridge', version: 1, id: request.id, ok: true, result: true, }; }); window.__TAURI__ = { core: { invoke: asTauriInvoke(invoke), }, }; return { invoke, requests }; } afterEach(() => { vi.restoreAllMocks(); window.history.replaceState(null, '', '/'); delete window.__TAURI__; resetNativeAppHostBridgeForTest(); resetHostRuntimeCacheForTest(); }); describe('platformHostBridgeSync', () => { test('平台壳草稿通知通过真实 HostBridge 请求本地系统通知', async () => { window.history.replaceState( null, '', nativeAppPath(['notification.showLocal']), ); const { invoke, requests } = installTauriHostBridgeRecorder(); await expect( sendPlatformHostDraftNotificationToHost({ title: ' 生成完成 ', body: ' 拼图草稿 puzzle-session-1 生成任务已完成 ', }), ).resolves.toBe(true); expect(invoke).toHaveBeenCalledWith('host_bridge_request', { request: expect.objectContaining({ method: 'notification.showLocal', payload: { title: '生成完成', body: '拼图草稿 puzzle-session-1 生成任务已完成', }, }), }); expect(requests).toHaveLength(1); }); test('平台壳草稿未读计数通过真实 HostBridge 同步应用角标', async () => { window.history.replaceState( null, '', nativeAppPath(['app.setBadgeCount']), ); const { invoke, requests } = installTauriHostBridgeRecorder(); await expect(syncPlatformHostDraftBadgeCountToHost(3)).resolves.toBe(true); expect(invoke).toHaveBeenCalledWith('host_bridge_request', { request: expect.objectContaining({ method: 'app.setBadgeCount', payload: { count: 3, }, }), }); expect(requests).toHaveLength(1); }); test('宿主未声明草稿通知和角标能力时平台壳保持 H5 回退', async () => { window.history.replaceState(null, '', nativeAppPath()); const { invoke } = installTauriHostBridgeRecorder(); await expect( sendPlatformHostDraftNotificationToHost({ title: '生成完成', body: '拼图草稿已完成。', }), ).resolves.toBe(false); await expect(syncPlatformHostDraftBadgeCountToHost(1)).resolves.toBe(false); expect(invoke).not.toHaveBeenCalled(); }); });