补齐移动壳运行态单测

移动壳 runtime helper 增加独立单测覆盖

原生壳结构门禁登记移动运行态测试

宿主壳文档和共享决策同步运行态测试边界
This commit is contained in:
2026-06-20 08:16:48 +08:00
parent 1307357099
commit 29bce53669
6 changed files with 127 additions and 4 deletions
@@ -72,6 +72,14 @@ const scannerPath = new URL('../src/host-bridge/scanner.ts', import.meta.url);
const scannerSource = fs.readFileSync(scannerPath, 'utf8');
const hostBridgeRuntimePath = new URL('../src/host-bridge/runtime.ts', import.meta.url);
const hostBridgeRuntimeSource = fs.readFileSync(hostBridgeRuntimePath, 'utf8');
const hostBridgeRuntimeTestPath = new URL(
'../src/host-bridge/runtime.test.ts',
import.meta.url,
);
const hostBridgeRuntimeTestSource = fs.readFileSync(
hostBridgeRuntimeTestPath,
'utf8',
);
const sharePath = new URL('../src/host-bridge/share.ts', import.meta.url);
const shareSource = fs.readFileSync(sharePath, 'utf8');
const shareTestPath = new URL('../src/host-bridge/share.test.ts', import.meta.url);
@@ -2110,6 +2118,19 @@ if (hostBridgeRuntimeSource.includes('capabilities: resolveMobileHostCapabilitie
'mobile shell runtime capabilities must use the same normalized platform reported in host.getRuntime',
);
}
for (const snippet of [
'reports iOS runtime with host version, bridge version and iOS capabilities',
'reports Android runtime without iOS-only app badge capability',
'wraps runtime metadata in the HostBridge response shape',
'hostVersion: MOBILE_SHELL_HOST_VERSION',
'bridgeVersion: HOST_BRIDGE_VERSION',
"not.toContain('app.setBadgeCount')",
"expect(getMobileRuntimePlatform()).toBe('android')",
]) {
if (!hostBridgeRuntimeTestSource.includes(snippet)) {
throw new Error(`mobile shell runtime tests missing ${snippet}`);
}
}
for (const snippet of [
"import appConfig from '../../app.json'",
@@ -0,0 +1,94 @@
import { Platform } from 'react-native';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import {
HOST_BRIDGE_PROTOCOL,
HOST_BRIDGE_VERSION,
type HostBridgeRequest,
} from '../../../../packages/shared/src/contracts/hostBridge';
import { MOBILE_SHELL_HOST_VERSION } from '../shell/runtime';
import {
getMobileHostBridgeRuntime,
getMobileHostBridgeRuntimeResponse,
getMobileRuntimePlatform,
} from './runtime';
vi.mock('react-native', () => ({
Platform: {
OS: 'ios',
},
}));
function request(): HostBridgeRequest {
return {
bridge: HOST_BRIDGE_PROTOCOL,
version: HOST_BRIDGE_VERSION,
id: 'runtime-request',
method: 'host.getRuntime',
};
}
function setPlatformOS(os: 'ios' | 'android') {
(Platform as { OS: 'ios' | 'android' }).OS = os;
}
beforeEach(() => {
setPlatformOS('ios');
});
describe('mobile HostBridge runtime helper', () => {
test('reports iOS runtime with host version, bridge version and iOS capabilities', () => {
expect(getMobileRuntimePlatform()).toBe('ios');
const runtime = getMobileHostBridgeRuntime();
expect(runtime).toEqual(
expect.objectContaining({
shell: 'expo_mobile',
platform: 'ios',
hostVersion: MOBILE_SHELL_HOST_VERSION,
bridgeVersion: HOST_BRIDGE_VERSION,
}),
);
expect(runtime.capabilities).toEqual(
expect.arrayContaining([
'host.getRuntime',
'appearance.getColorScheme',
'network.status',
'app.setBadgeCount',
'file.captureImage',
]),
);
});
test('reports Android runtime without iOS-only app badge capability', () => {
setPlatformOS('android');
const runtime = getMobileHostBridgeRuntime();
expect(getMobileRuntimePlatform()).toBe('android');
expect(runtime).toEqual(
expect.objectContaining({
shell: 'expo_mobile',
platform: 'android',
hostVersion: MOBILE_SHELL_HOST_VERSION,
bridgeVersion: HOST_BRIDGE_VERSION,
}),
);
expect(runtime.capabilities).toContain('host.getRuntime');
expect(runtime.capabilities).toContain('file.captureImage');
expect(runtime.capabilities).not.toContain('app.setBadgeCount');
});
test('wraps runtime metadata in the HostBridge response shape', () => {
const response = getMobileHostBridgeRuntimeResponse(request());
expect(response).toEqual({
bridge: HOST_BRIDGE_PROTOCOL,
version: HOST_BRIDGE_VERSION,
id: 'runtime-request',
ok: true,
result: getMobileHostBridgeRuntime(),
});
});
});
@@ -2948,3 +2948,10 @@
- 决策:新增 `apps/mobile-shell/src/host-bridge/badge.test.ts`,直接覆盖 iOS `PushNotificationIOS.setApplicationIconBadgeNumber` 设置与清除、非法数量和缺少 payload 时不触碰系统角标,以及 Android 在 payload 校验前返回 `unsupported_capability` 的顺序;移动壳单端配置检查和根级原生壳门禁登记该测试文件并反查关键断言片段。该变更不把 `app.setBadgeCount` 加入 Android base capability。
- 影响范围:`apps/mobile-shell/src/host-bridge/badge.test.ts``apps/mobile-shell/scripts/check-config.mjs``scripts/check-native-shells.mjs`、宿主壳方案文档、宿主壳能力统一协议文档。
- 验证方式:`npm run mobile-shell:test -- src/host-bridge/badge.test.ts``npm run mobile-shell:typecheck``npm run check:native-shells``npm run check:encoding``git diff --check`
## 2026-06-20 移动运行态 HostBridge 单测边界
- 背景:Expo 移动壳 `host.getRuntime` 是 H5 回读宿主版本、平台和 capability profile 的入口;此前 iOS / Android 平台差异和回包形状主要压在巨型 bridge 测试中,缺少对 `runtime.ts` helper 的直接覆盖。
- 决策:新增 `apps/mobile-shell/src/host-bridge/runtime.test.ts`,直接覆盖 iOS runtime 的 `hostVersion``bridgeVersion`、能力清单和 `app.setBadgeCount`Android runtime 不声明 iOS 专属角标能力,以及 `host.getRuntime` HostBridge 成功响应形状;移动壳单端配置检查和根级原生壳门禁登记该测试文件并反查关键断言片段。该变更不新增 capability,不改变入口 query 或 H5 runtime 回读策略。
- 影响范围:`apps/mobile-shell/src/host-bridge/runtime.test.ts``apps/mobile-shell/scripts/check-config.mjs``scripts/check-native-shells.mjs`、宿主壳方案文档、宿主壳能力统一协议文档。
- 验证方式:`npm run mobile-shell:test -- src/host-bridge/runtime.test.ts``npm run mobile-shell:typecheck``npm run check:native-shells``npm run check:encoding``git diff --check`
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -270,6 +270,7 @@ const expectedMobileHostBridgeFiles = [
'notifications.test.ts',
'notifications.ts',
'protocol.ts',
'runtime.test.ts',
'runtime.ts',
'scanner.ts',
'share.test.ts',