ba000111d7
H5 原生能力只信任真实 host.getRuntime 回包 移除桌面壳未声明网络事件白名单 补齐原生壳能力门控测试和共享决策记录
141 lines
3.7 KiB
TypeScript
141 lines
3.7 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { afterEach, describe, expect, test, vi } from 'vitest';
|
|
|
|
import {
|
|
resetHostRuntimeCacheForTest,
|
|
setHostRuntimeCacheForTest,
|
|
} from './host-bridge/hostBridge';
|
|
import { resetNativeAppHostBridgeForTest } from './host-bridge/nativeAppHostBridge';
|
|
import {
|
|
triggerRuntimeClickFeedback,
|
|
triggerRuntimeImpactFeedback,
|
|
} from './runtimeAudioFeedback';
|
|
|
|
function waitForNextTask() {
|
|
return new Promise<void>((resolve) => {
|
|
window.setTimeout(resolve, 0);
|
|
});
|
|
}
|
|
|
|
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;
|
|
};
|
|
}
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
window.history.replaceState(null, '', '/');
|
|
delete window.ReactNativeWebView;
|
|
delete window.__TAURI__;
|
|
resetNativeAppHostBridgeForTest();
|
|
resetHostRuntimeCacheForTest();
|
|
});
|
|
|
|
describe('runtimeAudioFeedback', () => {
|
|
test('普通浏览器点击反馈使用 vibration fallback', async () => {
|
|
const vibrate = vi.fn();
|
|
Object.defineProperty(navigator, 'vibrate', {
|
|
configurable: true,
|
|
value: vibrate,
|
|
});
|
|
|
|
triggerRuntimeImpactFeedback('light', 12);
|
|
await waitForNextTask();
|
|
|
|
expect(vibrate).toHaveBeenCalledWith([12]);
|
|
});
|
|
|
|
test('原生壳触觉反馈成功时不再触发浏览器 vibration fallback', async () => {
|
|
const vibrate = vi.fn();
|
|
const invoke = vi.fn(
|
|
async (_command: string, args?: Record<string, unknown>) => {
|
|
const request = (args as { request: { id: string } }).request;
|
|
return {
|
|
bridge: 'GenarrativeHostBridge',
|
|
version: 1,
|
|
id: request.id,
|
|
ok: true,
|
|
result: true,
|
|
};
|
|
},
|
|
);
|
|
Object.defineProperty(navigator, 'vibrate', {
|
|
configurable: true,
|
|
value: vibrate,
|
|
});
|
|
window.history.replaceState(
|
|
null,
|
|
'',
|
|
'/?clientRuntime=native_app&hostCapabilities=haptics.impact',
|
|
);
|
|
setHostRuntimeCacheForTest({
|
|
shell: 'tauri_desktop',
|
|
platform: 'linux',
|
|
hostVersion: '0.1.0',
|
|
bridgeVersion: 1,
|
|
capabilities: ['haptics.impact'],
|
|
});
|
|
window.__TAURI__ = {
|
|
core: {
|
|
invoke: asTauriInvoke(invoke),
|
|
},
|
|
};
|
|
|
|
triggerRuntimeClickFeedback(undefined, 0.6, {
|
|
fallbackVibrationPatternMs: 12,
|
|
hapticsStyle: 'medium',
|
|
});
|
|
await waitForNextTask();
|
|
|
|
expect(invoke).toHaveBeenCalledWith('host_bridge_request', {
|
|
request: expect.objectContaining({
|
|
method: 'haptics.impact',
|
|
payload: {
|
|
style: 'medium',
|
|
},
|
|
}),
|
|
});
|
|
expect(vibrate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('原生壳不支持触觉反馈时回退到浏览器 vibration', async () => {
|
|
const vibrate = vi.fn();
|
|
Object.defineProperty(navigator, 'vibrate', {
|
|
configurable: true,
|
|
value: vibrate,
|
|
});
|
|
window.history.replaceState(null, '', '/?clientRuntime=native_app');
|
|
window.__TAURI__ = {
|
|
core: {
|
|
invoke: asTauriInvoke(
|
|
vi.fn(async (_command: string, args?: Record<string, unknown>) => {
|
|
const request = (args as { request: { id: string } }).request;
|
|
return {
|
|
bridge: 'GenarrativeHostBridge',
|
|
version: 1,
|
|
id: request.id,
|
|
ok: false,
|
|
error: {
|
|
code: 'unsupported_method',
|
|
message: 'unsupported_method',
|
|
},
|
|
};
|
|
}),
|
|
),
|
|
},
|
|
};
|
|
|
|
triggerRuntimeImpactFeedback('light', 12);
|
|
await waitForNextTask();
|
|
|
|
expect(vibrate).toHaveBeenCalledWith([12]);
|
|
});
|
|
});
|