Browse Source

SONAR-12620 Auto-select the language when creating a Quality Profile

tags/8.5.0.37579
Jonathan Weibel 3 years ago
parent
commit
ad13f53308

+ 8
- 4
server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx View 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}
/>

+ 2
- 1
server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.tsx View 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>;

+ 4
- 2
server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx View 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}

+ 13
- 5
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/CreateProfileForm-test.tsx View 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}
/>
);

+ 7
- 1
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/PageHeader-test.tsx View File

@@ -20,7 +20,12 @@
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()}

+ 144
- 4
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/CreateProfileForm-test.tsx.snap View 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=""

+ 11
- 0
server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/PageHeader-test.tsx.snap View 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"

Loading…
Cancel
Save