锁定移动壳通知投递失败响应

移动壳通知通道创建失败返回稳定错误

移动壳通知调度失败返回稳定错误

移动壳配置检查补充通知投递失败边界反查
This commit is contained in:
2026-06-20 14:22:45 +08:00
parent 003d3240e3
commit e0d519686b
3 changed files with 56 additions and 16 deletions
@@ -1952,6 +1952,7 @@ for (const notificationSnippet of [
'normalizeHostBridgeLocalNotification(request.payload)',
"invalidRequest('title is required')",
"message: 'notification permission unavailable'",
"message: 'notification delivery unavailable'",
'showMobileLocalNotification(notification)',
'ok(request, await showMobileLocalNotification(notification))',
'HOST_BRIDGE_LOCAL_NOTIFICATION_DELIVERED_TO_SYSTEM_RESULT',
@@ -1964,7 +1965,10 @@ for (const notificationSnippet of [
for (const snippet of [
'rejects delivery when current permission lookup is unavailable',
'rejects delivery when permission request is unavailable',
'maps Android channel setup failures to stable delivery errors',
'maps native notification schedule failures to stable delivery errors',
"message: 'notification permission unavailable'",
"message: 'notification delivery unavailable'",
'expect(Notifications.setNotificationChannelAsync).not.toHaveBeenCalled()',
'expect(Notifications.scheduleNotificationAsync).not.toHaveBeenCalled()',
]) {
@@ -226,6 +226,35 @@ describe('mobile local notification helpers', () => {
});
});
test('maps Android channel setup failures to stable delivery errors', async () => {
setPlatformOS('android');
vi.mocked(Notifications.setNotificationChannelAsync).mockRejectedValueOnce(
new Error('native channel failed'),
);
await expect(
showMobileLocalNotification({ title: '生成完成' }),
).rejects.toMatchObject({
code: 'host_error',
message: 'notification delivery unavailable',
});
expect(Notifications.scheduleNotificationAsync).not.toHaveBeenCalled();
});
test('maps native notification schedule failures to stable delivery errors', async () => {
vi.mocked(Notifications.scheduleNotificationAsync).mockRejectedValueOnce(
new Error('native schedule failed'),
);
await expect(
showMobileLocalNotification({ title: '生成完成' }),
).rejects.toMatchObject({
code: 'host_error',
message: 'notification delivery unavailable',
});
});
test('normalizes HostBridge payload and wraps structured delivery result', async () => {
const response = await showMobileHostBridgeLocalNotification(
request({
@@ -74,23 +74,30 @@ export async function showMobileLocalNotification(
notification: LocalNotificationPayload,
) {
await ensureNotificationPermission();
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync(
HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID,
{
name: 'Genarrative',
importance: Notifications.AndroidImportance.DEFAULT,
},
);
}
try {
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync(
HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID,
{
name: 'Genarrative',
importance: Notifications.AndroidImportance.DEFAULT,
},
);
}
await Notifications.scheduleNotificationAsync({
content: notification,
trigger:
Platform.OS === 'android'
? { channelId: HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID }
: null,
});
await Notifications.scheduleNotificationAsync({
content: notification,
trigger:
Platform.OS === 'android'
? { channelId: HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID }
: null,
});
} catch {
throw {
code: 'host_error',
message: 'notification delivery unavailable',
} satisfies HostBridgeError;
}
return HOST_BRIDGE_LOCAL_NOTIFICATION_DELIVERED_TO_SYSTEM_RESULT;
}