diff options
author | Mathieu Suen <mathieu.suen@sonarsource.com> | 2022-09-30 11:49:19 +0200 |
---|---|---|
committer | Philippe Perrin <philippe.perrin@sonarsource.com> | 2022-10-07 12:13:56 +0200 |
commit | dc8937f26d12f7d1495617e0b236d707fc3ffca5 (patch) | |
tree | 862da455507bb591aaf33a486392541858794998 /server/sonar-web | |
parent | aa30ebf5a96f93701c3159dfc688540efc6f2c12 (diff) | |
download | sonarqube-dc8937f26d12f7d1495617e0b236d707fc3ffca5.tar.gz sonarqube-dc8937f26d12f7d1495617e0b236d707fc3ffca5.zip |
SONAR-17366 Migrate ezyme test to RTL for change admin password UI
Diffstat (limited to 'server/sonar-web')
5 files changed, 90 insertions, 597 deletions
diff --git a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordApp-it.tsx b/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordApp-it.tsx new file mode 100644 index 00000000000..587875f1dfe --- /dev/null +++ b/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordApp-it.tsx @@ -0,0 +1,90 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import { byLabelText, byRole, byText } from 'testing-library-selector'; +import { changePassword } from '../../../api/users'; +import { mockAppState } from '../../../helpers/testMocks'; +import { renderApp } from '../../../helpers/testReactTestingUtils'; +import { AppState } from '../../../types/appstate'; +import ChangeAdminPasswordApp from '../ChangeAdminPasswordApp'; +import { DEFAULT_ADMIN_PASSWORD } from '../constants'; + +jest.mock('../../../api/users', () => ({ + changePassword: jest.fn().mockResolvedValue({}) +})); + +const ui = { + updateButton: byRole('button', { name: 'update_verb' }), + passwordInput: byLabelText('users.change_admin_password.form.password', { + selector: 'input', + exact: false + }), + confirmInput: byLabelText('users.change_admin_password.form.confirm', { + selector: 'input', + exact: false + }), + unauthorizedMessage: byText('unauthorized.message'), + defaultPasswordWarningMessage: byText( + 'users.change_admin_password.form.cannot_use_default_password' + ) +}; + +it('should disallow change when not an admin', () => { + renderChangeAdminPasswordApp(mockAppState({ instanceUsesDefaultAdminCredentials: true })); + expect(ui.unauthorizedMessage.get()).toBeInTheDocument(); +}); + +it('should allow changing password when using the default admin password', async () => { + const user = userEvent.setup(); + renderChangeAdminPasswordApp( + mockAppState({ instanceUsesDefaultAdminCredentials: true, canAdmin: true }) + ); + expect(ui.updateButton.get()).toBeDisabled(); + await user.type(ui.passwordInput.get(), 'password'); + + expect(ui.updateButton.get()).toBeDisabled(); + await user.type(ui.confirmInput.get(), 'pass'); + expect(ui.updateButton.get()).toBeDisabled(); + await user.keyboard('word'); + expect(ui.updateButton.get()).toBeEnabled(); + await user.click(ui.updateButton.get()); + expect(changePassword).toHaveBeenCalledWith({ + login: 'admin', + password: 'password' + }); +}); + +it('should not allow to submit the default password', async () => { + const user = userEvent.setup(); + renderChangeAdminPasswordApp( + mockAppState({ instanceUsesDefaultAdminCredentials: true, canAdmin: true }) + ); + + await user.type(ui.passwordInput.get(), DEFAULT_ADMIN_PASSWORD); + await user.type(ui.confirmInput.get(), DEFAULT_ADMIN_PASSWORD); + + expect(ui.updateButton.get()).toBeDisabled(); + expect(ui.defaultPasswordWarningMessage.get()).toBeInTheDocument(); +}); + +function renderChangeAdminPasswordApp(appState?: AppState) { + return renderApp('admin/change_admin_password', <ChangeAdminPasswordApp />, { appState }); +} diff --git a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordApp-test.tsx b/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordApp-test.tsx deleted file mode 100644 index 054078b14cb..00000000000 --- a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordApp-test.tsx +++ /dev/null @@ -1,100 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { changePassword } from '../../../api/users'; -import { mockAppState, mockLocation } from '../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../helpers/testUtils'; -import { ChangeAdminPasswordApp } from '../ChangeAdminPasswordApp'; -import { DEFAULT_ADMIN_LOGIN, DEFAULT_ADMIN_PASSWORD } from '../constants'; - -jest.mock('../../../api/users', () => ({ - changePassword: jest.fn().mockResolvedValue(null) -})); - -beforeEach(jest.clearAllMocks); - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect( - shallowRender({ appState: mockAppState({ instanceUsesDefaultAdminCredentials: undefined }) }) - ).toMatchSnapshot('admin is not using the default password'); -}); - -it('should correctly handle input changes', () => { - const wrapper = shallowRender(); - - // Set different values; should not allow submission. - wrapper.instance().handlePasswordChange('new pass'); - wrapper.instance().handleConfirmPasswordChange('confirm pass'); - - expect(wrapper.state().passwordValue).toBe('new pass'); - expect(wrapper.state().confirmPasswordValue).toBe('confirm pass'); - expect(wrapper.state().canSubmit).toBe(false); - - // Set the same values; should allow submission. - wrapper.instance().handleConfirmPasswordChange('new pass'); - expect(wrapper.state().canSubmit).toBe(true); - - // Set the default admin password; should not allow submission. - wrapper.instance().handlePasswordChange(DEFAULT_ADMIN_PASSWORD); - expect(wrapper.state().canSubmit).toBe(false); -}); - -it('should correctly update the password', async () => { - (changePassword as jest.Mock).mockResolvedValueOnce(null).mockRejectedValueOnce(null); - const wrapper = shallowRender(); - wrapper.setState({ canSubmit: false, passwordValue: 'new pass' }); - - wrapper.instance().handleSubmit(); - expect(wrapper.state().submitting).toBe(false); - expect(changePassword).not.toBeCalled(); - - wrapper.setState({ canSubmit: true }); - wrapper.instance().handleSubmit(); - expect(wrapper.state().submitting).toBe(true); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().submitting).toBe(false); - expect(wrapper.state().success).toBe(true); - expect(changePassword).toBeCalledWith({ - login: DEFAULT_ADMIN_LOGIN, - password: 'new pass' - }); - - wrapper.instance().handleSubmit(); - expect(wrapper.state().submitting).toBe(true); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().submitting).toBe(false); - expect(wrapper.state().success).toBe(false); -}); - -function shallowRender(props: Partial<ChangeAdminPasswordApp['props']> = {}) { - return shallow<ChangeAdminPasswordApp>( - <ChangeAdminPasswordApp - appState={mockAppState({ canAdmin: true, instanceUsesDefaultAdminCredentials: true })} - location={mockLocation()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordAppRenderer-test.tsx b/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordAppRenderer-test.tsx deleted file mode 100644 index 4f8d66019a2..00000000000 --- a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/ChangeAdminPasswordAppRenderer-test.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { mockLocation } from '../../../helpers/testMocks'; -import { change, submit } from '../../../helpers/testUtils'; -import ChangeAdminPasswordAppRenderer, { - ChangeAdminPasswordAppRendererProps -} from '../ChangeAdminPasswordAppRenderer'; -import { DEFAULT_ADMIN_PASSWORD } from '../constants'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ canAdmin: false })).toMatchSnapshot('access denied'); - expect(shallowRender({ canSubmit: false })).toMatchSnapshot('cannot submit'); - expect(shallowRender({ submitting: true })).toMatchSnapshot('submitting'); - expect( - shallowRender({ - passwordValue: DEFAULT_ADMIN_PASSWORD, - confirmPasswordValue: DEFAULT_ADMIN_PASSWORD - }) - ).toMatchSnapshot('trying to use default admin password'); - expect(shallowRender({ success: true })).toMatchSnapshot('success'); -}); - -it('should correctly react to input changes', () => { - const onConfirmPasswordChange = jest.fn(); - const onPasswordChange = jest.fn(); - const wrapper = shallowRender({ onConfirmPasswordChange, onPasswordChange }); - - change(wrapper.find('#user-password'), 'new pass'); - change(wrapper.find('#confirm-user-password'), 'confirm pass'); - expect(onPasswordChange).toBeCalledWith('new pass'); - expect(onConfirmPasswordChange).toBeCalledWith('confirm pass'); -}); - -it('should correctly submit the form', () => { - const onSubmit = jest.fn(); - const wrapper = shallowRender({ onSubmit }); - - submit(wrapper.find('form')); - expect(onSubmit).toBeCalled(); -}); - -function shallowRender(props: Partial<ChangeAdminPasswordAppRendererProps> = {}) { - return shallow<ChangeAdminPasswordAppRendererProps>( - <ChangeAdminPasswordAppRenderer - canAdmin={true} - canSubmit={true} - passwordValue="password" - confirmPasswordValue="confirm" - onConfirmPasswordChange={jest.fn()} - onPasswordChange={jest.fn()} - onSubmit={jest.fn()} - submitting={false} - success={false} - location={mockLocation()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/__snapshots__/ChangeAdminPasswordApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/__snapshots__/ChangeAdminPasswordApp-test.tsx.snap deleted file mode 100644 index 1403f55f727..00000000000 --- a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/__snapshots__/ChangeAdminPasswordApp-test.tsx.snap +++ /dev/null @@ -1,46 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: admin is not using the default password 1`] = ` -<ChangeAdminPasswordAppRenderer - confirmPasswordValue="" - location={ - Object { - "hash": "", - "key": "key", - "pathname": "/path", - "query": Object {}, - "search": "", - "state": Object {}, - } - } - onConfirmPasswordChange={[Function]} - onPasswordChange={[Function]} - onSubmit={[Function]} - passwordValue="" - submitting={false} - success={true} -/> -`; - -exports[`should render correctly: default 1`] = ` -<ChangeAdminPasswordAppRenderer - canAdmin={true} - confirmPasswordValue="" - location={ - Object { - "hash": "", - "key": "key", - "pathname": "/path", - "query": Object {}, - "search": "", - "state": Object {}, - } - } - onConfirmPasswordChange={[Function]} - onPasswordChange={[Function]} - onSubmit={[Function]} - passwordValue="" - submitting={false} - success={false} -/> -`; diff --git a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/__snapshots__/ChangeAdminPasswordAppRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/__snapshots__/ChangeAdminPasswordAppRenderer-test.tsx.snap deleted file mode 100644 index c962cf50736..00000000000 --- a/server/sonar-web/src/main/js/apps/change-admin-password/__tests__/__snapshots__/ChangeAdminPasswordAppRenderer-test.tsx.snap +++ /dev/null @@ -1,373 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: access denied 1`] = `<Unauthorized />`; - -exports[`should render correctly: cannot submit 1`] = ` -<div - className="page-wrapper-simple" -> - <div - className="page-simple" - > - <h1 - className="text-center bg-danger big padded" - > - users.change_admin_password.instance_is_at_risk - </h1> - <p - className="text-center huge huge-spacer-top" - > - users.change_admin_password.header - </p> - <p - className="text-center huge-spacer-top huge-spacer-bottom" - > - users.change_admin_password.description - </p> - <form - className="text-center" - onSubmit={[Function]} - > - <h2 - className="big-spacer-bottom big" - > - users.change_admin_password.form.header - </h2> - <MandatoryFieldsExplanation - className="form-field" - /> - <div - className="form-field" - > - <label - htmlFor="user-password" - > - users.change_admin_password.form.password - <MandatoryFieldMarker /> - </label> - <input - id="user-password" - name="password" - onChange={[Function]} - required={true} - type="password" - value="password" - /> - </div> - <div - className="form-field" - > - <label - htmlFor="confirm-user-password" - > - users.change_admin_password.form.confirm - <MandatoryFieldMarker /> - </label> - <input - id="confirm-user-password" - name="confirm-password" - onChange={[Function]} - required={true} - type="password" - value="confirm" - /> - </div> - <div - className="form-field" - > - <SubmitButton - disabled={true} - > - update_verb - </SubmitButton> - </div> - </form> - </div> -</div> -`; - -exports[`should render correctly: default 1`] = ` -<div - className="page-wrapper-simple" -> - <div - className="page-simple" - > - <h1 - className="text-center bg-danger big padded" - > - users.change_admin_password.instance_is_at_risk - </h1> - <p - className="text-center huge huge-spacer-top" - > - users.change_admin_password.header - </p> - <p - className="text-center huge-spacer-top huge-spacer-bottom" - > - users.change_admin_password.description - </p> - <form - className="text-center" - onSubmit={[Function]} - > - <h2 - className="big-spacer-bottom big" - > - users.change_admin_password.form.header - </h2> - <MandatoryFieldsExplanation - className="form-field" - /> - <div - className="form-field" - > - <label - htmlFor="user-password" - > - users.change_admin_password.form.password - <MandatoryFieldMarker /> - </label> - <input - id="user-password" - name="password" - onChange={[Function]} - required={true} - type="password" - value="password" - /> - </div> - <div - className="form-field" - > - <label - htmlFor="confirm-user-password" - > - users.change_admin_password.form.confirm - <MandatoryFieldMarker /> - </label> - <input - id="confirm-user-password" - name="confirm-password" - onChange={[Function]} - required={true} - type="password" - value="confirm" - /> - </div> - <div - className="form-field" - > - <SubmitButton - disabled={false} - > - update_verb - </SubmitButton> - </div> - </form> - </div> -</div> -`; - -exports[`should render correctly: submitting 1`] = ` -<div - className="page-wrapper-simple" -> - <div - className="page-simple" - > - <h1 - className="text-center bg-danger big padded" - > - users.change_admin_password.instance_is_at_risk - </h1> - <p - className="text-center huge huge-spacer-top" - > - users.change_admin_password.header - </p> - <p - className="text-center huge-spacer-top huge-spacer-bottom" - > - users.change_admin_password.description - </p> - <form - className="text-center" - onSubmit={[Function]} - > - <h2 - className="big-spacer-bottom big" - > - users.change_admin_password.form.header - </h2> - <MandatoryFieldsExplanation - className="form-field" - /> - <div - className="form-field" - > - <label - htmlFor="user-password" - > - users.change_admin_password.form.password - <MandatoryFieldMarker /> - </label> - <input - id="user-password" - name="password" - onChange={[Function]} - required={true} - type="password" - value="password" - /> - </div> - <div - className="form-field" - > - <label - htmlFor="confirm-user-password" - > - users.change_admin_password.form.confirm - <MandatoryFieldMarker /> - </label> - <input - id="confirm-user-password" - name="confirm-password" - onChange={[Function]} - required={true} - type="password" - value="confirm" - /> - </div> - <div - className="form-field" - > - <SubmitButton - disabled={true} - > - update_verb - <i - className="spinner spacer-left" - /> - </SubmitButton> - </div> - </form> - </div> -</div> -`; - -exports[`should render correctly: success 1`] = ` -<div - className="page-wrapper-simple" -> - <div - className="page-simple" - > - <Alert - variant="success" - > - <p - className="spacer-bottom" - > - users.change_admin_password.form.success - </p> - <a - href="/" - > - users.change_admin_password.form.continue_to_app - </a> - </Alert> - </div> -</div> -`; - -exports[`should render correctly: trying to use default admin password 1`] = ` -<div - className="page-wrapper-simple" -> - <div - className="page-simple" - > - <h1 - className="text-center bg-danger big padded" - > - users.change_admin_password.instance_is_at_risk - </h1> - <p - className="text-center huge huge-spacer-top" - > - users.change_admin_password.header - </p> - <p - className="text-center huge-spacer-top huge-spacer-bottom" - > - users.change_admin_password.description - </p> - <form - className="text-center" - onSubmit={[Function]} - > - <h2 - className="big-spacer-bottom big" - > - users.change_admin_password.form.header - </h2> - <MandatoryFieldsExplanation - className="form-field" - /> - <div - className="form-field" - > - <label - htmlFor="user-password" - > - users.change_admin_password.form.password - <MandatoryFieldMarker /> - </label> - <input - id="user-password" - name="password" - onChange={[Function]} - required={true} - type="password" - value="admin" - /> - </div> - <div - className="form-field" - > - <label - htmlFor="confirm-user-password" - > - users.change_admin_password.form.confirm - <MandatoryFieldMarker /> - </label> - <input - id="confirm-user-password" - name="confirm-password" - onChange={[Function]} - required={true} - type="password" - value="admin" - /> - <Alert - className="spacer-top" - variant="warning" - > - users.change_admin_password.form.cannot_use_default_password - </Alert> - </div> - <div - className="form-field" - > - <SubmitButton - disabled={false} - > - update_verb - </SubmitButton> - </div> - </form> - </div> -</div> -`; |