test(#1394): pre-existing recover-token specs follow the new non-TTY path
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
The old specs mocked promptLine/promptSecret and relied on the prompt path being taken unconditionally — which is precisely the behavior #1394 removes (non-TTY must NOT sit on prompts). Under vitest stdin is non-TTY, so the new code correctly routed to piped-stdin credentials and the specs hung on the unmocked reader (4/7 timeouts). The specs now mock the piped-credentials seam with the same fixed values and assert that seam (not the prompts) was consulted; titles state the actual path. All 7 pass; suite 1667/1667 (remaining local failure is the known host pi-invariant, CI pins pi 0.84.1).
This commit is contained in:
@@ -16,11 +16,20 @@ vi.mock('./daemon.js', () => ({
|
|||||||
|
|
||||||
vi.mock('./login.js', () => ({
|
vi.mock('./login.js', () => ({
|
||||||
getGatewayUrl: vi.fn().mockReturnValue('http://localhost:14242'),
|
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('[email protected]'),
|
promptLine: vi.fn().mockResolvedValue('[email protected]'),
|
||||||
promptSecret: vi.fn().mockResolvedValue('test-password'),
|
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: '[email protected]',
|
||||||
|
password: 'test-password',
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
const mockFetch = vi.fn();
|
const mockFetch = vi.fn();
|
||||||
vi.stubGlobal('fetch', mockFetch);
|
vi.stubGlobal('fetch', mockFetch);
|
||||||
|
|
||||||
@@ -65,7 +74,7 @@ describe('ensureSession', () => {
|
|||||||
expect(mockSignIn).not.toHaveBeenCalled();
|
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: '[email protected]' });
|
mockLoadSession.mockReturnValueOnce({ cookie: 'old-cookie', userId: 'u1', email: '[email protected]' });
|
||||||
mockValidateSession.mockResolvedValueOnce(false);
|
mockValidateSession.mockResolvedValueOnce(false);
|
||||||
const newAuth = { cookie: fakeCookie, userId: 'u2', email: '[email protected]' };
|
const newAuth = { cookie: fakeCookie, userId: 'u2', email: '[email protected]' };
|
||||||
@@ -76,7 +85,7 @@ describe('ensureSession', () => {
|
|||||||
expect(mockSaveSession).toHaveBeenCalledWith(baseUrl, newAuth);
|
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);
|
mockLoadSession.mockReturnValueOnce(null);
|
||||||
const newAuth = { cookie: fakeCookie, userId: 'u2', email: '[email protected]' };
|
const newAuth = { cookie: fakeCookie, userId: 'u2', email: '[email protected]' };
|
||||||
mockSignIn.mockResolvedValueOnce(newAuth);
|
mockSignIn.mockResolvedValueOnce(newAuth);
|
||||||
@@ -84,6 +93,10 @@ describe('ensureSession', () => {
|
|||||||
const cookie = await ensureSession(baseUrl);
|
const cookie = await ensureSession(baseUrl);
|
||||||
expect(cookie).toBe(fakeCookie);
|
expect(cookie).toBe(fakeCookie);
|
||||||
expect(mockSignIn).toHaveBeenCalled();
|
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 () => {
|
it('exits non-zero when signIn fails', async () => {
|
||||||
@@ -111,7 +124,7 @@ describe('runRecoverToken', () => {
|
|||||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
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);
|
mockLoadSession.mockReturnValueOnce(null);
|
||||||
const newAuth = { cookie: fakeCookie, userId: 'u2', email: '[email protected]' };
|
const newAuth = { cookie: fakeCookie, userId: 'u2', email: '[email protected]' };
|
||||||
mockSignIn.mockResolvedValueOnce(newAuth);
|
mockSignIn.mockResolvedValueOnce(newAuth);
|
||||||
|
|||||||
Reference in New Issue
Block a user