1import { promptAsync } from '../../../utils/prompts'; 2import { ApiV2Error } from '../../rest/client'; 3import { showLoginPromptAsync } from '../actions'; 4import { retryUsernamePasswordAuthWithOTPAsync, UserSecondFactorDeviceMethod } from '../otp'; 5import { loginAsync } from '../user'; 6 7jest.mock('../../../log'); 8jest.mock('../../../utils/prompts'); 9jest.mock('../../rest/client', () => { 10 const { ApiV2Error } = jest.requireActual('../../rest/client'); 11 return { 12 ApiV2Error, 13 }; 14}); 15jest.mock('../otp'); 16jest.mock('../user'); 17 18const asMock = (fn: any): jest.Mock => fn; 19 20beforeEach(() => { 21 asMock(promptAsync).mockClear(); 22 asMock(promptAsync).mockImplementation(() => { 23 throw new Error('Should not be called'); 24 }); 25 26 asMock(loginAsync).mockClear(); 27}); 28 29describe(showLoginPromptAsync, () => { 30 it('prompts for OTP when 2FA is enabled', async () => { 31 asMock(promptAsync) 32 .mockImplementationOnce(() => ({ username: 'hello', password: 'world' })) 33 .mockImplementationOnce(() => ({ otp: '123456' })) 34 .mockImplementation(() => { 35 throw new Error("shouldn't happen"); 36 }); 37 asMock(loginAsync) 38 .mockImplementationOnce(async () => { 39 throw new ApiV2Error({ 40 message: 'An OTP is required', 41 code: 'ONE_TIME_PASSWORD_REQUIRED', 42 metadata: { 43 secondFactorDevices: [ 44 { 45 id: 'p0', 46 is_primary: true, 47 method: UserSecondFactorDeviceMethod.SMS, 48 sms_phone_number: 'testphone', 49 }, 50 ], 51 smsAutomaticallySent: true, 52 }, 53 }); 54 }) 55 .mockImplementation(() => {}); 56 57 await showLoginPromptAsync(); 58 59 expect(retryUsernamePasswordAuthWithOTPAsync).toHaveBeenCalledWith('hello', 'world', { 60 secondFactorDevices: [ 61 { 62 id: 'p0', 63 is_primary: true, 64 method: UserSecondFactorDeviceMethod.SMS, 65 sms_phone_number: 'testphone', 66 }, 67 ], 68 smsAutomaticallySent: true, 69 }); 70 }); 71 72 it('does not prompt if all required credentials are provided', async () => { 73 asMock(promptAsync).mockImplementation(() => { 74 throw new Error("shouldn't happen"); 75 }); 76 asMock(loginAsync).mockImplementation(() => {}); 77 78 await showLoginPromptAsync({ username: 'hello', password: 'world' }); 79 }); 80}); 81