aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src
diff options
context:
space:
mode:
authorGuillaume Peoc'h <guillaume.peoch@sonarsource.com>2022-04-01 14:10:42 +0200
committersonartech <sonartech@sonarsource.com>2022-04-05 20:03:16 +0000
commit58bb357d33d2813fd00b7f1345db18df3503a6be (patch)
treee81707955bf62f0818a218d152c2e41f9fa045b9 /server/sonar-web/src
parent052a4458e6225349fedb8a6ebd03347cd12a4753 (diff)
downloadsonarqube-58bb357d33d2813fd00b7f1345db18df3503a6be.tar.gz
sonarqube-58bb357d33d2813fd00b7f1345db18df3503a6be.zip
SONAR-16225 Update SelectLegacy in /quality-gates
Diffstat (limited to 'server/sonar-web/src')
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx66
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx11
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx12
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap95
5 files changed, 117 insertions, 73 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx
index ce6879efa16..7ff3701a4ba 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx
@@ -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)}
/>
);
}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx
index ea2f2fbd70c..47c6190c801 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx
@@ -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>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx
index 8aada4ac303..612607f9c19 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx
@@ -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' }));
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx
index 9e10425c133..da50d58ab68 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx
@@ -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> = {}) {
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap
index 5994dbc36f5..f11d813ff89 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap
@@ -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>