记录移动扫码权限请求失败
移动扫码权限请求异常时记录原始错误 移动扫码 overlay 测试覆盖权限请求失败路径 移动壳配置检查反查扫码权限失败日志边界 共享决策日志补充扫码权限失败边界
This commit is contained in:
@@ -2180,6 +2180,8 @@ for (const snippet of [
|
||||
'failQrCodeScan',
|
||||
'cancelQrCodeScan',
|
||||
'subscribeQrScannerState',
|
||||
'logQrScannerPermissionFailure(error)',
|
||||
"console.warn('mobile QR scanner permission request failed', error)",
|
||||
]) {
|
||||
if (!qrScannerOverlaySource.includes(snippet)) {
|
||||
throw new Error(`mobile shell QR scanner overlay missing ${snippet}`);
|
||||
@@ -2191,7 +2193,10 @@ for (const snippet of [
|
||||
'scanQrCode()',
|
||||
'requestCameraPermissionsAsync',
|
||||
"message: 'camera permission denied'",
|
||||
"message: 'camera permission unavailable'",
|
||||
"message: 'qr scan cancelled'",
|
||||
"test('logs and rejects the active scan when camera permission request fails'",
|
||||
"'mobile QR scanner permission request failed'",
|
||||
"barcodeTypes: ['qr']",
|
||||
"type: 'qr'",
|
||||
"value: 'https://app.genarrative.world/works/detail?work=PZ-1'",
|
||||
|
||||
@@ -118,6 +118,25 @@ describe('QrScannerOverlay', () => {
|
||||
expect(overlayHarness.cameraViewProps.current).toBeNull();
|
||||
});
|
||||
|
||||
test('logs and rejects the active scan when camera permission request fails', async () => {
|
||||
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
const error = new Error('camera unavailable');
|
||||
cameraPermissionMock.mockRejectedValue(error);
|
||||
render(<QrScannerOverlay />);
|
||||
|
||||
const scanPromise = scanQrCode();
|
||||
|
||||
await expect(scanPromise).rejects.toMatchObject({
|
||||
code: 'host_error',
|
||||
message: 'camera permission unavailable',
|
||||
});
|
||||
expect(warnSpy).toHaveBeenCalledWith(
|
||||
'mobile QR scanner permission request failed',
|
||||
error,
|
||||
);
|
||||
expect(overlayHarness.cameraViewProps.current).toBeNull();
|
||||
});
|
||||
|
||||
test('close button cancels the pending scan', async () => {
|
||||
cameraPermissionMock.mockResolvedValue({
|
||||
granted: true,
|
||||
|
||||
@@ -13,6 +13,10 @@ import {
|
||||
subscribeQrScannerState,
|
||||
} from '../host-bridge/scanner';
|
||||
|
||||
function logQrScannerPermissionFailure(error: unknown) {
|
||||
console.warn('mobile QR scanner permission request failed', error);
|
||||
}
|
||||
|
||||
export function QrScannerOverlay() {
|
||||
const [isActive, setIsActive] = useState(false);
|
||||
const [requestKey, setRequestKey] = useState(0);
|
||||
@@ -45,8 +49,9 @@ export function QrScannerOverlay() {
|
||||
}
|
||||
setHasPermission(true);
|
||||
})
|
||||
.catch(() => {
|
||||
.catch((error: unknown) => {
|
||||
if (!disposed) {
|
||||
logQrScannerPermissionFailure(error);
|
||||
failQrCodeScan('camera permission unavailable');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2951,6 +2951,13 @@
|
||||
- 影响范围:`apps/mobile-shell/src/shell/lifecycle.ts`、`apps/mobile-shell/src/shell/lifecycle.test.ts`、`apps/mobile-shell/scripts/check-config.mjs`。
|
||||
- 验证方式:`npm run mobile-shell:test -- src/shell/lifecycle.test.ts`、`npm run mobile-shell:config`、`npm run check:native-shells`、`npm run check:encoding`、`git diff --check`。
|
||||
|
||||
## 2026-06-20 移动扫码权限请求失败不可静默
|
||||
|
||||
- 背景:Expo 移动壳 `scanner.scanQrCode` 会通过真实 `expo-camera` 权限 API 启动扫码;如果权限请求 API 自身失败后只返回通用 `host_error` 而不记录原始错误,用户会看到扫码不可用但开发侧难以区分系统拒绝、原生模块异常或设备能力问题。
|
||||
- 决策:`QrScannerOverlay` 的 `Camera.requestCameraPermissionsAsync()` reject 路径必须调用 `logQrScannerPermissionFailure(...)` 输出 `mobile QR scanner permission request failed` 日志,再通过 `failQrCodeScan('camera permission unavailable')` 结束当前请求;`QrScannerOverlay.test.tsx` 必须覆盖该 reject 路径,移动壳配置检查反查日志 helper 和测试断言。
|
||||
- 影响范围:`apps/mobile-shell/src/shell/QrScannerOverlay.tsx`、`apps/mobile-shell/src/shell/QrScannerOverlay.test.tsx`、`apps/mobile-shell/scripts/check-config.mjs`。
|
||||
- 验证方式:`npm run mobile-shell:test -- src/shell/QrScannerOverlay.test.tsx`、`npm run mobile-shell:typecheck`、`npm run check:native-shells`、`npm run check:encoding`、`git diff --check`。
|
||||
|
||||
## 2026-06-20 移动分享单测边界
|
||||
|
||||
- 背景:Expo 移动壳 `share.open` / `share.setTarget` 已经由 `share.ts` 承接共享 HostBridge 分享 URL 归一和缓存目标,但关键边界主要压在巨型 `bridge.test.ts` 中,后续拆分桥接 helper 时容易遗漏非法显式 payload 不回退缓存、空分享拒绝和缓存目标保留语义。
|
||||
|
||||
Reference in New Issue
Block a user