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