fix(ext/popup): defensive Promise.allSettled in devices (Plan C Phase 5)
DEV-C P2: Promise.all meant one rejected RPC failed the whole render.
allSettled + per-slot fallback keeps the active-devices surface usable
when the revoked-list feed (or one bad ssh fingerprint) is down.
Two call sites converted in devices.ts:
1. list_devices + list_revoked pair — revoked failures now render an
inline "couldn't load" slot instead of failing the page.
2. sshFingerprint map — one bad public key falls back to '(unknown)'
instead of killing the whole device list.
trash.ts only has a single sendMessage in its load path on this branch,
so it has no Promise.all to migrate. Plan was written against a slightly
different snapshot; documented divergence in report.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,32 @@ describe('devices view', () => {
|
||||
expect(app.querySelector<HTMLButtonElement>('#register-confirm-btn')).not.toBeNull();
|
||||
});
|
||||
|
||||
// Plan C Phase 5 — defensive Promise.allSettled:
|
||||
// a rejected secondary feed (list_revoked) should not kill the whole render.
|
||||
it('renders devices when revoked list fails (load-error slot shown)', async () => {
|
||||
(sendMessage as ReturnType<typeof vi.fn>)
|
||||
.mockResolvedValueOnce({ ok: true, data: { devices: [{ name: 'CLI', public_key: 'k', added_at: 1 }] } })
|
||||
.mockRejectedValueOnce(new Error('boom'));
|
||||
|
||||
await renderDevices(app);
|
||||
|
||||
// Primary list still rendered.
|
||||
expect(app.innerHTML).toContain('CLI');
|
||||
// Inline fallback slot present.
|
||||
expect(app.innerHTML).toContain("Couldn't load revoked devices");
|
||||
});
|
||||
|
||||
it('renders devices when revoked list returns {ok:false}', async () => {
|
||||
(sendMessage as ReturnType<typeof vi.fn>)
|
||||
.mockResolvedValueOnce({ ok: true, data: { devices: [{ name: 'CLI', public_key: 'k', added_at: 1 }] } })
|
||||
.mockResolvedValueOnce({ ok: false, error: 'list_revoked_failed' });
|
||||
|
||||
await renderDevices(app);
|
||||
|
||||
expect(app.innerHTML).toContain('CLI');
|
||||
expect(app.innerHTML).toContain("Couldn't load revoked devices");
|
||||
});
|
||||
|
||||
it('confirming register sends register_this_device with the entered name', async () => {
|
||||
(chrome.storage.local.get as ReturnType<typeof vi.fn>).mockResolvedValueOnce({ device_name: 'Unknown' });
|
||||
// Initial render: list_devices + list_revoked.
|
||||
|
||||
Reference in New Issue
Block a user