]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-15695 Selection input changes for QG and QP pages
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Wed, 2 Feb 2022 16:41:23 +0000 (17:41 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 7 Feb 2022 20:02:53 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModal.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModal-test.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModal-test.tsx.snap
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap
server/sonar-web/src/main/js/apps/quality-profiles/details/ProfilePermissionsFormSelect.tsx
server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfilePermissionsFormSelect-test.tsx

index 38a4440e6d97f15495ec903d4fb4b00fb8d1d07e..de564c13adb8c4988e88fffccf72472c240ae424 100644 (file)
@@ -33,7 +33,7 @@ interface Props {
 
 interface State {
   loading: boolean;
-  query?: string;
+  query: string;
   searchResults: Array<UserBase | Group>;
   selection?: UserBase | Group;
 }
@@ -44,6 +44,7 @@ export default class QualityGatePermissionsAddModal extends React.Component<Prop
   mounted = false;
   state: State = {
     loading: false,
+    query: '',
     searchResults: []
   };
 
@@ -53,7 +54,9 @@ export default class QualityGatePermissionsAddModal extends React.Component<Prop
   }
 
   componentDidMount() {
+    const { query } = this.state;
     this.mounted = true;
+    this.handleSearch(query);
   }
 
   componentWillUnmount() {
@@ -85,10 +88,11 @@ export default class QualityGatePermissionsAddModal extends React.Component<Prop
     }
   };
 
-  handleInputChange = (query: string) => {
-    this.setState({ query });
-    if (query.length > 1) {
-      this.handleSearch(query);
+  handleInputChange = (newQuery: string) => {
+    const { query } = this.state;
+    if (query !== newQuery) {
+      this.setState({ query: newQuery });
+      this.handleSearch(newQuery);
     }
   };
 
index 07fb8b9ce3cba61c6385329f0bdc93456f4ff286..441f47666fd720a79782105e1db2c613b1dd9535 100644 (file)
@@ -23,7 +23,7 @@ import Modal from '../../../components/controls/Modal';
 import SelectLegacy from '../../../components/controls/SelectLegacy';
 import GroupIcon from '../../../components/icons/GroupIcon';
 import Avatar from '../../../components/ui/Avatar';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { translate } from '../../../helpers/l10n';
 import { Group, isUser } from '../../../types/quality-gates';
 import { UserBase } from '../../../types/types';
 
@@ -44,12 +44,11 @@ type Option = (UserBase | Group) & { value: string };
 export default function QualityGatePermissionsAddModalRenderer(
   props: QualityGatePermissionsAddModalRendererProps
 ) {
-  const { loading, query = '', searchResults, selection, submitting } = props;
+  const { loading, searchResults, selection, submitting } = props;
 
   const header = translate('quality_gates.permissions.grant');
 
-  const noResultsText =
-    query.length === 1 ? translateWithParameters('select2.tooShort', 2) : translate('no_results');
+  const noResultsText = translate('no_results');
 
   return (
     <Modal contentLabel={header} onRequestClose={props.onClose}>
index 9dfb39ca32ae4c090e91d0271527b9fbba1904e5..7ad0b1cecf64eeaa8485806a3aaf0ec732867a4e 100644 (file)
@@ -38,12 +38,31 @@ it('should render correctly', () => {
   expect(shallowRender()).toMatchSnapshot();
 });
 
+it('should fetch users and groups on mount', async () => {
+  (searchUsers as jest.Mock).mockResolvedValue({ users: [mockUserBase()] });
+  (searchGroups as jest.Mock).mockResolvedValue({ groups: [{ name: 'group' }] });
+
+  const wrapper = shallowRender();
+
+  expect(wrapper.state().loading).toBe(true);
+
+  await waitAndUpdate(wrapper);
+
+  expect(wrapper.state().loading).toBe(false);
+  expect(searchUsers).toBeCalledWith({ gateName: 'qualitygate', q: '', selected: 'deselected' });
+  expect(searchGroups).toBeCalledWith({
+    gateName: 'qualitygate',
+    q: '',
+    selected: 'deselected'
+  });
+  expect(wrapper.state().searchResults).toHaveLength(2);
+});
+
 it('should fetch users and groups', async () => {
   (searchUsers as jest.Mock).mockResolvedValueOnce({ users: [mockUserBase()] });
   (searchGroups as jest.Mock).mockResolvedValueOnce({ groups: [{ name: 'group' }] });
 
   const wrapper = shallowRender();
-
   const query = 'query';
 
   wrapper.instance().handleSearch(query);
@@ -71,13 +90,19 @@ it('should handle input change', () => {
   wrapper.instance().handleInputChange('a');
 
   expect(wrapper.state().query).toBe('a');
-  expect(handleSearch).not.toBeCalled();
+  expect(handleSearch).toBeCalled();
 
   const query = 'query';
   wrapper.instance().handleInputChange(query);
 
   expect(wrapper.state().query).toBe(query);
   expect(handleSearch).toBeCalledWith(query);
+
+  jest.clearAllMocks();
+  wrapper.instance().handleInputChange(query); // input change with same parameter
+
+  expect(wrapper.state().query).toBe(query);
+  expect(handleSearch).not.toBeCalled();
 });
 
 it('should handleSelection', () => {
index e4f85804b4828a675725580355dc8d93bdeb26bc..360a11c6027301b62fba280c4a6978154afc0246 100644 (file)
@@ -2,7 +2,7 @@
 
 exports[`should render correctly 1`] = `
 <QualityGatePermissionsAddModalRenderer
-  loading={false}
+  loading={true}
   onClose={[MockFunction]}
   onInputChange={[Function]}
   onSelection={[Function]}
index 7be52876dcf1cae3d618db49edb75ff82fffa98c..d479967b848b85a934886a68a38ed2d332883d06 100644 (file)
@@ -223,7 +223,7 @@ exports[`should render correctly: short query 1`] = `
           clearable={false}
           filterOptions={[Function]}
           isLoading={false}
-          noResultsText="select2.tooShort.2"
+          noResultsText="no_results"
           onChange={[MockFunction]}
           onInputChange={[MockFunction]}
           optionRenderer={[Function]}
index 884a3c05f8bbfe0aea84355f8046d1c52e03c1e0..a88e17f798fcfd5731eaee2228e56467aa8591d4 100644 (file)
@@ -22,7 +22,7 @@ import * as React from 'react';
 import SelectLegacy from '../../../components/controls/SelectLegacy';
 import GroupIcon from '../../../components/icons/GroupIcon';
 import Avatar from '../../../components/ui/Avatar';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { translate } from '../../../helpers/l10n';
 import { UserSelected } from '../../../types/types';
 import { Group } from './ProfilePermissions';
 
@@ -75,18 +75,16 @@ export default class ProfilePermissionsFormSelect extends React.PureComponent<Pr
     );
   };
 
-  handleInputChange = (query: string) => {
-    this.setState({ query });
-    if (query.length > 1) {
-      this.handleSearch(query);
+  handleInputChange = (newQuery: string) => {
+    const { query } = this.state;
+    if (query !== newQuery) {
+      this.setState({ query: newQuery });
+      this.handleSearch(newQuery);
     }
   };
 
   render() {
-    const noResultsText =
-      this.state.query.length === 1
-        ? translateWithParameters('select2.tooShort', 2)
-        : translate('no_results');
+    const noResultsText = translate('no_results');
 
     // create a uniq string both for users and groups
     const options = this.state.searchResults.map(r => ({ ...r, value: getStringValue(r) }));
index 235dc67aeb82583a0453a91fe22412e25fbc7fbe..9b4fbf37955ae7303d1be2fb282a04bc2e56a943 100644 (file)
@@ -52,8 +52,13 @@ it('searches', () => {
   onSearch.mockClear();
 
   wrapper.prop<Function>('onInputChange')('f');
-  expect(onSearch).not.toBeCalled();
+  expect(onSearch).toBeCalled();
 
   wrapper.prop<Function>('onInputChange')('foo');
   expect(onSearch).toBeCalledWith('foo');
+
+  onSearch.mockClear();
+
+  wrapper.prop<Function>('onInputChange')('foo');
+  expect(onSearch).not.toBeCalled();
 });