123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- import {browserHistory} from 'react-router';
- import {mount} from 'enzyme';
- import React from 'react';
- import OrganizationGeneralSettings from 'app/views/settings/organizationGeneralSettings';
- jest.mock('jquery');
- jest.mock('react-router', () => {
- return {
- browserHistory: {
- push: jest.fn(),
- replace: jest.fn(),
- },
- };
- });
- describe('OrganizationGeneralSettings', function() {
- const org = TestStubs.Organization();
- const ENDPOINT = `/organizations/${org.slug}/`;
- beforeEach(function() {
- MockApiClient.clearMockResponses();
- MockApiClient.addMockResponse({
- url: ENDPOINT,
- body: TestStubs.Organization(),
- });
- browserHistory.push.mockReset();
- browserHistory.replace.mockReset();
- });
- it('has LoadingError on error', async function() {
- MockApiClient.clearMockResponses();
- MockApiClient.addMockResponse({
- url: ENDPOINT,
- statusCode: 500,
- body: {},
- });
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext()
- );
- await tick();
- wrapper.update();
- expect(wrapper.find('LoadingIndicator')).toHaveLength(0);
- expect(wrapper.find('LoadingError')).toHaveLength(1);
- });
- it('can enable "early adopter"', async function() {
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext()
- );
- let mock = MockApiClient.addMockResponse({
- url: ENDPOINT,
- method: 'PUT',
- });
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- wrapper.find('Switch[id="isEarlyAdopter"]').simulate('click');
- expect(mock).toHaveBeenCalledWith(
- ENDPOINT,
- expect.objectContaining({
- data: {isEarlyAdopter: true},
- })
- );
- });
- it('changes org slug and redirects to new slug', async function() {
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext()
- );
- let mock = MockApiClient.addMockResponse({
- url: ENDPOINT,
- method: 'PUT',
- });
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- // Change slug
- wrapper
- .find('input[id="slug"]')
- .simulate('change', {target: {value: 'new-slug'}})
- .simulate('blur');
- wrapper.find('SaveButton').simulate('click');
- expect(mock).toHaveBeenCalledWith(
- ENDPOINT,
- expect.objectContaining({
- data: {slug: 'new-slug'},
- })
- );
- await tick();
- // Not sure why this needs to be async, but it does
- expect(browserHistory.replace).toHaveBeenCalledWith('/settings/new-slug/');
- });
- it('disables the entire form if user does not have write access', async function() {
- const readOnlyOrg = TestStubs.Organization({access: ['org:read']});
- MockApiClient.clearMockResponses();
- MockApiClient.addMockResponse({
- url: ENDPOINT,
- body: readOnlyOrg,
- });
- let wrapper = mount(
- <OrganizationGeneralSettings routes={[]} params={{orgId: readOnlyOrg.slug}} />,
- TestStubs.routerContext([{organization: readOnlyOrg}])
- );
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- expect(wrapper.find('Form FormField[disabled=false]')).toHaveLength(0);
- expect(
- wrapper
- .find('PermissionAlert')
- .first()
- .text()
- ).toEqual(
- 'These settings can only be edited by users with the owner or manager role.'
- );
- });
- it('does not have remove organization button', async function() {
- MockApiClient.clearMockResponses();
- MockApiClient.addMockResponse({
- url: ENDPOINT,
- body: TestStubs.Organization({
- projects: [{slug: 'project'}],
- access: ['org:write'],
- }),
- });
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext()
- );
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- expect(wrapper.find('Confirm[priority="danger"]')).toHaveLength(0);
- });
- it('can remove organization when org admin', async function() {
- MockApiClient.clearMockResponses();
- MockApiClient.addMockResponse({
- url: ENDPOINT,
- body: TestStubs.Organization({
- projects: [{slug: 'project'}],
- access: ['org:admin'],
- }),
- });
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext()
- );
- let mock = MockApiClient.addMockResponse({
- url: ENDPOINT,
- method: 'DELETE',
- });
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- wrapper.find('Confirm[priority="danger"]').simulate('click');
- // Lists projects in modal
- expect(wrapper.find('Modal .ref-projects')).toHaveLength(1);
- expect(wrapper.find('Modal .ref-projects li').text()).toBe('project');
- // Confirm delete
- wrapper.find('Modal Portal Button[priority="danger"]').simulate('click');
- expect(mock).toHaveBeenCalledWith(
- ENDPOINT,
- expect.objectContaining({
- method: 'DELETE',
- })
- );
- });
- it('shows require2fa switch w/ feature flag', async function() {
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext([
- {
- organization: TestStubs.Organization({
- features: ['require-2fa'],
- }),
- },
- ])
- );
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- expect(wrapper.find('Switch[name="require2FA"]')).toHaveLength(1);
- });
- it('enables require2fa but cancels confirm modal', async function() {
- let mock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/',
- method: 'PUT',
- });
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext([
- {
- organization: TestStubs.Organization({
- features: ['require-2fa'],
- }),
- },
- ])
- );
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- expect(wrapper.find('Switch[name="require2FA"]')).toHaveLength(1);
- wrapper.find('Switch[name="require2FA"]').simulate('click');
- expect(wrapper.find('Field[name="require2FA"] ModalDialog')).toHaveLength(1);
- // Cancel
- wrapper
- .find('Field[name="require2FA"] ModalDialog .modal-footer Button')
- .first()
- .simulate('click');
- expect(wrapper.find('Field[name="require2FA"] ModalDialog')).toHaveLength(0);
- expect(wrapper.find('Switch[name="require2FA"]').prop('isActive')).toBe(false);
- expect(mock).not.toHaveBeenCalled();
- });
- it('enables require2fa with confirm modal', async function() {
- let mock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/',
- method: 'PUT',
- });
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext([
- {
- organization: TestStubs.Organization({
- features: ['require-2fa'],
- }),
- },
- ])
- );
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- expect(wrapper.find('Switch[name="require2FA"]')).toHaveLength(1);
- wrapper.find('Switch[name="require2FA"]').simulate('click');
- expect(wrapper.find('Field[name="require2FA"] ModalDialog')).toHaveLength(1);
- // Confirm
- wrapper
- .find(
- 'Field[name="require2FA"] ModalDialog .modal-footer Button[priority="primary"]'
- )
- .simulate('click');
- expect(wrapper.find('Field[name="require2FA"] ModalDialog')).toHaveLength(0);
- expect(wrapper.find('Switch[name="require2FA"]').prop('isActive')).toBe(true);
- expect(mock).toHaveBeenCalledWith(
- '/organizations/org-slug/',
- expect.objectContaining({
- method: 'PUT',
- data: {
- require2FA: true,
- },
- })
- );
- });
- it('returns to "off" if switch enable fails (e.g. API error)', async function() {
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/',
- method: 'PUT',
- statusCode: 500,
- });
- let wrapper = mount(
- <OrganizationGeneralSettings params={{orgId: org.slug}} />,
- TestStubs.routerContext([
- {
- organization: TestStubs.Organization({
- features: ['require-2fa'],
- }),
- },
- ])
- );
- wrapper.setState({loading: false});
- await tick();
- wrapper.update();
- wrapper.find('Switch[name="require2FA"]').simulate('click');
- // hide console.error for this test
- sinon.stub(console, 'error');
- // Confirm but has API failure
- wrapper
- .find(
- 'Field[name="require2FA"] ModalDialog .modal-footer Button[priority="primary"]'
- )
- .simulate('click');
- await tick();
- wrapper.update();
- expect(wrapper.find('Switch[name="require2FA"]').prop('isActive')).toBe(false);
- // eslint-disable-next-line no-console
- console.error.restore();
- });
- });
|