From 914f3a4e69b2d5896bf71e71ee63f45d45303efe Mon Sep 17 00:00:00 2001 From: Wouter Admiraal Date: Thu, 19 Dec 2019 10:52:10 +0100 Subject: [PATCH] SONAR-12632 Rework leak period components --- .../branches/ApplicationLeakPeriodInfo.tsx | 46 +++++++++++ .../apps/overview/branches/LeakPeriodInfo.tsx | 38 +++++++++ .../branches/ProjectLeakPeriodInfo.tsx | 79 +++++++++++++++++++ .../ApplicationLeakPeriodInfo-test.tsx} | 32 +++----- .../__tests__/LeakPeriodInfo-test.tsx | 36 +++++++++ .../__tests__/ProjectLeakPeriodInfo-test.tsx | 70 ++++++++++++++++ .../ApplicationLeakPeriodLegend-test.tsx.snap | 65 --------------- .../sonar-web/src/main/js/helpers/periods.ts | 7 ++ 8 files changed, 289 insertions(+), 84 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/overview/branches/ApplicationLeakPeriodInfo.tsx create mode 100644 server/sonar-web/src/main/js/apps/overview/branches/LeakPeriodInfo.tsx create mode 100644 server/sonar-web/src/main/js/apps/overview/branches/ProjectLeakPeriodInfo.tsx rename server/sonar-web/src/main/js/apps/overview/{components/__tests__/ApplicationLeakPeriodLegend-test.tsx => branches/__tests__/ApplicationLeakPeriodInfo-test.tsx} (58%) create mode 100644 server/sonar-web/src/main/js/apps/overview/branches/__tests__/LeakPeriodInfo-test.tsx create mode 100644 server/sonar-web/src/main/js/apps/overview/branches/__tests__/ProjectLeakPeriodInfo-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/ApplicationLeakPeriodLegend-test.tsx.snap 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/components/__tests__/ApplicationLeakPeriodLegend-test.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ApplicationLeakPeriodInfo-test.tsx similarity index 58% rename from server/sonar-web/src/main/js/apps/overview/components/__tests__/ApplicationLeakPeriodLegend-test.tsx rename to server/sonar-web/src/main/js/apps/overview/branches/__tests__/ApplicationLeakPeriodInfo-test.tsx index 5ffe6553440..49a5368570d 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/ApplicationLeakPeriodLegend-test.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ApplicationLeakPeriodInfo-test.tsx @@ -19,26 +19,20 @@ */ import { shallow } from 'enzyme'; import * as React from 'react'; -import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import ApplicationLeakPeriodLegend from '../ApplicationLeakPeriodLegend'; +import { mockApplicationPeriod } from '../../../../helpers/mocks/application'; +import { + ApplicationLeakPeriodInfo, + ApplicationLeakPeriodInfoProps +} from '../ApplicationLeakPeriodInfo'; -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' } - ]) - ) -})); +jest.mock('../../../../components/intl/DateFromNow'); -it('renders', async () => { - const wrapper = shallow( - - ); - expect(wrapper).toMatchSnapshot(); - - await waitAndUpdate(wrapper); +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__/__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; +} -- 2.39.5