锁定移动震动失败边界

移动震动桥接把原生反馈失败转为稳定 host_error

移动震动单测覆盖原生反馈不可用错误

移动壳配置检查反查震动失败边界
This commit is contained in:
2026-06-20 12:04:49 +08:00
parent d8ef351c59
commit 97588de941
3 changed files with 35 additions and 1 deletions
@@ -65,6 +65,11 @@ const filePayloadsPath = new URL(
const filePayloadsSource = fs.readFileSync(filePayloadsPath, 'utf8');
const hapticsPath = new URL('../src/host-bridge/haptics.ts', import.meta.url);
const hapticsSource = fs.readFileSync(hapticsPath, 'utf8');
const hapticsTestPath = new URL(
'../src/host-bridge/haptics.test.ts',
import.meta.url,
);
const hapticsTestSource = fs.readFileSync(hapticsTestPath, 'utf8');
const hostBridgeNavigationPath = new URL(
'../src/host-bridge/navigation.ts',
import.meta.url,
@@ -2209,6 +2214,7 @@ if (
!hapticsSource.includes('Haptics.ImpactFeedbackStyle.Medium') ||
!hapticsSource.includes('Haptics.ImpactFeedbackStyle.Light') ||
!hapticsSource.includes('await Haptics.impactAsync(toExpoImpactStyle(style))') ||
!hapticsSource.includes("message: 'haptics impact unavailable'") ||
!hapticsSource.includes('ok(request, true)')
) {
throw new Error(
@@ -2216,6 +2222,15 @@ if (
);
}
for (const snippet of [
'reports unavailable native feedback with a stable HostBridge error',
"message: 'haptics impact unavailable'",
]) {
if (!hapticsTestSource.includes(snippet)) {
throw new Error(`mobile shell haptics tests missing ${snippet}`);
}
}
if (
dispatchSource.includes("from 'expo-haptics'") ||
dispatchSource.includes('Haptics.impactAsync') ||
@@ -66,6 +66,17 @@ describe('mobile haptics helpers', () => {
expect(Haptics.impactAsync).not.toHaveBeenCalled();
});
test('reports unavailable native feedback with a stable HostBridge error', async () => {
vi.mocked(Haptics.impactAsync).mockRejectedValueOnce(
new Error('native haptics failed'),
);
await expect(runMobileHapticsImpact('light')).rejects.toMatchObject({
code: 'host_error',
message: 'haptics impact unavailable',
});
});
test('wraps HostBridge success response after real impact dispatch', async () => {
const response = await runMobileHostBridgeHapticsImpact(
request({
+9 -1
View File
@@ -2,6 +2,7 @@ import * as Haptics from 'expo-haptics';
import {
type HapticsImpactPayload,
type HostBridgeError,
type HostBridgeRequest,
normalizeHostBridgeHapticsImpactStyle,
type HostBridgeHapticsImpactStyle,
@@ -22,7 +23,14 @@ export async function runMobileHapticsImpact(rawStyle: unknown) {
return false;
}
await Haptics.impactAsync(toExpoImpactStyle(style));
try {
await Haptics.impactAsync(toExpoImpactStyle(style));
} catch {
throw {
code: 'host_error',
message: 'haptics impact unavailable',
} satisfies HostBridgeError;
}
return true;
}