Browse Source

ref(test): Convert account security details to rtl and ts (#40638)

Priscila Oliveira 2 years ago
parent
commit
2058451a0e

+ 2 - 6
static/app/components/circleIndicator.tsx

@@ -6,16 +6,12 @@ type Props = {
   size?: number;
 };
 
-const getSize = (p: Props) => `
-  height: ${p.size}px;
-  width: ${p.size}px;
-`;
-
 const CircleIndicator = styled('div')<Props>`
   display: inline-block;
   position: relative;
   border-radius: 50%;
-  ${getSize};
+  height: ${p => p.size}px;
+  width: ${p => p.size}px;
   background: ${p => p.color ?? (p.enabled ? p.theme.success : p.theme.error)};
 `;
 

+ 0 - 201
static/app/views/settings/account/accountSecurity/accountSecurityDetails.spec.jsx

@@ -1,201 +0,0 @@
-import {mountWithTheme} from 'sentry-test/enzyme';
-import {initializeOrg} from 'sentry-test/initializeOrg';
-import {mountGlobalModal} from 'sentry-test/modal';
-
-import {Client} from 'sentry/api';
-import AccountSecurityDetails from 'sentry/views/settings/account/accountSecurity/accountSecurityDetails';
-import AccountSecurityWrapper from 'sentry/views/settings/account/accountSecurity/accountSecurityWrapper';
-
-const ENDPOINT = '/users/me/authenticators/';
-const ACCOUNT_EMAILS_ENDPOINT = '/users/me/emails/';
-const ORG_ENDPOINT = '/organizations/';
-
-describe('AccountSecurityDetails', function () {
-  let wrapper;
-  let routerContext;
-  let router;
-  let params;
-
-  describe('Totp', function () {
-    beforeAll(function () {
-      Client.clearMockResponses();
-      params = {
-        authId: 15,
-      };
-
-      ({router, routerContext} = initializeOrg({
-        router: {
-          params,
-        },
-      }));
-
-      Client.addMockResponse({
-        url: ENDPOINT,
-        body: TestStubs.AllAuthenticators(),
-      });
-      Client.addMockResponse({
-        url: ORG_ENDPOINT,
-        body: TestStubs.Organizations(),
-      });
-      Client.addMockResponse({
-        url: `${ENDPOINT}15/`,
-        body: TestStubs.Authenticators().Totp(),
-      });
-      Client.addMockResponse({
-        url: ACCOUNT_EMAILS_ENDPOINT,
-        body: TestStubs.AccountEmails(),
-      });
-      wrapper = mountWithTheme(
-        <AccountSecurityWrapper router={router} params={params}>
-          <AccountSecurityDetails router={router} params={params} />
-        </AccountSecurityWrapper>,
-        routerContext
-      );
-    });
-
-    it('has enrolled circle indicator', function () {
-      expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(true);
-    });
-
-    it('has created and last used dates', function () {
-      expect(wrapper.find('AuthenticatorDate')).toHaveLength(2);
-    });
-
-    it('can remove method', async function () {
-      const deleteMock = Client.addMockResponse({
-        url: `${ENDPOINT}15/`,
-        method: 'DELETE',
-      });
-
-      wrapper.find('RemoveConfirm Button').simulate('click');
-
-      const modal = await mountGlobalModal();
-      modal.find('Button[priority="primary"]').simulate('click');
-
-      expect(deleteMock).toHaveBeenCalled();
-    });
-
-    it('can remove one of multiple 2fa methods when org requires 2fa', async function () {
-      Client.addMockResponse({
-        url: ORG_ENDPOINT,
-        body: TestStubs.Organizations({require2FA: true}),
-      });
-      const deleteMock = Client.addMockResponse({
-        url: `${ENDPOINT}15/`,
-        method: 'DELETE',
-      });
-
-      wrapper = mountWithTheme(
-        <AccountSecurityWrapper router={router} params={params}>
-          <AccountSecurityDetails router={router} params={params} />
-        </AccountSecurityWrapper>,
-        routerContext
-      );
-
-      wrapper.find('RemoveConfirm Button').simulate('click');
-      const modal = await mountGlobalModal();
-      modal.find('Button[priority="primary"]').simulate('click');
-
-      expect(deleteMock).toHaveBeenCalled();
-    });
-
-    it('can not remove last 2fa method when org requires 2fa', async function () {
-      Client.addMockResponse({
-        url: ORG_ENDPOINT,
-        body: TestStubs.Organizations({require2FA: true}),
-      });
-      Client.addMockResponse({
-        url: ENDPOINT,
-        body: [TestStubs.Authenticators().Totp()],
-      });
-      const deleteMock = Client.addMockResponse({
-        url: `${ENDPOINT}15/`,
-        method: 'DELETE',
-      });
-
-      wrapper = mountWithTheme(
-        <AccountSecurityWrapper router={router} params={params}>
-          <AccountSecurityDetails router={router} params={params} />
-        </AccountSecurityWrapper>,
-        routerContext
-      );
-
-      wrapper.find('RemoveConfirm Button').simulate('click');
-      const modal = await mountGlobalModal();
-      expect(modal.find('Modal[show=true]').exists()).toBe(false);
-
-      expect(deleteMock).not.toHaveBeenCalled();
-    });
-  });
-
-  describe('Recovery', function () {
-    beforeEach(function () {
-      params = {authId: 16};
-      ({router, routerContext} = initializeOrg({
-        router: {
-          params,
-        },
-      }));
-
-      Client.clearMockResponses();
-      Client.addMockResponse({
-        url: ENDPOINT,
-        body: TestStubs.AllAuthenticators(),
-      });
-      Client.addMockResponse({
-        url: ORG_ENDPOINT,
-        body: TestStubs.Organizations(),
-      });
-      Client.addMockResponse({
-        url: `${ENDPOINT}16/`,
-        body: TestStubs.Authenticators().Recovery(),
-      });
-      Client.addMockResponse({
-        url: ACCOUNT_EMAILS_ENDPOINT,
-        body: TestStubs.AccountEmails(),
-      });
-
-      wrapper = mountWithTheme(
-        <AccountSecurityWrapper router={router} params={params}>
-          <AccountSecurityDetails router={router} params={params} />
-        </AccountSecurityWrapper>,
-        routerContext
-      );
-    });
-
-    it('has enrolled circle indicator', function () {
-      expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(true);
-    });
-
-    it('has created and last used dates', function () {
-      expect(wrapper.find('AuthenticatorDate')).toHaveLength(2);
-    });
-
-    it('does not have remove button', function () {
-      expect(wrapper.find('RemoveConfirm')).toHaveLength(0);
-    });
-
-    it('regenerates codes', function () {
-      const deleteMock = Client.addMockResponse({
-        url: `${ENDPOINT}16/`,
-        method: 'PUT',
-      });
-
-      wrapper.find('RecoveryCodes').prop('onRegenerateBackupCodes')();
-
-      expect(deleteMock).toHaveBeenCalled();
-    });
-
-    it('has copy, print and download buttons', function () {
-      const codes = 'ABCD-1234 \nEFGH-5678';
-
-      const downloadCodes = `Button[href="data:text/plain;charset=utf-8,${codes}"]`;
-      expect(wrapper.find(downloadCodes)).toHaveLength(1);
-      wrapper.find(downloadCodes).simulate('click');
-
-      expect(wrapper.find('button[aria-label="print"]')).toHaveLength(1);
-      expect(wrapper.find('iframe[name="printable"]')).toHaveLength(1);
-      expect(wrapper.find(`Clipboard[value="${codes}"]`)).toHaveLength(1);
-    });
-  });
-});

+ 399 - 0
static/app/views/settings/account/accountSecurity/accountSecurityDetails.spec.tsx

@@ -0,0 +1,399 @@
+import {initializeOrg} from 'sentry-test/initializeOrg';
+import {
+  render,
+  renderGlobalModal,
+  screen,
+  userEvent,
+} from 'sentry-test/reactTestingLibrary';
+
+import AccountSecurityDetails from 'sentry/views/settings/account/accountSecurity/accountSecurityDetails';
+import AccountSecurityWrapper from 'sentry/views/settings/account/accountSecurity/accountSecurityWrapper';
+
+const ENDPOINT = '/users/me/authenticators/';
+const ACCOUNT_EMAILS_ENDPOINT = '/users/me/emails/';
+const ORG_ENDPOINT = '/organizations/';
+
+describe('AccountSecurityDetails', function () {
+  describe('Totp', function () {
+    beforeAll(function () {
+      MockApiClient.addMockResponse({
+        url: ENDPOINT,
+        body: TestStubs.AllAuthenticators(),
+      });
+
+      MockApiClient.addMockResponse({
+        url: ORG_ENDPOINT,
+        body: TestStubs.Organizations(),
+      });
+
+      MockApiClient.addMockResponse({
+        url: `${ENDPOINT}15/`,
+        body: TestStubs.Authenticators().Totp(),
+      });
+
+      MockApiClient.addMockResponse({
+        url: ACCOUNT_EMAILS_ENDPOINT,
+        body: TestStubs.AccountEmails(),
+      });
+    });
+
+    it('has enrolled circle indicator', function () {
+      const params = {
+        authId: '15',
+      };
+      const {router, route, routerContext} = initializeOrg({
+        ...initializeOrg(),
+        router: {
+          params,
+        },
+      });
+
+      render(
+        <AccountSecurityWrapper
+          router={router}
+          location={router.location}
+          params={params}
+          routes={router.routes}
+          routeParams={router.params}
+          route={route}
+        >
+          <AccountSecurityDetails
+            router={router}
+            location={router.location}
+            params={params}
+            routes={router.routes}
+            routeParams={router.params}
+            route={route}
+            onRegenerateBackupCodes={jest.fn()}
+            deleteDisabled={false}
+          />
+        </AccountSecurityWrapper>,
+        {context: routerContext}
+      );
+
+      expect(screen.getByTestId('auth-status-enabled')).toBeInTheDocument();
+
+      // has created and last used dates
+      expect(screen.getByText('Created at')).toBeInTheDocument();
+      expect(screen.getByText('Last used')).toBeInTheDocument();
+    });
+
+    it('can remove method', async function () {
+      const deleteMock = MockApiClient.addMockResponse({
+        url: `${ENDPOINT}15/`,
+        method: 'DELETE',
+      });
+
+      const params = {
+        authId: '15',
+      };
+      const {router, route, routerContext} = initializeOrg({
+        ...initializeOrg(),
+        router: {
+          params,
+        },
+      });
+
+      render(
+        <AccountSecurityWrapper
+          router={router}
+          location={router.location}
+          params={params}
+          routes={router.routes}
+          routeParams={router.params}
+          route={route}
+        >
+          <AccountSecurityDetails
+            router={router}
+            location={router.location}
+            params={params}
+            routes={router.routes}
+            routeParams={router.params}
+            route={route}
+            onRegenerateBackupCodes={jest.fn()}
+            deleteDisabled={false}
+          />
+        </AccountSecurityWrapper>,
+        {context: routerContext}
+      );
+
+      userEvent.click(screen.getByRole('button', {name: 'Remove'}));
+
+      renderGlobalModal();
+
+      userEvent.click(await screen.findByRole('button', {name: 'Confirm'}));
+
+      expect(deleteMock).toHaveBeenCalled();
+    });
+
+    it('can remove one of multiple 2fa methods when org requires 2fa', async function () {
+      MockApiClient.addMockResponse({
+        url: ORG_ENDPOINT,
+        body: TestStubs.Organizations({require2FA: true}),
+      });
+
+      const deleteMock = MockApiClient.addMockResponse({
+        url: `${ENDPOINT}15/`,
+        method: 'DELETE',
+      });
+
+      const params = {
+        authId: '15',
+      };
+      const {router, route, routerContext} = initializeOrg({
+        ...initializeOrg(),
+        router: {
+          params,
+        },
+      });
+
+      render(
+        <AccountSecurityWrapper
+          router={router}
+          location={router.location}
+          params={params}
+          routes={router.routes}
+          routeParams={router.params}
+          route={route}
+        >
+          <AccountSecurityDetails
+            router={router}
+            location={router.location}
+            params={params}
+            routes={router.routes}
+            routeParams={router.params}
+            route={route}
+            onRegenerateBackupCodes={jest.fn()}
+            deleteDisabled={false}
+          />
+        </AccountSecurityWrapper>,
+        {context: routerContext}
+      );
+
+      userEvent.click(screen.getByRole('button', {name: 'Remove'}));
+
+      renderGlobalModal();
+
+      userEvent.click(await screen.findByRole('button', {name: 'Confirm'}));
+
+      expect(deleteMock).toHaveBeenCalled();
+    });
+
+    it('can not remove last 2fa method when org requires 2fa', function () {
+      MockApiClient.addMockResponse({
+        url: ORG_ENDPOINT,
+        body: TestStubs.Organizations({require2FA: true}),
+      });
+
+      MockApiClient.addMockResponse({
+        url: ENDPOINT,
+        body: [TestStubs.Authenticators().Totp()],
+      });
+
+      const params = {
+        authId: '15',
+      };
+
+      const {router, route, routerContext} = initializeOrg({
+        ...initializeOrg(),
+        router: {
+          params,
+        },
+      });
+
+      render(
+        <AccountSecurityWrapper
+          router={router}
+          location={router.location}
+          params={params}
+          routes={router.routes}
+          routeParams={router.params}
+          route={route}
+        >
+          <AccountSecurityDetails
+            router={router}
+            location={router.location}
+            params={params}
+            routes={router.routes}
+            routeParams={router.params}
+            route={route}
+            onRegenerateBackupCodes={jest.fn()}
+            deleteDisabled={false}
+          />
+        </AccountSecurityWrapper>,
+        {context: routerContext}
+      );
+
+      expect(screen.getByRole('button', {name: 'Remove'})).toBeDisabled();
+    });
+  });
+
+  describe('Recovery', function () {
+    beforeEach(function () {
+      MockApiClient.addMockResponse({
+        url: ENDPOINT,
+        body: TestStubs.AllAuthenticators(),
+      });
+
+      MockApiClient.addMockResponse({
+        url: ORG_ENDPOINT,
+        body: TestStubs.Organizations(),
+      });
+
+      MockApiClient.addMockResponse({
+        url: `${ENDPOINT}16/`,
+        body: TestStubs.Authenticators().Recovery(),
+      });
+
+      MockApiClient.addMockResponse({
+        url: ACCOUNT_EMAILS_ENDPOINT,
+        body: TestStubs.AccountEmails(),
+      });
+    });
+
+    it('has enrolled circle indicator', function () {
+      const params = {
+        authId: '16',
+      };
+
+      const {router, route, routerContext} = initializeOrg({
+        ...initializeOrg(),
+        router: {
+          params,
+        },
+      });
+
+      render(
+        <AccountSecurityWrapper
+          router={router}
+          location={router.location}
+          params={params}
+          routes={router.routes}
+          routeParams={router.params}
+          route={route}
+        >
+          <AccountSecurityDetails
+            router={router}
+            location={router.location}
+            params={params}
+            routes={router.routes}
+            routeParams={router.params}
+            route={route}
+            onRegenerateBackupCodes={jest.fn()}
+            deleteDisabled={false}
+          />
+        </AccountSecurityWrapper>,
+        {context: routerContext}
+      );
+
+      // does not have remove button
+      expect(screen.queryByRole('button', {name: 'Remove'})).not.toBeInTheDocument();
+    });
+
+    it('regenerates codes', async function () {
+      const deleteMock = MockApiClient.addMockResponse({
+        url: `${ENDPOINT}16/`,
+        method: 'PUT',
+      });
+
+      const params = {
+        authId: '16',
+      };
+
+      const {router, route, routerContext} = initializeOrg({
+        ...initializeOrg(),
+        router: {
+          params,
+        },
+      });
+
+      render(
+        <AccountSecurityWrapper
+          router={router}
+          location={router.location}
+          params={params}
+          routes={router.routes}
+          routeParams={router.params}
+          route={route}
+        >
+          <AccountSecurityDetails
+            router={router}
+            location={router.location}
+            params={params}
+            routes={router.routes}
+            routeParams={router.params}
+            route={route}
+            onRegenerateBackupCodes={jest.fn()}
+            deleteDisabled={false}
+          />
+        </AccountSecurityWrapper>,
+        {context: routerContext}
+      );
+
+      userEvent.click(screen.getByRole('button', {name: 'Regenerate Codes'}));
+
+      renderGlobalModal();
+
+      expect(
+        await screen.findByText(
+          'Are you sure you want to regenerate recovery codes? Your old codes will no longer work.'
+        )
+      ).toBeInTheDocument();
+
+      userEvent.click(screen.getByRole('button', {name: 'Confirm'}));
+
+      expect(deleteMock).toHaveBeenCalled();
+    });
+
+    it('has copy, print and download buttons', function () {
+      const params = {
+        authId: '16',
+      };
+
+      const {router, route, routerContext} = initializeOrg({
+        ...initializeOrg(),
+        router: {
+          params,
+        },
+      });
+
+      Object.defineProperty(document, 'queryCommandSupported', {
+        value: () => true,
+      });
+
+      render(
+        <AccountSecurityWrapper
+          router={router}
+          location={router.location}
+          params={params}
+          routes={router.routes}
+          routeParams={router.params}
+          route={route}
+        >
+          <AccountSecurityDetails
+            router={router}
+            location={router.location}
+            params={params}
+            routes={router.routes}
+            routeParams={router.params}
+            route={route}
+            onRegenerateBackupCodes={jest.fn()}
+            deleteDisabled={false}
+          />
+        </AccountSecurityWrapper>,
+        {context: routerContext}
+      );
+
+      expect(screen.getByRole('button', {name: 'print'})).toBeInTheDocument();
+
+      expect(screen.getByRole('button', {name: 'download'})).toHaveAttribute(
+        'href',
+        'data:text/plain;charset=utf-8,ABCD-1234 \nEFGH-5678'
+      );
+
+      expect(screen.getByTestId('frame')).toBeInTheDocument();
+
+      expect(screen.getByRole('button', {name: 'copy'})).toBeInTheDocument();
+    });
+  });
+});

+ 6 - 1
static/app/views/settings/account/accountSecurity/accountSecurityDetails.tsx

@@ -134,7 +134,12 @@ class AccountSecurityDetails extends AsyncView<Props, State> {
           title={
             <Fragment>
               <span>{authenticator.name}</span>
-              <AuthenticatorStatus enabled={authenticator.isEnrolled} />
+              <AuthenticatorStatus
+                data-test-id={`auth-status-${
+                  authenticator.isEnrolled ? 'enabled' : 'disabled'
+                }`}
+                enabled={authenticator.isEnrolled}
+              />
             </Fragment>
           }
           action={

+ 1 - 0
static/app/views/settings/account/accountSecurity/accountSecurityWrapper.tsx

@@ -58,6 +58,7 @@ class AccountSecurityWrapper extends AsyncComponent<Props, State> {
       addErrorMessage(t('Error regenerating backup codes'));
     }
   };
+
   handleRefresh = () => {
     this.fetchData();
   };

+ 1 - 1
static/app/views/settings/account/accountSecurity/components/recoveryCodes.tsx

@@ -87,7 +87,7 @@ const RecoveryCodes = ({
           <EmptyMessage>{t('You have no more recovery codes to use')}</EmptyMessage>
         )}
       </PanelBody>
-      <iframe name="printable" style={{display: 'none'}} />
+      <iframe data-test-id="frame" name="printable" style={{display: 'none'}} />
     </CodeContainer>
   );
 };