]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22418 Migrate CreateProfileForm
authorJeremy Davis <jeremy.davis@sonarsource.com>
Thu, 27 Jun 2024 13:05:58 +0000 (15:05 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 10 Jul 2024 20:02:38 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/quality-profiles/__tests__/QualityProfilesApp-it.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 13a165a85af223c342b2fd7b83cee9e4c27da00e..1fa99d63eeaaf3f62cd5bb124df8bed89942b683 100644 (file)
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import { getByText, screen } from '@testing-library/react';
+import { screen } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 import selectEvent from 'react-select-event';
 import { byRole, byText } from '~sonar-aligned/helpers/testSelector';
@@ -101,11 +101,11 @@ const ui = {
   }),
   listLinkJavaQualityProfile: byRole('link', { name: 'java quality profile' }),
   returnToList: byRole('link', { name: 'quality_profiles.page' }),
-  languageSelect: byRole('combobox', { name: 'language' }),
-  profileExtendSelect: byRole('combobox', {
+  languageSelect: byRole('searchbox', { name: 'language' }),
+  profileExtendSelect: byRole('searchbox', {
     name: 'quality_profiles.creation.choose_parent_quality_profile',
   }),
-  profileCopySelect: byRole('combobox', {
+  profileCopySelect: byRole('searchbox', {
     name: 'quality_profiles.creation.choose_copy_quality_profile',
   }),
   nameCreatePopupInput: byRole('textbox', { name: 'name required' }),
@@ -142,8 +142,7 @@ it('should list Quality Profiles and filter by language', async () => {
   // Creation form should have language pre-selected
   await user.click(await ui.createButton.find());
 
-  // eslint-disable-next-line testing-library/prefer-screen-queries
-  expect(getByText(ui.popup.get(), 'C')).toBeInTheDocument();
+  expect(ui.languageSelect.get()).toHaveValue('C');
 });
 
 describe('Evolution', () => {
@@ -203,8 +202,13 @@ describe('Create', () => {
     await user.click(ui.returnToList.get());
     await user.click(ui.createButton.get());
     await user.click(ui.extendRadio.get());
-    await selectEvent.select(ui.languageSelect.get(), 'C');
-    await selectEvent.select(ui.profileExtendSelect.get(), ui.newCQualityProfileName);
+
+    await user.click(ui.languageSelect.get());
+    await user.click(byRole('option', { name: 'C' }).get());
+
+    await user.click(ui.profileExtendSelect.get());
+    await user.click(byRole('option', { name: ui.newCQualityProfileName }).get());
+
     await user.type(ui.nameCreatePopupInput.get(), ui.newCQualityProfileNameFromCreateButton);
     await user.click(ui.createButton.get(ui.popup.get()));
 
@@ -227,8 +231,13 @@ describe('Create', () => {
     await user.click(ui.returnToList.get());
     await user.click(ui.createButton.get());
     await user.click(ui.copyRadio.get());
-    await selectEvent.select(ui.languageSelect.get(), 'C');
-    await selectEvent.select(ui.profileCopySelect.get(), ui.newCQualityProfileName);
+
+    await user.click(ui.languageSelect.get());
+    await user.click(byRole('option', { name: 'C' }).get());
+
+    await user.click(ui.profileCopySelect.get());
+    await user.click(byRole('option', { name: ui.newCQualityProfileName }).get());
+
     await user.type(ui.nameCreatePopupInput.get(), ui.newCQualityProfileNameFromCreateButton);
     await user.click(ui.createButton.get(ui.popup.get()));
 
@@ -242,7 +251,10 @@ describe('Create', () => {
 
     await user.click(await ui.createButton.find());
     await user.click(ui.blankRadio.get());
-    await selectEvent.select(ui.languageSelect.get(), 'C');
+
+    await user.click(ui.languageSelect.get());
+    await user.click(byRole('option', { name: 'C' }).get());
+
     await user.type(ui.nameCreatePopupInput.get(), ui.newCQualityProfileName);
     await user.click(ui.createButton.get(ui.popup.get()));
 
@@ -256,7 +268,9 @@ describe('Create', () => {
 
     await user.click(await ui.createButton.find());
     await user.click(ui.blankRadio.get());
-    await selectEvent.select(ui.languageSelect.get(), 'C');
+
+    await user.click(ui.languageSelect.get());
+    await user.click(byRole('option', { name: 'C' }).get());
 
     expect(ui.importerA.get()).toBeInTheDocument();
     expect(ui.importerB.get()).toBeInTheDocument();
index de64d5e3cefe409a36f7a19c569ca7512f9bfac4..5487a5d10b8688543860df14aaa0dc869590a896 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { Select, Spinner } from '@sonarsource/echoes-react';
 import {
   ButtonPrimary,
   FileInput,
   FlagMessage,
   FormField,
   InputField,
-  LabelValueSelectOption,
   LightLabel,
   Modal,
   Note,
-  PopupZLevel,
-  SearchSelectDropdown,
   SelectionCard,
-  Spinner,
 } from 'design-system';
 import { sortBy } from 'lodash';
 import * as React from 'react';
 import { useRef } from 'react';
 import { useIntl } from 'react-intl';
-import { SingleValue } from 'react-select';
 import { Location } from '~sonar-aligned/types/router';
 import {
   changeProfileParent,
@@ -110,8 +106,8 @@ export default function CreateProfileForm(props: Readonly<Props>) {
   );
 
   const handleLanguageChange = React.useCallback(
-    (option: SingleValue<LabelValueSelectOption<string>>) => {
-      setLanguage(option?.value);
+    (option: string) => {
+      setLanguage(option);
       setIsValidLanguage(true);
       setProfile(undefined);
       setIsValidProfile(false);
@@ -119,14 +115,6 @@ export default function CreateProfileForm(props: Readonly<Props>) {
     [setLanguage, setIsValidLanguage],
   );
 
-  const handleQualityProfileChange = React.useCallback(
-    (option: SingleValue<LabelValueSelectOption<Profile>>) => {
-      setProfile(option?.value);
-      setIsValidProfile(Boolean(option?.value));
-    },
-    [setProfile, setIsValidProfile],
-  );
-
   const handleFormSubmit = React.useCallback(async () => {
     setSubmitting(true);
     const profileKey = profile?.key;
@@ -194,25 +182,27 @@ export default function CreateProfileForm(props: Readonly<Props>) {
 
   const profilesForSelectedLanguage = profiles.filter((p) => p.language === selectedLanguage);
   const profileOptions = sortBy(profilesForSelectedLanguage, 'name').map((profile) => ({
+    ...profile,
     label: profile.isBuiltIn
       ? `${profile.name} (${intl.formatMessage({ id: 'quality_profiles.built_in' })})`
       : profile.name,
-    value: profile,
+    value: profile.key,
   }));
 
+  const handleQualityProfileChange = React.useCallback(
+    (option: string) => {
+      const selectedProfile = profileOptions.find((p) => p.key === option);
+      setProfile(selectedProfile);
+      setIsValidProfile(selectedProfile !== undefined);
+    },
+    [setProfile, setIsValidProfile, profileOptions],
+  );
+
   const languagesOptions = sortBy(languages, 'name').map((l) => ({
     label: l.name,
     value: l.key,
   }));
 
-  function handleSearch<T>(
-    options: { label: string; value: T }[],
-    query: string,
-    cb: (options: LabelValueSelectOption<T>[]) => void,
-  ) {
-    cb(options.filter((option) => option.label.toLowerCase().includes(query.toLowerCase())));
-  }
-
   return (
     <Modal
       headerTitle={header}
@@ -284,38 +274,37 @@ export default function CreateProfileForm(props: Readonly<Props>) {
           <div className="sw-my-4">
             <MandatoryFieldsExplanation />
           </div>
-          <FormField label={intl.formatMessage({ id: 'language' })} required>
-            <SearchSelectDropdown
-              controlAriaLabel={intl.formatMessage({ id: 'language' })}
-              autoFocus
-              inputId="create-profile-language-input"
-              name="language"
-              onChange={handleLanguageChange}
-              defaultOptions={languagesOptions}
-              loadOptions={(inputValue, cb) => handleSearch(languagesOptions, inputValue, cb)}
-              value={languagesOptions.find((o) => o.value === selectedLanguage)}
-              zLevel={PopupZLevel.Global}
-            />
-          </FormField>
+
+          <Select
+            className="sw-mb-4"
+            data={languagesOptions}
+            id="create-profile-language-input"
+            isRequired
+            isSearchable
+            label={intl.formatMessage({ id: 'language' })}
+            name="language"
+            onChange={handleLanguageChange}
+            value={selectedLanguage}
+          />
+
           {action !== undefined && (
-            <FormField label={intl.formatMessage({ id: 'quality_profiles.parent' })} required>
-              <SearchSelectDropdown
-                controlAriaLabel={intl.formatMessage({
-                  id:
-                    action === ProfileActionModals.Copy
-                      ? 'quality_profiles.creation.choose_copy_quality_profile'
-                      : 'quality_profiles.creation.choose_parent_quality_profile',
-                })}
-                autoFocus
-                inputId="create-profile-parent-input"
-                name="parentKey"
-                onChange={handleQualityProfileChange}
-                defaultOptions={profileOptions}
-                loadOptions={(inputValue, cb) => handleSearch(profileOptions, inputValue, cb)}
-                isSearchable
-                value={profileOptions.find((o) => o.value === profile)}
-              />
-            </FormField>
+            <Select
+              ariaLabel={intl.formatMessage({
+                id:
+                  action === ProfileActionModals.Copy
+                    ? 'quality_profiles.creation.choose_copy_quality_profile'
+                    : 'quality_profiles.creation.choose_parent_quality_profile',
+              })}
+              className="sw-mb-4"
+              data={profileOptions}
+              id="create-profile-parent-input"
+              isRequired
+              isSearchable
+              label={intl.formatMessage({ id: 'quality_profiles.parent' })}
+              name="parentKey"
+              onChange={handleQualityProfileChange}
+              value={profile?.key}
+            />
           )}
           <FormField
             htmlFor="create-profile-name"
@@ -354,11 +343,11 @@ export default function CreateProfileForm(props: Readonly<Props>) {
                     {intl.formatMessage({ id: 'quality_profiles.optional_configuration_file' })}
                   </Note>
                 </FormField>
-              ))}{' '}
+              ))}
             </form>
           )}
 
-          <Spinner loading={submitting || isLoading} />
+          <Spinner isLoading={submitting || isLoading} />
         </>
       }
     />
index 3ca9f75f082a7667cfd35461f1be26e8f4a97498..9dcbc2c1c7c46f5313cf734926215237ff380661 100644 (file)
@@ -97,7 +97,7 @@ export default function ProfilesList(props: Readonly<Props>) {
           header={renderHeader(languageKey, profilesToShow[languageKey].length)}
           data-language={languageKey}
         >
-          {profilesToShow[languageKey].map((profile) => (
+          {(profilesToShow[languageKey] ?? []).map((profile) => (
             <ProfilesListRow
               key={profile.key}
               profile={profile}
index 98fb41ad559c17e8d06090a81108afcec1a63407..6145e9dd6b040766d5c1a25790304c839f88aadf 100644 (file)
@@ -2123,7 +2123,7 @@ quality_profiles.cannot_set_default_no_rules=You must activate at least 1 rule b
 quality_profiles.warning.used_by_projects_no_rules=The current profile is used on several projects, but it has no active rules. Please activate at least 1 rule for this profile.
 quality_profiles.warning.is_default_no_rules=The current profile is the default profile, but it has no active rules. Please activate at least 1 rule for this profile.
 quality_profiles.x_sonarway_missing_rules={linkCount} Sonar way {count, plural, one {rule} other {rules}} not included
-quality_profiles.parent=Parent:
+quality_profiles.parent=Parent
 quality_profiles.parameter_set_to=Parameter {0} set to {1}
 quality_profile.summary_additional={count} additional {count, plural, one {rule} other {rules}}
 quality_profile.summary_fewer={count} fewer {count, plural, one {rule} other {rules}}