diff options
author | Guillaume Peoc'h <guillaume.peoch@sonarsource.com> | 2022-02-02 15:36:37 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-02-09 20:02:55 +0000 |
commit | 2b13f016dee62cc813d0374e9f835dee5f4cda28 (patch) | |
tree | a14a39e129bb993ab041c8b29af4f9963bdf0002 /server/sonar-web/src/main/js/apps/projectsManagement | |
parent | 2d48cb3c1eb4f6cd68bd091c4eb9d62fa71deff8 (diff) | |
download | sonarqube-2b13f016dee62cc813d0374e9f835dee5f4cda28.tar.gz sonarqube-2b13f016dee62cc813d0374e9f835dee5f4cda28.zip |
SONAR-15909 Extract AppState Redux
Diffstat (limited to 'server/sonar-web/src/main/js/apps/projectsManagement')
4 files changed, 29 insertions, 26 deletions
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/App.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/App.tsx index 7b090bbc3ee..be9c7f03620 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/App.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/App.tsx @@ -29,10 +29,10 @@ import ListFooter from '../../components/controls/ListFooter'; import { toShortNotSoISOString } from '../../helpers/dates'; import { translate } from '../../helpers/l10n'; import { hasGlobalPermission } from '../../helpers/users'; -import { getAppState, getCurrentUser, Store } from '../../store/rootReducer'; +import { getCurrentUser, Store } from '../../store/rootReducer'; import { Permissions } from '../../types/permissions'; import { SettingsKey } from '../../types/settings'; -import { AppState, LoggedInUser, Visibility } from '../../types/types'; +import { LoggedInUser, Visibility } from '../../types/types'; import CreateProjectForm from './CreateProjectForm'; import Header from './Header'; import Projects from './Projects'; @@ -40,7 +40,6 @@ import Search from './Search'; export interface Props { currentUser: LoggedInUser; - appState: Pick<AppState, 'qualifiers'>; } interface State { @@ -198,7 +197,7 @@ export class App extends React.PureComponent<Props, State> { }; render() { - const { appState, currentUser } = this.props; + const { currentUser } = this.props; const { defaultProjectVisibility } = this.state; return ( <div className="page page-limited" id="projects-management-page"> @@ -228,7 +227,6 @@ export class App extends React.PureComponent<Props, State> { query={this.state.query} ready={this.state.ready} selection={this.state.selection} - topLevelQualifiers={appState.qualifiers} total={this.state.total} visibility={this.state.visibility} /> @@ -262,7 +260,6 @@ export class App extends React.PureComponent<Props, State> { } const mapStateToProps = (state: Store) => ({ - appState: getAppState(state), currentUser: getCurrentUser(state) as LoggedInUser }); diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/Search.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/Search.tsx index 8f47af0fdf4..4d19a37e27a 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/Search.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/Search.tsx @@ -20,6 +20,7 @@ import { sortBy } from 'lodash'; import * as React from 'react'; import { Project } from '../../api/components'; +import withAppStateContext from '../../app/components/app-state/withAppStateContext'; import { Button } from '../../components/controls/buttons'; import Checkbox from '../../components/controls/Checkbox'; import DateInput from '../../components/controls/DateInput'; @@ -28,7 +29,7 @@ import SearchBox from '../../components/controls/SearchBox'; import SelectLegacy from '../../components/controls/SelectLegacy'; import QualifierIcon from '../../components/icons/QualifierIcon'; import { translate } from '../../helpers/l10n'; -import { Visibility } from '../../types/types'; +import { AppState, Visibility } from '../../types/types'; import BulkApplyTemplateModal from './BulkApplyTemplateModal'; import DeleteModal from './DeleteModal'; @@ -48,7 +49,7 @@ export interface Props { query: string; ready: boolean; selection: any[]; - topLevelQualifiers: string[]; + appState: AppState; total: number; visibility?: Visibility; } @@ -60,12 +61,12 @@ interface State { const QUALIFIERS_ORDER = ['TRK', 'VW', 'APP']; -export default class Search extends React.PureComponent<Props, State> { +export class Search extends React.PureComponent<Props, State> { mounted = false; state: State = { bulkApplyTemplateModal: false, deleteModal: false }; getQualifierOptions = () => { - const options = this.props.topLevelQualifiers.map(q => ({ + const options = this.props.appState.qualifiers.map(q => ({ label: translate('qualifiers', q), value: q })); @@ -281,3 +282,5 @@ export default class Search extends React.PureComponent<Props, State> { ); } } + +export default withAppStateContext(Search); diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx index cc02fe3436f..653e059a155 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx @@ -22,10 +22,9 @@ import * as React from 'react'; import { getComponents } from '../../../api/components'; import { changeProjectDefaultVisibility } from '../../../api/permissions'; import { getValues } from '../../../api/settings'; -import { mockAppState, mockLoggedInUser } from '../../../helpers/testMocks'; +import { mockLoggedInUser } from '../../../helpers/testMocks'; import { waitAndUpdate } from '../../../helpers/testUtils'; import { App, Props } from '../App'; -import Search from '../Search'; jest.mock('lodash', () => { const lodash = jest.requireActual('lodash'); @@ -65,7 +64,7 @@ it('fetches all projects on mount', async () => { it('selects provisioned', () => { const wrapper = shallowRender(); - wrapper.find('Search').prop<Function>('onProvisionedChanged')(true); + wrapper.find('withAppStateContext(Search)').prop<Function>('onProvisionedChanged')(true); expect(getComponents).lastCalledWith({ ...defaultSearchParameters, onProvisionedOnly: true, @@ -76,22 +75,21 @@ it('selects provisioned', () => { it('changes qualifier and resets provisioned', () => { const wrapper = shallowRender(); wrapper.setState({ provisioned: true }); - wrapper.find('Search').prop<Function>('onQualifierChanged')('VW'); + wrapper.find('withAppStateContext(Search)').prop<Function>('onQualifierChanged')('VW'); expect(getComponents).lastCalledWith({ ...defaultSearchParameters, qualifiers: 'VW' }); }); it('searches', () => { const wrapper = shallowRender(); - wrapper.find('Search').prop<Function>('onSearch')('foo'); + wrapper.find('withAppStateContext(Search)').prop<Function>('onSearch')('foo'); expect(getComponents).lastCalledWith({ ...defaultSearchParameters, q: 'foo', qualifiers: 'TRK' }); }); it('should handle date filtering', () => { const wrapper = shallowRender(); - wrapper - .find(Search) - .props() - .onDateChanged(new Date('2019-11-14T06:55:02.663Z')); + wrapper.find('withAppStateContext(Search)').prop<Function>('onDateChanged')( + '2019-11-14T06:55:02.663Z' + ); expect(getComponents).toHaveBeenCalledWith({ ...defaultSearchParameters, qualifiers: 'TRK', @@ -138,10 +136,10 @@ it('selects and deselects projects', async () => { wrapper.find('Projects').prop<Function>('onProjectDeselected')('foo'); expect(wrapper.state('selection')).toEqual(['bar']); - wrapper.find('Search').prop<Function>('onAllDeselected')(); + wrapper.find('withAppStateContext(Search)').prop<Function>('onAllDeselected')(); expect(wrapper.state('selection')).toEqual([]); - wrapper.find('Search').prop<Function>('onAllSelected')(); + wrapper.find('withAppStateContext(Search)').prop<Function>('onAllSelected')(); expect(wrapper.state('selection')).toEqual(['foo', 'bar']); }); @@ -165,7 +163,6 @@ it('creates project', () => { function shallowRender(props?: { [P in keyof Props]?: Props[P] }) { return shallow<App>( <App - appState={mockAppState({ qualifiers: ['TRK', 'VW', 'APP'] })} currentUser={mockLoggedInUser({ login: 'foo', permissions: { global: ['provisioning'] } })} {...props} /> diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx index 11dc6ea01f0..b4e3f13b637 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx @@ -19,8 +19,9 @@ */ import { shallow } from 'enzyme'; import * as React from 'react'; +import { mockAppState } from '../../../helpers/testMocks'; import { click } from '../../../helpers/testUtils'; -import Search, { Props } from '../Search'; +import { Props, Search } from '../Search'; it('renders', () => { expect(shallowRender()).toMatchSnapshot(); @@ -37,12 +38,17 @@ it('disables the delete and bulk apply buttons unless a project is selected', () }); it('render qualifiers filter', () => { - expect(shallowRender({ topLevelQualifiers: ['TRK', 'VW', 'APP'] })).toMatchSnapshot(); + expect( + shallowRender({ appState: mockAppState({ qualifiers: ['TRK', 'VW', 'APP'] }) }) + ).toMatchSnapshot(); }); it('updates qualifier', () => { const onQualifierChanged = jest.fn(); - const wrapper = shallowRender({ onQualifierChanged, topLevelQualifiers: ['TRK', 'VW', 'APP'] }); + const wrapper = shallowRender({ + onQualifierChanged, + appState: mockAppState({ qualifiers: ['TRK', 'VW', 'APP'] }) + }); wrapper.find('SelectLegacy[name="projects-qualifier"]').prop<Function>('onChange')({ value: 'VW' }); @@ -129,7 +135,7 @@ function shallowRender(props?: { [P in keyof Props]?: Props[P] }) { query="" ready={true} selection={[]} - topLevelQualifiers={['TRK']} + appState={mockAppState({ qualifiers: ['TRK'] })} total={17} {...props} /> |