recoveryOptionsModal.spec.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import styled from '@emotion/styled';
  2. import {
  3. AllAuthenticatorsFixture,
  4. AuthenticatorsFixture,
  5. } from 'sentry-fixture/authenticators';
  6. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  7. import {makeCloseButton} from 'sentry/components/globalModal/components';
  8. import RecoveryOptionsModal from 'sentry/components/modals/recoveryOptionsModal';
  9. describe('RecoveryOptionsModal', function () {
  10. const closeModal = jest.fn();
  11. const mockId = AuthenticatorsFixture().Recovery().authId;
  12. beforeEach(function () {
  13. MockApiClient.clearMockResponses();
  14. MockApiClient.addMockResponse({
  15. url: '/users/me/authenticators/',
  16. method: 'GET',
  17. body: AllAuthenticatorsFixture(),
  18. });
  19. });
  20. function renderComponent() {
  21. const styledWrapper = styled(c => c.children);
  22. render(
  23. <RecoveryOptionsModal
  24. Body={styledWrapper()}
  25. Header={p => <span>{p.children}</span>}
  26. Footer={styledWrapper()}
  27. authenticatorName="Authenticator App"
  28. closeModal={closeModal}
  29. CloseButton={makeCloseButton(() => {})}
  30. />
  31. );
  32. }
  33. it('can redirect to recovery codes if user skips backup phone setup', async function () {
  34. renderComponent();
  35. const skipButton = await screen.findByRole('button', {name: 'Skip this step'});
  36. expect(
  37. screen.queryByRole('button', {name: 'Get Recovery Codes'})
  38. ).not.toBeInTheDocument();
  39. // skip backup phone setup
  40. await userEvent.click(skipButton);
  41. const getCodesbutton = screen.getByRole('button', {name: 'Get Recovery Codes'});
  42. expect(getCodesbutton).toBeInTheDocument();
  43. expect(getCodesbutton).toHaveAttribute(
  44. 'href',
  45. `/settings/account/security/mfa/${mockId}/`
  46. );
  47. await userEvent.click(getCodesbutton);
  48. expect(closeModal).toHaveBeenCalled();
  49. });
  50. it('can redirect to backup phone setup', async function () {
  51. renderComponent();
  52. const backupPhoneButton = await screen.findByRole('button', {
  53. name: 'Add a Phone Number',
  54. });
  55. expect(backupPhoneButton).toBeInTheDocument();
  56. expect(backupPhoneButton).toHaveAttribute(
  57. 'href',
  58. '/settings/account/security/mfa/sms/enroll/'
  59. );
  60. await userEvent.click(backupPhoneButton);
  61. expect(closeModal).toHaveBeenCalled();
  62. });
  63. it('skips backup phone setup if text message authenticator unavailable', async function () {
  64. MockApiClient.clearMockResponses();
  65. MockApiClient.addMockResponse({
  66. url: '/users/me/authenticators/',
  67. method: 'GET',
  68. body: [AuthenticatorsFixture().Totp(), AuthenticatorsFixture().Recovery()],
  69. });
  70. renderComponent();
  71. const getCodesbutton = await screen.findByRole('button', {
  72. name: 'Get Recovery Codes',
  73. });
  74. expect(getCodesbutton).toBeInTheDocument();
  75. expect(getCodesbutton).toHaveAttribute(
  76. 'href',
  77. `/settings/account/security/mfa/${mockId}/`
  78. );
  79. expect(
  80. screen.queryByRole('button', {name: 'Skip this step'})
  81. ).not.toBeInTheDocument();
  82. expect(
  83. screen.queryByRole('button', {name: 'Add a Phone Number'})
  84. ).not.toBeInTheDocument();
  85. });
  86. it('renders the error message on API error', async () => {
  87. MockApiClient.clearMockResponses();
  88. MockApiClient.addMockResponse({
  89. url: '/users/me/authenticators/',
  90. method: 'GET',
  91. statusCode: 500,
  92. });
  93. renderComponent();
  94. const error = await screen.findByText('There was an error loading authenticators.');
  95. expect(error).toBeInTheDocument();
  96. });
  97. });