From: Stas Vilchik Date: Wed, 10 Jan 2018 16:43:55 +0000 (+0100) Subject: SONAR-10244 Warning message should disappear when first analysis is in progress X-Git-Tag: 7.0-RC1~25 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=2eafea5266c44d3c0334437e6fb6d8efe2bc20b8;p=sonarqube.git SONAR-10244 Warning message should disappear when first analysis is in progress --- diff --git a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx index eb02ba1d579..4e6a5c1ee97 100644 --- a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx @@ -24,10 +24,12 @@ import ComponentNav from './nav/component/ComponentNav'; import { Branch, Component } from '../types'; import handleRequiredAuthorization from '../utils/handleRequiredAuthorization'; import { getBranches } from '../../api/branches'; +import { Task, getTasksForComponent } from '../../api/ce'; import { getComponentData } from '../../api/components'; import { getComponentNavigation } from '../../api/nav'; import { fetchOrganizations } from '../../store/rootActions'; import { areThereCustomOrganizations } from '../../store/rootReducer'; +import { STATUSES } from '../../apps/background-tasks/constants'; interface Props { children: any; @@ -42,6 +44,9 @@ interface State { branches: Branch[]; loading: boolean; component: Component | null; + currentTask?: Task; + isInProgress?: boolean; + isPending?: boolean; } export class ComponentContainer extends React.PureComponent { @@ -102,6 +107,8 @@ export class ComponentContainer extends React.PureComponent { this.setState({ loading: false, branches, component }); } }, onError); + + this.fetchStatus(component); }, onError ); @@ -112,6 +119,21 @@ export class ComponentContainer extends React.PureComponent { return project ? getBranches(project.key) : Promise.resolve([]); }; + fetchStatus = (component: Component) => { + getTasksForComponent(component.key).then( + ({ current, queue }) => { + if (this.mounted) { + this.setState({ + currentTask: current, + isInProgress: queue.some(task => task.status === STATUSES.IN_PROGRESS), + isPending: queue.some(task => task.status === STATUSES.PENDING) + }); + } + }, + () => {} + ); + }; + handleComponentChange = (changes: {}) => { if (this.mounted) { this.setState(state => ({ component: { ...state.component, ...changes } })); @@ -149,6 +171,9 @@ export class ComponentContainer extends React.PureComponent { branches={branches} currentBranch={branch} component={component} + currentTask={this.state.currentTask} + isInProgress={this.state.isInProgress} + isPending={this.state.isPending} location={this.props.location} /> )} @@ -161,6 +186,8 @@ export class ComponentContainer extends React.PureComponent { branch, branches, component, + isInProgress: this.state.isInProgress, + isPending: this.state.isPending, onBranchesChange: this.handleBranchesChange, onComponentChange: this.handleComponentChange }) diff --git a/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx index 1ba8962fcbb..9fc7e3d7925 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx @@ -21,17 +21,22 @@ import * as React from 'react'; import { shallow, mount } from 'enzyme'; import { ComponentContainer } from '../ComponentContainer'; import { getBranches } from '../../../api/branches'; +import { getTasksForComponent } from '../../../api/ce'; import { getComponentData } from '../../../api/components'; import { getComponentNavigation } from '../../../api/nav'; jest.mock('../../../api/branches', () => ({ getBranches: jest.fn(() => Promise.resolve([])) })); +jest.mock('../../../api/ce', () => ({ + getTasksForComponent: jest.fn(() => Promise.resolve({ queue: [] })) +})); jest.mock('../../../api/components', () => ({ getComponentData: jest.fn(() => Promise.resolve({})) })); jest.mock('../../../api/nav', () => ({ getComponentNavigation: jest.fn(() => Promise.resolve({ - breadcrumbs: [{ key: 'portfolioKey', name: 'portfolio', qualifier: 'VW' }] + breadcrumbs: [{ key: 'portfolioKey', name: 'portfolio', qualifier: 'VW' }], + key: 'portfolioKey' }) ) })); @@ -47,6 +52,7 @@ beforeEach(() => { (getBranches as jest.Mock).mockClear(); (getComponentData as jest.Mock).mockClear(); (getComponentNavigation as jest.Mock).mockClear(); + (getTasksForComponent as jest.Mock).mockClear(); }); it('changes component', () => { @@ -137,3 +143,21 @@ it('loads organization', async () => { await new Promise(setImmediate); expect(fetchOrganizations).toBeCalledWith(['org']); }); + +it('fetches status', async () => { + (getComponentData as jest.Mock).mockImplementationOnce(() => + Promise.resolve({ organization: 'org' }) + ); + + mount( + + + + ); + + await new Promise(setImmediate); + expect(getTasksForComponent).toBeCalledWith('portfolioKey'); +}); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx index 39925c34c99..727d2f19d5f 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx @@ -26,7 +26,7 @@ import RecentHistory from '../../RecentHistory'; import * as theme from '../../../theme'; import { Branch, Component } from '../../../types'; import ContextNavBar from '../../../../components/nav/ContextNavBar'; -import { getTasksForComponent, PendingTask, Task } from '../../../../api/ce'; +import { Task } from '../../../../api/ce'; import { STATUSES } from '../../../../apps/background-tasks/constants'; import './ComponentNav.css'; @@ -34,52 +34,25 @@ interface Props { branches: Branch[]; currentBranch?: Branch; component: Component; - location: {}; -} - -interface State { currentTask?: Task; isInProgress?: boolean; isPending?: boolean; + location: {}; } -export default class ComponentNav extends React.PureComponent { +export default class ComponentNav extends React.PureComponent { mounted: boolean; - state: State = {}; - componentDidMount() { - this.mounted = true; - this.loadStatus(); this.populateRecentHistory(); } componentDidUpdate(prevProps: Props) { if (this.props.component.key !== prevProps.component.key) { - this.loadStatus(); this.populateRecentHistory(); } } - componentWillUnmount() { - this.mounted = false; - } - - loadStatus = () => { - getTasksForComponent(this.props.component.key).then( - (r: { queue: PendingTask[]; current: Task }) => { - if (this.mounted) { - this.setState({ - currentTask: r.current, - isInProgress: r.queue.some(task => task.status === STATUSES.IN_PROGRESS), - isPending: r.queue.some(task => task.status === STATUSES.PENDING) - }); - } - }, - () => {} - ); - }; - populateRecentHistory = () => { const { breadcrumbs } = this.props.component; const { qualifier } = breadcrumbs[breadcrumbs.length - 1]; @@ -94,7 +67,7 @@ export default class ComponentNav extends React.PureComponent { }; render() { - const { currentTask, isInProgress, isPending } = this.state; + const { currentTask, isInProgress, isPending } = this.props; let notifComponent; if (isInProgress || isPending || (currentTask && currentTask.status === STATUSES.FAILED)) { notifComponent = ( diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx index 4c30ef3b3a4..69d57e25d67 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx @@ -17,44 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* eslint-disable import/order */ import * as React from 'react'; -import { mount, shallow } from 'enzyme'; +import { shallow } from 'enzyme'; import ComponentNav from '../ComponentNav'; -jest.mock('../ComponentNavMeta', () => ({ - // eslint-disable-next-line - default: function ComponentNavMeta() { - return null; - } -})); - -jest.mock('../ComponentNavHeader', () => ({ - // eslint-disable-next-line - default: function ComponentNavHeader() { - return null; - } -})); - -jest.mock('../ComponentNavMenu', () => ({ - // eslint-disable-next-line - default: function ComponentNavMenu() { - return null; - } -})); - -jest.mock('../../../RecentHistory', () => ({ - default: { add: jest.fn() } -})); - -jest.mock('../../../../../api/ce', () => ({ - getTasksForComponent: jest.fn(() => Promise.resolve({ queue: [] })) -})); - -const getTasksForComponent = require('../../../../../api/ce').getTasksForComponent as jest.Mock< - any ->; - const component = { breadcrumbs: [{ key: 'component', name: 'component', qualifier: 'TRK' }], key: 'component', @@ -63,12 +29,6 @@ const component = { qualifier: 'TRK' }; -it('loads status', () => { - getTasksForComponent.mockClear(); - mount(); - expect(getTasksForComponent).toBeCalledWith('component'); -}); - it('renders', () => { const wrapper = shallow(); wrapper.setState({ isInProgress: true, isPending: true }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap index 25470b77544..e52606979cf 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap @@ -2,32 +2,10 @@ exports[`renders 1`] = ` - } > - - , organization?: string }, + isInProgress?: bool, + isPending?: bool, onComponentChange: {} => void, router: Object }; @@ -83,7 +85,12 @@ export default class App extends React.PureComponent { } if (!component.analysisDate) { - return ; + return ( + + ); } return ( diff --git a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.js b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.js deleted file mode 100644 index 634d019eb57..00000000000 --- a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -// @flow -import React from 'react'; -import { Link } from 'react-router'; -import { translate } from '../../../helpers/l10n'; - -/*:: -type Props = { - component: { key: string } -}; -*/ - -export default function EmptyOverview({ component } /*: Props */) { - const rawMessage = translate('provisioning.no_analysis.delete'); - const head = rawMessage.substr(0, rawMessage.indexOf('{0}')); - const tail = rawMessage.substr(rawMessage.indexOf('{0}') + 3); - - return ( -
-
{translate('provisioning.no_analysis')}
- -
- {head} - - {translate('provisioning.no_analysis.delete_project')} - - {tail} -
- -
-

{translate('key')}

- {component.key} -
-
- ); -} diff --git a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx new file mode 100644 index 00000000000..0dd1b07cb15 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx @@ -0,0 +1,58 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link } from 'react-router'; +import { translate } from '../../../helpers/l10n'; + +interface Props { + component: string; + showWarning?: boolean; +} + +export default function EmptyOverview({ component, showWarning }: Props) { + const rawMessage = translate('provisioning.no_analysis.delete'); + const head = rawMessage.substr(0, rawMessage.indexOf('{0}')); + const tail = rawMessage.substr(rawMessage.indexOf('{0}') + 3); + + return ( +
+ {showWarning && ( +
+
{translate('provisioning.no_analysis')}
+ +
+ {head} + + {translate('provisioning.no_analysis.delete_project')} + + {tail} +
+
+ )} + +
+

{translate('key')}

+ {component} +
+
+ ); +} diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/EmptyOverview-test.js b/server/sonar-web/src/main/js/apps/overview/components/__tests__/EmptyOverview-test.js deleted file mode 100644 index 7dc5868d23f..00000000000 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/EmptyOverview-test.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import { shallow } from 'enzyme'; -import EmptyOverview from '../EmptyOverview'; - -it('should render component key', () => { - const component = { - id: 'id', - key: 'abcd', - analysisDate: '2016-01-01' - }; - const output = shallow(); - expect(output.find('code').text()).toBe('abcd'); -}); diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/EmptyOverview-test.tsx b/server/sonar-web/src/main/js/apps/overview/components/__tests__/EmptyOverview-test.tsx new file mode 100644 index 00000000000..eeee97a8970 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/EmptyOverview-test.tsx @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { shallow } from 'enzyme'; +import EmptyOverview from '../EmptyOverview'; + +it('renders', () => { + expect(shallow()).toMatchSnapshot(); +}); + +it('does not render warning', () => { + expect(shallow()).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap new file mode 100644 index 00000000000..824034aef44 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`does not render warning 1`] = ` +
+
+

+ key +

+ + abcd + +
+
+`; + +exports[`renders 1`] = ` +
+
+

+ key +

+ + abcd + +
+
+`;