Przeglądaj źródła

SONAR-16225 Update SelectLegacy in /quality-gates

tags/9.5.0.56709
Guillaume Peoc'h 2 lat temu
rodzic
commit
58bb357d33

+ 1
- 0
server/sonar-web/package.json Wyświetl plik

@@ -127,6 +127,7 @@
"postcss-calc": "7.0.2",
"postcss-custom-properties": "9.1.1",
"prettier": "1.19.1",
"react-select-event": "5.4.0",
"remark": "11.0.2",
"remark-react": "7",
"ts-jest": "27.1.3",

+ 3
- 3
server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx Wyświetl plik

@@ -20,7 +20,7 @@
import { sortBy } from 'lodash';
import * as React from 'react';
import withMetricsContext from '../../../app/components/metrics/withMetricsContext';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import Select from '../../../components/controls/Select';
import { getLocalizedMetricDomain, translate } from '../../../helpers/l10n';
import { Dict, Metric } from '../../../types/types';
import { getLocalizedMetricNameNoDiffMetric } from '../utils';
@@ -76,13 +76,13 @@ export class MetricSelectComponent extends React.PureComponent<Props> {
});

return (
<SelectLegacy
<Select
className="text-middle quality-gate-metric-select"
id="condition-metric"
onChange={this.handleChange}
options={optionsWithDomains}
placeholder={translate('search.search_for_metrics')}
value={metric && metric.key}
value={optionsWithDomains.find(o => o.value === metric?.key)}
/>
);
}

+ 50
- 16
server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx Wyświetl plik

@@ -17,10 +17,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { identity, omit } from 'lodash';
import * as React from 'react';
import { components, ControlProps, OptionProps, SingleValueProps } from 'react-select';
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import SelectLegacy from '../../../components/controls/SelectLegacy';
import Select from '../../../components/controls/Select';
import GroupIcon from '../../../components/icons/GroupIcon';
import Avatar from '../../../components/ui/Avatar';
import { translate } from '../../../helpers/l10n';
@@ -31,7 +33,7 @@ export interface QualityGatePermissionsAddModalRendererProps {
onClose: () => void;
onInputChange: (query: string) => void;
onSubmit: (event: React.SyntheticEvent<HTMLFormElement>) => void;
onSelection: (selection: UserBase | Group) => void;
onSelection: (selection: Option) => void;
submitting: boolean;
loading: boolean;
query: string;
@@ -39,7 +41,7 @@ export interface QualityGatePermissionsAddModalRendererProps {
selection?: UserBase | Group;
}

type Option = (UserBase | Group) & { value: string };
export type Option = (UserBase | Group) & { value: string };

export default function QualityGatePermissionsAddModalRenderer(
props: QualityGatePermissionsAddModalRendererProps
@@ -50,6 +52,8 @@ export default function QualityGatePermissionsAddModalRenderer(

const noResultsText = translate('no_results');

const options = searchResults.map(r => ({ ...r, value: getValue(r) }));

return (
<Modal contentLabel={header} onRequestClose={props.onClose}>
<header className="modal-head">
@@ -59,22 +63,24 @@ export default function QualityGatePermissionsAddModalRenderer(
<div className="modal-body">
<div className="modal-field">
<label>{translate('quality_gates.permissions.search')}</label>
<SelectLegacy
autoFocus={true}
<Select
className="Select-big"
clearable={false}
// disable default react-select filtering
filterOptions={i => i}
autoFocus={true}
isClearable={false}
isSearchable={true}
placeholder=""
isLoading={loading}
noResultsText={noResultsText}
filterOptions={identity}
noOptionsMessage={() => noResultsText}
onChange={props.onSelection}
onInputChange={props.onInputChange}
optionRenderer={optionRenderer}
options={searchResults.map(r => ({ ...r, value: isUser(r) ? r.login : r.name }))}
placeholder=""
searchable={true}
value={selection}
valueRenderer={optionRenderer}
components={{
Option: optionRenderer,
SingleValue: singleValueRenderer,
Control: controlRenderer
}}
options={options}
value={options.find(o => o.value === (selection && getValue(selection)))}
/>
</div>
</div>
@@ -88,7 +94,11 @@ export default function QualityGatePermissionsAddModalRenderer(
);
}

function optionRenderer(option: Option) {
function getValue(option: UserBase | Group) {
return isUser(option) ? option.login : option.name;
}

export function customOptions(option: Option) {
return (
<>
{isUser(option) ? (
@@ -101,3 +111,27 @@ function optionRenderer(option: Option) {
</>
);
}

function optionRenderer(props: OptionProps<Option, false>) {
return (
<components.Option {...props} className="Select-option">
{customOptions(props.data)}
</components.Option>
);
}

function singleValueRenderer(props: SingleValueProps<Option>) {
return (
<components.SingleValue {...props} className="Select-value-label">
{customOptions(props.data)}
</components.SingleValue>
);
}

function controlRenderer(props: ControlProps<Option, false>) {
return (
<components.Control {...omit(props, ['children'])} className="abs-height-100 Select-control">
{props.children}
</components.Control>
);
}

+ 4
- 7
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx Wyświetl plik

@@ -19,6 +19,7 @@
*/
import { screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import selectEvent from 'react-select-event';
import { QualityGatesServiceMock } from '../../../../api/mocks/QualityGatesServiceMock';
import { mockAppState } from '../../../../helpers/testMocks';
import { renderApp } from '../../../../helpers/testReactTestingUtils';
@@ -146,8 +147,7 @@ it('should be able to add a condition', async () => {
let dialog = within(screen.getByRole('dialog'));

await user.click(dialog.getByRole('radio', { name: 'quality_gates.conditions.new_code' }));
await user.click(dialog.getByRole('combobox'));
await user.click(dialog.getByRole('option', { name: 'Issues' }));
await selectEvent.select(dialog.getByRole('textbox'), ['Issues']);
await user.click(dialog.getByRole('textbox', { name: 'quality_gates.conditions.value' }));
await user.keyboard('12{Enter}');

@@ -161,9 +161,7 @@ it('should be able to add a condition', async () => {
await user.click(await screen.findByText('quality_gates.add_condition'));

dialog = within(screen.getByRole('dialog'));

await user.click(dialog.getByLabelText('quality_gates.conditions.fails_when'));
await user.click(dialog.getByRole('option', { name: 'Info Issues' }));
await selectEvent.select(dialog.getByRole('textbox'), ['Info Issues']);
await user.click(dialog.getByRole('radio', { name: 'quality_gates.conditions.overall_code' }));
await user.click(dialog.getByLabelText('quality_gates.conditions.operator'));

@@ -183,8 +181,7 @@ it('should be able to add a condition', async () => {

dialog = within(screen.getByRole('dialog'));
await user.click(dialog.getByRole('radio', { name: 'quality_gates.conditions.overall_code' }));
await user.click(dialog.getByLabelText('quality_gates.conditions.fails_when'));
await user.click(dialog.getByRole('option', { name: 'Maintainability Rating' }));
await selectEvent.select(dialog.getByRole('textbox'), ['Maintainability Rating']);
await user.click(dialog.getByLabelText('quality_gates.conditions.value'));
await user.click(dialog.getByText('B'));
await user.click(dialog.getByRole('button', { name: 'quality_gates.add_condition' }));

+ 5
- 7
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx Wyświetl plik

@@ -19,9 +19,9 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import SelectLegacy from '../../../../components/controls/SelectLegacy';
import { mockUserBase } from '../../../../helpers/mocks/users';
import QualityGatePermissionsAddModalRenderer, {
customOptions,
QualityGatePermissionsAddModalRendererProps
} from '../QualityGatePermissionsAddModalRenderer';

@@ -38,12 +38,10 @@ it('should render correctly', () => {
});

it('should render options correctly', () => {
const wrapper = shallowRender();

const { optionRenderer = () => null } = wrapper.find(SelectLegacy).props();

expect(optionRenderer({ avatar: 'A', name: 'name', login: 'login' })).toMatchSnapshot('user');
expect(optionRenderer({ name: 'group name' })).toMatchSnapshot('group');
expect(
customOptions({ avatar: 'A', name: 'name', login: 'login', value: 'login' })
).toMatchSnapshot('user');
expect(customOptions({ name: 'group name', value: 'group name' })).toMatchSnapshot('group');
});

function shallowRender(overrides: Partial<QualityGatePermissionsAddModalRendererProps> = {}) {

+ 55
- 40
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap Wyświetl plik

@@ -24,20 +24,25 @@ exports[`should render correctly: default 1`] = `
<label>
quality_gates.permissions.search
</label>
<SelectLegacy
<Select
autoFocus={true}
className="Select-big"
clearable={false}
components={
Object {
"Control": [Function],
"Option": [Function],
"SingleValue": [Function],
}
}
filterOptions={[Function]}
isClearable={false}
isLoading={false}
noResultsText="no_results"
isSearchable={true}
noOptionsMessage={[Function]}
onChange={[MockFunction]}
onInputChange={[MockFunction]}
optionRenderer={[Function]}
options={Array []}
placeholder=""
searchable={true}
valueRenderer={[Function]}
/>
</div>
</div>
@@ -83,16 +88,23 @@ exports[`should render correctly: query and results 1`] = `
<label>
quality_gates.permissions.search
</label>
<SelectLegacy
<Select
autoFocus={true}
className="Select-big"
clearable={false}
components={
Object {
"Control": [Function],
"Option": [Function],
"SingleValue": [Function],
}
}
filterOptions={[Function]}
isClearable={false}
isLoading={false}
noResultsText="no_results"
isSearchable={true}
noOptionsMessage={[Function]}
onChange={[MockFunction]}
onInputChange={[MockFunction]}
optionRenderer={[Function]}
options={
Array [
Object {
@@ -106,8 +118,6 @@ exports[`should render correctly: query and results 1`] = `
]
}
placeholder=""
searchable={true}
valueRenderer={[Function]}
/>
</div>
</div>
@@ -153,25 +163,25 @@ exports[`should render correctly: selection 1`] = `
<label>
quality_gates.permissions.search
</label>
<SelectLegacy
<Select
autoFocus={true}
className="Select-big"
clearable={false}
components={
Object {
"Control": [Function],
"Option": [Function],
"SingleValue": [Function],
}
}
filterOptions={[Function]}
isClearable={false}
isLoading={false}
noResultsText="no_results"
isSearchable={true}
noOptionsMessage={[Function]}
onChange={[MockFunction]}
onInputChange={[MockFunction]}
optionRenderer={[Function]}
options={Array []}
placeholder=""
searchable={true}
value={
Object {
"login": "userlogin",
}
}
valueRenderer={[Function]}
/>
</div>
</div>
@@ -217,20 +227,25 @@ exports[`should render correctly: short query 1`] = `
<label>
quality_gates.permissions.search
</label>
<SelectLegacy
<Select
autoFocus={true}
className="Select-big"
clearable={false}
components={
Object {
"Control": [Function],
"Option": [Function],
"SingleValue": [Function],
}
}
filterOptions={[Function]}
isClearable={false}
isLoading={false}
noResultsText="no_results"
isSearchable={true}
noOptionsMessage={[Function]}
onChange={[MockFunction]}
onInputChange={[MockFunction]}
optionRenderer={[Function]}
options={Array []}
placeholder=""
searchable={true}
valueRenderer={[Function]}
/>
</div>
</div>
@@ -276,25 +291,25 @@ exports[`should render correctly: submitting 1`] = `
<label>
quality_gates.permissions.search
</label>
<SelectLegacy
<Select
autoFocus={true}
className="Select-big"
clearable={false}
components={
Object {
"Control": [Function],
"Option": [Function],
"SingleValue": [Function],
}
}
filterOptions={[Function]}
isClearable={false}
isLoading={false}
noResultsText="no_results"
isSearchable={true}
noOptionsMessage={[Function]}
onChange={[MockFunction]}
onInputChange={[MockFunction]}
optionRenderer={[Function]}
options={Array []}
placeholder=""
searchable={true}
value={
Object {
"login": "userlogin",
}
}
valueRenderer={[Function]}
/>
</div>
</div>

+ 26
- 0
server/sonar-web/yarn.lock Wyświetl plik

@@ -2722,6 +2722,22 @@ __metadata:
languageName: node
linkType: hard

"@testing-library/dom@npm:>=7":
version: 8.12.0
resolution: "@testing-library/dom@npm:8.12.0"
dependencies:
"@babel/code-frame": ^7.10.4
"@babel/runtime": ^7.12.5
"@types/aria-query": ^4.2.0
aria-query: ^5.0.0
chalk: ^4.1.0
dom-accessibility-api: ^0.5.9
lz-string: ^1.4.4
pretty-format: ^27.0.2
checksum: 2bbf5fa5c1e883571c440ccee76c0568fa5153b43c097456dd7146797256687352bfca9db574e0e78a022ce14722a6acaaba5f680ee16b95e12405501713d34d
languageName: node
linkType: hard

"@testing-library/jest-dom@npm:5.16.2":
version: 5.16.2
resolution: "@testing-library/jest-dom@npm:5.16.2"
@@ -3612,6 +3628,7 @@ __metadata:
react-redux: 5.1.1
react-router: 3.2.6
react-select: 4.3.1
react-select-event: 5.4.0
react-select-legacy: "npm:react-select@1.2.1"
react-virtualized: 9.22.3
redux: 4.1.2
@@ -10600,6 +10617,15 @@ __metadata:
languageName: node
linkType: hard

"react-select-event@npm:5.4.0":
version: 5.4.0
resolution: "react-select-event@npm:5.4.0"
dependencies:
"@testing-library/dom": ">=7"
checksum: 244b1bdff5374b56a7d8156859a10dfd3191573ac419a8f91a64283cde48517df83c90f2df1891fc74bceb548d21ace9a9cb87e252bf2f83f78e305ea577af53
languageName: node
linkType: hard

"react-select-legacy@npm:react-select@1.2.1":
version: 1.2.1
resolution: "react-select@npm:1.2.1"

Ładowanie…
Anuluj
Zapisz