49fffbca74
新增平台壳草稿通知和角标 HostBridge 同步层 补充真实 Tauri transport 单测和跳一跳完成集成测试 扩展原生壳门禁覆盖 H5 宿主消费链路 更新宿主壳协议、方案和共享决策记录
133 lines
3.8 KiB
TypeScript
133 lines
3.8 KiB
TypeScript
/* @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<string, unknown>) => Promise<unknown>,
|
|
) {
|
|
return async function tauriInvoke<Result = unknown>(
|
|
command: string,
|
|
args?: Record<string, unknown>,
|
|
) {
|
|
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<string, unknown>) => {
|
|
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();
|
|
});
|
|
});
|