--- /dev/null
+/*
+ * 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 (
+ <>
+ <div className="note spacer-top">
+ {translateWithParameters('overview.max_new_code_period_from_x', leakPeriod.projectName)}
+ </div>
+ <DateFromNow date={leakPeriod.date}>
+ {fromNow => (
+ <div className="note little-spacer-top">
+ {translateWithParameters('overview.started_x', fromNow)}
+ </div>
+ )}
+ </DateFromNow>
+ </>
+ );
+}
+
+export default React.memo(ApplicationLeakPeriodInfo);
--- /dev/null
+/*
+ * 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 <ApplicationLeakPeriodInfo leakPeriod={leakPeriod} />;
+ } else {
+ return <ProjectLeakPeriodInfo leakPeriod={leakPeriod} />;
+ }
+}
+
+export default React.memo(LeakPeriodInfo);
--- /dev/null
+/*
+ * 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<InjectedIntl, 'formatDate' | 'formatTime'>;
+ 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 <div className="note spacer-top">{leakPeriodLabel} </div>;
+ }
+
+ const leakPeriodDate = getPeriodDate(leakPeriod);
+
+ if (!leakPeriodDate) {
+ return null;
+ }
+
+ return (
+ <>
+ <div className="note spacer-top">{leakPeriodLabel}</div>
+ <DateFromNow date={leakPeriodDate}>
+ {fromNow => (
+ <div className="note little-spacer-top">
+ {translateWithParameters(
+ leakPeriod.mode === 'previous_analysis'
+ ? 'overview.previous_analysis_x'
+ : 'overview.started_x',
+ fromNow
+ )}
+ </div>
+ )}
+ </DateFromNow>
+ </>
+ );
+}
+
+export default React.memo(injectIntl(ProjectLeakPeriodInfo));
--- /dev/null
+/*
+ * 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<ApplicationLeakPeriodInfoProps> = {}) {
+ return shallow(<ApplicationLeakPeriodInfo leakPeriod={mockApplicationPeriod()} {...props} />);
+}
--- /dev/null
+/*
+ * 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<LeakPeriodInfoProps> = {}) {
+ return shallow(<LeakPeriodInfo leakPeriod={mockPeriod()} {...props} />);
+}
--- /dev/null
+/*
+ * 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<any>).mockReturnValueOnce(0);
+ expect(
+ shallowRender({ date: '2018-08-17T00:00:00+0200', mode: 'previous_version' })
+ ).toMatchSnapshot();
+});
+
+function shallowRender(period: Partial<T.Period> = {}) {
+ return shallow(
+ <ProjectLeakPeriodInfo
+ intl={{
+ formatDate: (date: string) => 'formatted.' + date,
+ formatTime: (date: string) => 'formattedTime.' + date
+ }}
+ leakPeriod={mockPeriod({ ...period })}
+ />
+ );
+}
+++ /dev/null
-/*
- * 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(
- <ApplicationLeakPeriodLegend
- component={{ key: 'foo', organization: 'bar', qualifier: 'APP' }}
- />
- );
- expect(wrapper).toMatchSnapshot();
-
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
-});
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`renders 1`] = `
-<Tooltip
- overlay={
- <i
- className="spinner spacer"
- />
- }
->
- <div
- className="overview-legend overview-legend-spaced-line"
- >
- issues.max_new_code_period
- :
-
- </div>
-</Tooltip>
-`;
-
-exports[`renders 2`] = `
-<Tooltip
- overlay={
- <ul
- className="text-left"
- >
- <li>
- Foo
- :
- <DateTooltipFormatter
- date="2017-01-01T11:39:03+0100"
- />
- </li>
- <li>
- Bar
- :
- <DateTooltipFormatter
- date="2017-02-01T11:39:03+0100"
- />
- </li>
- </ul>
- }
->
- <div
- className="overview-legend"
- >
- issues.max_new_code_period
- :
-
- <DateFromNow
- date="2017-01-01T11:39:03+0100"
- >
- <Component />
- </DateFromNow>
- <br />
- <span
- className="note"
- >
- from
- :
- Foo
- </span>
- </div>
-</Tooltip>
-`;
*/
import { parseDate } from 'sonar-ui-common/helpers/dates';
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import { ApplicationPeriod } from '../types/application';
function getPeriod<T extends T.Period | T.PeriodMeasure>(periods: T[] | undefined, index: number) {
if (!Array.isArray(periods)) {
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;
+}