From: Wouter Admiraal Date: Thu, 19 Dec 2019 09:52:10 +0000 (+0100) Subject: SONAR-12632 Rework leak period components X-Git-Tag: 8.2.0.32929~107 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=914f3a4e69b2d5896bf71e71ee63f45d45303efe;p=sonarqube.git SONAR-12632 Rework leak period components --- diff --git a/server/sonar-web/src/main/js/apps/overview/branches/ApplicationLeakPeriodInfo.tsx b/server/sonar-web/src/main/js/apps/overview/branches/ApplicationLeakPeriodInfo.tsx new file mode 100644 index 00000000000..1d27c582616 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/branches/ApplicationLeakPeriodInfo.tsx @@ -0,0 +1,46 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 { translateWithParameters } from 'sonar-ui-common/helpers/l10n'; +import DateFromNow from '../../../components/intl/DateFromNow'; +import { ApplicationPeriod } from '../../../types/application'; + +export interface ApplicationLeakPeriodInfoProps { + leakPeriod: ApplicationPeriod; +} + +export function ApplicationLeakPeriodInfo({ leakPeriod }: ApplicationLeakPeriodInfoProps) { + return ( + <> +
+ {translateWithParameters('overview.max_new_code_period_from_x', leakPeriod.projectName)} +
+ + {fromNow => ( +
+ {translateWithParameters('overview.started_x', fromNow)} +
+ )} +
+ + ); +} + +export default React.memo(ApplicationLeakPeriodInfo); diff --git a/server/sonar-web/src/main/js/apps/overview/branches/LeakPeriodInfo.tsx b/server/sonar-web/src/main/js/apps/overview/branches/LeakPeriodInfo.tsx new file mode 100644 index 00000000000..46dc08d95fc --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/branches/LeakPeriodInfo.tsx @@ -0,0 +1,38 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 { isApplicationPeriod } from '../../../helpers/periods'; +import { ApplicationPeriod } from '../../../types/application'; +import ApplicationLeakPeriodInfo from './ApplicationLeakPeriodInfo'; +import ProjectLeakPeriodInfo from './ProjectLeakPeriodInfo'; + +export interface LeakPeriodInfoProps { + leakPeriod: T.Period | ApplicationPeriod; +} + +export function LeakPeriodInfo({ leakPeriod }: LeakPeriodInfoProps) { + if (isApplicationPeriod(leakPeriod)) { + return ; + } else { + return ; + } +} + +export default React.memo(LeakPeriodInfo); diff --git a/server/sonar-web/src/main/js/apps/overview/branches/ProjectLeakPeriodInfo.tsx b/server/sonar-web/src/main/js/apps/overview/branches/ProjectLeakPeriodInfo.tsx new file mode 100644 index 00000000000..60728b5ed16 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/branches/ProjectLeakPeriodInfo.tsx @@ -0,0 +1,79 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 { InjectedIntl, injectIntl } from 'react-intl'; +import { translateWithParameters } from 'sonar-ui-common/helpers/l10n'; +import { longFormatterOption } from '../../../components/intl/DateFormatter'; +import DateFromNow from '../../../components/intl/DateFromNow'; +import { formatterOption } from '../../../components/intl/DateTimeFormatter'; +import { getPeriodDate, getPeriodLabel } from '../../../helpers/periods'; + +export interface ProjectLeakPeriodInfoProps { + intl: Pick; + leakPeriod: T.Period; +} + +export function ProjectLeakPeriodInfo(props: ProjectLeakPeriodInfoProps) { + const { + intl: { formatDate, formatTime }, + leakPeriod + } = props; + + const leakPeriodLabel = getPeriodLabel( + leakPeriod, + ['manual_baseline', 'SPECIFIC_ANALYSIS'].includes(leakPeriod.mode) + ? (date: string) => formatTime(date, formatterOption) + : (date: string) => formatDate(date, longFormatterOption) + ); + + if (!leakPeriodLabel) { + return null; + } + + if (leakPeriod.mode === 'days' || leakPeriod.mode === 'NUMBER_OF_DAYS') { + return
{leakPeriodLabel}
; + } + + const leakPeriodDate = getPeriodDate(leakPeriod); + + if (!leakPeriodDate) { + return null; + } + + return ( + <> +
{leakPeriodLabel}
+ + {fromNow => ( +
+ {translateWithParameters( + leakPeriod.mode === 'previous_analysis' + ? 'overview.previous_analysis_x' + : 'overview.started_x', + fromNow + )} +
+ )} +
+ + ); +} + +export default React.memo(injectIntl(ProjectLeakPeriodInfo)); diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ApplicationLeakPeriodInfo-test.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ApplicationLeakPeriodInfo-test.tsx new file mode 100644 index 00000000000..49a5368570d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ApplicationLeakPeriodInfo-test.tsx @@ -0,0 +1,38 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockApplicationPeriod } from '../../../../helpers/mocks/application'; +import { + ApplicationLeakPeriodInfo, + ApplicationLeakPeriodInfoProps +} from '../ApplicationLeakPeriodInfo'; + +jest.mock('../../../../components/intl/DateFromNow'); + +it('renders correctly', () => { + const wrapper = shallowRender(); + expect(wrapper).toMatchSnapshot(); + expect(wrapper.find('DateFromNow').dive()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/LeakPeriodInfo-test.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/LeakPeriodInfo-test.tsx new file mode 100644 index 00000000000..a6a8860f43f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/LeakPeriodInfo-test.tsx @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockApplicationPeriod } from '../../../../helpers/mocks/application'; +import { mockPeriod } from '../../../../helpers/testMocks'; +import { LeakPeriodInfo, LeakPeriodInfoProps } from '../LeakPeriodInfo'; + +it('renders correctly for projects', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +it('renders correctly for applications', () => { + expect(shallowRender({ leakPeriod: mockApplicationPeriod() })).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ProjectLeakPeriodInfo-test.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ProjectLeakPeriodInfo-test.tsx new file mode 100644 index 00000000000..862b9a9b22c --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ProjectLeakPeriodInfo-test.tsx @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 { differenceInDays } from 'date-fns'; +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockPeriod } from '../../../../helpers/testMocks'; +import { ProjectLeakPeriodInfo } from '../ProjectLeakPeriodInfo'; + +jest.mock('date-fns/difference_in_days', () => jest.fn().mockReturnValue(10)); + +it('should render correctly for 10 days', () => { + expect(shallowRender({ mode: 'days', parameter: '10' })).toMatchSnapshot(); +}); + +it('should render correctly for a specific date', () => { + expect(shallowRender({ mode: 'date', parameter: '2013-01-01' })).toMatchSnapshot(); +}); + +it('should render correctly for a specific version', () => { + expect(shallowRender({ mode: 'version', parameter: '0.1' })).toMatchSnapshot(); +}); + +it('should render correctly for "previous_version"', () => { + expect(shallowRender({ mode: 'previous_version' })).toMatchSnapshot(); +}); + +it('should render correctly for "previous_analysis"', () => { + expect(shallowRender({ mode: 'previous_analysis' })).toMatchSnapshot(); +}); + +it('should render correctly for "manual_baseline"', () => { + expect(shallowRender({ mode: 'manual_baseline' })).toMatchSnapshot(); + expect(shallowRender({ mode: 'manual_baseline', parameter: '1.1.2' })).toMatchSnapshot(); +}); + +it('should render a more precise date', () => { + (differenceInDays as jest.Mock).mockReturnValueOnce(0); + expect( + shallowRender({ date: '2018-08-17T00:00:00+0200', mode: 'previous_version' }) + ).toMatchSnapshot(); +}); + +function shallowRender(period: Partial = {}) { + return shallow( + 'formatted.' + date, + formatTime: (date: string) => 'formattedTime.' + date + }} + leakPeriod={mockPeriod({ ...period })} + /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/ApplicationLeakPeriodLegend-test.tsx b/server/sonar-web/src/main/js/apps/overview/components/__tests__/ApplicationLeakPeriodLegend-test.tsx deleted file mode 100644 index 5ffe6553440..00000000000 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/ApplicationLeakPeriodLegend-test.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import ApplicationLeakPeriodLegend from '../ApplicationLeakPeriodLegend'; - -jest.mock('../../../../api/application', () => ({ - getApplicationLeak: jest.fn(() => - Promise.resolve([ - { date: '2017-01-01T11:39:03+0100', project: 'foo', projectName: 'Foo' }, - { date: '2017-02-01T11:39:03+0100', project: 'bar', projectName: 'Bar' } - ]) - ) -})); - -it('renders', async () => { - const wrapper = shallow( - - ); - expect(wrapper).toMatchSnapshot(); - - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/ApplicationLeakPeriodLegend-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/ApplicationLeakPeriodLegend-test.tsx.snap deleted file mode 100644 index c01087c5fcf..00000000000 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/ApplicationLeakPeriodLegend-test.tsx.snap +++ /dev/null @@ -1,65 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renders 1`] = ` - - } -> -
- issues.max_new_code_period - : - -
-
-`; - -exports[`renders 2`] = ` - -
  • - Foo - : - -
  • -
  • - Bar - : - -
  • - - } -> -
    - issues.max_new_code_period - : - - - - -
    - - from - : - Foo - -
    -
    -`; diff --git a/server/sonar-web/src/main/js/helpers/periods.ts b/server/sonar-web/src/main/js/helpers/periods.ts index 70dda7212ba..8d714909592 100644 --- a/server/sonar-web/src/main/js/helpers/periods.ts +++ b/server/sonar-web/src/main/js/helpers/periods.ts @@ -19,6 +19,7 @@ */ import { parseDate } from 'sonar-ui-common/helpers/dates'; import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; +import { ApplicationPeriod } from '../types/application'; function getPeriod(periods: T[] | undefined, index: number) { if (!Array.isArray(periods)) { @@ -71,3 +72,9 @@ export function getPeriodLabel( export function getPeriodDate(period?: { date?: string }): Date | undefined { return period && period.date ? parseDate(period.date) : undefined; } + +export function isApplicationPeriod( + period: T.Period | ApplicationPeriod +): period is ApplicationPeriod { + return (period as ApplicationPeriod).project !== undefined; +}