1fa5bc561SWill Schurmanimport { asMock } from '../../../__tests__/asMock';
28d307f52SEvan Baconimport { promptAsync } from '../../../utils/prompts';
38d307f52SEvan Baconimport { ApiV2Error } from '../../rest/client';
48d307f52SEvan Baconimport { showLoginPromptAsync } from '../actions';
58d307f52SEvan Baconimport { retryUsernamePasswordAuthWithOTPAsync, UserSecondFactorDeviceMethod } from '../otp';
6*d88ac65dSlzkbimport { loginAsync, ssoLoginAsync } from '../user';
78d307f52SEvan Bacon
84c50faceSEvan Baconjest.mock('../../../log');
98d307f52SEvan Baconjest.mock('../../../utils/prompts');
108d307f52SEvan Baconjest.mock('../../rest/client', () => {
118d307f52SEvan Bacon  const { ApiV2Error } = jest.requireActual('../../rest/client');
128d307f52SEvan Bacon  return {
138d307f52SEvan Bacon    ApiV2Error,
148d307f52SEvan Bacon  };
158d307f52SEvan Bacon});
168d307f52SEvan Baconjest.mock('../otp');
178d307f52SEvan Baconjest.mock('../user');
188d307f52SEvan Bacon
198d307f52SEvan BaconbeforeEach(() => {
208d307f52SEvan Bacon  asMock(promptAsync).mockClear();
218d307f52SEvan Bacon  asMock(promptAsync).mockImplementation(() => {
228d307f52SEvan Bacon    throw new Error('Should not be called');
238d307f52SEvan Bacon  });
248d307f52SEvan Bacon
258d307f52SEvan Bacon  asMock(loginAsync).mockClear();
26*d88ac65dSlzkb  asMock(ssoLoginAsync).mockClear();
278d307f52SEvan Bacon});
288d307f52SEvan Bacon
298d307f52SEvan Bacondescribe(showLoginPromptAsync, () => {
308d307f52SEvan Bacon  it('prompts for OTP when 2FA is enabled', async () => {
318d307f52SEvan Bacon    asMock(promptAsync)
32fa5bc561SWill Schurman      .mockImplementationOnce(async () => ({ username: 'hello', password: 'world' }))
33fa5bc561SWill Schurman      .mockImplementationOnce(async () => ({ otp: '123456' }))
348d307f52SEvan Bacon      .mockImplementation(() => {
358d307f52SEvan Bacon        throw new Error("shouldn't happen");
368d307f52SEvan Bacon      });
378d307f52SEvan Bacon    asMock(loginAsync)
388d307f52SEvan Bacon      .mockImplementationOnce(async () => {
398d307f52SEvan Bacon        throw new ApiV2Error({
408d307f52SEvan Bacon          message: 'An OTP is required',
418d307f52SEvan Bacon          code: 'ONE_TIME_PASSWORD_REQUIRED',
428d307f52SEvan Bacon          metadata: {
438d307f52SEvan Bacon            secondFactorDevices: [
448d307f52SEvan Bacon              {
458d307f52SEvan Bacon                id: 'p0',
468d307f52SEvan Bacon                is_primary: true,
478d307f52SEvan Bacon                method: UserSecondFactorDeviceMethod.SMS,
488d307f52SEvan Bacon                sms_phone_number: 'testphone',
498d307f52SEvan Bacon              },
508d307f52SEvan Bacon            ],
518d307f52SEvan Bacon            smsAutomaticallySent: true,
528d307f52SEvan Bacon          },
538d307f52SEvan Bacon        });
548d307f52SEvan Bacon      })
55fa5bc561SWill Schurman      .mockImplementation(async () => {});
568d307f52SEvan Bacon
578d307f52SEvan Bacon    await showLoginPromptAsync();
588d307f52SEvan Bacon
598d307f52SEvan Bacon    expect(retryUsernamePasswordAuthWithOTPAsync).toHaveBeenCalledWith('hello', 'world', {
608d307f52SEvan Bacon      secondFactorDevices: [
618d307f52SEvan Bacon        {
628d307f52SEvan Bacon          id: 'p0',
638d307f52SEvan Bacon          is_primary: true,
648d307f52SEvan Bacon          method: UserSecondFactorDeviceMethod.SMS,
658d307f52SEvan Bacon          sms_phone_number: 'testphone',
668d307f52SEvan Bacon        },
678d307f52SEvan Bacon      ],
688d307f52SEvan Bacon      smsAutomaticallySent: true,
698d307f52SEvan Bacon    });
708d307f52SEvan Bacon  });
718d307f52SEvan Bacon
728d307f52SEvan Bacon  it('does not prompt if all required credentials are provided', async () => {
738d307f52SEvan Bacon    asMock(promptAsync).mockImplementation(() => {
748d307f52SEvan Bacon      throw new Error("shouldn't happen");
758d307f52SEvan Bacon    });
76fa5bc561SWill Schurman    asMock(loginAsync).mockImplementation(async () => {});
778d307f52SEvan Bacon
788d307f52SEvan Bacon    await showLoginPromptAsync({ username: 'hello', password: 'world' });
798d307f52SEvan Bacon  });
80*d88ac65dSlzkb
81*d88ac65dSlzkb  it('calls regular login if the sso flag is false', async () => {
82*d88ac65dSlzkb    asMock(promptAsync).mockImplementationOnce(async () => ({
83*d88ac65dSlzkb      username: 'USERNAME',
84*d88ac65dSlzkb      password: 'PASSWORD',
85*d88ac65dSlzkb    }));
86*d88ac65dSlzkb
87*d88ac65dSlzkb    await showLoginPromptAsync({ username: 'hello', password: 'world', sso: false });
88*d88ac65dSlzkb
89*d88ac65dSlzkb    expect(loginAsync).toHaveBeenCalledTimes(1);
90*d88ac65dSlzkb  });
91*d88ac65dSlzkb
92*d88ac65dSlzkb  it('calls regular login if the sso flag is undefined', async () => {
93*d88ac65dSlzkb    asMock(promptAsync)
94*d88ac65dSlzkb      .mockImplementationOnce(async () => ({ username: 'USERNAME', password: 'PASSWORD' }))
95*d88ac65dSlzkb      .mockImplementation(() => {
96*d88ac65dSlzkb        throw new Error("shouldn't happen");
97*d88ac65dSlzkb      });
98*d88ac65dSlzkb
99*d88ac65dSlzkb    await showLoginPromptAsync({ username: 'hello', password: 'world' });
100*d88ac65dSlzkb
101*d88ac65dSlzkb    expect(loginAsync).toHaveBeenCalledTimes(1);
102*d88ac65dSlzkb  });
103*d88ac65dSlzkb
104*d88ac65dSlzkb  it('calls SSO login if the sso flag is true', async () => {
105*d88ac65dSlzkb    asMock(promptAsync);
106*d88ac65dSlzkb    await showLoginPromptAsync({ username: 'hello', password: 'world', sso: true });
107*d88ac65dSlzkb
108*d88ac65dSlzkb    expect(ssoLoginAsync).toHaveBeenCalledTimes(1);
109*d88ac65dSlzkb  });
1108d307f52SEvan Bacon});
111