]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-12620 Auto-select the language when creating a Quality Profile
authorJonathan Weibel <jonathan.weibel@sonarsource.com>
Thu, 1 Oct 2020 09:14:51 +0000 (11:14 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 2 Oct 2020 20:07:42 +0000 (20:07 +0000)
server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/CreateProfileForm-test.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/PageHeader-test.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/CreateProfileForm-test.tsx.snap
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/PageHeader-test.tsx.snap

index 0ea80f8cca3e838cabc07ca37d1cd9803657ab48..4ac543498ede21a2dfb58f8a6d81d7233debce3f 100644 (file)
@@ -23,15 +23,18 @@ import { ResetButtonLink, SubmitButton } from 'sonar-ui-common/components/contro
 import Modal from 'sonar-ui-common/components/controls/Modal';
 import Select from 'sonar-ui-common/components/controls/Select';
 import { translate } from 'sonar-ui-common/helpers/l10n';
+import { parseAsOptionalString } from 'sonar-ui-common/helpers/query';
 import {
   changeProfileParent,
   createQualityProfile,
   getImporters
 } from '../../../api/quality-profiles';
+import { Location } from '../../../components/hoc/withRouter';
 import { Profile } from '../types';
 
 interface Props {
   languages: Array<{ key: string; name: string }>;
+  location: Location;
   onClose: () => void;
   onCreate: Function;
   organization: string | null;
@@ -115,10 +118,11 @@ export default class CreateProfileForm extends React.PureComponent<Props, State>
 
   render() {
     const header = translate('quality_profiles.new_profile');
+    const languageQueryFilter = parseAsOptionalString(this.props.location.query.language);
     const languages = sortBy(this.props.languages, 'name');
     let profiles: Array<{ label: string; value: string }> = [];
 
-    const selectedLanguage = this.state.language || languages[0].key;
+    const selectedLanguage = this.state.language || languageQueryFilter || languages[0].key;
     const importers = this.state.importers.filter(importer =>
       importer.languages.includes(selectedLanguage)
     );
@@ -176,9 +180,9 @@ export default class CreateProfileForm extends React.PureComponent<Props, State>
                   id="create-profile-language"
                   name="language"
                   onChange={this.handleLanguageChange}
-                  options={languages.map(language => ({
-                    label: language.name,
-                    value: language.key
+                  options={languages.map(l => ({
+                    label: l.name,
+                    value: l.key
                   }))}
                   value={selectedLanguage}
                 />
index b7ff4e359b8db40c2dc58acdf90e932d414bdf77..df836bd583ed22622a3621f197541379659a5c0b 100644 (file)
@@ -19,6 +19,7 @@
  */
 import * as React from 'react';
 import { Actions } from '../../../api/quality-profiles';
+import { Location } from '../../../components/hoc/withRouter';
 import { Profile } from '../types';
 import Evolution from './Evolution';
 import PageHeader from './PageHeader';
@@ -27,7 +28,7 @@ import ProfilesList from './ProfilesList';
 interface Props {
   actions: Actions;
   languages: Array<{ key: string; name: string }>;
-  location: { query: T.Dict<string> };
+  location: Location;
   organization: string | null;
   profiles: Profile[];
   updateProfiles: () => Promise<void>;
index bb141e8aee294e458982535a0fb9173c7febc83f..a4726522c1c1b491036ef3c2b68031215225b9b4 100644 (file)
@@ -23,7 +23,7 @@ import { Button } from 'sonar-ui-common/components/controls/buttons';
 import { Alert } from 'sonar-ui-common/components/ui/Alert';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 import { Actions } from '../../../api/quality-profiles';
-import { Router, withRouter } from '../../../components/hoc/withRouter';
+import { Location, Router, withRouter } from '../../../components/hoc/withRouter';
 import { Profile } from '../types';
 import { getProfilePath } from '../utils';
 import CreateProfileForm from './CreateProfileForm';
@@ -32,6 +32,7 @@ import RestoreProfileForm from './RestoreProfileForm';
 interface Props {
   actions: Actions;
   languages: Array<{ key: string; name: string }>;
+  location: Location;
   organization: string | null;
   profiles: Profile[];
   router: Pick<Router, 'push'>;
@@ -77,7 +78,7 @@ export class PageHeader extends React.PureComponent<Props, State> {
   };
 
   render() {
-    const { actions, languages, organization, profiles } = this.props;
+    const { actions, languages, location, organization, profiles } = this.props;
     return (
       <header className="page-header">
         <h1 className="page-title">{translate('quality_profiles.page')}</h1>
@@ -129,6 +130,7 @@ export class PageHeader extends React.PureComponent<Props, State> {
         {this.state.createFormOpen && (
           <CreateProfileForm
             languages={languages}
+            location={location}
             onClose={this.closeCreateForm}
             onCreate={this.handleCreate}
             organization={organization}
index e9e6000c61e4d9a28b281dbce4401c68825b46c4..3d766f9c2749550f7c9f41fc64115cf632b64092 100644 (file)
@@ -21,7 +21,7 @@ import { shallow } from 'enzyme';
 import * as React from 'react';
 import { mockEvent, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
 import { changeProfileParent, createQualityProfile } from '../../../../api/quality-profiles';
-import { mockQualityProfile } from '../../../../helpers/testMocks';
+import { mockLocation, mockQualityProfile } from '../../../../helpers/testMocks';
 import CreateProfileForm from '../CreateProfileForm';
 
 beforeEach(() => jest.clearAllMocks());
@@ -32,7 +32,7 @@ jest.mock('../../../../api/quality-profiles', () => ({
   getImporters: jest.fn().mockResolvedValue([
     {
       key: 'key_importer',
-      languages: ['lang1_importer', 'lang2_importer', 'kr'],
+      languages: ['lang1_importer', 'lang2_importer', 'js'],
       name: 'name_importer'
     }
   ])
@@ -41,7 +41,11 @@ jest.mock('../../../../api/quality-profiles', () => ({
 it('should render correctly', async () => {
   const wrapper = shallowRender();
   await waitAndUpdate(wrapper);
-  expect(wrapper).toMatchSnapshot();
+
+  expect(wrapper).toMatchSnapshot('default');
+  expect(
+    wrapper.setProps({ location: mockLocation({ query: { language: 'js' } }) })
+  ).toMatchSnapshot('with query filter');
 });
 
 it('should handle form submit correctly', async () => {
@@ -72,11 +76,15 @@ it('should handle form submit without parent correctly', async () => {
 function shallowRender(props?: Partial<CreateProfileForm['props']>) {
   return shallow<CreateProfileForm>(
     <CreateProfileForm
-      languages={[{ key: 'kr', name: 'Hangeul' }]}
+      languages={[
+        { key: 'js', name: 'JavaScript' },
+        { key: 'css', name: 'CSS' }
+      ]}
+      location={mockLocation()}
       onClose={jest.fn()}
       onCreate={jest.fn()}
       organization="org"
-      profiles={[mockQualityProfile()]}
+      profiles={[mockQualityProfile(), mockQualityProfile({ language: 'css' })]}
       {...props}
     />
   );
index 11990b1789f9d143d051ebbab95943ff57ea71d1..d71b11092fb978ae1db306254a112ae6c492c7a5 100644 (file)
 import { shallow } from 'enzyme';
 import * as React from 'react';
 import { click } from 'sonar-ui-common/helpers/testUtils';
-import { mockLanguage, mockQualityProfile, mockRouter } from '../../../../helpers/testMocks';
+import {
+  mockLanguage,
+  mockLocation,
+  mockQualityProfile,
+  mockRouter
+} from '../../../../helpers/testMocks';
 import { PageHeader } from '../PageHeader';
 
 it('should render correctly', () => {
@@ -46,6 +51,7 @@ function shallowRender(props: Partial<PageHeader['props']> = {}) {
     <PageHeader
       actions={{ create: false }}
       languages={[mockLanguage()]}
+      location={mockLocation()}
       organization="foo"
       profiles={[mockQualityProfile()]}
       router={mockRouter()}
index 6efd6aef32afe141e3591da9c8c1d13e5e95d3f8..c05fa79501e7c2deb58084d7d454fd3f9b887259 100644 (file)
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`should render correctly 1`] = `
+exports[`should render correctly: default 1`] = `
 <Modal
   contentLabel="quality_profiles.new_profile"
   onRequestClose={[MockFunction]}
@@ -66,12 +66,148 @@ exports[`should render correctly 1`] = `
           options={
             Array [
               Object {
-                "label": "Hangeul",
-                "value": "kr",
+                "label": "CSS",
+                "value": "css",
+              },
+              Object {
+                "label": "JavaScript",
+                "value": "js",
+              },
+            ]
+          }
+          value="css"
+        />
+      </div>
+      <div
+        className="modal-field"
+      >
+        <label
+          htmlFor="create-profile-parent"
+        >
+          quality_profiles.parent
+        </label>
+        <Select
+          clearable={true}
+          id="create-profile-parent"
+          name="parentKey"
+          onChange={[Function]}
+          options={
+            Array [
+              Object {
+                "label": "none",
+                "value": "",
+              },
+              Object {
+                "label": "name",
+                "value": "key",
+              },
+            ]
+          }
+          value=""
+        />
+      </div>
+      <input
+        name="hello-ie11"
+        type="hidden"
+        value=""
+      />
+    </div>
+    <div
+      className="modal-foot"
+    >
+      <SubmitButton
+        disabled={false}
+        id="create-profile-submit"
+      >
+        create
+      </SubmitButton>
+      <ResetButtonLink
+        id="create-profile-cancel"
+        onClick={[MockFunction]}
+      >
+        cancel
+      </ResetButtonLink>
+    </div>
+  </form>
+</Modal>
+`;
+
+exports[`should render correctly: with query filter 1`] = `
+<Modal
+  contentLabel="quality_profiles.new_profile"
+  onRequestClose={[MockFunction]}
+  size="small"
+>
+  <form
+    id="create-profile-form"
+    onSubmit={[Function]}
+  >
+    <div
+      className="modal-head"
+    >
+      <h2>
+        quality_profiles.new_profile
+      </h2>
+    </div>
+    <div
+      className="modal-body"
+    >
+      <div
+        className="modal-field"
+      >
+        <label
+          htmlFor="create-profile-name"
+        >
+          name
+          <em
+            className="mandatory"
+          >
+            *
+          </em>
+        </label>
+        <input
+          autoFocus={true}
+          id="create-profile-name"
+          maxLength={100}
+          name="name"
+          onChange={[Function]}
+          required={true}
+          size={50}
+          type="text"
+          value=""
+        />
+      </div>
+      <div
+        className="modal-field"
+      >
+        <label
+          htmlFor="create-profile-language"
+        >
+          language
+          <em
+            className="mandatory"
+          >
+            *
+          </em>
+        </label>
+        <Select
+          clearable={false}
+          id="create-profile-language"
+          name="language"
+          onChange={[Function]}
+          options={
+            Array [
+              Object {
+                "label": "CSS",
+                "value": "css",
+              },
+              Object {
+                "label": "JavaScript",
+                "value": "js",
               },
             ]
           }
-          value="kr"
+          value="js"
         />
       </div>
       <div
@@ -93,6 +229,10 @@ exports[`should render correctly 1`] = `
                 "label": "none",
                 "value": "",
               },
+              Object {
+                "label": "name",
+                "value": "key",
+              },
             ]
           }
           value=""
index 380a24788b4d5044a57565949e85d906d84d01dc..7f1fec70c618b41e5b0576fac57470fe3d5e601c 100644 (file)
@@ -194,6 +194,17 @@ exports[`should show a create form 1`] = `
         },
       ]
     }
+    location={
+      Object {
+        "action": "PUSH",
+        "hash": "",
+        "key": "key",
+        "pathname": "/path",
+        "query": Object {},
+        "search": "",
+        "state": Object {},
+      }
+    }
     onClose={[Function]}
     onCreate={[Function]}
     organization="foo"