强化桌面壳能力流测试门禁

要求 Tauri 桌面能力流由 desktop-shell:test 保护

要求每个桌面能力流关联带 Rust 单测的真实模块

同步项目决策日志中的桌面能力流测试约束
This commit is contained in:
2026-06-21 18:53:17 +08:00
parent c5b85a716a
commit 9081527a2b
2 changed files with 23 additions and 0 deletions
@@ -3228,5 +3228,6 @@
- 背景:Expo 移动壳和 Tauri 桌面壳的 capability 清单会直接影响 H5 是否展示和调用原生能力。如果新增 capability 只写进共享契约或 Rust / TS 能力清单,却没有登记真实宿主 API、分发入口、payload 边界和测试证据,H5 可能认为能力可用,但运行时没有对应真实链路。
- 决策:`scripts/check-native-shells.mjs` 必须对 Expo 移动壳和 Tauri 桌面壳做反向覆盖:共享契约中声明的每个移动端基础能力、iOS 额外能力和桌面能力,都必须在 `mobileCapabilityFlowContracts``desktopCapabilityFlowContracts` 中登记真实能力流证据。证据必须来自生产实现、宿主配置、边界测试或单端配置检查,不能用占位、生产 mock、fallback unsupported 分支或文档愿景替代真实链路。
- 2026-06-21 调整:Tauri 桌面能力流必须由根级 `desktop-shell:test` 保护,且每个 `desktopCapabilityFlowContracts` 条目至少关联一个带 Rust 单测的真实桌面壳模块;新增桌面 capability 时不能只登记 dispatch / 配置片段而没有 Rust 单元测试覆盖。
- 影响范围:`packages/shared/src/contracts/hostBridge.ts``apps/mobile-shell/src/host-bridge/``apps/mobile-shell/src/shell/``apps/desktop-shell/src-tauri/src/host_bridge/``apps/desktop-shell/src-tauri/src/shell/``scripts/check-native-shells.mjs`
- 验证方式:`npm run check:native-shells``npm run typecheck``npm run check:encoding``git diff --check`
+22
View File
@@ -3272,6 +3272,15 @@ function assertTauriDesktopCapabilityFlows() {
`Tauri desktop declared capabilities missing flow contracts: ${missingCapabilityContracts.join(', ')}`,
);
}
const desktopShellTestStep = steps.some(
(step) =>
step.label === 'desktop-shell-test' &&
step.args[0] === 'run' &&
step.args[1] === 'desktop-shell:test',
);
if (!desktopShellTestStep) {
throw new Error('Tauri desktop capability flows must be guarded by desktop-shell:test');
}
for (const contract of desktopCapabilityFlowContracts) {
if (!declaredCapabilitySet.has(contract.capability)) {
@@ -3295,6 +3304,19 @@ function assertTauriDesktopCapabilityFlows() {
`Tauri desktop ${contract.capability} flow`,
);
}
const testedRustFlowFiles = contract.files.filter((filePath) => {
if (!filePath.startsWith('apps/desktop-shell/src-tauri/src/') || !filePath.endsWith('.rs')) {
return false;
}
const source = fs.readFileSync(filePath, 'utf8');
return source.includes('#[test]');
});
if (testedRustFlowFiles.length === 0) {
throw new Error(
`Tauri desktop ${contract.capability} flow must include at least one Rust unit-tested module`,
);
}
}
}