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', () => {
|
it('legacy two-arg signature still works', () => {
|
||||||
expect(buildCallUndeliverableToast([fail()], true)).toMatch(/Could not reach nova/);
|
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
|
* - `reject`: the rejector's relay to the host failed; state was already cleared
|
||||||
* locally, so non-terminal info toast only.
|
* locally, so non-terminal info toast only.
|
||||||
* - `end`: the ender's relay to the host failed; state was already cleared locally.
|
* - `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
|
* Extracted from `useWebSocket.ts` so it can be unit-tested without pulling in
|
||||||
* the full WS handler graph (livekit / audio deps).
|
* the full WS handler graph (livekit / audio deps).
|
||||||
@@ -16,7 +19,7 @@
|
|||||||
export function buildCallUndeliverableToast(
|
export function buildCallUndeliverableToast(
|
||||||
failures: Array<{ reason: string; peerOrigin?: string; peerLabel?: string }>,
|
failures: Array<{ reason: string; peerOrigin?: string; peerLabel?: string }>,
|
||||||
terminal: boolean,
|
terminal: boolean,
|
||||||
phase: 'start' | 'accept' | 'reject' | 'end' = 'start',
|
phase: 'start' | 'accept' | 'reject' | 'end' | 'host_unreachable' = 'start',
|
||||||
): string {
|
): string {
|
||||||
const primary = failures[0];
|
const primary = failures[0];
|
||||||
const labelFor = (f: { peerLabel?: string; peerOrigin?: string }) =>
|
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.`;
|
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)
|
// phase === 'start' (default + legacy)
|
||||||
if (!terminal) {
|
if (!terminal) {
|
||||||
const labels = failures.map(labelFor).join(', ');
|
const labels = failures.map(labelFor).join(', ');
|
||||||
|
|||||||
Reference in New Issue
Block a user