]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18438 Migrating unit test for project quality profile page to RTL
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Wed, 23 Aug 2023 08:42:13 +0000 (10:42 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 24 Aug 2023 20:03:07 +0000 (20:03 +0000)
13 files changed:
server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesApp-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/ProjectQualityProfilesAppRenderer-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesApp-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/__snapshots__/ProjectQualityProfilesAppRenderer-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/__tests__/projectQualityProfilesApp-it.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/AddLanguageModal.tsx
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/SetQualityProfileModal.tsx
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/AddLanguageModal-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/LanguageProfileSelectOption-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/SetQualityProfileModal-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/AddLanguageModal-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/LanguageProfileSelectOption-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/SetQualityProfileModal-test.tsx.snap [deleted file]

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 (file)
index 87d6f8b..0000000
+++ /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<ProjectQualityProfilesApp['props']> = {}) {
-  return shallow<ProjectQualityProfilesApp>(
-    <ProjectQualityProfilesApp
-      component={mockComponent({
-        key: 'foo',
-        configuration: { showQualityProfiles: true },
-        qualityProfiles: [
-          { key: 'css2', name: 'CSS 2', language: 'css' },
-          { key: 'js', name: 'JS', language: 'js' },
-          { key: 'ts_default', name: 'TS (default)', language: 'ts' },
-          { key: 'html', name: 'HTML', language: 'html' },
-        ],
-      })}
-      {...props}
-    />
-  );
-}
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 (file)
index 72a7bdc..0000000
+++ /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<ProjectQualityProfilesAppRendererProps> = {}) {
-  return shallow<ProjectQualityProfilesAppRendererProps>(
-    <ProjectQualityProfilesAppRenderer
-      allProfiles={[
-        mockQualityProfile({ key: 'foo', language: 'js' }),
-        mockQualityProfile({ key: 'bar', language: 'css' }),
-        mockQualityProfile({ key: 'baz', language: 'html' }),
-      ]}
-      component={mockComponent()}
-      loading={false}
-      onAddLanguage={jest.fn()}
-      onCloseModal={jest.fn()}
-      onOpenAddLanguageModal={jest.fn()}
-      onOpenSetProfileModal={jest.fn()}
-      onSetProfile={jest.fn()}
-      projectProfiles={[
-        {
-          profile: mockQualityProfile({
-            key: 'foo',
-            name: 'Foo',
-            isDefault: true,
-            language: 'js',
-            languageName: 'JS',
-          }),
-          selected: false,
-        },
-        {
-          profile: mockQualityProfile({
-            key: 'bar',
-            name: 'Bar',
-            isDefault: true,
-            language: 'css',
-            languageName: 'CSS',
-          }),
-          selected: false,
-        },
-        {
-          profile: mockQualityProfile({
-            key: 'baz',
-            name: 'Baz',
-            language: 'html',
-            languageName: 'HTML',
-          }),
-          selected: true,
-        },
-      ]}
-      {...props}
-    />
-  );
-}
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 (file)
index ff942c1..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`renders correctly 1`] = `
-<ProjectQualityProfilesAppRenderer
-  component={
-    {
-      "breadcrumbs": [],
-      "configuration": {
-        "showQualityProfiles": true,
-      },
-      "key": "foo",
-      "name": "MyProject",
-      "qualifier": "TRK",
-      "qualityGate": {
-        "isDefault": true,
-        "key": "30",
-        "name": "Sonar way",
-      },
-      "qualityProfiles": [
-        {
-          "key": "css2",
-          "language": "css",
-          "name": "CSS 2",
-        },
-        {
-          "key": "js",
-          "language": "js",
-          "name": "JS",
-        },
-        {
-          "key": "ts_default",
-          "language": "ts",
-          "name": "TS (default)",
-        },
-        {
-          "key": "html",
-          "language": "html",
-          "name": "HTML",
-        },
-      ],
-      "tags": [],
-    }
-  }
-  loading={true}
-  onAddLanguage={[Function]}
-  onCloseModal={[Function]}
-  onOpenAddLanguageModal={[Function]}
-  onOpenSetProfileModal={[Function]}
-  onSetProfile={[Function]}
-/>
-`;
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 (file)
index cbadc5f..0000000
+++ /dev/null
@@ -1,920 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: add language 1`] = `
-<div
-  className="page page-limited"
-  id="project-quality-profiles"
->
-  <Suggestions
-    suggestions="project_quality_profiles"
-  />
-  <Helmet
-    defer={false}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    title="project_quality_profiles.page"
-  />
-  <A11ySkipTarget
-    anchor="profiles_main"
-  />
-  <header
-    className="page-header"
-  >
-    <div
-      className="page-title display-flex-center"
-    >
-      <h1>
-        project_quality_profiles.page
-         
-      </h1>
-      <HelpTooltip
-        className="spacer-left"
-        overlay={
-          <div
-            className="big-padded-top big-padded-bottom"
-          >
-            quality_profiles.list.projects.help
-          </div>
-        }
-      />
-    </div>
-  </header>
-  <div
-    className="boxed-group"
-  >
-    <h2
-      className="boxed-group-header"
-    >
-      project_quality_profile.subtitle
-    </h2>
-    <div
-      className="boxed-group-inner"
-    >
-      <p
-        className="big-spacer-bottom"
-      >
-        project_quality_profiles.page.description
-      </p>
-      <table
-        className="data zebra"
-      >
-        <thead>
-          <tr>
-            <th>
-              language
-            </th>
-            <th
-              className="thin nowrap"
-            >
-              project_quality_profile.current
-            </th>
-            <th
-              className="thin nowrap text-right"
-            >
-              coding_rules.filters.activation.active_rules
-            </th>
-            <th
-              aria-label="actions"
-            />
-          </tr>
-        </thead>
-        <tbody>
-          <tr
-            key="css"
-          >
-            <td>
-              CSS
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                <em>
-                  project_quality_profile.instance_default
-                </em>
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=bar",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-          <tr
-            key="html"
-          >
-            <td>
-              HTML
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                Baz
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=baz",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-          <tr
-            key="js"
-          >
-            <td>
-              JS
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                <em>
-                  project_quality_profile.instance_default
-                </em>
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=foo",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-        </tbody>
-      </table>
-      <div
-        className="big-spacer-top"
-      >
-        <h2>
-          project_quality_profile.add_language.title
-        </h2>
-        <p
-          className="spacer-top big-spacer-bottom"
-        >
-          project_quality_profile.add_language.description
-        </p>
-        <Button
-          disabled={false}
-          onClick={[MockFunction]}
-        >
-          <PlusCircleIcon
-            className="little-spacer-right"
-          />
-          project_quality_profile.add_language.action
-        </Button>
-      </div>
-      <withLanguagesContext(AddLanguageModal)
-        onClose={[MockFunction]}
-        onSubmit={[MockFunction]}
-        profilesByLanguage={
-          {
-            "css": [
-              {
-                "activeDeprecatedRuleCount": 2,
-                "activeRuleCount": 10,
-                "childrenCount": 0,
-                "depth": 1,
-                "isBuiltIn": false,
-                "isDefault": false,
-                "isInherited": false,
-                "key": "bar",
-                "language": "css",
-                "languageName": "JavaScript",
-                "name": "name",
-                "projectCount": 3,
-              },
-            ],
-            "html": [
-              {
-                "activeDeprecatedRuleCount": 2,
-                "activeRuleCount": 10,
-                "childrenCount": 0,
-                "depth": 1,
-                "isBuiltIn": false,
-                "isDefault": false,
-                "isInherited": false,
-                "key": "baz",
-                "language": "html",
-                "languageName": "JavaScript",
-                "name": "name",
-                "projectCount": 3,
-              },
-            ],
-            "js": [
-              {
-                "activeDeprecatedRuleCount": 2,
-                "activeRuleCount": 10,
-                "childrenCount": 0,
-                "depth": 1,
-                "isBuiltIn": false,
-                "isDefault": false,
-                "isInherited": false,
-                "key": "foo",
-                "language": "js",
-                "languageName": "JavaScript",
-                "name": "name",
-                "projectCount": 3,
-              },
-            ],
-          }
-        }
-        unavailableLanguages={
-          [
-            "js",
-            "css",
-            "html",
-          ]
-        }
-      />
-    </div>
-  </div>
-</div>
-`;
-
-exports[`should render correctly: default 1`] = `
-<div
-  className="page page-limited"
-  id="project-quality-profiles"
->
-  <Suggestions
-    suggestions="project_quality_profiles"
-  />
-  <Helmet
-    defer={false}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    title="project_quality_profiles.page"
-  />
-  <A11ySkipTarget
-    anchor="profiles_main"
-  />
-  <header
-    className="page-header"
-  >
-    <div
-      className="page-title display-flex-center"
-    >
-      <h1>
-        project_quality_profiles.page
-         
-      </h1>
-      <HelpTooltip
-        className="spacer-left"
-        overlay={
-          <div
-            className="big-padded-top big-padded-bottom"
-          >
-            quality_profiles.list.projects.help
-          </div>
-        }
-      />
-    </div>
-  </header>
-  <div
-    className="boxed-group"
-  >
-    <h2
-      className="boxed-group-header"
-    >
-      project_quality_profile.subtitle
-    </h2>
-    <div
-      className="boxed-group-inner"
-    >
-      <p
-        className="big-spacer-bottom"
-      >
-        project_quality_profiles.page.description
-      </p>
-      <table
-        className="data zebra"
-      >
-        <thead>
-          <tr>
-            <th>
-              language
-            </th>
-            <th
-              className="thin nowrap"
-            >
-              project_quality_profile.current
-            </th>
-            <th
-              className="thin nowrap text-right"
-            >
-              coding_rules.filters.activation.active_rules
-            </th>
-            <th
-              aria-label="actions"
-            />
-          </tr>
-        </thead>
-        <tbody>
-          <tr
-            key="css"
-          >
-            <td>
-              CSS
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                <em>
-                  project_quality_profile.instance_default
-                </em>
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=bar",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-          <tr
-            key="html"
-          >
-            <td>
-              HTML
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                Baz
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=baz",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-          <tr
-            key="js"
-          >
-            <td>
-              JS
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                <em>
-                  project_quality_profile.instance_default
-                </em>
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=foo",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-        </tbody>
-      </table>
-      <div
-        className="big-spacer-top"
-      >
-        <h2>
-          project_quality_profile.add_language.title
-        </h2>
-        <p
-          className="spacer-top big-spacer-bottom"
-        >
-          project_quality_profile.add_language.description
-        </p>
-        <Button
-          disabled={false}
-          onClick={[MockFunction]}
-        >
-          <PlusCircleIcon
-            className="little-spacer-right"
-          />
-          project_quality_profile.add_language.action
-        </Button>
-      </div>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`should render correctly: loading 1`] = `
-<div
-  className="page page-limited"
-  id="project-quality-profiles"
->
-  <Suggestions
-    suggestions="project_quality_profiles"
-  />
-  <Helmet
-    defer={false}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    title="project_quality_profiles.page"
-  />
-  <A11ySkipTarget
-    anchor="profiles_main"
-  />
-  <header
-    className="page-header"
-  >
-    <div
-      className="page-title display-flex-center"
-    >
-      <h1>
-        project_quality_profiles.page
-         
-      </h1>
-      <HelpTooltip
-        className="spacer-left"
-        overlay={
-          <div
-            className="big-padded-top big-padded-bottom"
-          >
-            quality_profiles.list.projects.help
-          </div>
-        }
-      />
-    </div>
-  </header>
-  <div
-    className="boxed-group"
-  >
-    <h2
-      className="boxed-group-header"
-    >
-      project_quality_profile.subtitle
-    </h2>
-    <div
-      className="boxed-group-inner"
-    >
-      <p
-        className="big-spacer-bottom"
-      >
-        project_quality_profiles.page.description
-      </p>
-      <i
-        className="spinner spacer-left"
-      />
-      <div
-        className="big-spacer-top"
-      >
-        <h2>
-          project_quality_profile.add_language.title
-        </h2>
-        <p
-          className="spacer-top big-spacer-bottom"
-        >
-          project_quality_profile.add_language.description
-        </p>
-        <Button
-          disabled={true}
-          onClick={[MockFunction]}
-        >
-          <PlusCircleIcon
-            className="little-spacer-right"
-          />
-          project_quality_profile.add_language.action
-        </Button>
-      </div>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`should render correctly: open profile 1`] = `
-<div
-  className="page page-limited"
-  id="project-quality-profiles"
->
-  <Suggestions
-    suggestions="project_quality_profiles"
-  />
-  <Helmet
-    defer={false}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    title="project_quality_profiles.page"
-  />
-  <A11ySkipTarget
-    anchor="profiles_main"
-  />
-  <header
-    className="page-header"
-  >
-    <div
-      className="page-title display-flex-center"
-    >
-      <h1>
-        project_quality_profiles.page
-         
-      </h1>
-      <HelpTooltip
-        className="spacer-left"
-        overlay={
-          <div
-            className="big-padded-top big-padded-bottom"
-          >
-            quality_profiles.list.projects.help
-          </div>
-        }
-      />
-    </div>
-  </header>
-  <div
-    className="boxed-group"
-  >
-    <h2
-      className="boxed-group-header"
-    >
-      project_quality_profile.subtitle
-    </h2>
-    <div
-      className="boxed-group-inner"
-    >
-      <p
-        className="big-spacer-bottom"
-      >
-        project_quality_profiles.page.description
-      </p>
-      <table
-        className="data zebra"
-      >
-        <thead>
-          <tr>
-            <th>
-              language
-            </th>
-            <th
-              className="thin nowrap"
-            >
-              project_quality_profile.current
-            </th>
-            <th
-              className="thin nowrap text-right"
-            >
-              coding_rules.filters.activation.active_rules
-            </th>
-            <th
-              aria-label="actions"
-            />
-          </tr>
-        </thead>
-        <tbody>
-          <tr
-            key="css"
-          >
-            <td>
-              CSS
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                <em>
-                  project_quality_profile.instance_default
-                </em>
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=bar",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-          <tr
-            key="html"
-          >
-            <td>
-              HTML
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                Baz
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=baz",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-          <tr
-            key="js"
-          >
-            <td>
-              JS
-            </td>
-            <td
-              className="thin nowrap"
-            >
-              <span
-                className="display-inline-flex-center"
-              >
-                <em>
-                  project_quality_profile.instance_default
-                </em>
-              </span>
-            </td>
-            <td
-              className="nowrap text-right"
-            >
-              <ForwardRef(Link)
-                to={
-                  {
-                    "pathname": "/coding_rules",
-                    "search": "?activation=true&qprofile=foo",
-                  }
-                }
-              >
-                10
-              </ForwardRef(Link)>
-            </td>
-            <td
-              className="text-right"
-            >
-              <Button
-                onClick={[Function]}
-              >
-                <EditIcon
-                  className="spacer-right"
-                />
-                project_quality_profile.change_profile
-              </Button>
-            </td>
-          </tr>
-        </tbody>
-      </table>
-      <div
-        className="big-spacer-top"
-      >
-        <h2>
-          project_quality_profile.add_language.title
-        </h2>
-        <p
-          className="spacer-top big-spacer-bottom"
-        >
-          project_quality_profile.add_language.description
-        </p>
-        <Button
-          disabled={false}
-          onClick={[MockFunction]}
-        >
-          <PlusCircleIcon
-            className="little-spacer-right"
-          />
-          project_quality_profile.add_language.action
-        </Button>
-      </div>
-      <SetQualityProfileModal
-        availableProfiles={
-          [
-            {
-              "activeDeprecatedRuleCount": 2,
-              "activeRuleCount": 10,
-              "childrenCount": 0,
-              "depth": 1,
-              "isBuiltIn": false,
-              "isDefault": false,
-              "isInherited": false,
-              "key": "foo",
-              "language": "js",
-              "languageName": "JavaScript",
-              "name": "name",
-              "projectCount": 3,
-            },
-          ]
-        }
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-          }
-        }
-        currentProfile={
-          {
-            "activeDeprecatedRuleCount": 2,
-            "activeRuleCount": 10,
-            "childrenCount": 0,
-            "depth": 1,
-            "isBuiltIn": false,
-            "isDefault": false,
-            "isInherited": false,
-            "key": "foo",
-            "language": "js",
-            "languageName": "JavaScript",
-            "name": "name",
-            "projectCount": 3,
-          }
-        }
-        onClose={[MockFunction]}
-        onSubmit={[MockFunction]}
-        usesDefault={true}
-      />
-    </div>
-  </div>
-</div>
-`;
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 (file)
index 0000000..9d4a2a0
--- /dev/null
@@ -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<Component> = { configuration: { showQualityProfiles: true } }
+) {
+  return renderAppWithComponentContext('project/quality_profiles', routes, context, {
+    component: mockComponent(componentOverrides),
+  });
+}
index 9c1839d1b468947a7533e9664769f9881340759c..450793fa3b4b8d692d91c0c8a5c5489977af1b0f 100644 (file)
@@ -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={{
index 01444a6ee3909b7dd15ad99a0a6999faee762f38..2cc134f8482c09aadbf2f5ade25cc7bf60b52cfa 100644 (file)
  */
 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
                     <div className="display-flex-center">
                       <Select
                         className="abs-width-300"
+                        aria-label={translate('project_quality_profile.always_use_specific')}
                         isDisabled={submitting || hasSelectedSysDefault}
                         onChange={({ value }: ProfileOption) => setSelected(value)}
                         options={profileOptions}
diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/AddLanguageModal-test.tsx b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/AddLanguageModal-test.tsx
deleted file mode 100644 (file)
index a0d9293..0000000
+++ /dev/null
@@ -1,106 +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, ShallowWrapper } from 'enzyme';
-import * as React from 'react';
-import Select from '../../../../components/controls/Select';
-import SimpleModal from '../../../../components/controls/SimpleModal';
-import { mockQualityProfile } from '../../../../helpers/testMocks';
-import { AddLanguageModal, AddLanguageModalProps } from '../AddLanguageModal';
-
-it('should render correctly', () => {
-  expect(diveIntoSimpleModal(shallowRender())).toMatchSnapshot('default');
-});
-
-it('should correctly handle changes', () => {
-  const onSubmit = jest.fn();
-  const wrapper = shallowRender({ onSubmit });
-
-  const langSelect = getLanguageSelect(wrapper);
-  let profileSelect = getProfileSelect(wrapper);
-
-  // Language select should only have 2; JS is not available. Profile Select
-  // should have none, as no language is selected yet.
-  expect(langSelect.props().options).toHaveLength(2);
-  expect(profileSelect.props().options).toHaveLength(0);
-
-  // Choose CSS.
-  const langChange = langSelect.props().onChange;
-
-  expect(langChange).toBeDefined();
-
-  langChange!({ value: 'css' });
-
-  // Should now show 2 available profiles.
-  profileSelect = getProfileSelect(wrapper);
-  expect(profileSelect.props().options).toHaveLength(2);
-  expect(profileSelect.props().options).toEqual(
-    expect.arrayContaining([expect.objectContaining({ isDisabled: true })])
-  );
-
-  // Choose 1 profile.
-  const profileChange = profileSelect.props().onChange;
-
-  expect(profileChange).toBeDefined();
-
-  profileChange!({ value: 'css2' });
-
-  submitSimpleModal(wrapper);
-  expect(onSubmit).toHaveBeenLastCalledWith('css2');
-});
-
-function diveIntoSimpleModal(wrapper: ShallowWrapper) {
-  return wrapper.find(SimpleModal).dive().children();
-}
-
-function getLanguageSelect(wrapper: ShallowWrapper) {
-  return diveIntoSimpleModal(wrapper).find(Select).at(0);
-}
-
-function getProfileSelect(wrapper: ShallowWrapper) {
-  return diveIntoSimpleModal(wrapper).find(Select).at(1);
-}
-
-function submitSimpleModal(wrapper: ShallowWrapper) {
-  wrapper.find(SimpleModal).props().onSubmit();
-}
-
-function shallowRender(props: Partial<AddLanguageModalProps> = {}) {
-  return shallow<AddLanguageModalProps>(
-    <AddLanguageModal
-      languages={{
-        css: { key: 'css', name: 'CSS' },
-        ts: { key: 'ts', name: 'TS' },
-        js: { key: 'js', name: 'JS' },
-      }}
-      onClose={jest.fn()}
-      onSubmit={jest.fn()}
-      profilesByLanguage={{
-        css: [
-          mockQualityProfile({ key: 'css', name: 'CSS', activeRuleCount: 0 }),
-          mockQualityProfile({ key: 'css2', name: 'CSS 2' }),
-        ],
-        ts: [mockQualityProfile({ key: 'ts', name: 'TS' })],
-        js: [mockQualityProfile({ key: 'js', name: 'JS' })],
-      }}
-      unavailableLanguages={['js']}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/LanguageProfileSelectOption-test.tsx b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/LanguageProfileSelectOption-test.tsx
deleted file mode 100644 (file)
index 456aae9..0000000
+++ /dev/null
@@ -1,52 +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 DisableableSelectOption from '../../../../components/common/DisableableSelectOption';
-import { mockProfileOption } from '../../../../helpers/mocks/quality-profiles';
-import LanguageProfileSelectOption, {
-  LanguageProfileSelectOptionProps,
-  ProfileOption,
-} from '../LanguageProfileSelectOption';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-});
-
-describe('tooltip', () => {
-  it('should render correctly', () => {
-    expect(renderTooltipOverly()).toMatchSnapshot('default');
-    expect(renderTooltipOverly({ label: undefined })).toMatchSnapshot('no link');
-  });
-});
-
-function renderTooltipOverly(overrides: Partial<ProfileOption> = {}) {
-  const wrapper = shallowRender(overrides);
-  const { disableTooltipOverlay } = wrapper.find(DisableableSelectOption).props();
-  return disableTooltipOverlay();
-}
-
-function shallowRender(overrides: Partial<ProfileOption> = {}) {
-  // satisfy the required props that the option actually gets from the select
-  const optionProps = {} as LanguageProfileSelectOptionProps;
-  return shallow(
-    <LanguageProfileSelectOption {...optionProps} data={{ ...mockProfileOption(), ...overrides }} />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/SetQualityProfileModal-test.tsx b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/SetQualityProfileModal-test.tsx
deleted file mode 100644 (file)
index 14f390e..0000000
+++ /dev/null
@@ -1,82 +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, ShallowWrapper } from 'enzyme';
-import * as React from 'react';
-import Radio from '../../../../components/controls/Radio';
-import Select from '../../../../components/controls/Select';
-import SimpleModal from '../../../../components/controls/SimpleModal';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { mockQualityProfile } from '../../../../helpers/testMocks';
-import SetQualityProfileModal, { SetQualityProfileModalProps } from '../SetQualityProfileModal';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(shallowRender({ usesDefault: true })).toMatchSnapshot('inherits system default');
-  expect(shallowRender({ component: mockComponent() })).toMatchSnapshot('needs reanalysis');
-});
-
-it('should correctly handle changes', () => {
-  const onSubmit = jest.fn();
-  const wrapper = shallowRender({ onSubmit }, false);
-
-  diveIntoSimpleModal(wrapper).find(Radio).at(0).props().onCheck('');
-  submitSimpleModal(wrapper);
-  expect(onSubmit).toHaveBeenLastCalledWith(undefined, 'foo');
-
-  diveIntoSimpleModal(wrapper).find(Radio).at(1).props().onCheck('');
-  diveIntoSimpleModal(wrapper).find(Select).props().onChange({ value: 'bar' });
-  submitSimpleModal(wrapper);
-  expect(onSubmit).toHaveBeenLastCalledWith('bar', 'foo');
-
-  const change = diveIntoSimpleModal(wrapper).find(Select).props().onChange;
-
-  expect(change).toBeDefined();
-
-  change!({ value: 'bar' });
-  submitSimpleModal(wrapper);
-  expect(onSubmit).toHaveBeenLastCalledWith('bar', 'foo');
-});
-
-function diveIntoSimpleModal(wrapper: ShallowWrapper) {
-  return wrapper.find(SimpleModal).dive().children();
-}
-
-function submitSimpleModal(wrapper: ShallowWrapper) {
-  wrapper.find(SimpleModal).props().onSubmit();
-}
-
-function shallowRender(props: Partial<SetQualityProfileModalProps> = {}, dive = true) {
-  const wrapper = shallow<SetQualityProfileModalProps>(
-    <SetQualityProfileModal
-      availableProfiles={[
-        mockQualityProfile({ key: 'foo', isDefault: true, language: 'js' }),
-        mockQualityProfile({ key: 'bar', language: 'js', activeRuleCount: 0 }),
-      ]}
-      component={mockComponent({ qualityProfiles: [{ key: 'foo', name: 'Foo', language: 'js' }] })}
-      currentProfile={mockQualityProfile({ key: 'foo', language: 'js' })}
-      onClose={jest.fn()}
-      onSubmit={jest.fn()}
-      usesDefault={false}
-      {...props}
-    />
-  );
-
-  return dive ? diveIntoSimpleModal(wrapper) : wrapper;
-}
diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/AddLanguageModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/AddLanguageModal-test.tsx.snap
deleted file mode 100644 (file)
index da7e47c..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: default 1`] = `
-[
-  <div
-    className="modal-head"
-  >
-    <h2>
-      project_quality_profile.add_language_modal.title
-    </h2>
-  </div>,
-  <form
-    onSubmit={[Function]}
-  >
-    <div
-      className="modal-body"
-    >
-      <div
-        className="big-spacer-bottom"
-      >
-        <div
-          className="little-spacer-bottom"
-        >
-          <label
-            className="text-bold"
-            htmlFor="language"
-          >
-            project_quality_profile.add_language_modal.choose_language
-          </label>
-        </div>
-        <Select
-          className="abs-width-300"
-          id="language"
-          isDisabled={false}
-          onChange={[Function]}
-          options={
-            [
-              {
-                "label": "CSS",
-                "value": "css",
-              },
-              {
-                "label": "TS",
-                "value": "ts",
-              },
-            ]
-          }
-        />
-      </div>
-      <div
-        className="big-spacer-bottom"
-      >
-        <div
-          className="little-spacer-bottom"
-        >
-          <label
-            className="text-bold"
-            htmlFor="profiles"
-          >
-            project_quality_profile.add_language_modal.choose_profile
-          </label>
-        </div>
-        <Select
-          className="abs-width-300"
-          components={
-            {
-              "Option": [Function],
-            }
-          }
-          id="profiles"
-          isDisabled={true}
-          onChange={[Function]}
-          options={[]}
-          value={null}
-        />
-      </div>
-    </div>
-    <div
-      className="modal-foot"
-    >
-      <SubmitButton
-        disabled={true}
-      >
-        save
-      </SubmitButton>
-      <ButtonLink
-        disabled={false}
-        onClick={[Function]}
-      >
-        cancel
-      </ButtonLink>
-    </div>
-  </form>,
-]
-`;
diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/LanguageProfileSelectOption-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/LanguageProfileSelectOption-test.tsx.snap
deleted file mode 100644 (file)
index 7f69b06..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: default 1`] = `
-<Option
-  data={
-    {
-      "isDisabled": false,
-      "label": "Profile 1",
-      "language": "Java",
-      "value": "profile-1",
-    }
-  }
->
-  <div>
-    <DisableableSelectOption
-      disableTooltipOverlay={[Function]}
-      disabledReason="project_quality_profile.add_language_modal.no_active_rules"
-      option={
-        {
-          "isDisabled": false,
-          "label": "Profile 1",
-          "language": "Java",
-          "value": "profile-1",
-        }
-      }
-    />
-  </div>
-</Option>
-`;
-
-exports[`tooltip should render correctly: default 1`] = `
-<React.Fragment>
-  <p>
-    project_quality_profile.add_language_modal.profile_unavailable_no_active_rules
-  </p>
-  <ForwardRef(Link)
-    to={
-      {
-        "pathname": "/profiles/show",
-        "search": "?name=Profile+1&language=Java",
-      }
-    }
-  >
-    project_quality_profile.add_language_modal.go_to_profile
-  </ForwardRef(Link)>
-</React.Fragment>
-`;
-
-exports[`tooltip should render correctly: no link 1`] = `
-<React.Fragment>
-  <p>
-    project_quality_profile.add_language_modal.profile_unavailable_no_active_rules
-  </p>
-</React.Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/SetQualityProfileModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/__snapshots__/SetQualityProfileModal-test.tsx.snap
deleted file mode 100644 (file)
index 97099a9..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: default 1`] = `
-[
-  <div
-    className="modal-head"
-  >
-    <h2>
-      project_quality_profile.change_lang_X_profile.JavaScript
-    </h2>
-  </div>,
-  <form
-    onSubmit={[Function]}
-  >
-    <div
-      className="modal-body"
-    >
-      <div
-        className="big-spacer-bottom"
-      >
-        <Radio
-          checked={false}
-          className="display-flex-start"
-          disabled={false}
-          onCheck={[Function]}
-          value="-1"
-        >
-          <div
-            className="spacer-left"
-          >
-            <div
-              className="little-spacer-bottom"
-            >
-              project_quality_profile.always_use_default
-            </div>
-            <div
-              className="display-flex-center"
-            >
-              <span
-                className="text-muted spacer-right"
-              >
-                current_noun
-                :
-              </span>
-              name
-            </div>
-          </div>
-        </Radio>
-      </div>
-      <div
-        className="big-spacer-bottom"
-      >
-        <Radio
-          checked={true}
-          className="display-flex-start"
-          disabled={false}
-          onCheck={[Function]}
-          value="foo"
-        >
-          <div
-            className="spacer-left"
-          >
-            <div
-              className="little-spacer-bottom"
-            >
-              project_quality_profile.always_use_specific
-            </div>
-            <div
-              className="display-flex-center"
-            >
-              <Select
-                className="abs-width-300"
-                components={
-                  {
-                    "Option": [Function],
-                  }
-                }
-                isDisabled={false}
-                onChange={[Function]}
-                options={
-                  [
-                    {
-                      "isDisabled": false,
-                      "label": "name",
-                      "language": "js",
-                      "value": "foo",
-                    },
-                    {
-                      "isDisabled": true,
-                      "label": "name",
-                      "language": "js",
-                      "value": "bar",
-                    },
-                  ]
-                }
-                value={
-                  {
-                    "isDisabled": false,
-                    "label": "name",
-                    "language": "js",
-                    "value": "foo",
-                  }
-                }
-              />
-            </div>
-          </div>
-        </Radio>
-      </div>
-    </div>
-    <div
-      className="modal-foot"
-    >
-      <SubmitButton
-        disabled={true}
-      >
-        save
-      </SubmitButton>
-      <ButtonLink
-        disabled={false}
-        onClick={[Function]}
-      >
-        cancel
-      </ButtonLink>
-    </div>
-  </form>,
-]
-`;
-
-exports[`should render correctly: inherits system default 1`] = `
-[
-  <div
-    className="modal-head"
-  >
-    <h2>
-      project_quality_profile.change_lang_X_profile.JavaScript
-    </h2>
-  </div>,
-  <form
-    onSubmit={[Function]}
-  >
-    <div
-      className="modal-body"
-    >
-      <div
-        className="big-spacer-bottom"
-      >
-        <Radio
-          checked={true}
-          className="display-flex-start"
-          disabled={false}
-          onCheck={[Function]}
-          value="-1"
-        >
-          <div
-            className="spacer-left"
-          >
-            <div
-              className="little-spacer-bottom"
-            >
-              project_quality_profile.always_use_default
-            </div>
-            <div
-              className="display-flex-center"
-            >
-              <span
-                className="text-muted spacer-right"
-              >
-                current_noun
-                :
-              </span>
-              name
-            </div>
-          </div>
-        </Radio>
-      </div>
-      <div
-        className="big-spacer-bottom"
-      >
-        <Radio
-          checked={false}
-          className="display-flex-start"
-          disabled={false}
-          onCheck={[Function]}
-          value="foo"
-        >
-          <div
-            className="spacer-left"
-          >
-            <div
-              className="little-spacer-bottom"
-            >
-              project_quality_profile.always_use_specific
-            </div>
-            <div
-              className="display-flex-center"
-            >
-              <Select
-                className="abs-width-300"
-                components={
-                  {
-                    "Option": [Function],
-                  }
-                }
-                isDisabled={true}
-                onChange={[Function]}
-                options={
-                  [
-                    {
-                      "isDisabled": false,
-                      "label": "name",
-                      "language": "js",
-                      "value": "foo",
-                    },
-                    {
-                      "isDisabled": true,
-                      "label": "name",
-                      "language": "js",
-                      "value": "bar",
-                    },
-                  ]
-                }
-                value={
-                  {
-                    "isDisabled": false,
-                    "label": "name",
-                    "language": "js",
-                    "value": "foo",
-                  }
-                }
-              />
-            </div>
-          </div>
-        </Radio>
-      </div>
-    </div>
-    <div
-      className="modal-foot"
-    >
-      <SubmitButton
-        disabled={true}
-      >
-        save
-      </SubmitButton>
-      <ButtonLink
-        disabled={false}
-        onClick={[Function]}
-      >
-        cancel
-      </ButtonLink>
-    </div>
-  </form>,
-]
-`;
-
-exports[`should render correctly: needs reanalysis 1`] = `
-[
-  <div
-    className="modal-head"
-  >
-    <h2>
-      project_quality_profile.change_lang_X_profile.JavaScript
-    </h2>
-  </div>,
-  <form
-    onSubmit={[Function]}
-  >
-    <div
-      className="modal-body"
-    >
-      <div
-        className="big-spacer-bottom"
-      >
-        <Radio
-          checked={false}
-          className="display-flex-start"
-          disabled={false}
-          onCheck={[Function]}
-          value="-1"
-        >
-          <div
-            className="spacer-left"
-          >
-            <div
-              className="little-spacer-bottom"
-            >
-              project_quality_profile.always_use_default
-            </div>
-            <div
-              className="display-flex-center"
-            >
-              <span
-                className="text-muted spacer-right"
-              >
-                current_noun
-                :
-              </span>
-              name
-            </div>
-          </div>
-        </Radio>
-      </div>
-      <div
-        className="big-spacer-bottom"
-      >
-        <Radio
-          checked={true}
-          className="display-flex-start"
-          disabled={false}
-          onCheck={[Function]}
-          value="foo"
-        >
-          <div
-            className="spacer-left"
-          >
-            <div
-              className="little-spacer-bottom"
-            >
-              project_quality_profile.always_use_specific
-            </div>
-            <div
-              className="display-flex-center"
-            >
-              <Select
-                className="abs-width-300"
-                components={
-                  {
-                    "Option": [Function],
-                  }
-                }
-                isDisabled={false}
-                onChange={[Function]}
-                options={
-                  [
-                    {
-                      "isDisabled": false,
-                      "label": "name",
-                      "language": "js",
-                      "value": "foo",
-                    },
-                    {
-                      "isDisabled": true,
-                      "label": "name",
-                      "language": "js",
-                      "value": "bar",
-                    },
-                  ]
-                }
-                value={
-                  {
-                    "isDisabled": false,
-                    "label": "name",
-                    "language": "js",
-                    "value": "foo",
-                  }
-                }
-              />
-            </div>
-          </div>
-        </Radio>
-      </div>
-      <Alert
-        variant="warning"
-      >
-        project_quality_profile.requires_new_analysis
-      </Alert>
-    </div>
-    <div
-      className="modal-foot"
-    >
-      <SubmitButton
-        disabled={true}
-      >
-        save
-      </SubmitButton>
-      <ButtonLink
-        disabled={false}
-        onClick={[Function]}
-      >
-        cancel
-      </ButtonLink>
-    </div>
-  </form>,
-]
-`;