From 1b56ac8451ff954e941204e5ef205832d8cf41c4 Mon Sep 17 00:00:00 2001 From: justinhelmer <1403438+justinhelmer@users.noreply.github.com> Date: Sat, 3 Oct 2026 13:57:17 +0000 Subject: [PATCH 1/2] fix: show concise identity in quiet whoami output Co-Authored-By: coreplane-switchboard[bot] <318072483+coreplane-switchboard[bot]@users.noreply.github.com> --- src/commands/auth/whoami.ts | 4 +++ test/auth-whoami.test.ts | 64 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 test/auth-whoami.test.ts diff --git a/src/commands/auth/whoami.ts b/src/commands/auth/whoami.ts index f662fde..7af04f4 100644 --- a/src/commands/auth/whoami.ts +++ b/src/commands/auth/whoami.ts @@ -10,6 +10,10 @@ export const authWhoamiCommand: Command = { async execute(config: Config): Promise { const api = new PolylaneAPI(config); const user = await api.authWhoami(); + if (config.quiet && config.output === 'text') { + process.stdout.write(`Signed in as ${user.email || user.id}\n`); + return; + } formatOutput(config, user); }, }; diff --git a/test/auth-whoami.test.ts b/test/auth-whoami.test.ts new file mode 100644 index 0000000..c05ff1a --- /dev/null +++ b/test/auth-whoami.test.ts @@ -0,0 +1,64 @@ +import { after, before, beforeEach, describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import { authWhoamiCommand } from '../src/commands/auth/whoami'; +import { mockConfig } from './helpers/config'; + +const user = { + id: 'user_123', + email: 'dev@example.test', + username: 'dev', + scope: 'read write', + _html_url: 'https://console.example.test/users/user_123', +}; + +describe('auth whoami', () => { + const originalFetch = globalThis.fetch; + const originalWrite = process.stdout.write; + let stdout = ''; + + before(() => { + process.stdout.write = ((chunk: string | Uint8Array): boolean => { + stdout += String(chunk); + return true; + }) as typeof process.stdout.write; + }); + + beforeEach(() => { + delete process.env.POLYLANE_API_KEY; + stdout = ''; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + assert.equal(String(input), 'https://api.example.test/v1/auth/whoami'); + assert.equal(new Headers(init?.headers).get('x-api-key'), 'test-key'); + return Response.json({ success: true, error: null, result: user }); + }) as typeof fetch; + }); + + after(() => { + globalThis.fetch = originalFetch; + process.stdout.write = originalWrite; + }); + + it('keeps the full identity in ordinary text output', async () => { + await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', output: 'text' }), {}, {}); + assert.match(stdout, /id\s+user_123/); + assert.match(stdout, /email\s+dev@example\.test/); + assert.match(stdout, /scope\s+read write/); + assert.match(stdout, /Console: https:\/\/console\.example\.test\/users\/user_123/); + }); + + it('prints only the email on one line in quiet text output', async () => { + await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', output: 'text', quiet: true }), {}, {}); + assert.equal(stdout, 'Signed in as dev@example.test\n'); + }); + + it('preserves structured JSON even when quiet is set', async () => { + await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', output: 'json', quiet: true }), {}, {}); + assert.deepEqual(JSON.parse(stdout), user); + }); + + it('uses the user id when an email is unavailable', async () => { + globalThis.fetch = (async () => Response.json({ success: true, error: null, result: { id: 'user_123', email: '' } })) as typeof fetch; + await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', output: 'text', quiet: true }), {}, {}); + assert.equal(stdout, 'Signed in as user_123\n'); + }); +}); From 142b304ff3cdd91af5165b9abb6c7f9d1b3d4ee7 Mon Sep 17 00:00:00 2001 From: Justin Helmer <1403438+justinhelmer@users.noreply.github.com> Date: Sat, 3 Oct 2026 07:24:03 -0700 Subject: [PATCH 2/2] test: isolate whoami auth fixture from stored credentials --- test/auth-whoami.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/auth-whoami.test.ts b/test/auth-whoami.test.ts index c05ff1a..266543f 100644 --- a/test/auth-whoami.test.ts +++ b/test/auth-whoami.test.ts @@ -39,7 +39,7 @@ describe('auth whoami', () => { }); it('keeps the full identity in ordinary text output', async () => { - await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', output: 'text' }), {}, {}); + await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', apiKeySource: 'flag', output: 'text' }), {}, {}); assert.match(stdout, /id\s+user_123/); assert.match(stdout, /email\s+dev@example\.test/); assert.match(stdout, /scope\s+read write/); @@ -47,18 +47,18 @@ describe('auth whoami', () => { }); it('prints only the email on one line in quiet text output', async () => { - await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', output: 'text', quiet: true }), {}, {}); + await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', apiKeySource: 'flag', output: 'text', quiet: true }), {}, {}); assert.equal(stdout, 'Signed in as dev@example.test\n'); }); it('preserves structured JSON even when quiet is set', async () => { - await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', output: 'json', quiet: true }), {}, {}); + await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', apiKeySource: 'flag', output: 'json', quiet: true }), {}, {}); assert.deepEqual(JSON.parse(stdout), user); }); it('uses the user id when an email is unavailable', async () => { globalThis.fetch = (async () => Response.json({ success: true, error: null, result: { id: 'user_123', email: '' } })) as typeof fetch; - await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', output: 'text', quiet: true }), {}, {}); + await authWhoamiCommand.execute(mockConfig({ apiKey: 'test-key', apiKeySource: 'flag', output: 'text', quiet: true }), {}, {}); assert.equal(stdout, 'Signed in as user_123\n'); }); });