From 2c87d302b7bcc99ceb98a59134052d7e25bb78cf Mon Sep 17 00:00:00 2001 From: Revanshu Paliwal Date: Wed, 23 Aug 2023 10:42:13 +0200 Subject: [PATCH] SONAR-18438 Migrating unit test for project quality profile page to RTL --- .../ProjectQualityProfilesApp-test.tsx | 235 ----- ...ProjectQualityProfilesAppRenderer-test.tsx | 91 -- .../ProjectQualityProfilesApp-test.tsx.snap | 51 - ...ctQualityProfilesAppRenderer-test.tsx.snap | 920 ------------------ .../projectQualityProfilesApp-it.tsx | 252 +++++ .../components/AddLanguageModal.tsx | 8 +- .../components/SetQualityProfileModal.tsx | 3 +- .../__tests__/AddLanguageModal-test.tsx | 106 -- .../LanguageProfileSelectOption-test.tsx | 52 - .../__tests__/SetQualityProfileModal-test.tsx | 82 -- .../AddLanguageModal-test.tsx.snap | 95 -- .../LanguageProfileSelectOption-test.tsx.snap | 55 -- .../SetQualityProfileModal-test.tsx.snap | 384 -------- 13 files changed, 261 insertions(+), 2073 deletions(-) delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesApp-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesAppRenderer-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesApp-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesAppRenderer-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/projectQualityProfilesApp-it.tsx delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/AddLanguageModal-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/LanguageProfileSelectOption-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/SetQualityProfileModal-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/AddLanguageModal-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/LanguageProfileSelectOption-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/SetQualityProfileModal-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesApp-test.tsx b/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesApp-test.tsx deleted file mode 100644 index 87d6f8b15b2..00000000000 --- a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesApp-test.tsx +++ /dev/null @@ -1,235 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2023 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 { - associateProject, - dissociateProject, - getProfileProjects, - ProfileProject, - searchQualityProfiles, -} from '../../../api/quality-profiles'; -import handleRequiredAuthorization from '../../../app/utils/handleRequiredAuthorization'; -import { mockComponent } from '../../../helpers/mocks/component'; -import { waitAndUpdate } from '../../../helpers/testUtils'; -import { ProjectQualityProfilesApp } from '../ProjectQualityProfilesApp'; - -jest.mock('../../../api/quality-profiles', () => { - const { mockQualityProfile } = jest.requireActual('../../../helpers/testMocks'); - - return { - associateProject: jest.fn().mockResolvedValue({}), - dissociateProject: jest.fn().mockResolvedValue({}), - searchQualityProfiles: jest.fn().mockResolvedValue({ - profiles: [ - mockQualityProfile({ key: 'css', language: 'css' }), - mockQualityProfile({ key: 'css2', language: 'css' }), - mockQualityProfile({ key: 'css_default', language: 'css', isDefault: true }), - mockQualityProfile({ key: 'java', language: 'java' }), - mockQualityProfile({ key: 'java_default', language: 'java', isDefault: true }), - mockQualityProfile({ key: 'js', language: 'js' }), - mockQualityProfile({ key: 'js_default', language: 'js', isDefault: true }), - mockQualityProfile({ key: 'ts_default', language: 'ts', isDefault: true }), - mockQualityProfile({ key: 'html', language: 'html' }), - mockQualityProfile({ key: 'html_default', language: 'html', isDefault: true }), - ], - }), - getProfileProjects: jest.fn(({ key }) => { - const results: ProfileProject[] = []; - if (key === 'js' || key === 'css' || key === 'html_default') { - results.push({ - key: 'foo', - name: 'Foo', - selected: true, - }); - } else if (key === 'html') { - results.push({ - key: 'foobar', - name: 'FooBar', - selected: true, - }); - } - return Promise.resolve({ results }); - }), - }; -}); - -jest.mock('../../../helpers/globalMessages', () => ({ - addGlobalSuccessMessage: jest.fn(), -})); - -jest.mock('../../../app/utils/handleRequiredAuthorization', () => jest.fn()); - -beforeEach(jest.clearAllMocks); - -it('renders correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -it('correctly checks permissions', () => { - const wrapper = shallowRender({ - component: mockComponent({ configuration: { showQualityProfiles: false } }), - }); - expect(wrapper.type()).toBeNull(); - expect(handleRequiredAuthorization).toHaveBeenCalled(); -}); - -it('correctly fetches and treats profile data', async () => { - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - - expect(searchQualityProfiles).toHaveBeenCalled(); - expect(getProfileProjects).toHaveBeenCalledTimes(10); - - expect(wrapper.state().projectProfiles).toEqual([ - expect.objectContaining({ - profile: expect.objectContaining({ key: 'css' }), - selected: true, - }), - expect.objectContaining({ - profile: expect.objectContaining({ key: 'js' }), - selected: true, - }), - expect.objectContaining({ - profile: expect.objectContaining({ key: 'html_default' }), - selected: true, - }), - expect.objectContaining({ - profile: expect.objectContaining({ key: 'ts_default' }), - selected: false, - }), - ]); -}); - -it('correctly sets a profile', async () => { - const wrapper = shallowRender(); - const instance = wrapper.instance(); - await waitAndUpdate(wrapper); - - // Dissociate a selected profile. - instance.handleSetProfile(undefined, 'css'); - expect(dissociateProject).toHaveBeenLastCalledWith( - expect.objectContaining({ key: 'css' }), - 'foo' - ); - await waitAndUpdate(wrapper); - expect(wrapper.state().projectProfiles).toEqual( - expect.arrayContaining([ - { - profile: expect.objectContaining({ key: 'css_default' }), - // It's not explicitly selected, as we're inheriting the default. - selected: false, - }, - ]) - ); - - // Associate a new profile. - instance.handleSetProfile('css2', 'css_default'); - expect(associateProject).toHaveBeenLastCalledWith( - expect.objectContaining({ key: 'css2' }), - 'foo' - ); - await waitAndUpdate(wrapper); - expect(wrapper.state().projectProfiles).toEqual( - expect.arrayContaining([ - { - profile: expect.objectContaining({ key: 'css2' }), - // It's explicitly selected. - selected: true, - }, - ]) - ); - - // Dissociate a default profile that was inherited. - (dissociateProject as jest.Mock).mockClear(); - instance.handleSetProfile(undefined, 'ts_default'); - // It won't call the WS. - expect(dissociateProject).not.toHaveBeenCalled(); - - // Associate a default profile that was already inherited. - instance.handleSetProfile('ts_default', 'ts_default'); - expect(associateProject).toHaveBeenLastCalledWith( - expect.objectContaining({ key: 'ts_default' }), - 'foo' - ); - await waitAndUpdate(wrapper); - expect(wrapper.state().projectProfiles).toEqual( - expect.arrayContaining([ - { - profile: expect.objectContaining({ key: 'ts_default' }), - // It's explicitly selected, even though it is the default profile. - selected: true, - }, - ]) - ); -}); - -it('correctly adds a new language', async () => { - const wrapper = shallowRender(); - const instance = wrapper.instance(); - await waitAndUpdate(wrapper); - - instance.handleAddLanguage('java'); - expect(associateProject).toHaveBeenLastCalledWith( - expect.objectContaining({ key: 'java' }), - 'foo' - ); - await waitAndUpdate(wrapper); - expect(wrapper.state().projectProfiles).toEqual( - expect.arrayContaining([ - { - profile: expect.objectContaining({ key: 'java' }), - // It must be explicitly selected. Adding an unanalyzed language can - // only happen by explicitly choosing a profile. - selected: true, - }, - ]) - ); -}); - -it('correctly handles WS errors', async () => { - (searchQualityProfiles as jest.Mock).mockRejectedValueOnce(null); - (getProfileProjects as jest.Mock).mockRejectedValueOnce(null); - - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - - expect(wrapper.state().allProfiles).toHaveLength(0); - expect(wrapper.state().projectProfiles).toHaveLength(0); - expect(wrapper.state().loading).toBe(false); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesAppRenderer-test.tsx b/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesAppRenderer-test.tsx deleted file mode 100644 index 72a7bdc6180..00000000000 --- a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesAppRenderer-test.tsx +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2023 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 { mockComponent } from '../../../helpers/mocks/component'; -import { mockQualityProfile } from '../../../helpers/testMocks'; -import ProjectQualityProfilesAppRenderer, { - ProjectQualityProfilesAppRendererProps, -} from '../ProjectQualityProfilesAppRenderer'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ loading: true })).toMatchSnapshot('loading'); - expect( - shallowRender({ - showProjectProfileInModal: { - profile: mockQualityProfile({ key: 'foo', language: 'js' }), - selected: false, - }, - }) - ).toMatchSnapshot('open profile'); - expect(shallowRender({ showAddLanguageModal: true })).toMatchSnapshot('add language'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesApp-test.tsx.snap deleted file mode 100644 index ff942c16387..00000000000 --- a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesApp-test.tsx.snap +++ /dev/null @@ -1,51 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renders correctly 1`] = ` - -`; diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesAppRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesAppRenderer-test.tsx.snap deleted file mode 100644 index cbadc5f89c5..00000000000 --- a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesAppRenderer-test.tsx.snap +++ /dev/null @@ -1,920 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: add language 1`] = ` -
- - - -
-
-

- project_quality_profiles.page - -

- - quality_profiles.list.projects.help -
- } - /> -
- -
-

- project_quality_profile.subtitle -

-
-

- project_quality_profiles.page.description -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- language - - project_quality_profile.current - - coding_rules.filters.activation.active_rules - -
- CSS - - - - project_quality_profile.instance_default - - - - - 10 - - - -
- HTML - - - Baz - - - - 10 - - - -
- JS - - - - project_quality_profile.instance_default - - - - - 10 - - - -
-
-

- project_quality_profile.add_language.title -

-

- project_quality_profile.add_language.description -

- -
- -
-
- -`; - -exports[`should render correctly: default 1`] = ` -
- - - -
-
-

- project_quality_profiles.page - -

- - quality_profiles.list.projects.help -
- } - /> -
- -
-

- project_quality_profile.subtitle -

-
-

- project_quality_profiles.page.description -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- language - - project_quality_profile.current - - coding_rules.filters.activation.active_rules - -
- CSS - - - - project_quality_profile.instance_default - - - - - 10 - - - -
- HTML - - - Baz - - - - 10 - - - -
- JS - - - - project_quality_profile.instance_default - - - - - 10 - - - -
-
-

- project_quality_profile.add_language.title -

-

- project_quality_profile.add_language.description -

- -
-
-
- -`; - -exports[`should render correctly: loading 1`] = ` -
- - - -
-
-

- project_quality_profiles.page - -

- - quality_profiles.list.projects.help -
- } - /> -
- -
-

- project_quality_profile.subtitle -

-
-

- project_quality_profiles.page.description -

- -
-

- project_quality_profile.add_language.title -

-

- project_quality_profile.add_language.description -

- -
-
-
- -`; - -exports[`should render correctly: open profile 1`] = ` -
- - - -
-
-

- project_quality_profiles.page - -

- - quality_profiles.list.projects.help -
- } - /> -
- -
-

- project_quality_profile.subtitle -

-
-

- project_quality_profiles.page.description -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- language - - project_quality_profile.current - - coding_rules.filters.activation.active_rules - -
- CSS - - - - project_quality_profile.instance_default - - - - - 10 - - - -
- HTML - - - Baz - - - - 10 - - - -
- JS - - - - project_quality_profile.instance_default - - - - - 10 - - - -
-
-

- project_quality_profile.add_language.title -

-

- project_quality_profile.add_language.description -

- -
- -
-
- -`; diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/projectQualityProfilesApp-it.tsx b/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/projectQualityProfilesApp-it.tsx new file mode 100644 index 00000000000..9d4a2a0bca1 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/projectQualityProfilesApp-it.tsx @@ -0,0 +1,252 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 selectEvent from 'react-select-event'; +import { + ProfileProject, + associateProject, + getProfileProjects, + searchQualityProfiles, +} from '../../../api/quality-profiles'; +import handleRequiredAuthorization from '../../../app/utils/handleRequiredAuthorization'; +import { addGlobalSuccessMessage } from '../../../helpers/globalMessages'; +import { mockComponent } from '../../../helpers/mocks/component'; +import { + RenderContext, + renderAppWithComponentContext, +} from '../../../helpers/testReactTestingUtils'; +import { byLabelText, byRole, byText } from '../../../helpers/testSelector'; +import { Component } from '../../../types/types'; +import routes from '../routes'; + +jest.mock('../../../api/quality-profiles', () => { + const { mockQualityProfile } = jest.requireActual('../../../helpers/testMocks'); + + return { + associateProject: jest.fn().mockResolvedValue({}), + dissociateProject: jest.fn().mockResolvedValue({}), + searchQualityProfiles: jest.fn().mockResolvedValue({ + profiles: [ + mockQualityProfile({ + key: 'css', + language: 'css', + name: 'css profile', + languageName: 'CSS', + }), + mockQualityProfile({ + key: 'java', + language: 'java', + name: 'java profile', + languageName: 'Java', + }), + mockQualityProfile({ + key: 'js', + language: 'js', + name: 'js profile', + languageName: 'JavaScript', + }), + mockQualityProfile({ + key: 'ts', + language: 'ts', + isDefault: true, + name: 'ts profile', + languageName: 'Typescript', + }), + mockQualityProfile({ + key: 'html', + language: 'html', + name: 'html profile', + languageName: 'HTML', + }), + mockQualityProfile({ + key: 'html_default', + language: 'html', + isDefault: true, + isBuiltIn: true, + name: 'html default profile', + languageName: 'HTML', + }), + ], + }), + getProfileProjects: jest.fn(({ key }) => { + const results: ProfileProject[] = []; + if (key === 'css' || key === 'java' || key === 'js' || key === 'ts' || key === 'java') { + results.push({ + key: 'my-project', + name: 'My project', + selected: true, + }); + } + return Promise.resolve({ results }); + }), + }; +}); + +jest.mock('../../../helpers/globalMessages', () => { + const globalMessages = jest.requireActual('../../../helpers/globalMessages'); + return { + ...globalMessages, + addGlobalSuccessMessage: jest.fn(), + }; +}); + +jest.mock('../../../app/utils/handleRequiredAuthorization', () => jest.fn()); + +beforeEach(jest.clearAllMocks); + +const ui = { + pageTitle: byText('project_quality_profiles.page'), + pageSubTitle: byText('project_quality_profile.subtitle'), + pageDescription: byText('project_quality_profiles.page.description'), + helpTooltip: byLabelText('help'), + profileRows: byRole('row'), + addLanguageButton: byRole('button', { name: 'project_quality_profile.add_language.action' }), + modalAddLanguageTitle: byText('project_quality_profile.add_language_modal.title'), + selectLanguage: byRole('combobox', { + name: 'project_quality_profile.add_language_modal.choose_language', + }), + selectProfile: byRole('combobox', { + name: 'project_quality_profile.add_language_modal.choose_profile', + }), + selectUseSpecificProfile: byRole('combobox', { + name: 'project_quality_profile.always_use_specific', + }), + buttonSave: byRole('button', { name: 'save' }), + buttonChangeProfile: byRole('button', { name: 'project_quality_profile.change_profile' }), + htmlLanguage: byText('HTML'), + htmlProfile: byText('html profile'), + cssLanguage: byText('CSS'), + cssProfile: byText('css profile'), + htmlDefaultProfile: byText('html default profile'), + htmlActiveRuleslink: byRole('link', { name: '10' }), + radioButtonUseInstanceDefault: byRole('radio', { + name: /project_quality_profile.always_use_default/, + }), + radioButtonUseSpecific: byRole('radio', { name: /project_quality_profile.always_use_specific/ }), + newAnalysisWarningMessage: byText('project_quality_profile.requires_new_analysis'), + builtInTag: byText('quality_profiles.built_in'), +}; + +it('should be able to add and change profile for languages', async () => { + const user = userEvent.setup(); + renderProjectQualityProfilesApp({ + languages: { + css: { key: 'css', name: 'CSS' }, + ts: { key: 'ts', name: 'TS' }, + js: { key: 'js', name: 'JS' }, + java: { key: 'java', name: 'JAVA' }, + html: { key: 'html', name: 'HTML' }, + }, + }); + + expect(ui.pageTitle.get()).toBeInTheDocument(); + expect(ui.pageSubTitle.get()).toBeInTheDocument(); + expect(ui.pageDescription.get()).toBeInTheDocument(); + expect(ui.addLanguageButton.get()).toBeInTheDocument(); + await expect(ui.helpTooltip.get()).toHaveATooltipWithContent( + 'quality_profiles.list.projects.help' + ); + expect(ui.profileRows.getAll()).toHaveLength(5); + expect(ui.cssLanguage.get()).toBeInTheDocument(); + expect(ui.cssProfile.get()).toBeInTheDocument(); + + await user.click(ui.addLanguageButton.get()); + + // Opens the add language modal + expect(ui.modalAddLanguageTitle.get()).toBeInTheDocument(); + expect(ui.selectLanguage.get()).toBeEnabled(); + expect(ui.selectProfile.get()).toBeDisabled(); + expect(ui.buttonSave.get()).toBeInTheDocument(); + + await selectEvent.select(ui.selectLanguage.get(), 'HTML'); + expect(ui.selectProfile.get()).toBeEnabled(); + await selectEvent.select(ui.selectProfile.get(), 'html profile'); + await user.click(ui.buttonSave.get()); + expect(associateProject).toHaveBeenLastCalledWith( + expect.objectContaining({ key: 'html', name: 'html profile' }), + 'my-project' + ); + expect(addGlobalSuccessMessage).toHaveBeenCalledWith( + 'project_quality_profile.successfully_updated.HTML' + ); + + // Updates the page after API call + const htmlRow = byRole('row', { + name: 'HTML html profile 10 project_quality_profile.change_profile', + }); + + expect(ui.htmlLanguage.get()).toBeInTheDocument(); + expect(ui.htmlProfile.get()).toBeInTheDocument(); + expect(ui.profileRows.getAll()).toHaveLength(6); + expect(htmlRow.get()).toBeInTheDocument(); + expect(htmlRow.byRole('link', { name: '10' }).get()).toHaveAttribute( + 'href', + '/coding_rules?activation=true&qprofile=html' + ); + expect(ui.builtInTag.query()).not.toBeInTheDocument(); + + await user.click( + htmlRow.byRole('button', { name: 'project_quality_profile.change_profile' }).get() + ); + + //Opens modal to change profile + expect(ui.radioButtonUseInstanceDefault.get()).not.toBeChecked(); + expect(ui.radioButtonUseSpecific.get()).toBeChecked(); + expect(ui.newAnalysisWarningMessage.get()).toBeInTheDocument(); + expect(ui.selectUseSpecificProfile.get()).toBeInTheDocument(); + + await selectEvent.select(ui.selectUseSpecificProfile.get(), 'html default profile'); + await user.click(ui.buttonSave.get()); + + expect(addGlobalSuccessMessage).toHaveBeenCalledWith( + 'project_quality_profile.successfully_updated.HTML' + ); + + // Updates the page after API call + expect(ui.htmlProfile.query()).not.toBeInTheDocument(); + expect(ui.htmlDefaultProfile.get()).toBeInTheDocument(); + expect(ui.builtInTag.get()).toBeInTheDocument(); +}); + +it('should call authorization api when permissions is not proper', () => { + renderProjectQualityProfilesApp({}, { configuration: { showQualityProfiles: false } }); + expect(handleRequiredAuthorization).toHaveBeenCalled(); +}); + +it('should still show page with add language button when api fails', () => { + jest.mocked(searchQualityProfiles).mockRejectedValueOnce(null); + jest.mocked(getProfileProjects).mockRejectedValueOnce(null); + + renderProjectQualityProfilesApp(); + expect(ui.pageTitle.get()).toBeInTheDocument(); + expect(ui.pageSubTitle.get()).toBeInTheDocument(); + expect(ui.pageDescription.get()).toBeInTheDocument(); + expect(ui.addLanguageButton.get()).toBeInTheDocument(); +}); + +function renderProjectQualityProfilesApp( + context?: RenderContext, + componentOverrides: Partial = { configuration: { showQualityProfiles: true } } +) { + return renderAppWithComponentContext('project/quality_profiles', routes, context, { + component: mockComponent(componentOverrides), + }); +} diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/AddLanguageModal.tsx b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/AddLanguageModal.tsx index 9c1839d1b46..450793fa3b4 100644 --- a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/AddLanguageModal.tsx +++ b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/AddLanguageModal.tsx @@ -21,9 +21,9 @@ import { difference } from 'lodash'; import * as React from 'react'; import { Profile } from '../../../api/quality-profiles'; import withLanguagesContext from '../../../app/components/languages/withLanguagesContext'; -import { ButtonLink, SubmitButton } from '../../../components/controls/buttons'; import Select, { LabelValueSelectOption } from '../../../components/controls/Select'; import SimpleModal from '../../../components/controls/SimpleModal'; +import { ButtonLink, SubmitButton } from '../../../components/controls/buttons'; import { translate } from '../../../helpers/l10n'; import { Languages } from '../../../types/languages'; import { Dict } from '../../../types/types'; @@ -90,6 +90,9 @@ export function AddLanguageModal(props: AddLanguageModalProps) { className="abs-width-300" isDisabled={submitting} id="language" + aria-label={translate( + 'project_quality_profile.add_language_modal.choose_language' + )} onChange={({ value }: LabelValueSelectOption) => { setSelected({ language: value, key: undefined }); }} @@ -107,6 +110,9 @@ export function AddLanguageModal(props: AddLanguageModalProps) { className="abs-width-300" isDisabled={submitting || !language} id="profiles" + aria-label={translate( + 'project_quality_profile.add_language_modal.choose_profile' + )} onChange={({ value }: ProfileOption) => setSelected({ language, key: value })} options={profileOptions} components={{ diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/SetQualityProfileModal.tsx b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/SetQualityProfileModal.tsx index 01444a6ee39..2cc134f8482 100644 --- a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/SetQualityProfileModal.tsx +++ b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/SetQualityProfileModal.tsx @@ -19,10 +19,10 @@ */ import * as React from 'react'; import { Profile } from '../../../api/quality-profiles'; -import { ButtonLink, SubmitButton } from '../../../components/controls/buttons'; import Radio from '../../../components/controls/Radio'; import Select from '../../../components/controls/Select'; import SimpleModal from '../../../components/controls/SimpleModal'; +import { ButtonLink, SubmitButton } from '../../../components/controls/buttons'; import { Alert } from '../../../components/ui/Alert'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { Component } from '../../../types/types'; @@ -126,6 +126,7 @@ export default function SetQualityProfileModal(props: SetQualityProfileModalProp
-
-
-
- -
- -
- - - - -
- - save - - - cancel - -
- , -] -`; - -exports[`should render correctly: inherits system default 1`] = ` -[ -
-

- project_quality_profile.change_lang_X_profile.JavaScript -

-
, -
-
-
- -
-
- project_quality_profile.always_use_default -
-
- - current_noun - : - - name -
-
-
-
-
- -
-
- project_quality_profile.always_use_specific -
-
- -
-
-
-
- - project_quality_profile.requires_new_analysis - -
-
- - save - - - cancel - -
-
, -] -`; -- 2.39.5