mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-10-30 14:49:14 +00:00
321 lines
8.3 KiB
TypeScript
321 lines
8.3 KiB
TypeScript
import {AccountEmailsFixture} from 'sentry-fixture/accountEmails';
|
|
import {
|
|
AllAuthenticatorsFixture,
|
|
AuthenticatorsFixture,
|
|
} from 'sentry-fixture/authenticators';
|
|
import {OrganizationsFixture} from 'sentry-fixture/organizations';
|
|
|
|
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 () {
|
|
beforeEach(() => {
|
|
MockApiClient.clearMockResponses();
|
|
});
|
|
describe('Totp', function () {
|
|
beforeEach(function () {
|
|
MockApiClient.addMockResponse({
|
|
url: ENDPOINT,
|
|
body: AllAuthenticatorsFixture(),
|
|
});
|
|
|
|
MockApiClient.addMockResponse({
|
|
url: ORG_ENDPOINT,
|
|
body: OrganizationsFixture(),
|
|
});
|
|
|
|
MockApiClient.addMockResponse({
|
|
url: `${ENDPOINT}15/`,
|
|
body: AuthenticatorsFixture().Totp(),
|
|
});
|
|
|
|
MockApiClient.addMockResponse({
|
|
url: ACCOUNT_EMAILS_ENDPOINT,
|
|
body: AccountEmailsFixture(),
|
|
});
|
|
});
|
|
|
|
it('has enrolled circle indicator', async function () {
|
|
const params = {
|
|
authId: '15',
|
|
};
|
|
const {routerProps, routerContext} = initializeOrg({
|
|
router: {
|
|
params,
|
|
},
|
|
});
|
|
|
|
render(
|
|
<AccountSecurityWrapper {...routerProps}>
|
|
<AccountSecurityDetails
|
|
{...routerProps}
|
|
onRegenerateBackupCodes={jest.fn()}
|
|
deleteDisabled={false}
|
|
/>
|
|
</AccountSecurityWrapper>,
|
|
{context: routerContext}
|
|
);
|
|
|
|
expect(await screen.findByTestId('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 {routerProps, routerContext} = initializeOrg({
|
|
router: {
|
|
params,
|
|
},
|
|
});
|
|
|
|
render(
|
|
<AccountSecurityWrapper {...routerProps}>
|
|
<AccountSecurityDetails
|
|
{...routerProps}
|
|
onRegenerateBackupCodes={jest.fn()}
|
|
deleteDisabled={false}
|
|
/>
|
|
</AccountSecurityWrapper>,
|
|
{context: routerContext}
|
|
);
|
|
|
|
await userEvent.click(await screen.findByRole('button', {name: 'Remove'}));
|
|
|
|
renderGlobalModal();
|
|
|
|
await 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: OrganizationsFixture({require2FA: true}),
|
|
});
|
|
|
|
const deleteMock = MockApiClient.addMockResponse({
|
|
url: `${ENDPOINT}15/`,
|
|
method: 'DELETE',
|
|
});
|
|
|
|
const params = {
|
|
authId: '15',
|
|
};
|
|
const {routerProps, routerContext} = initializeOrg({
|
|
router: {
|
|
params,
|
|
},
|
|
});
|
|
|
|
render(
|
|
<AccountSecurityWrapper {...routerProps}>
|
|
<AccountSecurityDetails
|
|
{...routerProps}
|
|
onRegenerateBackupCodes={jest.fn()}
|
|
deleteDisabled={false}
|
|
/>
|
|
</AccountSecurityWrapper>,
|
|
{context: routerContext}
|
|
);
|
|
|
|
await userEvent.click(await screen.findByRole('button', {name: 'Remove'}));
|
|
|
|
renderGlobalModal();
|
|
|
|
await userEvent.click(await screen.findByRole('button', {name: 'Confirm'}));
|
|
|
|
expect(deleteMock).toHaveBeenCalled();
|
|
});
|
|
|
|
it('can not remove last 2fa method when org requires 2fa', async function () {
|
|
MockApiClient.addMockResponse({
|
|
url: ORG_ENDPOINT,
|
|
body: OrganizationsFixture({require2FA: true}),
|
|
});
|
|
|
|
MockApiClient.addMockResponse({
|
|
url: ENDPOINT,
|
|
body: [AuthenticatorsFixture().Totp()],
|
|
});
|
|
|
|
const params = {
|
|
authId: '15',
|
|
};
|
|
|
|
const {routerContext, routerProps} = initializeOrg({
|
|
router: {
|
|
params,
|
|
},
|
|
});
|
|
|
|
render(
|
|
<AccountSecurityWrapper {...routerProps}>
|
|
<AccountSecurityDetails
|
|
{...routerProps}
|
|
onRegenerateBackupCodes={jest.fn()}
|
|
deleteDisabled={false}
|
|
/>
|
|
</AccountSecurityWrapper>,
|
|
{context: routerContext}
|
|
);
|
|
|
|
expect(await screen.findByRole('button', {name: 'Remove'})).toBeDisabled();
|
|
});
|
|
});
|
|
|
|
describe('Recovery', function () {
|
|
beforeEach(function () {
|
|
MockApiClient.addMockResponse({
|
|
url: ENDPOINT,
|
|
body: AllAuthenticatorsFixture(),
|
|
});
|
|
|
|
MockApiClient.addMockResponse({
|
|
url: ORG_ENDPOINT,
|
|
body: OrganizationsFixture(),
|
|
});
|
|
|
|
MockApiClient.addMockResponse({
|
|
url: `${ENDPOINT}16/`,
|
|
body: AuthenticatorsFixture().Recovery(),
|
|
});
|
|
|
|
MockApiClient.addMockResponse({
|
|
url: ACCOUNT_EMAILS_ENDPOINT,
|
|
body: AccountEmailsFixture(),
|
|
});
|
|
});
|
|
|
|
it('has enrolled circle indicator', function () {
|
|
const params = {
|
|
authId: '16',
|
|
};
|
|
|
|
const {routerProps, routerContext} = initializeOrg({
|
|
router: {
|
|
params,
|
|
},
|
|
});
|
|
|
|
render(
|
|
<AccountSecurityWrapper {...routerProps}>
|
|
<AccountSecurityDetails
|
|
{...routerProps}
|
|
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 {routerProps, routerContext} = initializeOrg({
|
|
router: {
|
|
params,
|
|
},
|
|
});
|
|
|
|
render(
|
|
<AccountSecurityWrapper {...routerProps}>
|
|
<AccountSecurityDetails
|
|
{...routerProps}
|
|
onRegenerateBackupCodes={jest.fn()}
|
|
deleteDisabled={false}
|
|
/>
|
|
</AccountSecurityWrapper>,
|
|
{context: routerContext}
|
|
);
|
|
|
|
await userEvent.click(
|
|
await screen.findByRole('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();
|
|
|
|
await userEvent.click(screen.getByRole('button', {name: 'Confirm'}));
|
|
|
|
expect(deleteMock).toHaveBeenCalled();
|
|
});
|
|
|
|
it('has copy, print and download buttons', async function () {
|
|
const params = {
|
|
authId: '16',
|
|
};
|
|
|
|
const {routerProps, routerContext} = initializeOrg({
|
|
router: {
|
|
params,
|
|
},
|
|
});
|
|
|
|
Object.defineProperty(document, 'queryCommandSupported', {
|
|
value: () => true,
|
|
});
|
|
|
|
render(
|
|
<AccountSecurityWrapper {...routerProps}>
|
|
<AccountSecurityDetails
|
|
{...routerProps}
|
|
onRegenerateBackupCodes={jest.fn()}
|
|
deleteDisabled={false}
|
|
/>
|
|
</AccountSecurityWrapper>,
|
|
{context: routerContext}
|
|
);
|
|
|
|
expect(await screen.findByRole('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();
|
|
});
|
|
});
|
|
});
|