From b16ece93b86029b2adea69bb6e1d754fb8335a92 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Fri, 24 Apr 2026 21:15:21 +0200 Subject: [PATCH] feat(web): no_recipient toast copy arm (#18) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit buildCallUndeliverableToast renders "{peerLabel} couldn't ring anyone." for the single-failure terminal case; multi-failure + non-terminal paths fall through to existing lines (which already fold the new reason in by peer label). TDD — four new assertions. --- .../useWebSocket.callUndeliverable.test.ts | 36 +++++++++++++++++++ .../web/src/utils/callUndeliverableToast.ts | 2 ++ 2 files changed, 38 insertions(+) diff --git a/packages/web/src/hooks/__tests__/useWebSocket.callUndeliverable.test.ts b/packages/web/src/hooks/__tests__/useWebSocket.callUndeliverable.test.ts index 2a3c9840..f6ef623e 100644 --- a/packages/web/src/hooks/__tests__/useWebSocket.callUndeliverable.test.ts +++ b/packages/web/src/hooks/__tests__/useWebSocket.callUndeliverable.test.ts @@ -54,4 +54,40 @@ describe('buildCallUndeliverableToast', () => { expect(msg.toLowerCase()).toContain('orbit'); expect(msg.toLowerCase()).toContain('peered'); }); + + it('renders no_recipient single-failure terminal copy', () => { + const fail = (peerLabel = 'Orbit') => ({ + reason: 'no_recipient', + peerOrigin: 'https://orbit.local', + peerLabel, + }); + expect(buildCallUndeliverableToast([fail()], true, 'start')) + .toBe("Orbit couldn't ring anyone."); + }); + + it('no_recipient falls back to origin when peerLabel missing', () => { + const fail = { + reason: 'no_recipient', + peerOrigin: 'https://orbit.local', + }; + expect(buildCallUndeliverableToast([fail], true, 'start')) + .toMatch(/orbit\.local couldn't ring anyone\./); + }); + + it('no_recipient in a multi-failure terminal falls back to multi-instance copy', () => { + const failures = [ + { reason: 'no_recipient', peerOrigin: 'https://orbit.local', peerLabel: 'Orbit' }, + { reason: 'peer_transient_failure', peerOrigin: 'https://nova.local', peerLabel: 'Nova' }, + ]; + expect(buildCallUndeliverableToast(failures, true, 'start')) + .toMatch(/Could not reach 2 instances: Orbit, Nova/); + }); + + it('no_recipient non-terminal uses the existing "Some participants" line', () => { + const failures = [ + { reason: 'no_recipient', peerOrigin: 'https://orbit.local', peerLabel: 'Orbit' }, + ]; + expect(buildCallUndeliverableToast(failures, false, 'start')) + .toMatch(/Some participants could not be reached: Orbit/); + }); }); diff --git a/packages/web/src/utils/callUndeliverableToast.ts b/packages/web/src/utils/callUndeliverableToast.ts index dd4aeefc..47060e78 100644 --- a/packages/web/src/utils/callUndeliverableToast.ts +++ b/packages/web/src/utils/callUndeliverableToast.ts @@ -76,6 +76,8 @@ export function buildCallUndeliverableToast( return `Could not reach ${label}. Try again in a moment.`; case 'livekit_unavailable': return 'Voice is not configured on this instance.'; + case 'no_recipient': + return `${label} couldn't ring anyone.`; default: return `Call to ${label} could not be placed.`; }