123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- import React from 'react';
- import {mountWithTheme} from 'sentry-test/enzyme';
- import {Client} from 'app/api';
- import AccountSecurity from 'app/views/settings/account/accountSecurity';
- import AccountSecurityWrapper from 'app/views/settings/account/accountSecurity/accountSecurityWrapper';
- const ENDPOINT = '/users/me/authenticators/';
- const ORG_ENDPOINT = '/organizations/';
- const AUTH_ENDPOINT = '/auth/';
- describe('AccountSecurity', function() {
- beforeEach(function() {
- Client.clearMockResponses();
- Client.addMockResponse({
- url: ORG_ENDPOINT,
- body: TestStubs.Organizations(),
- });
- });
- it('renders empty', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [],
- });
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- expect(wrapper.find('EmptyMessage')).toHaveLength(1);
- expect(wrapper.find('TwoFactorRequired')).toHaveLength(0);
- });
- it('renders a primary interface that is enrolled', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [TestStubs.Authenticators().Totp({configureButton: 'Info'})],
- });
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- expect(wrapper.find('AuthenticatorName').prop('children')).toBe('Authenticator App');
- // There should be an "Info" button
- expect(
- wrapper
- .find('Button[className="details-button"]')
- .first()
- .prop('children')
- ).toBe('Info');
- // Remove button
- expect(wrapper.find('Button[icon="icon-trash"]')).toHaveLength(1);
- expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(true);
- expect(wrapper.find('TwoFactorRequired')).toHaveLength(0);
- });
- it('can delete enrolled authenticator', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [
- TestStubs.Authenticators().Totp({
- authId: '15',
- configureButton: 'Info',
- }),
- ],
- });
- const deleteMock = Client.addMockResponse({
- url: `${ENDPOINT}15/`,
- method: 'DELETE',
- });
- expect(deleteMock).not.toHaveBeenCalled();
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(true);
- // This will open confirm modal
- wrapper.find('Button[icon="icon-trash"]').simulate('click');
- // Confirm
- wrapper
- .find('Modal Button')
- .last()
- .simulate('click');
- expect(deleteMock).toHaveBeenCalled();
- setTimeout(() => {
- wrapper.update();
- expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(false);
- }, 1);
- // still has another 2fa method
- expect(wrapper.find('TwoFactorRequired')).toHaveLength(0);
- });
- it('can remove one of multiple 2fa methods when org requires 2fa', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [
- TestStubs.Authenticators().Totp({
- authId: '15',
- configureButton: 'Info',
- }),
- TestStubs.Authenticators().U2f(),
- ],
- });
- Client.addMockResponse({
- url: ORG_ENDPOINT,
- body: TestStubs.Organizations({require2FA: true}),
- });
- const deleteMock = Client.addMockResponse({
- url: `${ENDPOINT}15/`,
- method: 'DELETE',
- });
- expect(deleteMock).not.toHaveBeenCalled();
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- expect(
- wrapper
- .find('AuthenticatorStatus')
- .first()
- .prop('enabled')
- ).toBe(true);
- expect(
- wrapper
- .find('RemoveConfirm')
- .first()
- .prop('disabled')
- ).toBe(false);
- expect(
- wrapper
- .find('Tooltip')
- .first()
- .prop('disabled')
- ).toBe(true);
- // This will open confirm modal
- wrapper
- .find('Button[icon="icon-trash"]')
- .first()
- .simulate('click');
- // Confirm
- wrapper
- .find('Modal Button')
- .last()
- .simulate('click');
- expect(deleteMock).toHaveBeenCalled();
- });
- it('can not remove last 2fa method when org requires 2fa', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [
- TestStubs.Authenticators().Totp({
- authId: '15',
- configureButton: 'Info',
- }),
- ],
- });
- Client.addMockResponse({
- url: ORG_ENDPOINT,
- body: TestStubs.Organizations({require2FA: true}),
- });
- const deleteMock = Client.addMockResponse({
- url: `${ENDPOINT}15/`,
- method: 'DELETE',
- });
- expect(deleteMock).not.toHaveBeenCalled();
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(true);
- expect(wrapper.find('RemoveConfirm').prop('disabled')).toBe(true);
- expect(wrapper.find('Tooltip').prop('disabled')).toBe(false);
- expect(wrapper.find('Tooltip').prop('title')).toContain('test 1 and test 2');
- // This will open confirm modal
- wrapper.find('Button[icon="icon-trash"]').simulate('click');
- // Confirm
- expect(wrapper.find('Modal Button')).toHaveLength(0);
- expect(deleteMock).not.toHaveBeenCalled();
- });
- it('renders a primary interface that is not enrolled', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [TestStubs.Authenticators().Totp({isEnrolled: false})],
- });
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- expect(wrapper.find('AuthenticatorName').prop('children')).toBe('Authenticator App');
- // There should be an "Add" button
- expect(
- wrapper
- .find('Button[className="enroll-button"]')
- .first()
- .prop('children')
- ).toBe('Add');
- expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(false);
- // user is not 2fa enrolled
- expect(wrapper.find('TwoFactorRequired')).toHaveLength(1);
- });
- it('renders a backup interface that is not enrolled', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [TestStubs.Authenticators().Recovery({isEnrolled: false})],
- });
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- expect(wrapper.find('AuthenticatorName').prop('children')).toBe('Recovery Codes');
- // There should be an View Codes button
- expect(wrapper.find('Button[className="details-button"]')).toHaveLength(0);
- expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(false);
- // user is not 2fa enrolled
- expect(wrapper.find('TwoFactorRequired')).toHaveLength(1);
- });
- it('renders a backup interface that is enrolled', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [TestStubs.Authenticators().Recovery({isEnrolled: true})],
- });
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- expect(wrapper.find('AuthenticatorName').prop('children')).toBe('Recovery Codes');
- // There should be an View Codes button
- expect(
- wrapper
- .find('Button[className="details-button"]')
- .first()
- .prop('children')
- ).toBe('View Codes');
- expect(wrapper.find('AuthenticatorStatus').prop('enabled')).toBe(true);
- });
- it('can change password', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [TestStubs.Authenticators().Recovery({isEnrolled: false})],
- });
- const url = '/users/me/password/';
- const mock = Client.addMockResponse({
- url,
- method: 'PUT',
- });
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- wrapper
- .find('PasswordForm input[name="password"]')
- .simulate('change', {target: {value: 'oldpassword'}});
- wrapper
- .find('PasswordForm input[name="passwordNew"]')
- .simulate('change', {target: {value: 'newpassword'}});
- wrapper
- .find('PasswordForm input[name="passwordVerify"]')
- .simulate('change', {target: {value: 'newpassword'}});
- wrapper.find('PasswordForm form').simulate('submit');
- expect(mock).toHaveBeenCalledWith(
- url,
- expect.objectContaining({
- method: 'PUT',
- data: {
- password: 'oldpassword',
- passwordNew: 'newpassword',
- passwordVerify: 'newpassword',
- },
- })
- );
- // user is not 2fa enrolled
- expect(wrapper.find('TwoFactorRequired')).toHaveLength(1);
- });
- it('requires current password to be entered', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [TestStubs.Authenticators().Recovery({isEnrolled: false})],
- });
- const url = '/users/me/password/';
- const mock = Client.addMockResponse({
- url,
- method: 'PUT',
- });
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- wrapper
- .find('PasswordForm input[name="passwordNew"]')
- .simulate('change', {target: {value: 'newpassword'}});
- wrapper
- .find('PasswordForm input[name="passwordVerify"]')
- .simulate('change', {target: {value: 'newpassword'}});
- wrapper.find('PasswordForm form').simulate('submit');
- expect(mock).not.toHaveBeenCalled();
- // user is not 2fa enrolled
- expect(wrapper.find('TwoFactorRequired')).toHaveLength(1);
- });
- it('can expire all sessions', function() {
- Client.addMockResponse({
- url: ENDPOINT,
- body: [TestStubs.Authenticators().Recovery({isEnrolled: false})],
- });
- const mock = Client.addMockResponse({
- url: AUTH_ENDPOINT,
- body: {all: true},
- method: 'DELETE',
- status: 204,
- });
- const wrapper = mountWithTheme(
- <AccountSecurityWrapper>
- <AccountSecurity />
- </AccountSecurityWrapper>,
- TestStubs.routerContext()
- );
- wrapper.find('Button[data-test-id="signoutAll"]').simulate('click');
- expect(mock).toHaveBeenCalled();
- });
- });
|