锁定移动震动失败边界
移动震动桥接把原生反馈失败转为稳定 host_error 移动震动单测覆盖原生反馈不可用错误 移动壳配置检查反查震动失败边界
This commit is contained in:
@@ -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({
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user