Browse Source

SONAR-14760 Fix quality gate condition link in the overview page.

tags/9.0.0.45539
Mathieu Suen 2 years ago
parent
commit
3cd819d9bc

+ 29
- 16
server/sonar-web/src/main/js/apps/overview/components/QualityGateCondition.tsx View File

@@ -23,12 +23,15 @@ import { Link } from 'react-router';
import IssueTypeIcon from 'sonar-ui-common/components/icons/IssueTypeIcon';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { formatMeasure } from 'sonar-ui-common/helpers/measures';
import { Location } from 'sonar-ui-common/helpers/urls';
import Measure from '../../../components/measure/Measure';
import DrilldownLink from '../../../components/shared/DrilldownLink';
import { getBranchLikeQuery } from '../../../helpers/branch-like';
import { isDiffMetric } from '../../../helpers/measures';
import { getComponentIssuesUrl } from '../../../helpers/urls';
import { getComponentIssuesUrl, getComponentSecurityHotspotsUrl } from '../../../helpers/urls';
import { BranchLike } from '../../../types/branch-like';
import { IssueType } from '../../../types/issues';
import { MetricKey } from '../../../types/metrics';
import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates';

interface Props {
@@ -50,6 +53,16 @@ export default class QualityGateCondition extends React.PureComponent<Props> {
return getComponentIssuesUrl(this.props.component.key, query);
};

getUrlForSecurityHotspot(sinceLeakPeriod: boolean) {
const query: T.Dict<string | undefined> = {
...getBranchLikeQuery(this.props.branchLike)
};
if (sinceLeakPeriod) {
Object.assign(query, { sinceLeakPeriod: 'true' });
}
return getComponentSecurityHotspotsUrl(this.props.component.key, query);
}

getUrlForCodeSmells(sinceLeakPeriod: boolean) {
return this.getIssuesUrl(sinceLeakPeriod, { types: 'CODE_SMELL' });
}
@@ -71,12 +84,6 @@ export default class QualityGateCondition extends React.PureComponent<Props> {
});
}

getUrlForType(type: string, sinceLeakPeriod: boolean) {
return type === 'CODE_SMELL'
? this.getUrlForCodeSmells(sinceLeakPeriod)
: this.getUrlForBugsOrVulnerabilities(type, sinceLeakPeriod);
}

wrapWithLink(children: React.ReactNode) {
const { branchLike, component, condition } = this.props;

@@ -87,17 +94,23 @@ export default class QualityGateCondition extends React.PureComponent<Props> {

const metricKey = condition.measure.metric.key;

const RATING_METRICS_MAPPING: T.Dict<[string, boolean]> = {
reliability_rating: ['BUG', false],
new_reliability_rating: ['BUG', true],
security_rating: ['VULNERABILITY', false],
new_security_rating: ['VULNERABILITY', true],
sqale_rating: ['CODE_SMELL', false],
new_maintainability_rating: ['CODE_SMELL', true]
const METRICS_TO_URL_MAPPING: T.Dict<() => Location> = {
[MetricKey.reliability_rating]: () =>
this.getUrlForBugsOrVulnerabilities(IssueType.Bug, false),
[MetricKey.new_reliability_rating]: () =>
this.getUrlForBugsOrVulnerabilities(IssueType.Bug, true),
[MetricKey.security_rating]: () =>
this.getUrlForBugsOrVulnerabilities(IssueType.Vulnerability, false),
[MetricKey.new_security_rating]: () =>
this.getUrlForBugsOrVulnerabilities(IssueType.Vulnerability, true),
[MetricKey.sqale_rating]: () => this.getUrlForCodeSmells(false),
[MetricKey.new_maintainability_rating]: () => this.getUrlForCodeSmells(true),
[MetricKey.security_hotspots_reviewed]: () => this.getUrlForSecurityHotspot(false),
[MetricKey.new_security_hotspots_reviewed]: () => this.getUrlForSecurityHotspot(true)
};

return RATING_METRICS_MAPPING[metricKey] ? (
<Link className={className} to={this.getUrlForType(...RATING_METRICS_MAPPING[metricKey])}>
return METRICS_TO_URL_MAPPING[metricKey] ? (
<Link className={className} to={METRICS_TO_URL_MAPPING[metricKey]()}>
{children}
</Link>
) : (

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

@@ -22,63 +22,30 @@ 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 { MetricKey } from '../../../../types/metrics';
import { QualityGateStatusConditionEnhanced } from '../../../../types/quality-gates';
import QualityGateCondition from '../QualityGateCondition';

it('open_issues', () => {
const condition = quickMock('open_issues', 'INT');
expect(shallowRender({ condition })).toMatchSnapshot();
});

it('new_open_issues', () => {
const condition = quickMock('new_open_issues', 'INT', true);
expect(shallowRender({ condition })).toMatchSnapshot();
});

it('reliability_rating', () => {
const condition = quickMock('reliability_rating');
expect(shallowRender({ condition })).toMatchSnapshot();
});

it('security_rating', () => {
const condition = quickMock('security_rating');
expect(shallowRender({ condition })).toMatchSnapshot();
});

it('sqale_rating', () => {
const condition = quickMock('sqale_rating');
expect(shallowRender({ condition })).toMatchSnapshot();
});

it('new_reliability_rating', () => {
const condition = quickMock('new_reliability_rating', 'RATING', true);
expect(shallowRender({ condition })).toMatchSnapshot();
});

it('new_security_rating', () => {
const condition = quickMock('new_security_rating', 'RATING', true);
expect(shallowRender({ condition })).toMatchSnapshot();
});

it('new_maintainability_rating', () => {
const condition = quickMock('new_maintainability_rating', 'RATING', true);
it.each([
[quickMock(MetricKey.open_issues, 'INT')],
[quickMock(MetricKey.reliability_rating)],
[quickMock(MetricKey.security_rating)],
[quickMock(MetricKey.sqale_rating)],
[quickMock(MetricKey.new_reliability_rating, 'RATING', true)],
[quickMock(MetricKey.new_security_rating, 'RATING', true)],
[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();
});

it('should work with branch', () => {
const condition = quickMock('new_maintainability_rating');
expect(
shallow(
<QualityGateCondition
branchLike={mockBranch()}
component={{ key: 'abcd-key' }}
condition={condition}
/>
)
).toMatchSnapshot();
const condition = quickMock(MetricKey.new_maintainability_rating);
expect(shallowRender({ branchLike: mockBranch(), condition })).toMatchSnapshot();
});

function shallowRender(props = {}) {
function shallowRender(props: Partial<QualityGateCondition['props']>) {
return shallow(
<QualityGateCondition
component={{ key: 'abcd-key' }}
@@ -89,7 +56,7 @@ function shallowRender(props = {}) {
}

function quickMock(
metric: string,
metric: MetricKey,
type = 'RATING',
addPeriod = false
): QualityGateStatusConditionEnhanced {

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

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

exports[`new_maintainability_rating 1`] = `
exports[`should render correclty 1`] = `
<DrilldownLink
className="overview-quality-gate-condition overview-quality-gate-condition-error"
component="abcd-key"
metric="open_issues"
sinceLeakPeriod={false}
>
<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"
/>
open_issues
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT
1
</span>
</div>
</div>
</DrilldownLink>
`;

exports[`should render correclty 2`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
onlyActiveOnIndex={false}
@@ -11,8 +53,8 @@ exports[`new_maintainability_rating 1`] = `
"query": Object {
"id": "abcd-key",
"resolved": "false",
"sinceLeakPeriod": "true",
"types": "CODE_SMELL",
"severities": "BLOCKER,CRITICAL,MAJOR,MINOR",
"types": "BUG",
},
}
}
@@ -25,7 +67,7 @@ exports[`new_maintainability_rating 1`] = `
>
<Measure
decimals={2}
metricKey="new_maintainability_rating"
metricKey="reliability_rating"
metricType="RATING"
value="3"
/>
@@ -36,9 +78,9 @@ exports[`new_maintainability_rating 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="new_maintainability_rating"
query="reliability_rating"
/>
new_maintainability_rating
reliability_rating
</span>
<span
className="little-spacer-top small text-muted"
@@ -52,12 +94,22 @@ exports[`new_maintainability_rating 1`] = `
</Link>
`;

exports[`new_open_issues 1`] = `
<DrilldownLink
exports[`should render correclty 3`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
component="abcd-key"
metric="new_open_issues"
sinceLeakPeriod={true}
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/issues",
"query": Object {
"id": "abcd-key",
"resolved": "false",
"severities": "BLOCKER,CRITICAL,MAJOR,MINOR",
"types": "VULNERABILITY",
},
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
@@ -67,8 +119,8 @@ exports[`new_open_issues 1`] = `
>
<Measure
decimals={2}
metricKey="new_open_issues"
metricType="INT"
metricKey="security_rating"
metricType="RATING"
value="3"
/>
</div>
@@ -78,23 +130,23 @@ exports[`new_open_issues 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="new_open_issues"
query="security_rating"
/>
new_open_issues
security_rating
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT
quality_gates.operator.GT.rating
1
A
</span>
</div>
</div>
</DrilldownLink>
</Link>
`;

exports[`new_reliability_rating 1`] = `
exports[`should render correclty 4`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
onlyActiveOnIndex={false}
@@ -105,9 +157,7 @@ exports[`new_reliability_rating 1`] = `
"query": Object {
"id": "abcd-key",
"resolved": "false",
"severities": "BLOCKER,CRITICAL,MAJOR,MINOR",
"sinceLeakPeriod": "true",
"types": "BUG",
"types": "CODE_SMELL",
},
}
}
@@ -120,7 +170,7 @@ exports[`new_reliability_rating 1`] = `
>
<Measure
decimals={2}
metricKey="new_reliability_rating"
metricKey="sqale_rating"
metricType="RATING"
value="3"
/>
@@ -131,9 +181,9 @@ exports[`new_reliability_rating 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="new_reliability_rating"
query="sqale_rating"
/>
new_reliability_rating
sqale_rating
</span>
<span
className="little-spacer-top small text-muted"
@@ -147,7 +197,7 @@ exports[`new_reliability_rating 1`] = `
</Link>
`;

exports[`new_security_rating 1`] = `
exports[`should render correclty 5`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
onlyActiveOnIndex={false}
@@ -160,7 +210,7 @@ exports[`new_security_rating 1`] = `
"resolved": "false",
"severities": "BLOCKER,CRITICAL,MAJOR,MINOR",
"sinceLeakPeriod": "true",
"types": "VULNERABILITY",
"types": "BUG",
},
}
}
@@ -173,7 +223,7 @@ exports[`new_security_rating 1`] = `
>
<Measure
decimals={2}
metricKey="new_security_rating"
metricKey="new_reliability_rating"
metricType="RATING"
value="3"
/>
@@ -184,9 +234,9 @@ exports[`new_security_rating 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="new_security_rating"
query="new_reliability_rating"
/>
new_security_rating
new_reliability_rating
</span>
<span
className="little-spacer-top small text-muted"
@@ -200,12 +250,23 @@ exports[`new_security_rating 1`] = `
</Link>
`;

exports[`open_issues 1`] = `
<DrilldownLink
exports[`should render correclty 6`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
component="abcd-key"
metric="open_issues"
sinceLeakPeriod={false}
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/issues",
"query": Object {
"id": "abcd-key",
"resolved": "false",
"severities": "BLOCKER,CRITICAL,MAJOR,MINOR",
"sinceLeakPeriod": "true",
"types": "VULNERABILITY",
},
}
}
>
<div
className="overview-quality-gate-condition-container display-flex-center"
@@ -215,8 +276,8 @@ exports[`open_issues 1`] = `
>
<Measure
decimals={2}
metricKey="open_issues"
metricType="INT"
metricKey="new_security_rating"
metricType="RATING"
value="3"
/>
</div>
@@ -226,23 +287,23 @@ exports[`open_issues 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="open_issues"
query="new_security_rating"
/>
open_issues
new_security_rating
</span>
<span
className="little-spacer-top small text-muted"
>
quality_gates.operator.GT
quality_gates.operator.GT.rating
1
A
</span>
</div>
</div>
</DrilldownLink>
</Link>
`;

exports[`reliability_rating 1`] = `
exports[`should render correclty 7`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
onlyActiveOnIndex={false}
@@ -253,8 +314,8 @@ exports[`reliability_rating 1`] = `
"query": Object {
"id": "abcd-key",
"resolved": "false",
"severities": "BLOCKER,CRITICAL,MAJOR,MINOR",
"types": "BUG",
"sinceLeakPeriod": "true",
"types": "CODE_SMELL",
},
}
}
@@ -267,7 +328,7 @@ exports[`reliability_rating 1`] = `
>
<Measure
decimals={2}
metricKey="reliability_rating"
metricKey="new_maintainability_rating"
metricType="RATING"
value="3"
/>
@@ -278,9 +339,9 @@ exports[`reliability_rating 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="reliability_rating"
query="new_maintainability_rating"
/>
reliability_rating
new_maintainability_rating
</span>
<span
className="little-spacer-top small text-muted"
@@ -294,19 +355,21 @@ exports[`reliability_rating 1`] = `
</Link>
`;

exports[`security_rating 1`] = `
exports[`should render correclty 8`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/issues",
"pathname": "/security_hotspots",
"query": Object {
"assignedToMe": undefined,
"branch": undefined,
"hotspots": undefined,
"id": "abcd-key",
"resolved": "false",
"severities": "BLOCKER,CRITICAL,MAJOR,MINOR",
"types": "VULNERABILITY",
"pullRequest": undefined,
"sinceLeakPeriod": undefined,
},
}
}
@@ -319,7 +382,7 @@ exports[`security_rating 1`] = `
>
<Measure
decimals={2}
metricKey="security_rating"
metricKey="security_hotspots_reviewed"
metricType="RATING"
value="3"
/>
@@ -330,9 +393,9 @@ exports[`security_rating 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="security_rating"
query="security_hotspots_reviewed"
/>
security_rating
security_hotspots_reviewed
</span>
<span
className="little-spacer-top small text-muted"
@@ -346,20 +409,21 @@ exports[`security_rating 1`] = `
</Link>
`;

exports[`should work with branch 1`] = `
exports[`should render correclty 9`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/issues",
"pathname": "/security_hotspots",
"query": Object {
"branch": "branch-6.7",
"assignedToMe": undefined,
"branch": undefined,
"hotspots": undefined,
"id": "abcd-key",
"resolved": "false",
"pullRequest": undefined,
"sinceLeakPeriod": "true",
"types": "CODE_SMELL",
},
}
}
@@ -372,7 +436,7 @@ exports[`should work with branch 1`] = `
>
<Measure
decimals={2}
metricKey="new_maintainability_rating"
metricKey="new_security_hotspots_reviewed"
metricType="RATING"
value="3"
/>
@@ -383,9 +447,9 @@ exports[`should work with branch 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="new_maintainability_rating"
query="new_security_hotspots_reviewed"
/>
new_maintainability_rating
new_security_hotspots_reviewed
</span>
<span
className="little-spacer-top small text-muted"
@@ -399,7 +463,7 @@ exports[`should work with branch 1`] = `
</Link>
`;

exports[`sqale_rating 1`] = `
exports[`should work with branch 1`] = `
<Link
className="overview-quality-gate-condition overview-quality-gate-condition-error"
onlyActiveOnIndex={false}
@@ -408,8 +472,10 @@ exports[`sqale_rating 1`] = `
Object {
"pathname": "/project/issues",
"query": Object {
"branch": "branch-6.7",
"id": "abcd-key",
"resolved": "false",
"sinceLeakPeriod": "true",
"types": "CODE_SMELL",
},
}
@@ -423,7 +489,7 @@ exports[`sqale_rating 1`] = `
>
<Measure
decimals={2}
metricKey="sqale_rating"
metricKey="new_maintainability_rating"
metricType="RATING"
value="3"
/>
@@ -434,9 +500,9 @@ exports[`sqale_rating 1`] = `
>
<IssueTypeIcon
className="little-spacer-right"
query="sqale_rating"
query="new_maintainability_rating"
/>
sqale_rating
new_maintainability_rating
</span>
<span
className="little-spacer-top small text-muted"

Loading…
Cancel
Save