Browse Source

SONAR-18536 Migrate enzyme to RTL for Project Overview

tags/10.0.0.68432
guillaume-peoch-sonarsource 1 year ago
parent
commit
e2874ce9c4
52 changed files with 598 additions and 13673 deletions
  1. 0
    11
      server/sonar-web/src/main/js/apps/overview/branches/BranchOverview.tsx
  2. 1
    2
      server/sonar-web/src/main/js/apps/overview/branches/LeakPeriodInfo.tsx
  3. 0
    71
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-test.tsx
  4. 0
    45
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/Analysis-test.tsx
  5. 0
    38
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/ApplicationLeakPeriodInfo-test.tsx
  6. 0
    0
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx
  7. 0
    43
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/DrilldownMeasureValue-test.tsx
  8. 0
    55
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/Event-test.tsx
  9. 0
    78
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/FirstAnalysisNextStepsNotif-test.tsx
  10. 0
    36
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/LeakPeriodInfo-test.tsx
  11. 0
    131
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/MeasuresPanel-test.tsx
  12. 0
    71
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/NoCodeWarning-test.tsx
  13. 46
    22
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/ProjectLeakPeriodInfo-test.tsx
  14. 0
    86
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanel-test.tsx
  15. 0
    65
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanelSection-test.tsx
  16. 0
    307
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ActivityPanel-test.tsx.snap
  17. 0
    81
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/Analysis-test.tsx.snap
  18. 0
    19
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ApplicationLeakPeriodInfo-test.tsx.snap
  19. 0
    48
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/DrilldownMeasureValue-test.tsx.snap
  20. 0
    53
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/Event-test.tsx.snap
  21. 0
    124
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/FirstAnalysisNextStepsNotif-test.tsx.snap
  22. 0
    25
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/LeakPeriodInfo-test.tsx.snap
  23. 0
    5914
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/MeasuresPanel-test.tsx.snap
  24. 0
    131
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ProjectLeakPeriodInfo-test.tsx.snap
  25. 0
    770
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanel-test.tsx.snap
  26. 0
    429
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanelSection-test.tsx.snap
  27. 34
    40
      server/sonar-web/src/main/js/apps/overview/components/App.tsx
  28. 19
    22
      server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx
  29. 56
    26
      server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.tsx
  30. 0
    65
      server/sonar-web/src/main/js/apps/overview/components/__tests__/EmptyOverview-test.tsx
  31. 32
    41
      server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx
  32. 17
    21
      server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueRating-test.tsx
  33. 70
    23
      server/sonar-web/src/main/js/apps/overview/components/__tests__/LeakPeriodLegend-test.tsx
  34. 67
    54
      server/sonar-web/src/main/js/apps/overview/components/__tests__/MeasurementLabel-test.tsx
  35. 23
    7
      server/sonar-web/src/main/js/apps/overview/components/__tests__/QualityGateCondition-test.tsx
  36. 37
    14
      server/sonar-web/src/main/js/apps/overview/components/__tests__/QualityGateConditions-test.tsx
  37. 17
    15
      server/sonar-web/src/main/js/apps/overview/components/__tests__/SonarLintPromotion-test.tsx
  38. 0
    179
      server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap
  39. 0
    198
      server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap
  40. 0
    256
      server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueRating-test.tsx.snap
  41. 0
    128
      server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/LeakPeriodLegend-test.tsx.snap
  42. 0
    419
      server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/MeasurementLabel-test.tsx.snap
  43. 0
    477
      server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/QualityGateCondition-test.tsx.snap
  44. 0
    28
      server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/SonarLintPromition-test.tsx.snap
  45. 0
    54
      server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/AfterMergeEstimate-test.tsx
  46. 0
    32
      server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/LargeQualityGateBadge-test.tsx
  47. 177
    0
      server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx
  48. 0
    134
      server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-test.tsx
  49. 0
    37
      server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/AfterMergeEstimate-test.tsx.snap
  50. 0
    93
      server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/LargeQualityGateBadge-test.tsx.snap
  51. 0
    2653
      server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/PullRequestOverview-test.tsx.snap
  52. 2
    2
      sonar-core/src/main/resources/org/sonar/l10n/core.properties

+ 0
- 11
server/sonar-web/src/main/js/apps/overview/branches/BranchOverview.tsx View File

@@ -33,7 +33,6 @@ import {
getBranchLikeDisplayName,
getBranchLikeQuery,
isMainBranch,
isSameBranchLike,
} from '../../../helpers/branch-like';
import { parseDate, toNotSoISOString } from '../../../helpers/dates';
import { enhanceConditionWithMeasure, enhanceMeasuresWithMetrics } from '../../../helpers/measures';
@@ -98,16 +97,6 @@ export default class BranchOverview extends React.PureComponent<Props, State> {
this.loadHistory();
}

componentDidUpdate(prevProps: Props) {
if (
this.props.component.key !== prevProps.component.key ||
!isSameBranchLike(this.props.branch, prevProps.branch)
) {
this.loadStatus();
this.loadHistory();
}
}

componentWillUnmount() {
this.mounted = false;
}

+ 1
- 2
server/sonar-web/src/main/js/apps/overview/branches/LeakPeriodInfo.tsx View File

@@ -31,9 +31,8 @@ export interface LeakPeriodInfoProps {
export function LeakPeriodInfo({ leakPeriod }: LeakPeriodInfoProps) {
if (isApplicationPeriod(leakPeriod)) {
return <ApplicationLeakPeriodInfo leakPeriod={leakPeriod} />;
} else {
return <ProjectLeakPeriodInfo leakPeriod={leakPeriod} />;
}
return <ProjectLeakPeriodInfo leakPeriod={leakPeriod} />;
}

export default React.memo(LeakPeriodInfo);

+ 0
- 71
server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-test.tsx View File

@@ -1,71 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 GraphsHistory from '../../../../components/activity-graph/GraphsHistory';
import { parseDate } from '../../../../helpers/dates';
import { mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockAnalysis, mockAnalysisEvent } from '../../../../helpers/mocks/project-activity';
import { mockMeasure, mockMetric } from '../../../../helpers/testMocks';
import { GraphType } from '../../../../types/project-activity';
import { ActivityPanel, ActivityPanelProps } from '../ActivityPanel';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ loading: true, analyses: undefined })).toMatchSnapshot();
});

it('should correctly pass the leak period start date', () => {
// Leak period start is more recent than the oldest historic measure.
let { leakPeriodDate } = shallowRender({
leakPeriodDate: parseDate('2017-08-27T16:33:50+0200'),
})
.find(GraphsHistory)
.props();

expect(leakPeriodDate!.getTime()).toBe(1503844430000); /* 2017-08-27T16:33:50+0200 */

// Leak period start is older than the oldest historic measure.
({ leakPeriodDate } = shallowRender({ leakPeriodDate: parseDate('2015-08-27T16:33:50+0200') })
.find(GraphsHistory)
.props());

expect(leakPeriodDate!.getTime()).toBe(1477578830000); /* 2016-10-27T16:33:50+0200 */
});

function shallowRender(props: Partial<ActivityPanelProps> = {}) {
return shallow(
<ActivityPanel
analyses={[mockAnalysis({ events: [mockAnalysisEvent()] }), mockAnalysis()]}
branchLike={mockMainBranch()}
component={mockComponent()}
graph={GraphType.issues}
loading={false}
measuresHistory={[mockMeasure()].map((m) => ({
...m,
history: [{ date: parseDate('2016-10-27T16:33:50+0200'), value: '20' }],
}))}
metrics={[mockMetric({ key: 'bugs' })]}
onGraphChange={jest.fn()}
{...props}
/>
);
}

+ 0
- 45
server/sonar-web/src/main/js/apps/overview/branches/__tests__/Analysis-test.tsx View File

@@ -1,45 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockAnalysis } from '../../../../helpers/mocks/project-activity';
import { ComponentQualifier } from '../../../../types/component';
import { ProjectAnalysisEventCategory } from '../../../../types/project-activity';
import { Analysis, AnalysisProps } from '../Analysis';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ qualifier: ComponentQualifier.Application })).toMatchSnapshot();
});

function shallowRender(props: Partial<AnalysisProps> = {}) {
return shallow(
<Analysis
analysis={mockAnalysis({
events: [
{ key: '1', category: ProjectAnalysisEventCategory.Other, name: 'test' },
{ key: '2', category: ProjectAnalysisEventCategory.Version, name: '6.5-SNAPSHOT' },
],
})}
qualifier={ComponentQualifier.Project}
{...props}
/>
);
}

+ 0
- 38
server/sonar-web/src/main/js/apps/overview/branches/__tests__/ApplicationLeakPeriodInfo-test.tsx View File

@@ -1,38 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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} />);
}

server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-test.tsx → server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx View File


+ 0
- 43
server/sonar-web/src/main/js/apps/overview/branches/__tests__/DrilldownMeasureValue-test.tsx View File

@@ -1,43 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { MetricKey } from '../../../../types/metrics';
import { DrilldownMeasureValue, DrilldownMeasureValueProps } from '../DrilldownMeasureValue';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ metric: MetricKey.bugs })).toMatchSnapshot('measure not found');
});

function shallowRender(props: Partial<DrilldownMeasureValueProps> = {}) {
return shallow(
<DrilldownMeasureValue
branchLike={mockMainBranch()}
component={mockComponent()}
measures={[mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.tests }) })]}
metric={MetricKey.tests}
{...props}
/>
);
}

+ 0
- 55
server/sonar-web/src/main/js/apps/overview/branches/__tests__/Event-test.tsx View File

@@ -1,55 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { AnalysisEvent, ProjectAnalysisEventCategory } from '../../../../types/project-activity';
import { Event } from '../Event';

it('should render an event correctly', () => {
expect(
shallow(
<Event event={{ key: '1', category: ProjectAnalysisEventCategory.Other, name: 'test' }} />
)
).toMatchSnapshot();
});

it('should render a version correctly', () => {
expect(
shallow(
<Event
event={{ key: '2', category: ProjectAnalysisEventCategory.Version, name: '6.5-SNAPSHOT' }}
/>
)
).toMatchSnapshot();
});

it('should render rich quality gate event', () => {
const event: AnalysisEvent = {
category: ProjectAnalysisEventCategory.QualityGate,
key: 'foo1234',
name: '',
qualityGate: {
failing: [{ branch: 'master', key: 'foo', name: 'Foo' }],
status: 'ERROR',
stillFailing: true,
},
};
expect(shallow(<Event event={event} />)).toMatchSnapshot();
});

+ 0
- 78
server/sonar-web/src/main/js/apps/overview/branches/__tests__/FirstAnalysisNextStepsNotif-test.tsx View File

@@ -1,78 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockProjectAlmBindingResponse } from '../../../../helpers/mocks/alm-settings';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component';
import {
FirstAnalysisNextStepsNotif,
FirstAnalysisNextStepsNotifProps,
} from '../FirstAnalysisNextStepsNotif';

it('should render correctly', () => {
expect(shallowRender({ currentUser: mockCurrentUser() }).type()).toBeNull();
expect(
shallowRender({
component: mockComponent({ qualifier: ComponentQualifier.Application }),
}).type()
).toBeNull();
expect(shallowRender({ detectedCIOnLastAnalysis: false })).toMatchSnapshot(
'show prompt to configure CI'
);
expect(
shallowRender({
projectBinding: undefined,
})
).toMatchSnapshot('show prompt to configure PR decoration, regular user');
expect(
shallowRender({
component: mockComponent({ configuration: { showSettings: true } }),
projectBinding: undefined,
})
).toMatchSnapshot('show prompt to configure PR decoration, project admin');
expect(
shallowRender({
projectBinding: undefined,
detectedCIOnLastAnalysis: false,
})
).toMatchSnapshot('show prompt to configure PR decoration + CI, regular user');
expect(
shallowRender({
component: mockComponent({ configuration: { showSettings: true } }),
projectBinding: undefined,
detectedCIOnLastAnalysis: false,
})
).toMatchSnapshot('show prompt to configure PR decoration + CI, project admin');
});

function shallowRender(props: Partial<FirstAnalysisNextStepsNotifProps> = {}) {
return shallow<FirstAnalysisNextStepsNotifProps>(
<FirstAnalysisNextStepsNotif
component={mockComponent()}
branchesEnabled={true}
currentUser={mockLoggedInUser()}
detectedCIOnLastAnalysis={true}
projectBinding={mockProjectAlmBindingResponse()}
{...props}
/>
);
}

+ 0
- 36
server/sonar-web/src/main/js/apps/overview/branches/__tests__/LeakPeriodInfo-test.tsx View File

@@ -1,36 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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} />);
}

+ 0
- 131
server/sonar-web/src/main/js/apps/overview/branches/__tests__/MeasuresPanel-test.tsx View File

@@ -1,131 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 BoxedTabs from '../../../../components/controls/BoxedTabs';
import { mockBranch, mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import {
mockLocation,
mockMeasureEnhanced,
mockMetric,
mockPeriod,
} from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component';
import { MetricKey } from '../../../../types/metrics';
import { MeasuresPanel, MeasuresPanelProps, MeasuresPanelTabs } from '../MeasuresPanel';

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useEffect: jest.fn().mockImplementation((f) => f()),
};
});

it('should render correctly for projects', () => {
const wrapper = shallowRender();
expect(wrapper).toMatchSnapshot('default');
wrapper.find(BoxedTabs).prop<Function>('onSelect')(MeasuresPanelTabs.Overall);
expect(wrapper).toMatchSnapshot('overall');
});

it('should render correctly for applications', () => {
const wrapper = shallowRender({
component: mockComponent({ qualifier: ComponentQualifier.Application }),
});
expect(wrapper).toMatchSnapshot('default');
wrapper.find(BoxedTabs).prop<Function>('onSelect')(MeasuresPanelTabs.Overall);
expect(wrapper).toMatchSnapshot('overall');
});

it('should render correctly if there is no new code measures', () => {
const wrapper = shallowRender({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) }),
],
});
wrapper.find(BoxedTabs).prop<Function>('onSelect')(MeasuresPanelTabs.New);
expect(wrapper).toMatchSnapshot();
});

it('should render correctly if branch is misconfigured', () => {
const wrapper = shallowRender({
branch: mockBranch({ name: 'own-reference' }),
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) }),
],
period: mockPeriod({ date: undefined, mode: 'REFERENCE_BRANCH', parameter: 'own-reference' }),
});
wrapper.find(BoxedTabs).prop<Function>('onSelect')(MeasuresPanelTabs.New);
expect(wrapper).toMatchSnapshot('hide settings');

wrapper.setProps({ component: mockComponent({ configuration: { showSettings: true } }) });
expect(wrapper).toMatchSnapshot('show settings');
});

it('should render correctly if there is no coverage', () => {
expect(
shallowRender({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_bugs }) }),
],
})
).toMatchSnapshot();
});

it('should render correctly if the data is still loading', () => {
expect(shallowRender({ loading: true })).toMatchSnapshot();
});

it('should render correctly when code scope is overall code', () => {
expect(
shallowRender({
location: mockLocation({ pathname: '/dashboard', query: { code_scope: 'overall' } }),
})
).toMatchSnapshot();
});

it('should render correctly when code scope is new code', () => {
expect(
shallowRender({
location: mockLocation({ pathname: '/dashboard', query: { code_scope: 'new' } }),
})
).toMatchSnapshot();
});

function shallowRender(props: Partial<MeasuresPanelProps> = {}) {
return shallow<MeasuresPanelProps>(
<MeasuresPanel
branch={mockMainBranch()}
component={mockComponent()}
measures={[
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_bugs }) }),
]}
location={mockLocation()}
{...props}
/>
);
}

+ 0
- 71
server/sonar-web/src/main/js/apps/overview/branches/__tests__/NoCodeWarning-test.tsx View File

@@ -1,71 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockBranch, mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component';
import { MetricKey } from '../../../../types/metrics';
import { NoCodeWarning } from '../NoCodeWarning';

it('should render correctly if the project has no lines of code', () => {
const wrapper = shallowRender();
expect(wrapper.children().text()).toBe('overview.project.main_branch_no_lines_of_code');

wrapper.setProps({ branchLike: mockBranch({ name: 'branch-foo' }) });
expect(wrapper.children().text()).toBe('overview.project.branch_X_no_lines_of_code.branch-foo');

wrapper.setProps({ branchLike: undefined });
expect(wrapper.children().text()).toBe('overview.project.no_lines_of_code');
});

it('should correctly if the project is empty', () => {
const wrapper = shallowRender({ measures: [] });
expect(wrapper.children().text()).toBe('overview.project.main_branch_empty');

wrapper.setProps({ branchLike: mockBranch({ name: 'branch-foo' }) });
expect(wrapper.children().text()).toBe('overview.project.branch_X_empty.branch-foo');

wrapper.setProps({ branchLike: undefined });
expect(wrapper.children().text()).toBe('overview.project.empty');
});

it('should render correctly if the application is empty or has no lines of code', () => {
const wrapper = shallowRender({
component: mockComponent({ qualifier: ComponentQualifier.Application }),
measures: [mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.projects }) })],
});
expect(wrapper.children().text()).toBe('portfolio.app.no_lines_of_code');

wrapper.setProps({ measures: [] });
expect(wrapper.children().text()).toBe('portfolio.app.empty');
});

function shallowRender(props = {}) {
return shallow(
<NoCodeWarning
branchLike={mockMainBranch()}
component={mockComponent()}
measures={[mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) })]}
{...props}
/>
);
}

+ 46
- 22
server/sonar-web/src/main/js/apps/overview/branches/__tests__/ProjectLeakPeriodInfo-test.tsx View File

@@ -17,11 +17,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { screen } from '@testing-library/react';
import { differenceInDays } from 'date-fns';
import { shallow } from 'enzyme';
import * as React from 'react';
import { IntlShape } from 'react-intl';
import { mockPeriod } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { Period } from '../../../../types/types';
import { ProjectLeakPeriodInfo } from '../ProjectLeakPeriodInfo';

@@ -30,44 +31,67 @@ jest.mock('date-fns', () => {
return { ...actual, differenceInDays: jest.fn().mockReturnValue(10) };
});

it('should render correctly for 10 days', () => {
expect(shallowRender({ mode: 'days', parameter: '10' })).toMatchSnapshot();
it('should render correctly for 10 days', async () => {
renderProjectLeakPeriodInfo({ mode: 'days', parameter: '10' });
expect(await screen.findByText('overview.period.days.10')).toBeInTheDocument();
});

it('should render correctly for a specific date', () => {
expect(shallowRender({ mode: 'date', parameter: '2013-01-01' })).toMatchSnapshot();
it('should render correctly for a specific date', async () => {
renderProjectLeakPeriodInfo({ mode: 'date', parameter: '2013-01-01' });
expect(await screen.findByText('overview.period.date.formatted.2013-01-01')).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*ago/)).toBeInTheDocument();
});

it('should render correctly for a specific version', () => {
expect(shallowRender({ mode: 'version', parameter: '0.1' })).toMatchSnapshot();
it('should render correctly for a specific version', async () => {
renderProjectLeakPeriodInfo({ mode: 'version', parameter: '0.1' });
expect(await screen.findByText('overview.period.version.0.1')).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*ago/)).toBeInTheDocument();
});

it('should render correctly for "previous_version"', () => {
expect(shallowRender({ mode: 'previous_version' })).toMatchSnapshot();
it('should render correctly for "previous_version"', async () => {
renderProjectLeakPeriodInfo({ mode: 'previous_version' });
expect(await screen.findByText('overview.period.previous_version_only_date')).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*ago/)).toBeInTheDocument();
});

it('should render correctly for "previous_analysis"', () => {
expect(shallowRender({ mode: 'previous_analysis' })).toMatchSnapshot();
it('should render correctly for "previous_analysis"', async () => {
renderProjectLeakPeriodInfo({ mode: 'previous_analysis' });
expect(await screen.findByText('overview.period.previous_analysis.')).toBeInTheDocument();
expect(await screen.findByText(/overview\.previous_analysis_x\..*ago/)).toBeInTheDocument();
});

it('should render correctly for "REFERENCE_BRANCH"', () => {
expect(shallowRender({ mode: 'REFERENCE_BRANCH', parameter: 'master' })).toMatchSnapshot();
it('should render correctly for "REFERENCE_BRANCH"', async () => {
renderProjectLeakPeriodInfo({
mode: 'REFERENCE_BRANCH',
parameter: 'master',
});
expect(await screen.findByText('overview.period.reference_branch.master')).toBeInTheDocument();
});

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 correctly for "manual_baseline"', async () => {
const rtl = renderProjectLeakPeriodInfo({ mode: 'manual_baseline' });

expect(
await screen.findByText(/overview\.period\.manual_baseline\.formattedTime\..*/)
).toBeInTheDocument();
rtl.unmount();
renderProjectLeakPeriodInfo({ mode: 'manual_baseline', parameter: '1.1.2' });
expect(await screen.findByText('overview.period.manual_baseline.1.1.2')).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*ago/)).toBeInTheDocument();
});

it('should render a more precise date', () => {
it('should render a more precise date', async () => {
(differenceInDays as jest.Mock<any>).mockReturnValueOnce(0);
expect(
shallowRender({ date: '2018-08-17T00:00:00+0200', mode: 'previous_version' })
).toMatchSnapshot();
renderProjectLeakPeriodInfo({
date: '2018-08-17T00:00:00+0200',
mode: 'previous_version',
});
expect(await screen.findByText('overview.period.previous_version_only_date')).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*ago/)).toBeInTheDocument();
});

function shallowRender(period: Partial<Period> = {}) {
return shallow(
function renderProjectLeakPeriodInfo(period: Partial<Period> = {}) {
return renderComponent(
<ProjectLeakPeriodInfo
intl={
{

+ 0
- 86
server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanel-test.tsx View File

@@ -1,86 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockComponent } from '../../../../helpers/mocks/component';
import {
mockQualityGateStatus,
mockQualityGateStatusConditionEnhanced,
} from '../../../../helpers/mocks/quality-gates';
import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component';
import { MetricKey } from '../../../../types/metrics';
import { QualityGatePanel, QualityGatePanelProps } from '../QualityGatePanel';

it('should render correctly for projects', () => {
expect(shallowRender()).toMatchSnapshot();
expect(
shallowRender({ qgStatuses: [mockQualityGateStatus({ status: 'OK', failedConditions: [] })] })
).toMatchSnapshot();

const wrapper = shallowRender({
qgStatuses: [mockQualityGateStatus({ ignoredConditions: true })],
});
expect(wrapper).toMatchSnapshot();
});

it('should render correctly for applications', () => {
expect(
shallowRender({
component: mockComponent({ qualifier: ComponentQualifier.Application }),
qgStatuses: [
mockQualityGateStatus(),
mockQualityGateStatus({
failedConditions: [
mockQualityGateStatusConditionEnhanced(),
mockQualityGateStatusConditionEnhanced({
measure: mockMeasureEnhanced({
metric: mockMetric({ key: MetricKey.new_code_smells }),
}),
metric: MetricKey.new_code_smells,
}),
],
}),
],
})
).toMatchSnapshot();

const wrapper = shallowRender({
component: mockComponent({ qualifier: ComponentQualifier.Application }),
qgStatuses: [
mockQualityGateStatus(),
mockQualityGateStatus({
status: 'OK',
failedConditions: [],
}),
],
});
expect(wrapper).toMatchSnapshot();
});

function shallowRender(props: Partial<QualityGatePanelProps> = {}) {
return shallow(
<QualityGatePanel
component={mockComponent()}
qgStatuses={[mockQualityGateStatus()]}
{...props}
/>
);
}

+ 0
- 65
server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanelSection-test.tsx View File

@@ -1,65 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import {
mockQualityGateStatus,
mockQualityGateStatusConditionEnhanced,
} from '../../../../helpers/mocks/quality-gates';
import { ComponentQualifier } from '../../../../types/component';
import { MetricKey } from '../../../../types/metrics';
import { CaycStatus } from '../../../../types/types';
import { QualityGatePanelSection, QualityGatePanelSectionProps } from '../QualityGatePanelSection';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(
shallowRender({
qgStatus: mockQualityGateStatus({
failedConditions: [],
status: 'OK',
caycStatus: CaycStatus.Compliant,
}),
}).type()
).toBeNull();
expect(
shallowRender({ component: mockComponent({ qualifier: ComponentQualifier.Application }) })
).toMatchSnapshot();
});

function shallowRender(props: Partial<QualityGatePanelSectionProps> = {}) {
return shallow(
<QualityGatePanelSection
branchLike={mockMainBranch()}
component={mockComponent()}
qgStatus={mockQualityGateStatus({
failedConditions: [
mockQualityGateStatusConditionEnhanced({ metric: MetricKey.bugs }),
mockQualityGateStatusConditionEnhanced({ metric: MetricKey.new_bugs }),
],
status: 'ERROR',
caycStatus: CaycStatus.NonCompliant,
})}
{...props}
/>
);
}

+ 0
- 307
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ActivityPanel-test.tsx.snap View File

@@ -1,307 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div
className="overview-panel big-spacer-top"
data-test="overview__activity-panel"
>
<h2
className="overview-panel-title"
>
overview.activity
</h2>
<div
className="overview-panel-content"
>
<div
className="display-flex-row"
>
<div
className="display-flex-column flex-1"
>
<div
className="overview-panel-padded display-flex-column flex-1"
>
<GraphsHeader
graph="issues"
metrics={
[
{
"id": "bugs",
"key": "bugs",
"name": "bugs",
"type": "PERCENT",
},
]
}
onUpdateGraph={[MockFunction]}
/>
<GraphsHistory
analyses={[]}
ariaLabel="overview.activity.graph_shows_data_for_x.metric.bugs.name, metric.code_smells.name, metric.vulnerabilities.name"
canShowDataAsTable={false}
graph="issues"
graphs={
[
[
{
"data": [
{
"x": 2016-10-27T14:33:50.000Z,
"y": 20,
},
],
"name": "bugs",
"translatedName": "bugs",
"type": "PERCENT",
},
],
]
}
loading={false}
measuresHistory={
[
{
"bestValue": true,
"history": [
{
"date": 2016-10-27T14:33:50.000Z,
"value": "20",
},
],
"metric": "bugs",
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
]
}
series={
[
{
"data": [
{
"x": 2016-10-27T14:33:50.000Z,
"y": 20,
},
],
"name": "bugs",
"translatedName": "bugs",
"type": "PERCENT",
},
]
}
/>
</div>
<div
className="overview-panel-padded bordered-top text-right"
>
<ActivityLink
branchLike={
{
"analysisDate": "2018-01-01",
"excludedFromPurge": true,
"isMain": true,
"name": "master",
}
}
component="my-project"
graph="issues"
/>
</div>
</div>
<div
className="overview-panel-padded bordered-left width-30"
>
<div
data-test="overview__activity-analyses"
>
<DeferredSpinner
className="spacer-top spacer-left"
loading={false}
>
<ul
className="spacer-top spacer-left"
>
<Memo(Analysis)
analysis={
{
"date": "2017-03-01T09:36:01+0100",
"events": [
{
"category": "QUALITY_GATE",
"description": "Lorem ipsum dolor sit amet",
"key": "E11",
"name": "Lorem ipsum",
"qualityGate": {
"failing": [
{
"branch": "master",
"key": "foo",
"name": "Foo",
},
{
"branch": "feature/bar",
"key": "bar",
"name": "Bar",
},
],
"status": "ERROR",
"stillFailing": true,
},
},
],
"key": "foo",
"projectVersion": "1.0",
}
}
key="foo"
qualifier="TRK"
/>
</ul>
</DeferredSpinner>
</div>
</div>
</div>
</div>
</div>
`;

exports[`should render correctly 2`] = `
<div
className="overview-panel big-spacer-top"
data-test="overview__activity-panel"
>
<h2
className="overview-panel-title"
>
overview.activity
</h2>
<div
className="overview-panel-content"
>
<div
className="display-flex-row"
>
<div
className="display-flex-column flex-1"
>
<div
className="overview-panel-padded display-flex-column flex-1"
>
<GraphsHeader
graph="issues"
metrics={
[
{
"id": "bugs",
"key": "bugs",
"name": "bugs",
"type": "PERCENT",
},
]
}
onUpdateGraph={[MockFunction]}
/>
<GraphsHistory
analyses={[]}
ariaLabel="overview.activity.graph_shows_data_for_x.metric.bugs.name, metric.code_smells.name, metric.vulnerabilities.name"
canShowDataAsTable={false}
graph="issues"
graphs={
[
[
{
"data": [
{
"x": 2016-10-27T14:33:50.000Z,
"y": 20,
},
],
"name": "bugs",
"translatedName": "bugs",
"type": "PERCENT",
},
],
]
}
loading={true}
measuresHistory={
[
{
"bestValue": true,
"history": [
{
"date": 2016-10-27T14:33:50.000Z,
"value": "20",
},
],
"metric": "bugs",
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
]
}
series={
[
{
"data": [
{
"x": 2016-10-27T14:33:50.000Z,
"y": 20,
},
],
"name": "bugs",
"translatedName": "bugs",
"type": "PERCENT",
},
]
}
/>
</div>
<div
className="overview-panel-padded bordered-top text-right"
>
<ActivityLink
branchLike={
{
"analysisDate": "2018-01-01",
"excludedFromPurge": true,
"isMain": true,
"name": "master",
}
}
component="my-project"
graph="issues"
/>
</div>
</div>
<div
className="overview-panel-padded bordered-left width-30"
>
<div
data-test="overview__activity-analyses"
>
<DeferredSpinner
className="spacer-top spacer-left"
loading={true}
>
<p
className="spacer-top spacer-left note"
>
no_results
</p>
</DeferredSpinner>
</div>
</div>
</div>
</div>
</div>
`;

+ 0
- 81
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/Analysis-test.tsx.snap View File

@@ -1,81 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<li
className="overview-analysis"
>
<div
className="small little-spacer-bottom"
>
<strong>
<DateTimeFormatter
date="2017-03-01T09:36:01+0100"
/>
</strong>
</div>
<div
className="overview-activity-events"
>
<Memo(Event)
event={
{
"category": "VERSION",
"key": "2",
"name": "6.5-SNAPSHOT",
}
}
key="2"
/>
<Memo(Event)
event={
{
"category": "OTHER",
"key": "1",
"name": "test",
}
}
key="1"
/>
</div>
</li>
`;

exports[`should render correctly 2`] = `
<li
className="overview-analysis"
>
<div
className="small little-spacer-bottom"
>
<strong>
<DateTimeFormatter
date="2017-03-01T09:36:01+0100"
/>
</strong>
</div>
<div
className="overview-activity-events"
>
<Memo(Event)
event={
{
"category": "VERSION",
"key": "2",
"name": "6.5-SNAPSHOT",
}
}
key="2"
/>
<Memo(Event)
event={
{
"category": "OTHER",
"key": "1",
"name": "test",
}
}
key="1"
/>
</div>
</li>
`;

+ 0
- 19
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ApplicationLeakPeriodInfo-test.tsx.snap View File

@@ -1,19 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders correctly 1`] = `
<div
className="note spacer-top display-inline-flex-center"
>
<DateFromNow
date="2017-10-01"
>
<Component />
</DateFromNow>
<HelpTooltip
className="little-spacer-left"
overlay="overview.max_new_code_period_from_x.Foo"
/>
</div>
`;

exports[`renders correctly 2`] = `"overview.started_x.2017-10-01"`;

+ 0
- 48
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/DrilldownMeasureValue-test.tsx.snap View File

@@ -1,48 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: default 1`] = `
<div
className="display-flex-column display-flex-center"
>
<span>
<DrilldownLink
ariaLabel="overview.see_more_details_on_x_y.1.0.metric.tests.name"
branchLike={
{
"analysisDate": "2018-01-01",
"excludedFromPurge": true,
"isMain": true,
"name": "master",
}
}
className="overview-measures-value text-light"
component="my-project"
metric="tests"
>
1
</DrilldownLink>
</span>
<span
className="spacer-top"
>
tests
</span>
</div>
`;

exports[`should render correctly: measure not found 1`] = `
<div
className="display-flex-column display-flex-center"
>
<span
className="overview-measures-value text-light"
>
-
</span>
<span
className="spacer-top"
>
bugs
</span>
</div>
`;

+ 0
- 53
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/Event-test.tsx.snap View File

@@ -1,53 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render a version correctly 1`] = `
<span
className="overview-analysis-event analysis-version text-ellipsis max-width-80"
title="version 6.5-SNAPSHOT"
>
6.5-SNAPSHOT
</span>
`;

exports[`should render an event correctly 1`] = `
<div
className="overview-analysis-event"
>
<span
className="note text-ellipsis width-80"
>
event.category.OTHER
:
</span>
<strong>
test
</strong>
</div>
`;

exports[`should render rich quality gate event 1`] = `
<div
className="overview-analysis-event"
>
<span
className="note"
>
event.category.QUALITY_GATE
:
</span>
<FormattedMessage
defaultMessage="event.quality_gate.still_x"
id="event.quality_gate.still_x"
values={
{
"status": <Level
level="ERROR"
small={true}
/>,
}
}
/>
</div>
`;

+ 0
- 124
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/FirstAnalysisNextStepsNotif-test.tsx.snap View File

@@ -1,124 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: show prompt to configure CI 1`] = `
<DismissableAlert
alertKey="config_ci_pr_deco.my-project"
variant="info"
>
<FormattedMessage
defaultMessage="overview.project.next_steps.set_up_ci"
id="overview.project.next_steps.set_up_ci"
values={
{
"link": <ForwardRef(Link)
to={
{
"pathname": "/tutorials",
"search": "?id=my-project",
}
}
>
overview.project.next_steps.links.set_up_ci
</ForwardRef(Link)>,
}
}
/>
</DismissableAlert>
`;

exports[`should render correctly: show prompt to configure PR decoration + CI, project admin 1`] = `
<DismissableAlert
alertKey="config_ci_pr_deco.my-project"
variant="info"
>
<FormattedMessage
defaultMessage="overview.project.next_steps.set_up_pr_deco_and_ci.admin"
id="overview.project.next_steps.set_up_pr_deco_and_ci.admin"
values={
{
"link_ci": <ForwardRef(Link)
to={
{
"pathname": "/tutorials",
"search": "?id=my-project",
}
}
>
overview.project.next_steps.links.set_up_ci
</ForwardRef(Link)>,
"link_project_settings": <ForwardRef(Link)
to={
{
"pathname": "/project/settings",
"search": "?id=my-project&category=pull_request_decoration_binding",
}
}
>
overview.project.next_steps.links.project_settings
</ForwardRef(Link)>,
}
}
/>
</DismissableAlert>
`;

exports[`should render correctly: show prompt to configure PR decoration + CI, regular user 1`] = `
<DismissableAlert
alertKey="config_ci_pr_deco.my-project"
variant="info"
>
<FormattedMessage
defaultMessage="overview.project.next_steps.set_up_pr_deco_and_ci"
id="overview.project.next_steps.set_up_pr_deco_and_ci"
values={
{
"link_ci": <ForwardRef(Link)
to={
{
"pathname": "/tutorials",
"search": "?id=my-project",
}
}
>
overview.project.next_steps.links.set_up_ci
</ForwardRef(Link)>,
}
}
/>
</DismissableAlert>
`;

exports[`should render correctly: show prompt to configure PR decoration, project admin 1`] = `
<DismissableAlert
alertKey="config_ci_pr_deco.my-project"
variant="info"
>
<FormattedMessage
defaultMessage="overview.project.next_steps.set_up_pr_deco.admin"
id="overview.project.next_steps.set_up_pr_deco.admin"
values={
{
"link_project_settings": <ForwardRef(Link)
to={
{
"pathname": "/project/settings",
"search": "?id=my-project&category=pull_request_decoration_binding",
}
}
>
overview.project.next_steps.links.project_settings
</ForwardRef(Link)>,
}
}
/>
</DismissableAlert>
`;

exports[`should render correctly: show prompt to configure PR decoration, regular user 1`] = `
<DismissableAlert
alertKey="config_ci_pr_deco.my-project"
variant="info"
>
overview.project.next_steps.set_up_pr_deco
</DismissableAlert>
`;

+ 0
- 25
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/LeakPeriodInfo-test.tsx.snap View File

@@ -1,25 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders correctly for applications 1`] = `
<Memo(ApplicationLeakPeriodInfo)
leakPeriod={
{
"date": "2017-10-01",
"project": "foo",
"projectName": "Foo",
}
}
/>
`;

exports[`renders correctly for projects 1`] = `
<Memo(injectIntl(ProjectLeakPeriodInfo))
leakPeriod={
{
"date": "2019-04-23T02:12:32+0100",
"index": 0,
"mode": "previous_version",
}
}
/>
`;

+ 0
- 5914
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/MeasuresPanel-test.tsx.snap
File diff suppressed because it is too large
View File


+ 0
- 131
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ProjectLeakPeriodInfo-test.tsx.snap View File

@@ -1,131 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render a more precise date 1`] = `
<Fragment>
<div
className="note spacer-top text-ellipsis"
title="overview.period.previous_version_only_date"
>
overview.period.previous_version_only_date
</div>
<DateFromNow
date={2018-08-16T22:00:00.000Z}
>
<Component />
</DateFromNow>
</Fragment>
`;

exports[`should render correctly for "REFERENCE_BRANCH" 1`] = `
<div
className="note spacer-top"
>
overview.period.reference_branch.master
</div>
`;

exports[`should render correctly for "manual_baseline" 1`] = `
<Fragment>
<div
className="note spacer-top text-ellipsis"
title="overview.period.manual_baseline.formattedTime.2019-04-23T02:12:32+0100"
>
overview.period.manual_baseline.formattedTime.2019-04-23T02:12:32+0100
</div>
<DateFromNow
date={2019-04-23T01:12:32.000Z}
>
<Component />
</DateFromNow>
</Fragment>
`;

exports[`should render correctly for "manual_baseline" 2`] = `
<Fragment>
<div
className="note spacer-top text-ellipsis"
title="overview.period.manual_baseline.1.1.2"
>
overview.period.manual_baseline.1.1.2
</div>
<DateFromNow
date={2019-04-23T01:12:32.000Z}
>
<Component />
</DateFromNow>
</Fragment>
`;

exports[`should render correctly for "previous_analysis" 1`] = `
<Fragment>
<div
className="note spacer-top text-ellipsis"
title="overview.period.previous_analysis."
>
overview.period.previous_analysis.
</div>
<DateFromNow
date={2019-04-23T01:12:32.000Z}
>
<Component />
</DateFromNow>
</Fragment>
`;

exports[`should render correctly for "previous_version" 1`] = `
<Fragment>
<div
className="note spacer-top text-ellipsis"
title="overview.period.previous_version_only_date"
>
overview.period.previous_version_only_date
</div>
<DateFromNow
date={2019-04-23T01:12:32.000Z}
>
<Component />
</DateFromNow>
</Fragment>
`;

exports[`should render correctly for 10 days 1`] = `
<div
className="note spacer-top"
>
overview.period.days.10
</div>
`;

exports[`should render correctly for a specific date 1`] = `
<Fragment>
<div
className="note spacer-top text-ellipsis"
title="overview.period.date.formatted.2013-01-01"
>
overview.period.date.formatted.2013-01-01
</div>
<DateFromNow
date={2019-04-23T01:12:32.000Z}
>
<Component />
</DateFromNow>
</Fragment>
`;

exports[`should render correctly for a specific version 1`] = `
<Fragment>
<div
className="note spacer-top text-ellipsis"
title="overview.period.version.0.1"
>
overview.period.version.0.1
</div>
<DateFromNow
date={2019-04-23T01:12:32.000Z}
>
<Component />
</DateFromNow>
</Fragment>
`;

+ 0
- 770
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanel-test.tsx.snap View File

@@ -1,770 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly for applications 1`] = `
<div
className="overview-panel"
data-test="overview__quality-gate-panel"
>
<div
className="display-flex-center spacer-bottom"
>
<h2
className="overview-panel-title null-spacer-bottom"
>
overview.quality_gate
</h2>
<HelpTooltip
className="little-spacer-left"
overlay={
<div
className="big-padded-top big-padded-bottom"
>
overview.quality_gate.help
</div>
}
/>
</div>
<div>
<div
className="overview-quality-gate-badge-large failed"
>
<div
className="big-spacer-bottom huge h3"
>
metric.level.ERROR
</div>
<span
className="small"
>
overview.X_conditions_failed.3
</span>
</div>
<div
data-test="overview__quality-gate-conditions"
>
<Memo(QualityGatePanelSection)
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "APP",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
}
}
key="foo"
qgStatus={
{
"caycStatus": "compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
/>
<Memo(QualityGatePanelSection)
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "APP",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
}
}
key="foo"
qgStatus={
{
"caycStatus": "compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "new_code_smells",
"key": "new_code_smells",
"name": "new_code_smells",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "new_code_smells",
"op": "GT",
},
],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
/>
</div>
</div>
<withCurrentUserContext(SonarLintPromotion)
qgConditions={
[
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "new_code_smells",
"key": "new_code_smells",
"name": "new_code_smells",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "new_code_smells",
"op": "GT",
},
]
}
/>
</div>
`;

exports[`should render correctly for applications 2`] = `
<div
className="overview-panel"
data-test="overview__quality-gate-panel"
>
<div
className="display-flex-center spacer-bottom"
>
<h2
className="overview-panel-title null-spacer-bottom"
>
overview.quality_gate
</h2>
<HelpTooltip
className="little-spacer-left"
overlay={
<div
className="big-padded-top big-padded-bottom"
>
overview.quality_gate.help
</div>
}
/>
</div>
<div>
<div
className="overview-quality-gate-badge-large failed"
>
<div
className="big-spacer-bottom huge h3"
>
metric.level.ERROR
</div>
<span
className="small"
>
overview.X_conditions_failed.1
</span>
</div>
<div
data-test="overview__quality-gate-conditions"
>
<Memo(QualityGatePanelSection)
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "APP",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
}
}
key="foo"
qgStatus={
{
"caycStatus": "compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
/>
<Memo(QualityGatePanelSection)
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "APP",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
}
}
key="foo"
qgStatus={
{
"caycStatus": "compliant",
"failedConditions": [],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "OK",
}
}
/>
</div>
</div>
<withCurrentUserContext(SonarLintPromotion)
qgConditions={
[
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
]
}
/>
</div>
`;

exports[`should render correctly for projects 1`] = `
<div
className="overview-panel"
data-test="overview__quality-gate-panel"
>
<div
className="display-flex-center spacer-bottom"
>
<h2
className="overview-panel-title null-spacer-bottom"
>
overview.quality_gate
</h2>
<HelpTooltip
className="little-spacer-left"
overlay={
<div
className="big-padded-top big-padded-bottom"
>
overview.quality_gate.help
</div>
}
/>
</div>
<div>
<div
className="overview-quality-gate-badge-large failed"
>
<div
className="big-spacer-bottom huge h3"
>
metric.level.ERROR
</div>
<span
className="small"
>
overview.X_conditions_failed.1
</span>
</div>
<div
data-test="overview__quality-gate-conditions"
>
<Memo(QualityGatePanelSection)
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "TRK",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
}
}
key="foo"
qgStatus={
{
"caycStatus": "compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
/>
</div>
</div>
<withCurrentUserContext(SonarLintPromotion)
qgConditions={
[
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
]
}
/>
</div>
`;

exports[`should render correctly for projects 2`] = `
<div
className="overview-panel"
data-test="overview__quality-gate-panel"
>
<div
className="display-flex-center spacer-bottom"
>
<h2
className="overview-panel-title null-spacer-bottom"
>
overview.quality_gate
</h2>
<HelpTooltip
className="little-spacer-left"
overlay={
<div
className="big-padded-top big-padded-bottom"
>
overview.quality_gate.help
</div>
}
/>
</div>
<div>
<div
className="overview-quality-gate-badge-large success"
>
<div
className="big-spacer-bottom huge h3"
>
metric.level.OK
</div>
<span
className="small"
>
overview.quality_gate_all_conditions_passed
</span>
</div>
</div>
<withCurrentUserContext(SonarLintPromotion)
qgConditions={[]}
/>
</div>
`;

exports[`should render correctly for projects 3`] = `
<div
className="overview-panel"
data-test="overview__quality-gate-panel"
>
<div
className="display-flex-center spacer-bottom"
>
<h2
className="overview-panel-title null-spacer-bottom"
>
overview.quality_gate
</h2>
<HelpTooltip
className="little-spacer-left"
overlay={
<div
className="big-padded-top big-padded-bottom"
>
overview.quality_gate.help
</div>
}
/>
</div>
<Alert
className="big-spacer-bottom"
display="inline"
variant="info"
>
<span
className="text-middle"
>
overview.quality_gate.ignored_conditions
</span>
<HelpTooltip
className="spacer-left"
overlay="overview.quality_gate.ignored_conditions.tooltip"
/>
</Alert>
<div>
<div
className="overview-quality-gate-badge-large failed"
>
<div
className="big-spacer-bottom huge h3"
>
metric.level.ERROR
</div>
<span
className="small"
>
overview.X_conditions_failed.1
</span>
</div>
<div
data-test="overview__quality-gate-conditions"
>
<Memo(QualityGatePanelSection)
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "TRK",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
}
}
key="foo"
qgStatus={
{
"caycStatus": "compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
],
"ignoredConditions": true,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
/>
</div>
</div>
<withCurrentUserContext(SonarLintPromotion)
qgConditions={
[
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "foo",
"op": "GT",
},
]
}
/>
</div>
`;

+ 0
- 429
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanelSection-test.tsx.snap View File

@@ -1,429 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div
className="overview-quality-gate-conditions"
>
<div
className="big-padded bordered-bottom overview-quality-gate-conditions-list"
>
<CleanAsYouCodeWarning
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "TRK",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
}
}
/>
</div>
<div
className="big-padded overview-quality-gate-conditions-section-title h4"
>
quality_gates.conditions.new_code_x.1
</div>
<Memo(QualityGateConditions)
component={
{
"caycStatus": "non-compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "bugs",
"op": "GT",
},
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "new_bugs",
"op": "GT",
},
],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
failedConditions={
[
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "new_bugs",
"op": "GT",
},
]
}
/>
<div
className="big-padded overview-quality-gate-conditions-section-title h4"
>
quality_gates.conditions.overall_code_x.1
</div>
<Memo(QualityGateConditions)
component={
{
"caycStatus": "non-compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "bugs",
"op": "GT",
},
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "new_bugs",
"op": "GT",
},
],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
failedConditions={
[
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "bugs",
"op": "GT",
},
]
}
/>
</div>
`;

exports[`should render correctly 2`] = `
<div
className="overview-quality-gate-conditions"
>
<ButtonPlain
aria-expanded={true}
aria-label="overview.quality_gate.hide_project_conditions_x.Foo"
className="width-100 text-left"
onClick={[Function]}
>
<div
className="display-flex-center"
>
<div
className="overview-quality-gate-conditions-project-name text-ellipsis h3"
title="Foo"
>
<ChevronDownIcon />
<span
className="spacer-left"
>
Foo
</span>
</div>
</div>
</ButtonPlain>
<div
className="big-padded overview-quality-gate-conditions-section-title h4"
>
quality_gates.conditions.new_code_x.1
</div>
<Memo(QualityGateConditions)
component={
{
"caycStatus": "non-compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "bugs",
"op": "GT",
},
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "new_bugs",
"op": "GT",
},
],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
failedConditions={
[
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "new_bugs",
"op": "GT",
},
]
}
/>
<div
className="big-padded overview-quality-gate-conditions-section-title h4"
>
quality_gates.conditions.overall_code_x.1
</div>
<Memo(QualityGateConditions)
component={
{
"caycStatus": "non-compliant",
"failedConditions": [
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "bugs",
"op": "GT",
},
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "new_bugs",
"op": "GT",
},
],
"ignoredConditions": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
}
}
failedConditions={
[
{
"actual": "10",
"error": "0",
"level": "ERROR",
"measure": {
"bestValue": true,
"leak": "1",
"metric": {
"id": "coverage",
"key": "coverage",
"name": "coverage",
"type": "PERCENT",
},
"period": {
"bestValue": true,
"index": 1,
"value": "1.0",
},
"value": "1.0",
},
"metric": "bugs",
"op": "GT",
},
]
}
/>
</div>
`;

+ 34
- 40
server/sonar-web/src/main/js/apps/overview/components/App.tsx View File

@@ -33,7 +33,7 @@ import BranchOverview from '../branches/BranchOverview';
import PullRequestOverview from '../pullRequests/PullRequestOverview';
import EmptyOverview from './EmptyOverview';

interface Props extends WithAvailableFeaturesProps {
interface AppProps extends WithAvailableFeaturesProps {
branchLike?: BranchLike;
branchLikes: BranchLike[];
component: Component;
@@ -42,49 +42,43 @@ interface Props extends WithAvailableFeaturesProps {
projectBinding?: ProjectAlmBindingResponse;
}

export class App extends React.PureComponent<Props> {
isPortfolio = () => {
return isPortfolioLike(this.props.component.qualifier);
};
export function App(props: AppProps) {
const { branchLike, branchLikes, component, projectBinding, isPending, isInProgress } = props;
const branchSupportEnabled = props.hasFeature(Feature.BranchSupport);

render() {
const { branchLike, branchLikes, component, projectBinding } = this.props;
const branchSupportEnabled = this.props.hasFeature(Feature.BranchSupport);

if (this.isPortfolio()) {
return null;
}
if (isPortfolioLike(component.qualifier)) {
return null;
}

return isPullRequest(branchLike) ? (
<main>
<Suggestions suggestions="pull_requests" />
<PullRequestOverview branchLike={branchLike} component={component} />
</main>
) : (
<main>
<Suggestions suggestions="overview" />
return isPullRequest(branchLike) ? (
<main>
<Suggestions suggestions="pull_requests" />
<PullRequestOverview branchLike={branchLike} component={component} />
</main>
) : (
<main>
<Suggestions suggestions="overview" />

{!component.analysisDate && (
<EmptyOverview
branchLike={branchLike}
branchLikes={branchLikes}
component={component}
hasAnalyses={this.props.isPending || this.props.isInProgress}
projectBinding={projectBinding}
/>
)}
{!component.analysisDate && (
<EmptyOverview
branchLike={branchLike}
branchLikes={branchLikes}
component={component}
hasAnalyses={isPending || isInProgress}
projectBinding={projectBinding}
/>
)}

{component.analysisDate && (
<BranchOverview
branch={branchLike}
branchesEnabled={branchSupportEnabled}
component={component}
projectBinding={projectBinding}
/>
)}
</main>
);
}
{component.analysisDate && (
<BranchOverview
branch={branchLike}
branchesEnabled={branchSupportEnabled}
component={component}
projectBinding={projectBinding}
/>
)}
</main>
);
}

export default withComponentContext(withAvailableFeatures(App));

+ 19
- 22
server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx View File

@@ -18,12 +18,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import TutorialSelection from '../../../components/tutorials/TutorialSelection';
import { Alert } from '../../../components/ui/Alert';
import { getBranchLikeDisplayName, isBranch, isMainBranch } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { ProjectAlmBindingResponse } from '../../../types/alm-settings';
import { BranchLike } from '../../../types/branch-like';
import { ComponentQualifier } from '../../../types/component';
@@ -45,7 +44,9 @@ export function EmptyOverview(props: EmptyOverviewProps) {
if (component.qualifier === ComponentQualifier.Application) {
return (
<div className="page page-limited">
<Alert variant="warning">{translate('provisioning.no_analysis.application')}</Alert>
<Alert variant="warning" aria-label={translate('provisioning.no_analysis.application')}>
{translate('provisioning.no_analysis.application')}
</Alert>
</div>
);
} else if (!isBranch(branchLike)) {
@@ -62,25 +63,15 @@ export function EmptyOverview(props: EmptyOverviewProps) {

let warning;
if (isLoggedIn(currentUser) && showWarning && hasBadBranchConfig) {
warning = (
<FormattedMessage
defaultMessage={translate('provisioning.no_analysis_on_main_branch.bad_configuration')}
id="provisioning.no_analysis_on_main_branch.bad_configuration"
values={{
branchName: getBranchLikeDisplayName(branchLike),
branchType: translate('branches.main_branch'),
}}
/>
warning = translateWithParameters(
'provisioning.no_analysis_on_main_branch.bad_configuration',
getBranchLikeDisplayName(branchLike),
translate('branches.main_branch')
);
} else {
warning = (
<FormattedMessage
defaultMessage={translate('provisioning.no_analysis_on_main_branch')}
id="provisioning.no_analysis_on_main_branch"
values={{
branchName: getBranchLikeDisplayName(branchLike),
}}
/>
warning = translateWithParameters(
'provisioning.no_analysis_on_main_branch',
getBranchLikeDisplayName(branchLike)
);
}

@@ -88,7 +79,11 @@ export function EmptyOverview(props: EmptyOverviewProps) {
<div className="page page-limited">
{isLoggedIn(currentUser) ? (
<>
{showWarning && <Alert variant="warning">{warning}</Alert>}
{showWarning && (
<Alert variant="warning" aria-label={warning}>
{warning}
</Alert>
)}
{showTutorial && (
<TutorialSelection
component={component}
@@ -99,7 +94,9 @@ export function EmptyOverview(props: EmptyOverviewProps) {
)}
</>
) : (
<Alert variant="warning">{warning}</Alert>
<Alert variant="warning" aria-label={warning}>
{warning}
</Alert>
)}
</div>
);

+ 56
- 26
server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.tsx View File

@@ -17,36 +17,66 @@
* 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 { screen } from '@testing-library/react';
import * as React from 'react';
import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
import BranchOverview from '../../branches/BranchOverview';
import PullRequestOverview from '../../pullRequests/PullRequestOverview';
import CurrentUserContextProvider from '../../../../app/components/current-user/CurrentUserContextProvider';
import { mockBranch, mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockCurrentUser } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { ComponentQualifier } from '../../../../types/component';
import { App } from '../App';

const component = {
key: 'foo',
analysisDate: '2016-01-01',
breadcrumbs: [],
name: 'Foo',
qualifier: 'TRK',
version: '0.0.1',
};

it('should render BranchOverview', () => {
expect(getWrapper().find(BranchOverview).exists()).toBe(true);
expect(getWrapper({ branchLike: mockPullRequest() }).find(PullRequestOverview).exists()).toBe(
true
);
it('should render Empty Overview for Application with no analysis', async () => {
renderApp({ component: mockComponent({ qualifier: ComponentQualifier.Application }) });

expect(
await screen.findByRole('alert', { name: 'provisioning.no_analysis.application' })
).toBeInTheDocument();
});

it('should render Empty Overview on main branch with no analysis', async () => {
renderApp({}, mockCurrentUser());

expect(
await screen.findByRole('alert', { name: 'provisioning.no_analysis_on_main_branch.master' })
).toBeInTheDocument();
});

it('should render Empty Overview on main branch with multiple branches with bad configuration', async () => {
renderApp({ branchLikes: [mockBranch(), mockBranch()] });

expect(
await screen.findByRole('alert', {
name: 'provisioning.no_analysis_on_main_branch.bad_configuration.master.branches.main_branch',
})
).toBeInTheDocument();
});

it('should not render for portfolios and subportfolios', () => {
const rtl = renderApp({
component: mockComponent({ qualifier: ComponentQualifier.Portfolio }),
});
expect(rtl.container).toBeEmptyDOMElement();

rtl.unmount();

renderApp({
component: mockComponent({ qualifier: ComponentQualifier.Portfolio }),
});
expect(rtl.container).toBeEmptyDOMElement();
});

function getWrapper(props = {}) {
return shallow(
<App
hasFeature={jest.fn().mockReturnValue(false)}
branchLikes={[]}
component={component}
{...props}
/>
function renderApp(props = {}, userProps = {}) {
return renderComponent(
<CurrentUserContextProvider currentUser={mockCurrentUser({ isLoggedIn: true, ...userProps })}>
<App
hasFeature={jest.fn().mockReturnValue(false)}
branchLikes={[]}
branchLike={mockMainBranch()}
component={mockComponent()}
{...props}
/>
</CurrentUserContextProvider>
);
}

+ 0
- 65
server/sonar-web/src/main/js/apps/overview/components/__tests__/EmptyOverview-test.tsx View File

@@ -1,65 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockProjectGithubBindingResponse } from '../../../../helpers/mocks/alm-settings';
import { mockBranch, mockMainBranch, mockPullRequest } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component';
import { EmptyOverview, EmptyOverviewProps } from '../EmptyOverview';

it('renders correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ hasAnalyses: true })).toMatchSnapshot();
expect(shallowRender({ currentUser: mockCurrentUser() })).toMatchSnapshot();
expect(shallowRender({ projectBinding: mockProjectGithubBindingResponse() })).toMatchSnapshot();
});

it('should render another message when there are branches', () => {
expect(shallowRender({ branchLikes: [mockMainBranch(), mockBranch()] })).toMatchSnapshot();
expect(
shallowRender({
branchLikes: [mockMainBranch(), mockBranch(), mockBranch({ name: 'branch-7.8' })],
})
).toMatchSnapshot();
});

it('should not render warning message for pull requests', () => {
expect(shallowRender({ branchLike: mockPullRequest() }).type()).toBeNull();
});

it('should not render the tutorial for applications', () => {
expect(
shallowRender({ component: mockComponent({ qualifier: ComponentQualifier.Application }) })
).toMatchSnapshot();
});

function shallowRender(props: Partial<EmptyOverviewProps> = {}) {
return shallow<EmptyOverviewProps>(
<EmptyOverview
branchLike={mockMainBranch()}
branchLikes={[mockMainBranch()]}
component={mockComponent({ version: '0.0.1' })}
currentUser={mockLoggedInUser()}
{...props}
/>
);
}

+ 32
- 41
server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx View File

@@ -17,74 +17,65 @@
* 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 { screen } from '@testing-library/react';
import * as React from 'react';
import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { IssueType } from '../../../../types/issues';
import { MetricKey } from '../../../../types/metrics';
import { IssueLabel, IssueLabelProps } from '../IssueLabel';

it('should render correctly for bugs', () => {
it('should render correctly for bugs', async () => {
const measures = [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_bugs }) }),
];
expect(shallowRender({ measures })).toMatchSnapshot();
expect(shallowRender({ measures, useDiffMetric: true })).toMatchSnapshot();
});

it('should render correctly for code smells', () => {
const type = IssueType.CodeSmell;
const measures = [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.code_smells }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_code_smells }) }),
];
expect(shallowRender({ measures, type })).toMatchSnapshot();
expect(shallowRender({ measures, type, useDiffMetric: true })).toMatchSnapshot();
});
const rtl = renderIssueLabel({ measures });
expect(
await screen.findByRole('link', {
name: 'overview.see_list_of_x_y_issues.1.0.metric.bugs.name',
})
).toBeInTheDocument();

it('should render correctly for vulnerabilities', () => {
const type = IssueType.Vulnerability;
const measures = [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.vulnerabilities }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_vulnerabilities }) }),
];
expect(shallowRender({ measures, type })).toMatchSnapshot();
expect(shallowRender({ measures, type, useDiffMetric: true })).toMatchSnapshot();
rtl.unmount();

renderIssueLabel({ measures, useDiffMetric: true });

expect(
await screen.findByRole('link', {
name: 'overview.see_list_of_x_y_issues.1.0.metric.new_bugs.name',
})
).toBeInTheDocument();
});

it('should render correctly for hotspots', () => {
it('should render correctly for hotspots with tooltip', async () => {
const helpTooltip = 'tooltip text';
const type = IssueType.SecurityHotspot;
const measures = [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.security_hotspots }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_security_hotspots }) }),
];

renderIssueLabel({
helpTooltip,
measures,
type,
});

expect(
shallowRender({
helpTooltip,
measures,
type,
})
).toMatchSnapshot();
expect(
shallowRender({
helpTooltip,
measures,
type,
useDiffMetric: true,
await screen.findByRole('link', {
name: 'overview.see_list_of_x_y_issues.1.0.metric.security_hotspots.name',
})
).toMatchSnapshot();
});
).toBeInTheDocument();

it('should render correctly if no values are present', () => {
expect(shallowRender()).toMatchSnapshot();
expect(await screen.findByText('tooltip text')).toBeInTheDocument();
});

function shallowRender(props: Partial<IssueLabelProps> = {}) {
return shallow(
function renderIssueLabel(props: Partial<IssueLabelProps> = {}) {
return renderComponent(
<IssueLabel
branchLike={mockPullRequest()}
component={mockComponent()}

+ 17
- 21
server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueRating-test.tsx View File

@@ -17,40 +17,36 @@
* 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 { screen } from '@testing-library/react';
import * as React from 'react';
import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { IssueType } from '../../../../types/issues';
import { MetricKey } from '../../../../types/metrics';
import { IssueRating, IssueRatingProps } from '../IssueRating';

it('should render correctly for bugs', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ useDiffMetric: true })).toMatchSnapshot();
});

it('should render correctly for code smells', () => {
expect(shallowRender({ type: IssueType.CodeSmell })).toMatchSnapshot();
expect(shallowRender({ type: IssueType.CodeSmell, useDiffMetric: true })).toMatchSnapshot();
});
it('should render correctly for vulnerabilities', async () => {
renderIssueRating({ type: IssueType.Vulnerability });
expect(await screen.findByText('metric_domain.Security')).toBeInTheDocument();

it('should render correctly for vulnerabilities', () => {
expect(shallowRender({ type: IssueType.Vulnerability })).toMatchSnapshot();
expect(shallowRender({ type: IssueType.Vulnerability, useDiffMetric: true })).toMatchSnapshot();
renderIssueRating({ type: IssueType.Vulnerability, useDiffMetric: true });
const labels = await screen.findAllByText('metric_domain.Security');
expect(labels).toHaveLength(2);
const tooltips = await screen.findAllByText('metric.security_rating.tooltip.A');
expect(tooltips).toHaveLength(2);
});

it('should render correctly if no values are present', () => {
expect(
shallowRender({
measures: [mockMeasureEnhanced({ metric: mockMetric({ key: 'NONE' }) })],
})
).toMatchSnapshot();
it('should render correctly if no values are present', async () => {
renderIssueRating({
measures: [mockMeasureEnhanced({ metric: mockMetric({ key: 'NONE' }) })],
});
expect(await screen.findByText('metric_domain.Reliability')).toBeInTheDocument();
});

function shallowRender(props: Partial<IssueRatingProps> = {}) {
return shallow(
function renderIssueRating(props: Partial<IssueRatingProps> = {}) {
return renderComponent(
<IssueRating
branchLike={mockPullRequest()}
component={mockComponent()}

+ 70
- 23
server/sonar-web/src/main/js/apps/overview/components/__tests__/LeakPeriodLegend-test.tsx View File

@@ -17,10 +17,11 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { screen } from '@testing-library/react';
import { differenceInDays } from 'date-fns';
import { shallow } from 'enzyme';
import * as React from 'react';
import { IntlShape } from 'react-intl';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { Period } from '../../../../types/types';
import { LeakPeriodLegend } from '../LeakPeriodLegend';

@@ -29,40 +30,90 @@ jest.mock('date-fns', () => {
return { ...actual, differenceInDays: jest.fn().mockReturnValue(10) };
});

it('10 days', () => {
expect(getWrapper({ mode: 'days', parameter: '10' })).toMatchSnapshot();
it('10 days', async () => {
renderLeakPeriodLegend({ mode: 'days', parameter: '10' });

expect(
await screen.findByText('overview.new_code_period_x.overview.period.days.10')
).toBeInTheDocument();
});

it('date', () => {
expect(getWrapper({ mode: 'date', parameter: '2013-01-01' })).toMatchSnapshot();
it('date', async () => {
renderLeakPeriodLegend({ mode: 'date', parameter: '2013-01-01' });

expect(
await screen.findByText('overview.new_code_period_x.overview.period.date.formatted.2013-01-01')
).toBeInTheDocument();
expect(await screen.findByText('overview.started_x.9 years ago')).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_on_x\..*/)).toBeInTheDocument();
});

it('version', () => {
expect(findLegend(getWrapper({ mode: 'version', parameter: '0.1' }))).toMatchSnapshot();
it('version', async () => {
renderLeakPeriodLegend({ mode: 'version', parameter: '0.1' });

expect(
await screen.findByText('overview.new_code_period_x.overview.period.version.0.1')
).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*/)).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_on_x\..*/)).toBeInTheDocument();
});

it('previous_version', () => {
expect(findLegend(getWrapper({ mode: 'previous_version' }))).toMatchSnapshot();
it('previous_version', async () => {
renderLeakPeriodLegend({ mode: 'previous_version' });

expect(
await screen.findByText('overview.new_code_period_x.overview.period.previous_version_only_date')
).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*/)).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_on_x\..*/)).toBeInTheDocument();
});

it('previous_analysis', () => {
expect(findLegend(getWrapper({ mode: 'previous_analysis' }))).toMatchSnapshot();
it('previous_analysis', async () => {
renderLeakPeriodLegend({ mode: 'previous_analysis' });

expect(
await screen.findByText('overview.new_code_period_x.overview.period.previous_analysis.')
).toBeInTheDocument();
expect(await screen.findByText(/overview\.previous_analysis_x\..*/)).toBeInTheDocument();
expect(await screen.findByText(/overview\.previous_analysis_x\..*/)).toBeInTheDocument();
});

it('manual_baseline', () => {
expect(findLegend(getWrapper({ mode: 'manual_baseline' }))).toMatchSnapshot();
expect(findLegend(getWrapper({ mode: 'manual_baseline', parameter: '1.1.2' }))).toMatchSnapshot();
it('manual_baseline', async () => {
const rtl = renderLeakPeriodLegend({ mode: 'manual_baseline' });

expect(
await screen.findByText(
/overview\.new_code_period_x\.overview\.period\.manual_baseline\.formattedTime\..*/
)
).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*/)).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_on_x\..*/)).toBeInTheDocument();

rtl.unmount();
renderLeakPeriodLegend({ mode: 'manual_baseline', parameter: '1.1.2' });

expect(
await screen.findByText('overview.new_code_period_x.overview.period.manual_baseline.1.1.2')
).toBeInTheDocument();
expect(
await screen.findByText('overview.new_code_period_x.overview.period.manual_baseline.1.1.2')
).toBeInTheDocument();
});

it('should render a more precise date', () => {
it('should render a more precise date', async () => {
(differenceInDays as jest.Mock<any>).mockReturnValueOnce(0);

renderLeakPeriodLegend({ date: '2018-08-17T00:00:00+0200', mode: 'previous_version' });

expect(
getWrapper({ date: '2018-08-17T00:00:00+0200', mode: 'previous_version' })
).toMatchSnapshot();
await screen.findByText('overview.new_code_period_x.overview.period.previous_version_only_date')
).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_x\..*/)).toBeInTheDocument();
expect(await screen.findByText(/overview\.started_on_x\..*/)).toBeInTheDocument();
});

function getWrapper(period: Partial<Period> = {}) {
return shallow(
function renderLeakPeriodLegend(period: Partial<Period> = {}) {
return renderComponent(
<LeakPeriodLegend
intl={
{
@@ -79,7 +130,3 @@ function getWrapper(period: Partial<Period> = {}) {
/>
);
}

function findLegend(wrapper: any) {
return wrapper.find('.overview-legend');
}

+ 67
- 54
server/sonar-web/src/main/js/apps/overview/components/__tests__/MeasurementLabel-test.tsx View File

@@ -17,78 +17,91 @@
* 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 { screen } from '@testing-library/react';
import * as React from 'react';
import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { MetricKey } from '../../../../types/metrics';
import { MeasurementType } from '../../utils';
import MeasurementLabel from '../MeasurementLabel';

it('should render correctly for coverage', () => {
expect(shallowRender()).toMatchSnapshot();
expect(
shallowRender({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.lines_to_cover }) }),
],
})
).toMatchSnapshot();
expect(
shallowRender({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_lines_to_cover }) }),
],
useDiffMetric: true,
})
).toMatchSnapshot();
it('should render correctly for coverage', async () => {
renderMeasurementLabel();
expect(await screen.findByText('metric.coverage.name')).toBeInTheDocument();

renderMeasurementLabel({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.lines_to_cover }) }),
],
});
expect(await screen.findByText('metric.coverage.name')).toBeInTheDocument();
expect(await screen.findByText('overview.coverage_on_X_lines')).toBeInTheDocument();

renderMeasurementLabel({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_lines_to_cover }) }),
],
useDiffMetric: true,
});
expect(screen.getByRole('link', { name: /.*new_coverage.*/ })).toBeInTheDocument();
expect(await screen.findByText('overview.coverage_on_X_lines')).toBeInTheDocument();
expect(await screen.findByText('overview.coverage_on_X_new_lines')).toBeInTheDocument();
});

it('should render correctly for duplications', () => {
it('should render correctly for duplications', async () => {
renderMeasurementLabel({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.duplicated_lines_density }) }),
],
type: MeasurementType.Duplication,
});
expect(
shallowRender({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.duplicated_lines_density }) }),
],
type: MeasurementType.Duplication,
screen.getByRole('link', {
name: 'overview.see_more_details_on_x_of_y.1.0%.metric.duplicated_lines_density.name',
})
).toMatchSnapshot();
expect(
shallowRender({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.duplicated_lines_density }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.ncloc }) }),
],
type: MeasurementType.Duplication,
})
).toMatchSnapshot();
).toBeInTheDocument();
expect(await screen.findByText('metric.duplicated_lines_density.short_name')).toBeInTheDocument();

renderMeasurementLabel({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.duplicated_lines_density }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.ncloc }) }),
],
type: MeasurementType.Duplication,
});
expect(await screen.findByText('metric.duplicated_lines_density.short_name')).toBeInTheDocument();
expect(await screen.findByText('overview.duplications_on_X_lines')).toBeInTheDocument();

renderMeasurementLabel({
measures: [
mockMeasureEnhanced({
metric: mockMetric({ key: MetricKey.new_duplicated_lines_density }),
}),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_lines }) }),
],
type: MeasurementType.Duplication,
useDiffMetric: true,
});

expect(
shallowRender({
measures: [
mockMeasureEnhanced({
metric: mockMetric({ key: MetricKey.new_duplicated_lines_density }),
}),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_lines }) }),
],
type: MeasurementType.Duplication,
useDiffMetric: true,
screen.getByRole('link', {
name: 'overview.see_more_details_on_x_of_y.1.0%.metric.new_duplicated_lines_density.name',
})
).toMatchSnapshot();
});

it('should render correctly with no value', () => {
expect(shallowRender({ measures: [] })).toMatchSnapshot();
).toBeInTheDocument();
expect(await screen.findByText('overview.duplications_on_X_new_lines')).toBeInTheDocument();
});

it('should render correctly when centered', () => {
expect(shallowRender({ centered: true })).toMatchSnapshot();
it('should render correctly with no value', async () => {
renderMeasurementLabel({ measures: [] });
expect(await screen.findByText('metric.coverage.name')).toBeInTheDocument();
});

function shallowRender(props: Partial<MeasurementLabel['props']> = {}) {
return shallow(
function renderMeasurementLabel(props: Partial<MeasurementLabel['props']> = {}) {
return renderComponent(
<MeasurementLabel
branchLike={mockPullRequest()}
component={mockComponent()}

+ 23
- 7
server/sonar-web/src/main/js/apps/overview/components/__tests__/QualityGateCondition-test.tsx View File

@@ -17,11 +17,12 @@
* 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 { screen } from '@testing-library/react';
import * as React from 'react';
import { mockBranch } from '../../../../helpers/mocks/branch-like';
import { mockQualityGateStatusConditionEnhanced } from '../../../../helpers/mocks/quality-gates';
import { mockMetric } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { MetricKey } from '../../../../types/metrics';
import { QualityGateStatusConditionEnhanced } from '../../../../types/quality-gates';
import QualityGateCondition from '../QualityGateCondition';
@@ -36,17 +37,32 @@ it.each([
[quickMock(MetricKey.new_maintainability_rating, 'RATING', true)],
[quickMock(MetricKey.security_hotspots_reviewed)],
[quickMock(MetricKey.new_security_hotspots_reviewed, 'RATING', true)],
])('should render correclty', (condition) => {
expect(shallowRender({ condition })).toMatchSnapshot();
])('should render correclty', async (condition) => {
renderQualityGateCondition({ condition });
expect(
await screen.findByText(`metric.${condition.measure.metric.name}.name`)
).toBeInTheDocument();

expect(
await screen.findByText(`quality_gates.operator.${condition.op}`, { exact: false })
).toBeInTheDocument();
// if (condition.measure.metric.type === 'RATING') {
// expect(await screen.findByText('.rating', { exact: false })).toBeInTheDocument();
// }
});

it('should work with branch', () => {
it('should work with branch', async () => {
const condition = quickMock(MetricKey.new_maintainability_rating);
expect(shallowRender({ branchLike: mockBranch(), condition })).toMatchSnapshot();
renderQualityGateCondition({ branchLike: mockBranch(), condition });

expect(await screen.findByText('metric.new_maintainability_rating.name')).toBeInTheDocument();
expect(
await screen.findByText('quality_gates.operator.GT.rating', { exact: false })
).toBeInTheDocument();
});

function shallowRender(props: Partial<QualityGateCondition['props']>) {
return shallow(
function renderQualityGateCondition(props: Partial<QualityGateCondition['props']>) {
return renderComponent(
<QualityGateCondition
component={{ key: 'abcd-key' }}
condition={mockQualityGateStatusConditionEnhanced()}

+ 37
- 14
server/sonar-web/src/main/js/apps/overview/components/__tests__/QualityGateConditions-test.tsx View File

@@ -17,33 +17,56 @@
* 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 { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import * as React from 'react';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockQualityGateStatusConditionEnhanced } from '../../../../helpers/mocks/quality-gates';
import { click } from '../../../../helpers/testUtils';
import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { QualityGateStatusConditionEnhanced } from '../../../../types/quality-gates';
import { QualityGateConditions, QualityGateConditionsProps } from '../QualityGateConditions';

it('should render correctly', () => {
const wrapper = shallowRender();
expect(wrapper.find('QualityGateCondition').length).toBe(10);
const ALL_CONDITIONS = 10;
const HALF_CONDITIONS = 5;

it('should render correctly', async () => {
renderQualityGateConditions();
expect(await screen.findAllByText(/.*metric..+.name.*/)).toHaveLength(ALL_CONDITIONS);

expect(await screen.findAllByText('quality_gates.operator', { exact: false })).toHaveLength(
ALL_CONDITIONS
);
});

it('should be collapsible', () => {
const wrapper = shallowRender({ collapsible: true });
expect(wrapper.find('QualityGateCondition').length).toBe(5);
click(wrapper.find('ButtonLink'));
expect(wrapper.find('QualityGateCondition').length).toBe(10);
it('should be collapsible', async () => {
renderQualityGateConditions({ collapsible: true });
const user = userEvent.setup();

expect(await screen.findAllByText(/.*metric..+.name.*/)).toHaveLength(HALF_CONDITIONS);
expect(await screen.findAllByText('quality_gates.operator', { exact: false })).toHaveLength(
HALF_CONDITIONS
);

await user.click(screen.getByRole('button', { name: 'overview.X_more_failed_conditions.5' }));

expect(await screen.findAllByText(/.*metric..+.name.*/)).toHaveLength(ALL_CONDITIONS);
expect(await screen.findAllByText('quality_gates.operator', { exact: false })).toHaveLength(
ALL_CONDITIONS
);
});

function shallowRender(props: Partial<QualityGateConditionsProps> = {}) {
function renderQualityGateConditions(props: Partial<QualityGateConditionsProps> = {}) {
const conditions: QualityGateStatusConditionEnhanced[] = [];
for (let i = 10; i > 0; --i) {
conditions.push(mockQualityGateStatusConditionEnhanced());
for (let i = ALL_CONDITIONS; i > 0; --i) {
conditions.push(
mockQualityGateStatusConditionEnhanced({
measure: mockMeasureEnhanced({ metric: mockMetric({ key: i.toString() }) }),
})
);
}

return shallow(
return renderComponent(
<QualityGateConditions component={mockComponent()} failedConditions={conditions} {...props} />
);
}

server/sonar-web/src/main/js/apps/overview/components/__tests__/SonarLintPromition-test.tsx → server/sonar-web/src/main/js/apps/overview/components/__tests__/SonarLintPromotion-test.tsx View File

@@ -17,25 +17,24 @@
* 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 { screen } from '@testing-library/react';
import * as React from 'react';
import { mockQualityGateStatusCondition } from '../../../../helpers/mocks/quality-gates';
import { mockCurrentUser } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { MetricKey } from '../../../../types/metrics';
import { SonarLintPromotion, SonarLintPromotionProps } from '../SonarLintPromotion';

it('should render correctly', () => {
expect(shallowRender().type()).toBeNull();
renderSonarLintPromotion();
expect(
shallowRender({ currentUser: mockCurrentUser({ usingSonarLintConnectedMode: true }) }).type()
).toBeNull();
screen.queryByText('overview.fix_failed_conditions_with_sonarlint')
).not.toBeInTheDocument();

renderSonarLintPromotion({ currentUser: mockCurrentUser({ usingSonarLintConnectedMode: true }) });
expect(
shallowRender({
qgConditions: [
mockQualityGateStatusCondition({ metric: MetricKey.new_bugs, level: 'ERROR' }),
],
})
).toMatchSnapshot('has failed condition');
screen.queryByText('overview.fix_failed_conditions_with_sonarlint')
).not.toBeInTheDocument();
});

it.each(
@@ -53,13 +52,16 @@ it.each(
MetricKey.new_maintainability_rating,
MetricKey.new_reliability_rating,
].map(Array.of)
)('should show message for %s', (metric) => {
const wrapper = shallowRender({
)('should show message for %s', async (metric) => {
renderSonarLintPromotion({
qgConditions: [mockQualityGateStatusCondition({ metric: metric as string })],
});
expect(wrapper.type()).not.toBeNull();

expect(
await screen.findByText('overview.fix_failed_conditions_with_sonarlint')
).toBeInTheDocument();
});

function shallowRender(props: Partial<SonarLintPromotionProps> = {}) {
return shallow(<SonarLintPromotion currentUser={mockCurrentUser()} {...props} />);
function renderSonarLintPromotion(props: Partial<SonarLintPromotionProps> = {}) {
return renderComponent(<SonarLintPromotion currentUser={mockCurrentUser()} {...props} />);
}

+ 0
- 179
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap View File

@@ -1,179 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders correctly 1`] = `
<div
className="page page-limited"
>
<withRouter(TutorialSelection)
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "TRK",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
"version": "0.0.1",
}
}
currentUser={
{
"dismissedNotices": {
"educationPrinciples": false,
},
"groups": [],
"isLoggedIn": true,
"login": "luke",
"name": "Skywalker",
"scmAccounts": [],
}
}
willRefreshAutomatically={true}
/>
</div>
`;

exports[`renders correctly 2`] = `
<div
className="page page-limited"
/>
`;

exports[`renders correctly 3`] = `
<div
className="page page-limited"
>
<Alert
variant="warning"
>
<FormattedMessage
defaultMessage="provisioning.no_analysis_on_main_branch"
id="provisioning.no_analysis_on_main_branch"
values={
{
"branchName": "master",
}
}
/>
</Alert>
</div>
`;

exports[`renders correctly 4`] = `
<div
className="page page-limited"
>
<withRouter(TutorialSelection)
component={
{
"breadcrumbs": [],
"key": "my-project",
"name": "MyProject",
"qualifier": "TRK",
"qualityGate": {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": [
{
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": [],
"version": "0.0.1",
}
}
currentUser={
{
"dismissedNotices": {
"educationPrinciples": false,
},
"groups": [],
"isLoggedIn": true,
"login": "luke",
"name": "Skywalker",
"scmAccounts": [],
}
}
projectBinding={
{
"alm": "github",
"key": "foo",
"monorepo": true,
"repository": "PROJECT_KEY",
}
}
willRefreshAutomatically={true}
/>
</div>
`;

exports[`should not render the tutorial for applications 1`] = `
<div
className="page page-limited"
>
<Alert
variant="warning"
>
provisioning.no_analysis.application
</Alert>
</div>
`;

exports[`should render another message when there are branches 1`] = `
<div
className="page page-limited"
>
<Alert
variant="warning"
>
<FormattedMessage
defaultMessage="provisioning.no_analysis_on_main_branch.bad_configuration"
id="provisioning.no_analysis_on_main_branch.bad_configuration"
values={
{
"branchName": "master",
"branchType": "branches.main_branch",
}
}
/>
</Alert>
</div>
`;

exports[`should render another message when there are branches 2`] = `
<div
className="page page-limited"
>
<Alert
variant="warning"
>
<FormattedMessage
defaultMessage="provisioning.no_analysis_on_main_branch.bad_configuration"
id="provisioning.no_analysis_on_main_branch.bad_configuration"
values={
{
"branchName": "master",
"branchType": "branches.main_branch",
}
}
/>
</Alert>
</div>
`;

+ 0
- 198
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap View File

@@ -1,198 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly for bugs 1`] = `
<Fragment>
<ForwardRef(Link)
aria-label="overview.see_list_of_x_y_issues.1.0.metric.bugs.name"
className="overview-measures-value text-light"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?pullRequest=1001&resolved=false&types=BUG&inNewCodePeriod=false&id=my-project",
}
}
>
1
</ForwardRef(Link)>
<BugIcon
className="big-spacer-left little-spacer-right"
/>
metric.bugs.name
</Fragment>
`;

exports[`should render correctly for bugs 2`] = `
<Fragment>
<ForwardRef(Link)
aria-label="overview.see_list_of_x_y_issues.1.0.metric.new_bugs.name"
className="overview-measures-value text-light"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?pullRequest=1001&resolved=false&types=BUG&inNewCodePeriod=true&id=my-project",
}
}
>
1
</ForwardRef(Link)>
<BugIcon
className="big-spacer-left little-spacer-right"
/>
metric.new_bugs.name
</Fragment>
`;

exports[`should render correctly for code smells 1`] = `
<Fragment>
<ForwardRef(Link)
aria-label="overview.see_list_of_x_y_issues.1.0.metric.code_smells.name"
className="overview-measures-value text-light"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?pullRequest=1001&resolved=false&types=CODE_SMELL&inNewCodePeriod=false&id=my-project",
}
}
>
1
</ForwardRef(Link)>
<CodeSmellIcon
className="big-spacer-left little-spacer-right"
/>
metric.code_smells.name
</Fragment>
`;

exports[`should render correctly for code smells 2`] = `
<Fragment>
<ForwardRef(Link)
aria-label="overview.see_list_of_x_y_issues.1.0.metric.new_code_smells.name"
className="overview-measures-value text-light"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?pullRequest=1001&resolved=false&types=CODE_SMELL&inNewCodePeriod=true&id=my-project",
}
}
>
1
</ForwardRef(Link)>
<CodeSmellIcon
className="big-spacer-left little-spacer-right"
/>
metric.new_code_smells.name
</Fragment>
`;

exports[`should render correctly for hotspots 1`] = `
<Fragment>
<ForwardRef(Link)
aria-label="overview.see_list_of_x_y_issues.1.0.metric.security_hotspots.name"
className="overview-measures-value text-light"
to={
{
"hash": "",
"pathname": "/security_hotspots",
"search": "?id=my-project&pullRequest=1001&inNewCodePeriod=false",
}
}
>
1
</ForwardRef(Link)>
<SecurityHotspotIcon
className="big-spacer-left little-spacer-right"
/>
metric.security_hotspots.name
<HelpTooltip
className="little-spacer-left"
overlay="tooltip text"
/>
</Fragment>
`;

exports[`should render correctly for hotspots 2`] = `
<Fragment>
<ForwardRef(Link)
aria-label="overview.see_list_of_x_y_issues.1.0.metric.new_security_hotspots.name"
className="overview-measures-value text-light"
to={
{
"hash": "",
"pathname": "/security_hotspots",
"search": "?id=my-project&pullRequest=1001&inNewCodePeriod=true",
}
}
>
1
</ForwardRef(Link)>
<SecurityHotspotIcon
className="big-spacer-left little-spacer-right"
/>
metric.new_security_hotspots.name
<HelpTooltip
className="little-spacer-left"
overlay="tooltip text"
/>
</Fragment>
`;

exports[`should render correctly for vulnerabilities 1`] = `
<Fragment>
<ForwardRef(Link)
aria-label="overview.see_list_of_x_y_issues.1.0.metric.vulnerabilities.name"
className="overview-measures-value text-light"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?pullRequest=1001&resolved=false&types=VULNERABILITY&inNewCodePeriod=false&id=my-project",
}
}
>
1
</ForwardRef(Link)>
<VulnerabilityIcon
className="big-spacer-left little-spacer-right"
/>
metric.vulnerabilities.name
</Fragment>
`;

exports[`should render correctly for vulnerabilities 2`] = `
<Fragment>
<ForwardRef(Link)
aria-label="overview.see_list_of_x_y_issues.1.0.metric.new_vulnerabilities.name"
className="overview-measures-value text-light"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?pullRequest=1001&resolved=false&types=VULNERABILITY&inNewCodePeriod=true&id=my-project",
}
}
>
1
</ForwardRef(Link)>
<VulnerabilityIcon
className="big-spacer-left little-spacer-right"
/>
metric.new_vulnerabilities.name
</Fragment>
`;

exports[`should render correctly if no values are present 1`] = `
<Fragment>
<span
aria-label="no_data"
className="overview-measures-empty-value"
/>
<BugIcon
className="big-spacer-left little-spacer-right"
/>
metric.bugs.name
</Fragment>
`;

+ 0
- 256
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueRating-test.tsx.snap View File

@@ -1,256 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly for bugs 1`] = `
<Fragment>
<span
className="flex-1 big-spacer-right text-right"
>
metric_domain.Reliability
</span>
<Tooltip
overlay={
<withAppStateContext(RatingTooltipContent)
metricKey="reliability_rating"
value="1.0"
/>
}
>
<span>
<DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="link-no-underline link-rating"
component="my-project"
metric="reliability_rating"
>
<Rating
value="1.0"
/>
</DrilldownLink>
</span>
</Tooltip>
</Fragment>
`;

exports[`should render correctly for bugs 2`] = `
<Fragment>
<span
className="flex-1 big-spacer-right text-right"
>
metric_domain.Reliability
</span>
<Tooltip
overlay={
<withAppStateContext(RatingTooltipContent)
metricKey="new_reliability_rating"
value="1.0"
/>
}
>
<span>
<DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="link-no-underline link-rating"
component="my-project"
metric="new_reliability_rating"
>
<Rating
value="1.0"
/>
</DrilldownLink>
</span>
</Tooltip>
</Fragment>
`;

exports[`should render correctly for code smells 1`] = `
<Fragment>
<span
className="flex-1 big-spacer-right text-right"
>
metric_domain.Maintainability
</span>
<Tooltip
overlay={
<withAppStateContext(RatingTooltipContent)
metricKey="sqale_rating"
value="1.0"
/>
}
>
<span>
<DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="link-no-underline link-rating"
component="my-project"
metric="sqale_rating"
>
<Rating
value="1.0"
/>
</DrilldownLink>
</span>
</Tooltip>
</Fragment>
`;

exports[`should render correctly for code smells 2`] = `
<Fragment>
<span
className="flex-1 big-spacer-right text-right"
>
metric_domain.Maintainability
</span>
<Tooltip
overlay={
<withAppStateContext(RatingTooltipContent)
metricKey="new_maintainability_rating"
value="1.0"
/>
}
>
<span>
<DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="link-no-underline link-rating"
component="my-project"
metric="new_maintainability_rating"
>
<Rating
value="1.0"
/>
</DrilldownLink>
</span>
</Tooltip>
</Fragment>
`;

exports[`should render correctly for vulnerabilities 1`] = `
<Fragment>
<span
className="flex-1 big-spacer-right text-right"
>
metric_domain.Security
</span>
<Tooltip
overlay={
<withAppStateContext(RatingTooltipContent)
metricKey="security_rating"
value="1.0"
/>
}
>
<span>
<DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="link-no-underline link-rating"
component="my-project"
metric="security_rating"
>
<Rating
value="1.0"
/>
</DrilldownLink>
</span>
</Tooltip>
</Fragment>
`;

exports[`should render correctly for vulnerabilities 2`] = `
<Fragment>
<span
className="flex-1 big-spacer-right text-right"
>
metric_domain.Security
</span>
<Tooltip
overlay={
<withAppStateContext(RatingTooltipContent)
metricKey="new_security_rating"
value="1.0"
/>
}
>
<span>
<DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="link-no-underline link-rating"
component="my-project"
metric="new_security_rating"
>
<Rating
value="1.0"
/>
</DrilldownLink>
</span>
</Tooltip>
</Fragment>
`;

exports[`should render correctly if no values are present 1`] = `
<Fragment>
<span
className="flex-1 big-spacer-right text-right"
>
metric_domain.Reliability
</span>
<div
className="padded"
>
<Rating />
</div>
</Fragment>
`;

+ 0
- 128
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/LeakPeriodLegend-test.tsx.snap View File

@@ -1,128 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`10 days 1`] = `
<div
className="overview-legend overview-legend-spaced-line"
>
overview.new_code_period_x.overview.period.days.10
</div>
`;

exports[`date 1`] = `
<Tooltip
overlay={
<DateFormatter
date={2013-09-21T22:00:00.000Z}
long={true}
>
[Function]
</DateFormatter>
}
>
<div
className="overview-legend"
>
overview.new_code_period_x.overview.period.date.formatted.2013-01-01
<br />
<DateFromNow
date={2013-09-21T22:00:00.000Z}
>
<Component />
</DateFromNow>
</div>
</Tooltip>
`;

exports[`manual_baseline 1`] = `
<div
className="overview-legend"
>
overview.new_code_period_x.overview.period.manual_baseline.formattedTime.2013-09-22T00:00:00+0200
<br />
<DateFromNow
date={2013-09-21T22:00:00.000Z}
>
<Component />
</DateFromNow>
</div>
`;

exports[`manual_baseline 2`] = `
<div
className="overview-legend"
>
overview.new_code_period_x.overview.period.manual_baseline.1.1.2
<br />
<DateFromNow
date={2013-09-21T22:00:00.000Z}
>
<Component />
</DateFromNow>
</div>
`;

exports[`previous_analysis 1`] = `
<div
className="overview-legend"
>
overview.new_code_period_x.overview.period.previous_analysis.
<br />
<DateFromNow
date={2013-09-21T22:00:00.000Z}
>
<Component />
</DateFromNow>
</div>
`;

exports[`previous_version 1`] = `
<div
className="overview-legend"
>
overview.new_code_period_x.overview.period.previous_version_only_date
<br />
<DateFromNow
date={2013-09-21T22:00:00.000Z}
>
<Component />
</DateFromNow>
</div>
`;

exports[`should render a more precise date 1`] = `
<Tooltip
overlay={
<DateTimeFormatter
date={2018-08-16T22:00:00.000Z}
>
[Function]
</DateTimeFormatter>
}
>
<div
className="overview-legend"
>
overview.new_code_period_x.overview.period.previous_version_only_date
<br />
<DateFromNow
date={2018-08-16T22:00:00.000Z}
>
<Component />
</DateFromNow>
</div>
</Tooltip>
`;

exports[`version 1`] = `
<div
className="overview-legend"
>
overview.new_code_period_x.overview.period.version.0.1
<br />
<DateFromNow
date={2013-09-21T22:00:00.000Z}
>
<Component />
</DateFromNow>
</div>
`;

+ 0
- 419
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/MeasurementLabel-test.tsx.snap View File

@@ -1,419 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly for coverage 1`] = `
<div
className="display-flex-center"
>
<span
className="big-spacer-right"
>
<CoverageRating
size="big"
value={1}
/>
</span>
<div
className="display-flex-column"
>
<span>
<DrilldownLink
ariaLabel="overview.see_more_details_on_x_of_y.1.0%.metric.coverage.name"
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="overview-measures-value text-light"
component="my-project"
metric="coverage"
>
1.0%
</DrilldownLink>
</span>
<span
className="spacer-top"
>
metric.coverage.name
</span>
</div>
</div>
`;

exports[`should render correctly for coverage 2`] = `
<div
className="display-flex-center"
>
<span
className="big-spacer-right"
>
<CoverageRating
size="big"
value={1}
/>
</span>
<div
className="display-flex-column"
>
<span>
<DrilldownLink
ariaLabel="overview.see_more_details_on_x_of_y.1.0%.metric.coverage.name"
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="overview-measures-value text-light"
component="my-project"
metric="coverage"
>
1.0%
</DrilldownLink>
</span>
<span
className="spacer-top"
>
<FormattedMessage
defaultMessage="overview.coverage_on_X_lines"
id="overview.coverage_on_X_lines"
values={
{
"count": <DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="big"
component="my-project"
metric="lines_to_cover"
>
1
</DrilldownLink>,
}
}
/>
</span>
</div>
</div>
`;

exports[`should render correctly for coverage 3`] = `
<div
className="display-flex-center"
>
<span
className="big-spacer-right"
>
<CoverageRating
size="big"
value={1}
/>
</span>
<div
className="display-flex-column"
>
<span>
<DrilldownLink
ariaLabel="overview.see_more_details_on_x_of_y.1.0%.metric.new_coverage.name"
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="overview-measures-value text-light"
component="my-project"
metric="new_coverage"
>
1.0%
</DrilldownLink>
</span>
<span
className="spacer-top"
>
<FormattedMessage
defaultMessage="overview.coverage_on_X_new_lines"
id="overview.coverage_on_X_new_lines"
values={
{
"count": <DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="big"
component="my-project"
metric="new_lines_to_cover"
>
1
</DrilldownLink>,
}
}
/>
</span>
</div>
</div>
`;

exports[`should render correctly for duplications 1`] = `
<div
className="display-flex-center"
>
<span
className="big-spacer-right"
>
<DuplicationsRating
size="big"
value={1}
/>
</span>
<div
className="display-flex-column"
>
<span>
<DrilldownLink
ariaLabel="overview.see_more_details_on_x_of_y.1.0%.metric.duplicated_lines_density.name"
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="overview-measures-value text-light"
component="my-project"
metric="duplicated_lines_density"
>
1.0%
</DrilldownLink>
</span>
<span
className="spacer-top"
>
metric.duplicated_lines_density.short_name
</span>
</div>
</div>
`;

exports[`should render correctly for duplications 2`] = `
<div
className="display-flex-center"
>
<span
className="big-spacer-right"
>
<DuplicationsRating
size="big"
value={1}
/>
</span>
<div
className="display-flex-column"
>
<span>
<DrilldownLink
ariaLabel="overview.see_more_details_on_x_of_y.1.0%.metric.duplicated_lines_density.name"
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="overview-measures-value text-light"
component="my-project"
metric="duplicated_lines_density"
>
1.0%
</DrilldownLink>
</span>
<span
className="spacer-top"
>
<FormattedMessage
defaultMessage="overview.duplications_on_X_lines"
id="overview.duplications_on_X_lines"
values={
{
"count": <DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="big"
component="my-project"
metric="ncloc"
>
1
</DrilldownLink>,
}
}
/>
</span>
</div>
</div>
`;

exports[`should render correctly for duplications 3`] = `
<div
className="display-flex-center"
>
<span
className="big-spacer-right"
>
<DuplicationsRating
size="big"
value={1}
/>
</span>
<div
className="display-flex-column"
>
<span>
<DrilldownLink
ariaLabel="overview.see_more_details_on_x_of_y.1.0%.metric.new_duplicated_lines_density.name"
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="overview-measures-value text-light"
component="my-project"
metric="new_duplicated_lines_density"
>
1.0%
</DrilldownLink>
</span>
<span
className="spacer-top"
>
<FormattedMessage
defaultMessage="overview.duplications_on_X_new_lines"
id="overview.duplications_on_X_new_lines"
values={
{
"count": <DrilldownLink
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="big"
component="my-project"
metric="new_lines"
>
1
</DrilldownLink>,
}
}
/>
</span>
</div>
</div>
`;

exports[`should render correctly when centered 1`] = `
<div
className="display-flex-column flex-1"
>
<div
className="display-flex-center display-flex-justify-center"
>
<span
className="big-spacer-right"
>
<CoverageRating
size="big"
value={1}
/>
</span>
<DrilldownLink
ariaLabel="overview.see_more_details_on_x_of_y.1.0%.metric.coverage.name"
branchLike={
{
"analysisDate": "2018-01-01",
"base": "master",
"branch": "feature/foo/bar",
"key": "1001",
"target": "master",
"title": "Foo Bar feature",
}
}
className="overview-measures-value text-light"
component="my-project"
metric="coverage"
>
1.0%
</DrilldownLink>
</div>
<div
className="spacer-top text-center"
>
metric.coverage.name
</div>
</div>
`;

exports[`should render correctly with no value 1`] = `
<div
className="display-flex-center"
>
<span
aria-label="no_data"
className="overview-measures-empty-value"
/>
<span
className="big-spacer-left"
>
metric.coverage.name
</span>
</div>
`;

+ 0
- 477
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/QualityGateCondition-test.tsx.snap View File

@@ -1,477 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correclty 1`] = `
<li>
<DrilldownLink
className="overview-quality-gate-condition overview-quality-gate-condition-error"
component="abcd-key"
inNewCodePeriod={false}
metric="open_issues"
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="open_issues"
metricType="INT"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="open_issues"
/>
metric.open_issues.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT
1
</span>
</div>
</div>
</DrilldownLink>
</li>
`;

exports[`should render correclty 2`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?resolved=false&types=BUG&severities=BLOCKER%2CCRITICAL%2CMAJOR%2CMINOR&id=abcd-key",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="reliability_rating"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="reliability_rating"
/>
metric.reliability_rating.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

exports[`should render correclty 3`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?resolved=false&types=VULNERABILITY&severities=BLOCKER%2CCRITICAL%2CMAJOR%2CMINOR&id=abcd-key",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="security_rating"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="security_rating"
/>
metric.security_rating.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

exports[`should render correclty 4`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?resolved=false&types=CODE_SMELL&id=abcd-key",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="sqale_rating"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="sqale_rating"
/>
metric.sqale_rating.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

exports[`should render correclty 5`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?resolved=false&types=BUG&severities=BLOCKER%2CCRITICAL%2CMAJOR%2CMINOR&inNewCodePeriod=true&id=abcd-key",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="new_reliability_rating"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="new_reliability_rating"
/>
metric.new_reliability_rating.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

exports[`should render correclty 6`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?resolved=false&types=VULNERABILITY&severities=BLOCKER%2CCRITICAL%2CMAJOR%2CMINOR&inNewCodePeriod=true&id=abcd-key",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="new_security_rating"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="new_security_rating"
/>
metric.new_security_rating.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

exports[`should render correclty 7`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?resolved=false&types=CODE_SMELL&inNewCodePeriod=true&id=abcd-key",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="new_maintainability_rating"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="new_maintainability_rating"
/>
metric.new_maintainability_rating.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

exports[`should render correclty 8`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/security_hotspots",
"search": "?id=abcd-key",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="security_hotspots_reviewed"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="security_hotspots_reviewed"
/>
metric.security_hotspots_reviewed.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

exports[`should render correclty 9`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/security_hotspots",
"search": "?id=abcd-key&inNewCodePeriod=true",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="new_security_hotspots_reviewed"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="new_security_hotspots_reviewed"
/>
metric.new_security_hotspots_reviewed.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

exports[`should work with branch 1`] = `
<li>
<ForwardRef(Link)
className="overview-quality-gate-condition overview-quality-gate-condition-error"
to={
{
"hash": "",
"pathname": "/project/issues",
"search": "?resolved=false&branch=branch-6.7&types=CODE_SMELL&inNewCodePeriod=true&id=abcd-key",
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
>
<div
className="overview-quality-gate-condition-value text-center spacer-right"
>
<Measure
decimals={2}
metricKey="new_maintainability_rating"
metricType="RATING"
value="3"
/>
</div>
<div>
<span
className="overview-quality-gate-condition-metric little-spacer-right"
>
<IssueTypeIcon
className="little-spacer-right"
query="new_maintainability_rating"
/>
metric.new_maintainability_rating.name
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT.rating
A
</span>
</div>
</div>
</ForwardRef(Link)>
</li>
`;

+ 0
- 28
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/SonarLintPromition-test.tsx.snap View File

@@ -1,28 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: has failed condition 1`] = `
<div
className="it__overview__sonarlint-promotion big-spacer-top overview-quality-gate-sonar-lint-info"
>
<FormattedMessage
defaultMessage="overview.fix_failed_conditions_with_sonarlint"
id="overview.fix_failed_conditions_with_sonarlint"
values={
{
"link": <React.Fragment>
<a
href="https://www.sonarqube.org/sonarlint/?referrer=sonarqube"
rel="noopener noreferrer"
target="_blank"
>
SonarLint
</a>
<SonarLintIcon
size={16}
/>
</React.Fragment>,
}
}
/>
</div>
`;

+ 0
- 54
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/AfterMergeEstimate-test.tsx View File

@@ -1,54 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { MetricKey } from '../../../../types/metrics';
import { MeasurementType } from '../../utils';
import { AfterMergeEstimate, AfterMergeEstimateProps } from '../AfterMergeEstimate';

it('should render correctly for coverage', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should render correctly for duplications', () => {
expect(
shallowRender({
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.duplicated_lines_density }) }),
],
type: MeasurementType.Duplication,
})
).toMatchSnapshot();
});

it('should render correctly with no value', () => {
expect(shallowRender({ measures: [] })).toMatchSnapshot();
});

function shallowRender(props: Partial<AfterMergeEstimateProps> = {}) {
return shallow(
<AfterMergeEstimate
measures={[mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) })]}
type={MeasurementType.Coverage}
{...props}
/>
);
}

+ 0
- 32
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/LargeQualityGateBadge-test.tsx View File

@@ -1,32 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockComponent } from '../../../../helpers/mocks/component';
import { LargeQualityGateBadge } from '../LargeQualityGateBadge';

it('should render correctly for SQ', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ level: 'OK' })).toMatchSnapshot();
});

function shallowRender(props = {}) {
return shallow(<LargeQualityGateBadge component={mockComponent()} level="ERROR" {...props} />);
}

+ 177
- 0
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx View File

@@ -0,0 +1,177 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { screen } from '@testing-library/react';
import * as React from 'react';
import CurrentUserContextProvider from '../../../../app/components/current-user/CurrentUserContextProvider';
import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockQualityGateStatusCondition } from '../../../../helpers/mocks/quality-gates';
import { mockLoggedInUser, mockMetric, mockPeriod } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { ComponentQualifier } from '../../../../types/component';
import { MetricKey } from '../../../../types/metrics';
import { PullRequestOverview } from '../PullRequestOverview';

jest.mock('../../../../api/measures', () => {
return {
...jest.requireActual('../../../../types/metrics'),
getMeasuresWithMetrics: jest.fn().mockResolvedValue({
component: {
key: '',
name: '',
qualifier: ComponentQualifier.Project,
measures: [
mockQualityGateStatusCondition({
error: '1.0',
metric: MetricKey.new_coverage,
period: 1,
}),
mockQualityGateStatusCondition({
error: '1.0',
metric: MetricKey.duplicated_lines,
period: 1,
}),
mockQualityGateStatusCondition({
error: '3',
metric: MetricKey.new_bugs,
period: 1,
}),
],
},
metrics: [
mockMetric({ key: MetricKey.new_coverage }),
mockMetric({
key: MetricKey.duplicated_lines,
}),
mockMetric({
key: MetricKey.new_bugs,
type: 'INT',
}),
],
period: mockPeriod(),
}),
};
});

jest.mock('../../../../api/quality-gates', () => {
const { mockQualityGateProjectStatus, mockQualityGateApplicationStatus } = jest.requireActual(
'../../../../helpers/mocks/quality-gates'
);
const { MetricKey } = jest.requireActual('../../../../types/metrics');
return {
getQualityGateProjectStatus: jest.fn().mockResolvedValue(
mockQualityGateProjectStatus({
status: 'ERROR',
conditions: [
{
actualValue: '2',
comparator: 'GT',
errorThreshold: '1',
metricKey: MetricKey.new_reliability_rating,
periodIndex: 1,
status: 'ERROR',
},
{
actualValue: '5',
comparator: 'GT',
errorThreshold: '2.0',
metricKey: MetricKey.bugs,
periodIndex: 0,
status: 'ERROR',
},
{
actualValue: '2',
comparator: 'GT',
errorThreshold: '1.0',
metricKey: 'unknown_metric',
periodIndex: 0,
status: 'ERROR',
},
],
})
),
getApplicationQualityGate: jest.fn().mockResolvedValue(mockQualityGateApplicationStatus()),
};
});

it('should render correctly for a passed QG', async () => {
renderPullRequestOverview({ status: 'OK', conditions: [] });

expect(await screen.findByText('metric.level.OK')).toBeInTheDocument();
expect(screen.queryByText('overview.failed_conditions')).not.toBeInTheDocument();
});

it('should render correctly if conditions are ignored', async () => {
renderPullRequestOverview({ conditions: [], ignoredConditions: true });

expect(await screen.findByText('overview.quality_gate.ignored_conditions')).toBeInTheDocument();
});

it('should render correctly for a failed QG', async () => {
renderPullRequestOverview({
status: 'ERROR',
conditions: [
mockQualityGateStatusCondition({
error: '2.0',
metric: MetricKey.new_coverage,
period: 1,
}),
mockQualityGateStatusCondition({
error: '1.0',
metric: MetricKey.duplicated_lines,
period: 1,
}),
mockQualityGateStatusCondition({
error: '3',
metric: MetricKey.new_bugs,
period: 1,
}),
],
});

expect(await screen.findByText('metric.level.ERROR')).toBeInTheDocument();

expect(await screen.findByText('overview.failed_conditions')).toBeInTheDocument();

expect(await screen.findByText('metric.new_coverage.name')).toBeInTheDocument();
expect(await screen.findByText('quality_gates.operator.GT 2.0%')).toBeInTheDocument();

expect(await screen.findByText('metric.duplicated_lines.name')).toBeInTheDocument();
expect(await screen.findByText('quality_gates.operator.GT 1.0%')).toBeInTheDocument();

expect(screen.getByText('quality_gates.operator.GT 3')).toBeInTheDocument();
});

function renderPullRequestOverview(props: Partial<PullRequestOverview['props']> = {}) {
renderComponent(
<CurrentUserContextProvider currentUser={mockLoggedInUser()}>
<PullRequestOverview
fetchBranchStatus={jest.fn()}
branchLike={mockPullRequest()}
component={mockComponent({
breadcrumbs: [mockComponent({ key: 'foo' })],
key: 'foo',
name: 'Foo',
})}
{...props}
/>
</CurrentUserContextProvider>
);
}

+ 0
- 134
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-test.tsx View File

@@ -1,134 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { getMeasuresWithMetrics } from '../../../../api/measures';
import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockQualityGateStatusCondition } from '../../../../helpers/mocks/quality-gates';
import { waitAndUpdate } from '../../../../helpers/testUtils';
import { PR_METRICS } from '../../utils';
import { PullRequestOverview } from '../PullRequestOverview';

jest.mock('../../../../api/measures', () => {
const { mockMeasure, mockMetric } = jest.requireActual('../../../../helpers/testMocks');
return {
getMeasuresWithMetrics: jest.fn().mockResolvedValue({
component: {
measures: [
mockMeasure({ metric: 'new_bugs' }),
mockMeasure({ metric: 'new_vulnerabilities' }),
mockMeasure({ metric: 'new_code_smells' }),
mockMeasure({ metric: 'new_security_hotspots' }),
],
},
metrics: [
mockMetric({ key: 'new_bugs', name: 'new_bugs', id: 'new_bugs' }),
mockMetric({
key: 'new_vulnerabilities',
name: 'new_vulnerabilities',
id: 'new_vulnerabilities',
}),
mockMetric({ key: 'new_code_smells', name: 'new_code_smells', id: 'new_code_smells' }),
mockMetric({
key: 'new_security_hotspots',
name: 'new_security_hotspots',
id: 'new_security_hotspots',
}),
],
}),
};
});

beforeEach(() => {
jest.clearAllMocks();
});

it('should render correctly for a passed QG', async () => {
const fetchBranchStatus = jest.fn();

const wrapper = shallowRender({ fetchBranchStatus, status: 'OK' });

wrapper.setProps({ conditions: [] });

await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();

expect(wrapper.find('QualityGateConditions').exists()).toBe(false);

expect(getMeasuresWithMetrics).toHaveBeenCalled();
expect(fetchBranchStatus).toHaveBeenCalled();
});

it('should render correctly if conditions are ignored', async () => {
const wrapper = shallowRender({ conditions: [], ignoredConditions: true });
await waitAndUpdate(wrapper);
expect(wrapper.find('Alert').exists()).toBe(true);
});

it('should render correctly for a failed QG', async () => {
const wrapper = shallowRender({
status: 'ERROR',
conditions: [
mockQualityGateStatusCondition({
error: '1.0',
level: 'OK',
metric: 'new_bugs',
period: 1,
}),
mockQualityGateStatusCondition({
error: '1.0',
metric: 'new_code_smells',
period: 1,
}),
],
});
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
});

it('should correctly fetch all required metrics for a passing QG', async () => {
const wrapper = shallowRender({ conditions: [] });
await waitAndUpdate(wrapper);
expect(getMeasuresWithMetrics).toHaveBeenCalledWith('my-project', PR_METRICS, expect.any(Object));
});

it('should correctly fetch all required metrics for a failing QG', async () => {
const wrapper = shallowRender({
conditions: [mockQualityGateStatusCondition({ level: 'ERROR', metric: 'foo' })],
});
await waitAndUpdate(wrapper);
expect(getMeasuresWithMetrics).toHaveBeenCalledWith(
'my-project',
[...PR_METRICS, 'foo'],
expect.any(Object)
);
});

function shallowRender(props: Partial<PullRequestOverview['props']> = {}) {
return shallow(
<PullRequestOverview
branchLike={mockPullRequest()}
component={mockComponent()}
fetchBranchStatus={jest.fn()}
{...props}
/>
);
}

+ 0
- 37
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/AfterMergeEstimate-test.tsx.snap View File

@@ -1,37 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly for coverage 1`] = `
<div
className="display-flex-center"
>
<span
className="huge"
>
1.0%
</span>
<span
className="label flex-1 spacer-left text-right"
>
component_measures.facet_category.overall_category.estimated
</span>
</div>
`;

exports[`should render correctly for duplications 1`] = `
<div
className="display-flex-center"
>
<span
className="huge"
>
1.0%
</span>
<span
className="label flex-1 spacer-left text-right"
>
component_measures.facet_category.overall_category.estimated
</span>
</div>
`;

exports[`should render correctly with no value 1`] = `""`;

+ 0
- 93
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/LargeQualityGateBadge-test.tsx.snap View File

@@ -1,93 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly for SQ 1`] = `
<div
className="overview-quality-gate-badge-large small failed"
>
<div
className="display-flex-center"
>
<span>
overview.on_new_code_long
</span>
<HelpTooltip
className="little-spacer-left"
overlay={
<FormattedMessage
defaultMessage="overview.quality_gate.conditions_on_new_code"
id="overview.quality_gate.conditions_on_new_code"
values={
{
"link": <ForwardRef(Link)
to={
{
"pathname": "/quality_gates/show/Sonar%20way",
}
}
>
overview.quality_gate
</ForwardRef(Link)>,
}
}
/>
}
>
<HelpIcon
fill="rgba(255,255,255,0.62)"
size={12}
/>
</HelpTooltip>
</div>
<div
className="huge-spacer-top huge h3"
>
metric.level.ERROR
</div>
</div>
`;

exports[`should render correctly for SQ 2`] = `
<div
className="overview-quality-gate-badge-large small success"
>
<div
className="display-flex-center"
>
<span>
overview.on_new_code_long
</span>
<HelpTooltip
className="little-spacer-left"
overlay={
<FormattedMessage
defaultMessage="overview.quality_gate.conditions_on_new_code"
id="overview.quality_gate.conditions_on_new_code"
values={
{
"link": <ForwardRef(Link)
to={
{
"pathname": "/quality_gates/show/Sonar%20way",
}
}
>
overview.quality_gate
</ForwardRef(Link)>,
}
}
/>
}
>
<HelpIcon
fill="rgba(255,255,255,0.62)"
size={12}
/>
</HelpTooltip>
</div>
<div
className="huge-spacer-top huge h3"
>
metric.level.OK
</div>
</div>
`;

+ 0
- 2653
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/PullRequestOverview-test.tsx.snap
File diff suppressed because it is too large
View File


+ 2
- 2
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -2215,8 +2215,8 @@ my_account.preferences.keyboard_shortcuts.disabled=Keyboard shortcuts are disabl
provisioning.no_analysis=No analysis has been performed since creation. The only available section is the configuration.
provisioning.no_analysis.delete=Either you should retry analysis or simply {link}.
provisioning.no_analysis.delete_project=delete the project
provisioning.no_analysis_on_main_branch="{branchName}" branch has not been analyzed yet.
provisioning.no_analysis_on_main_branch.bad_configuration="{branchName}" branch has not been analyzed yet and you have multiple branches already. It looks like it is not your {branchType}, check your configuration.
provisioning.no_analysis_on_main_branch="{0}" branch has not been analyzed yet.
provisioning.no_analysis_on_main_branch.bad_configuration="{0}" branch has not been analyzed yet and you have multiple branches already. It looks like it is not your {1}, check your configuration.
provisioning.only_provisioned=Only Provisioned
provisioning.only_provisioned.tooltip=Provisioned projects are projects that have been created, but have not been analyzed yet.
provisioning.no_analysis.application=No analysis has been performed since creation. Analyze a project to see information here.

Loading…
Cancel
Save