feat(web): host_unreachable phase copy for dm_call_undeliverable (TDD)
This commit is contained in:
@@ -34,4 +34,24 @@ describe('buildCallUndeliverableToast', () => {
|
||||
it('legacy two-arg signature still works', () => {
|
||||
expect(buildCallUndeliverableToast([fail()], true)).toMatch(/Could not reach nova/);
|
||||
});
|
||||
|
||||
it('builds warning copy for host_unreachable (peer_transient_failure)', () => {
|
||||
const msg = buildCallUndeliverableToast(
|
||||
[{ reason: 'peer_transient_failure', peerOrigin: 'https://orbit.local', peerLabel: 'Orbit' }],
|
||||
true,
|
||||
'host_unreachable',
|
||||
);
|
||||
expect(msg.toLowerCase()).toContain('orbit');
|
||||
expect(msg.toLowerCase()).toContain('unreachable');
|
||||
});
|
||||
|
||||
it('builds warning copy for host_unreachable (peer_rejected)', () => {
|
||||
const msg = buildCallUndeliverableToast(
|
||||
[{ reason: 'peer_rejected', peerOrigin: 'https://orbit.local', peerLabel: 'Orbit' }],
|
||||
true,
|
||||
'host_unreachable',
|
||||
);
|
||||
expect(msg.toLowerCase()).toContain('orbit');
|
||||
expect(msg.toLowerCase()).toContain('peered');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
* - `reject`: the rejector's relay to the host failed; state was already cleared
|
||||
* locally, so non-terminal info toast only.
|
||||
* - `end`: the ender's relay to the host failed; state was already cleared locally.
|
||||
* - `host_unreachable`: the call was terminated by the sentinel worker because the
|
||||
* host peer became permanently unreachable. Always terminal. A single failure entry
|
||||
* is expected; multiple fall back to a generic line.
|
||||
*
|
||||
* Extracted from `useWebSocket.ts` so it can be unit-tested without pulling in
|
||||
* the full WS handler graph (livekit / audio deps).
|
||||
@@ -16,7 +19,7 @@
|
||||
export function buildCallUndeliverableToast(
|
||||
failures: Array<{ reason: string; peerOrigin?: string; peerLabel?: string }>,
|
||||
terminal: boolean,
|
||||
phase: 'start' | 'accept' | 'reject' | 'end' = 'start',
|
||||
phase: 'start' | 'accept' | 'reject' | 'end' | 'host_unreachable' = 'start',
|
||||
): string {
|
||||
const primary = failures[0];
|
||||
const labelFor = (f: { peerLabel?: string; peerOrigin?: string }) =>
|
||||
@@ -37,6 +40,21 @@ export function buildCallUndeliverableToast(
|
||||
return `Couldn't notify ${labels} that you hung up. Remote participants may see the call for up to 60 seconds.`;
|
||||
}
|
||||
|
||||
// host_unreachable: call terminated because the host peer became unreachable.
|
||||
// Terminal is always true in this phase. A single failure entry is expected;
|
||||
// zero or multiple fall back to a generic line.
|
||||
if (phase === 'host_unreachable') {
|
||||
const [f] = failures;
|
||||
if (!f || failures.length !== 1) {
|
||||
return 'Call ended — host instance became unreachable.';
|
||||
}
|
||||
const label = f.peerLabel || f.peerOrigin?.replace(/^https?:\/\//, '') || 'the host instance';
|
||||
if (f.reason === 'peer_rejected') {
|
||||
return `Call ended — this instance is no longer peered with ${label}.`;
|
||||
}
|
||||
return `Call ended — ${label} became unreachable.`;
|
||||
}
|
||||
|
||||
// phase === 'start' (default + legacy)
|
||||
if (!terminal) {
|
||||
const labels = failures.map(labelFor).join(', ');
|
||||
|
||||
Reference in New Issue
Block a user