diff --git a/packages/mosaic/src/commands/gateway/recover-token.spec.ts b/packages/mosaic/src/commands/gateway/recover-token.spec.ts index d00bc0db..aef6c75b 100644 --- a/packages/mosaic/src/commands/gateway/recover-token.spec.ts +++ b/packages/mosaic/src/commands/gateway/recover-token.spec.ts @@ -16,11 +16,20 @@ vi.mock('./daemon.js', () => ({ vi.mock('./login.js', () => ({ getGatewayUrl: vi.fn().mockReturnValue('http://localhost:14242'), - // promptLine/promptSecret are used by ensureSession; return fixed values so tests don't block on stdin + // promptLine/promptSecret are used by ensureSession on the TTY path; return fixed + // values so tests never block on stdin. promptLine: vi.fn().mockResolvedValue('test@example.com'), promptSecret: vi.fn().mockResolvedValue('test-password'), })); +// #1394: non-TTY runs resolve credentials from piped stdin instead of prompts. +vi.mock('./piped-credentials.js', () => ({ + readCredentialsFromPipedStdin: vi.fn().mockResolvedValue({ + email: 'test@example.com', + password: 'test-password', + }), +})); + const mockFetch = vi.fn(); vi.stubGlobal('fetch', mockFetch); @@ -65,7 +74,7 @@ describe('ensureSession', () => { expect(mockSignIn).not.toHaveBeenCalled(); }); - it('prompts for credentials and signs in when stored session is invalid', async () => { + it('resolves piped-stdin credentials and signs in when stored session is invalid', async () => { mockLoadSession.mockReturnValueOnce({ cookie: 'old-cookie', userId: 'u1', email: 'a@b.com' }); mockValidateSession.mockResolvedValueOnce(false); const newAuth = { cookie: fakeCookie, userId: 'u2', email: 'a@b.com' }; @@ -76,7 +85,7 @@ describe('ensureSession', () => { expect(mockSaveSession).toHaveBeenCalledWith(baseUrl, newAuth); }); - it('prompts for credentials when no session exists', async () => { + it('resolves piped-stdin credentials when no session exists', async () => { mockLoadSession.mockReturnValueOnce(null); const newAuth = { cookie: fakeCookie, userId: 'u2', email: 'a@b.com' }; mockSignIn.mockResolvedValueOnce(newAuth); @@ -84,6 +93,10 @@ describe('ensureSession', () => { const cookie = await ensureSession(baseUrl); expect(cookie).toBe(fakeCookie); expect(mockSignIn).toHaveBeenCalled(); + // The non-TTY path resolves credentials from the piped-stdin seam, not prompts. + expect( + vi.mocked(await import('./piped-credentials.js')).readCredentialsFromPipedStdin, + ).toHaveBeenCalled(); }); it('exits non-zero when signIn fails', async () => { @@ -111,7 +124,7 @@ describe('runRecoverToken', () => { vi.spyOn(console, 'error').mockImplementation(() => {}); }); - it('prompts for login, mints a token, and persists it when no session exists', async () => { + it('signs in via piped stdin, mints a token, and persists it when no session exists', async () => { mockLoadSession.mockReturnValueOnce(null); const newAuth = { cookie: fakeCookie, userId: 'u2', email: 'admin@test.com' }; mockSignIn.mockResolvedValueOnce(newAuth);