diff --git a/packages/cli/src/__tests__/chat-shell.template.test.ts b/packages/cli/src/__tests__/chat-shell.template.test.ts index e31745f7fd2..f1f133e9280 100644 --- a/packages/cli/src/__tests__/chat-shell.template.test.ts +++ b/packages/cli/src/__tests__/chat-shell.template.test.ts @@ -141,7 +141,7 @@ describe('chat-shell.handlebars', () => { ...withOneMissingAccount, ready: true, connectedCount: 1, - barText: 'All 1 account connected · ready to chat', + barText: 'Account connected · ready to chat', credentials: [ { id: 'cred-1', @@ -159,6 +159,8 @@ describe('chat-shell.handlebars', () => { // The dialog is what carries Disconnect, so Manage has somewhere to land. expect(html).toContain('btn-disconnect'); expect(html).toContain('Connected as visitor@example.com'); + // "All" only reads correctly once there's more than one account to be "all" of. + expect(html).toContain('Account connected · ready to chat'); }); it('keeps the control in test mode while accounts are outstanding', async () => { @@ -497,6 +499,16 @@ describe('chat-shell.handlebars', () => { const row = makeElement({ 'data-row-key': 'cred-1::system-n8n', 'data-id': 'cred-1' }); row.querySelector = (selector: string) => (selector === '.connect' ? connectButton : null); + // The bar's own connect click, captured so a test can trigger the real + // single-account round trip (openConnect -> popup -> success signal), the + // same path `barText`'s live recompute runs through. + const barTextEl = makeElement(); + const clickHandlers: Array<() => void> = []; + const barAction = makeElement(); + barAction.addEventListener = (type: string, fn: () => void) => { + if (type === 'click') clickHandlers.push(fn); + }; + const posted: Array> = []; const frame = { ...makeElement(), @@ -508,10 +520,13 @@ describe('chat-shell.handlebars', () => { 'n8n-chat-frame': frame, 'n8n-connect-bar': bar, 'n8n-connect-overlay': overlay, + 'n8n-connect-bar-text': barTextEl, + 'n8n-connect-bar-action': barAction, }; const listeners: Array<(event: unknown) => void> = []; const opened: string[] = []; + const popup = { closed: false }; const doc = { getElementById: (id: string) => byId[id] ?? makeElement(), querySelector: (selector: string) => (selector === '.cred-row' ? row : makeElement()), @@ -529,7 +544,7 @@ describe('chat-shell.handlebars', () => { parent: {}, open: (url: string) => { opened.push(url); - return null; + return popup; }, }; @@ -561,7 +576,14 @@ describe('chat-shell.handlebars', () => { return opened; } - return { overlay, opened, send }; + return { + overlay, + opened, + send, + barTextEl, + clickConnect: () => clickHandlers.forEach((fn) => fn()), + signalSuccess: () => listeners.forEach((fn) => fn({ source: popup, data: 'success' })), + }; } const rejection = (ids: unknown) => ({ type: 'n8n-chat-credentials-rejected', ids }); @@ -638,5 +660,17 @@ describe('chat-shell.handlebars', () => { send(rejection(['cred-1'])); expect(rows[0].getAttribute('data-connected')).toBeNull(); }); + + // "All 1 account connected" reads wrong once the last (only) account connects + // live in the browser - the same text `connectBarText` already gets right for + // the initial, server-rendered state. + it('says "Account connected", not "All 1 account connected", once the only account connects', async () => { + const { barTextEl, clickConnect, signalSuccess } = await runSingleAccountBarScript(); + + clickConnect(); + signalSuccess(); + + expect(barTextEl.textContent).toBe('Account connected · ready to chat'); + }); }); }); diff --git a/packages/cli/templates/chat-shell.handlebars b/packages/cli/templates/chat-shell.handlebars index bdc4ac1623c..4e0efdb4b6a 100644 --- a/packages/cli/templates/chat-shell.handlebars +++ b/packages/cli/templates/chat-shell.handlebars @@ -426,8 +426,12 @@ function barText(count) { var remaining = Math.max(total - count, 0); if (remaining === 0) { - return TEST_MODE - ? "You're testing with your own connected accounts. Visitors will need to connect their own." + if (TEST_MODE) { + return "You're testing with your own connected accounts. Visitors will need to connect their own."; + } + // "All" only reads correctly once there's more than one account to be "all" of. + return total === 1 + ? 'Account connected · ready to chat' : 'All ' + total + ' ' + accountsLabel(total) + ' connected · ready to chat'; } if (hasFailed()) return 'Connection failed · try again';