import { getOperatorLabel } from '../../../helpers/qualityGates';
import { getComponentDrilldownUrl } from '../../../helpers/urls';
import { BranchLike } from '../../../types/branch-like';
+import { SoftwareQuality } from '../../../types/clean-code-taxonomy';
import { IssueType } from '../../../types/issues';
import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates';
import { Component, Dict, Metric } from '../../../types/types';
import { getLocalizedMetricNameNoDiffMetric } from '../../quality-gates/utils';
-import { RATING_TO_SEVERITIES_MAPPING } from '../utils';
+import { MQR_RATING_TO_SEVERITIES_MAPPING, RATING_TO_SEVERITIES_MAPPING } from '../utils';
interface Props {
branchLike?: BranchLike;
return this.getIssuesUrl(inNewCodePeriod, { types: 'CODE_SMELL' });
}
+ getUrlForSoftwareQualityRatings(quality: SoftwareQuality, isNewCode: boolean) {
+ const { condition } = this.props;
+ const threshold = condition.level === 'ERROR' ? condition.error : condition.warning;
+
+ if (quality === SoftwareQuality.Maintainability) {
+ return this.getIssuesUrl(isNewCode, {
+ impactSoftwareQualities: quality,
+ });
+ }
+
+ return this.getIssuesUrl(isNewCode, {
+ impactSeverities: MQR_RATING_TO_SEVERITIES_MAPPING[Number(threshold) - 1],
+ impactSoftwareQualities: quality,
+ });
+ }
+
getUrlForBugsOrVulnerabilities(type: string, inNewCodePeriod: boolean) {
const { condition } = this.props;
const threshold = condition.level === 'ERROR' ? condition.error : condition.warning;
[MetricKey.new_maintainability_rating]: () => this.getUrlForCodeSmells(true),
[MetricKey.security_hotspots_reviewed]: () => this.getUrlForSecurityHotspot(false),
[MetricKey.new_security_hotspots_reviewed]: () => this.getUrlForSecurityHotspot(true),
+ // MQR
+ [MetricKey.new_software_quality_reliability_rating]: () =>
+ this.getUrlForSoftwareQualityRatings(SoftwareQuality.Reliability, true),
+ [MetricKey.new_software_quality_security_rating]: () =>
+ this.getUrlForSoftwareQualityRatings(SoftwareQuality.Security, true),
+ [MetricKey.new_software_quality_maintainability_rating]: () =>
+ this.getUrlForSoftwareQualityRatings(SoftwareQuality.Maintainability, true),
+ [MetricKey.software_quality_reliability_rating]: () =>
+ this.getUrlForSoftwareQualityRatings(SoftwareQuality.Reliability, false),
+ [MetricKey.software_quality_security_rating]: () =>
+ this.getUrlForSoftwareQualityRatings(SoftwareQuality.Security, false),
+ [MetricKey.software_quality_maintainability_rating]: () =>
+ this.getUrlForSoftwareQualityRatings(SoftwareQuality.Maintainability, false),
};
if (METRICS_TO_URL_MAPPING[metricKey]) {
import { screen } from '@testing-library/react';
import { byRole } from '~sonar-aligned/helpers/testSelector';
import { Status } from '~sonar-aligned/types/common';
-import { MetricKey } from '~sonar-aligned/types/metrics';
+import { MetricKey, MetricType } from '~sonar-aligned/types/metrics';
import CurrentUserContextProvider from '../../../../app/components/current-user/CurrentUserContextProvider';
-import { mockQualityGate, mockQualityGateStatus } from '../../../../helpers/mocks/quality-gates';
+import {
+ mockQualityGate,
+ mockQualityGateStatus,
+ mockQualityGateStatusConditionEnhanced,
+} from '../../../../helpers/mocks/quality-gates';
import { mockLoggedInUser } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { CaycStatus } from '../../../../types/types';
import { CurrentUser, NoticeType } from '../../../../types/users';
import QualityGatePanelSection, { QualityGatePanelSectionProps } from '../QualityGatePanelSection';
-const failedConditions = [
- {
- level: 'ERROR' as Status,
+const mockCondition = (metric: MetricKey, type = MetricType.Rating) =>
+ mockQualityGateStatusConditionEnhanced({
+ level: 'ERROR',
+ metric,
measure: {
- metric: {
- id: 'metricId1',
- key: MetricKey.new_coverage,
- name: 'metricName1',
- type: 'metricType1',
- },
+ metric: { id: metric, key: metric, name: metric, type },
},
- metric: MetricKey.new_coverage,
- op: 'op1',
- },
- {
- level: 'ERROR' as Status,
- measure: {
- metric: {
- id: 'metricId2',
- key: MetricKey.security_hotspots,
- name: 'metricName2',
- type: 'metricType2',
- },
- },
- metric: MetricKey.security_hotspots,
- op: 'op2',
- },
- {
- level: 'ERROR' as Status,
- measure: {
- metric: {
- id: 'metricId2',
- key: MetricKey.new_violations,
- name: 'metricName2',
- type: 'metricType2',
- },
- },
- metric: MetricKey.new_violations,
- op: 'op2',
- },
+ });
+
+const failedConditions = [
+ mockCondition(MetricKey.new_coverage),
+ mockCondition(MetricKey.security_hotspots),
+ mockCondition(MetricKey.new_violations),
];
const qgStatus = mockQualityGateStatus({
expect(await byRole('alertdialog').query()).not.toBeInTheDocument();
});
+it('should render correct links for ratings with "overall code" failed conditions', () => {
+ renderQualityGatePanelSection(
+ {
+ isApplication: false,
+ isNewCode: false,
+ qgStatus: {
+ ...qgStatus,
+ failedConditions: [
+ mockCondition(MetricKey.sqale_rating),
+ mockCondition(MetricKey.reliability_rating),
+ mockCondition(MetricKey.security_rating),
+ mockCondition(MetricKey.software_quality_security_rating),
+ mockCondition(MetricKey.software_quality_reliability_rating),
+ mockCondition(MetricKey.software_quality_maintainability_rating),
+ ],
+ },
+ qualityGate: mockQualityGate({ isBuiltIn: true }),
+ },
+ mockLoggedInUser({
+ dismissedNotices: { [NoticeType.OVERVIEW_ZERO_NEW_ISSUES_SIMPLIFICATION]: true },
+ }),
+ );
+
+ expect(byRole('link', { name: /sqale_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&types=CODE_SMELL&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /reliability_rating/ }).getAt(0)).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&types=BUG&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /security_rating/ }).getAt(0)).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&types=VULNERABILITY&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /software_quality_security_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&impactSoftwareQualities=SECURITY&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /software_quality_reliability_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&impactSoftwareQualities=RELIABILITY&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /software_quality_maintainability_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&impactSoftwareQualities=MAINTAINABILITY&id=qgStatusKey',
+ );
+});
+
+it('should render correct links for ratings with "new code" failed conditions', () => {
+ renderQualityGatePanelSection(
+ {
+ isApplication: false,
+ qgStatus: {
+ ...qgStatus,
+ failedConditions: [
+ mockCondition(MetricKey.new_maintainability_rating),
+ mockCondition(MetricKey.new_security_rating),
+ mockCondition(MetricKey.new_reliability_rating),
+ mockCondition(MetricKey.new_software_quality_security_rating),
+ mockCondition(MetricKey.new_software_quality_reliability_rating),
+ mockCondition(MetricKey.new_software_quality_maintainability_rating),
+ ],
+ },
+ qualityGate: mockQualityGate({ isBuiltIn: true }),
+ },
+ mockLoggedInUser({
+ dismissedNotices: { [NoticeType.OVERVIEW_ZERO_NEW_ISSUES_SIMPLIFICATION]: true },
+ }),
+ );
+
+ expect(byRole('link', { name: /new_maintainability_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&types=CODE_SMELL&inNewCodePeriod=true&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /new_security_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&types=VULNERABILITY&inNewCodePeriod=true&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /new_reliability_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&types=BUG&inNewCodePeriod=true&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /new_software_quality_security_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&impactSoftwareQualities=SECURITY&inNewCodePeriod=true&id=qgStatusKey',
+ );
+ expect(byRole('link', { name: /new_software_quality_reliability_rating/ }).get()).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&impactSoftwareQualities=RELIABILITY&inNewCodePeriod=true&id=qgStatusKey',
+ );
+ expect(
+ byRole('link', { name: /new_software_quality_maintainability_rating/ }).get(),
+ ).toHaveAttribute(
+ 'href',
+ '/project/issues?issueStatuses=OPEN%2CCONFIRMED&impactSoftwareQualities=MAINTAINABILITY&inNewCodePeriod=true&id=qgStatusKey',
+ );
+});
+
function renderQualityGatePanelSection(
props: Partial<QualityGatePanelSectionProps> = {},
currentUser: CurrentUser = mockLoggedInUser(),
import { ISSUETYPE_METRIC_KEYS_MAP } from '../../helpers/issues';
import { translate } from '../../helpers/l10n';
import { parseAsString } from '../../helpers/query';
-import { SoftwareQuality } from '../../types/clean-code-taxonomy';
+import { SoftwareImpactSeverity, SoftwareQuality } from '../../types/clean-code-taxonomy';
import { IssueType } from '../../types/issues';
import { AnalysisMeasuresVariations, MeasureHistory } from '../../types/project-activity';
import { QualityGateStatusConditionEnhanced } from '../../types/quality-gates';
'BLOCKER',
];
+export const MQR_RATING_TO_SEVERITIES_MAPPING = [
+ `${SoftwareImpactSeverity.Blocker},${SoftwareImpactSeverity.High},${SoftwareImpactSeverity.Medium},${SoftwareImpactSeverity.Info}`,
+ `${SoftwareImpactSeverity.Blocker},${SoftwareImpactSeverity.High},${SoftwareImpactSeverity.Medium}`,
+ `${SoftwareImpactSeverity.Blocker},${SoftwareImpactSeverity.High}`,
+ `${SoftwareImpactSeverity.Blocker}`,
+];
+
export const RATING_METRICS_MAPPING: Dict<IssueType> = {
[MetricKey.reliability_rating]: IssueType.Bug,
[MetricKey.new_reliability_rating]: IssueType.Bug,
*/
import { MetricKey } from '~sonar-aligned/types/metrics';
+import { SoftwareImpactSeverity, SoftwareQuality } from '../../../types/clean-code-taxonomy';
import { propsToIssueParams } from '../utils';
describe('propsToIssueParams', () => {
issueStatuses: 'FALSE_POSITIVE',
});
});
+ it.each([
+ [MetricKey.software_quality_info_issues, { impactSeverities: SoftwareImpactSeverity.Info }],
+ [MetricKey.software_quality_low_issues, { impactSeverities: SoftwareImpactSeverity.Low }],
+ [MetricKey.software_quality_medium_issues, { impactSeverities: SoftwareImpactSeverity.Medium }],
+ [MetricKey.software_quality_high_issues, { impactSeverities: SoftwareImpactSeverity.High }],
+ [
+ MetricKey.software_quality_blocker_issues,
+ { impactSeverities: SoftwareImpactSeverity.Blocker },
+ ],
+ [MetricKey.new_software_quality_info_issues, { impactSeverities: SoftwareImpactSeverity.Info }],
+ [MetricKey.new_software_quality_low_issues, { impactSeverities: SoftwareImpactSeverity.Low }],
+ [
+ MetricKey.new_software_quality_medium_issues,
+ { impactSeverities: SoftwareImpactSeverity.Medium },
+ ],
+ [MetricKey.new_software_quality_high_issues, { impactSeverities: SoftwareImpactSeverity.High }],
+ [
+ MetricKey.new_software_quality_blocker_issues,
+ { impactSeverities: SoftwareImpactSeverity.Blocker },
+ ],
+ [
+ MetricKey.software_quality_reliability_issues,
+ { impactSoftwareQualities: SoftwareQuality.Reliability },
+ ],
+ [
+ MetricKey.software_quality_maintainability_issues,
+ { impactSoftwareQualities: SoftwareQuality.Maintainability },
+ ],
+ [
+ MetricKey.software_quality_security_issues,
+ { impactSoftwareQualities: SoftwareQuality.Security },
+ ],
+ [
+ MetricKey.new_software_quality_reliability_issues,
+ { impactSoftwareQualities: SoftwareQuality.Reliability },
+ ],
+ [
+ MetricKey.new_software_quality_maintainability_issues,
+ { impactSoftwareQualities: SoftwareQuality.Maintainability },
+ ],
+ [
+ MetricKey.new_software_quality_security_issues,
+ { impactSoftwareQualities: SoftwareQuality.Security },
+ ],
+ ])(`should render correct params for %s`, (metricKey, result) => {
+ expect(propsToIssueParams(metricKey)).toEqual({
+ issueStatuses: 'OPEN,CONFIRMED',
+ ...result,
+ });
+ });
});
*/
import { MetricKey } from '~sonar-aligned/types/metrics';
+import { SoftwareImpactSeverity, SoftwareQuality } from '../../types/clean-code-taxonomy';
import { IssueStatus } from '../../types/issues';
import { Dict } from '../../types/types';
MetricKey.vulnerabilities,
MetricKey.new_vulnerabilities,
MetricKey.prioritized_rule_issues,
+ // MQR
+ MetricKey.new_software_quality_info_issues,
+ MetricKey.new_software_quality_low_issues,
+ MetricKey.new_software_quality_medium_issues,
+ MetricKey.new_software_quality_high_issues,
+ MetricKey.new_software_quality_blocker_issues,
+ MetricKey.software_quality_info_issues,
+ MetricKey.software_quality_low_issues,
+ MetricKey.software_quality_medium_issues,
+ MetricKey.software_quality_high_issues,
+ MetricKey.software_quality_blocker_issues,
+ MetricKey.new_software_quality_maintainability_issues,
+ MetricKey.new_software_quality_reliability_issues,
+ MetricKey.new_software_quality_security_issues,
+ MetricKey.software_quality_maintainability_issues,
+ MetricKey.software_quality_reliability_issues,
+ MetricKey.software_quality_security_issues,
+ MetricKey.new_software_quality_maintainability_rating,
+ MetricKey.software_quality_maintainability_rating,
];
export const DEFAULT_ISSUES_QUERY = {
[MetricKey.vulnerabilities]: { types: 'VULNERABILITY' },
[MetricKey.new_vulnerabilities]: { types: 'VULNERABILITY' },
[MetricKey.prioritized_rule_issues]: { prioritizedRule: 'true' },
+ // MQR
+ [MetricKey.new_software_quality_info_issues]: { impactSeverities: SoftwareImpactSeverity.Info },
+ [MetricKey.new_software_quality_low_issues]: { impactSeverities: SoftwareImpactSeverity.Low },
+ [MetricKey.new_software_quality_medium_issues]: {
+ impactSeverities: SoftwareImpactSeverity.Medium,
+ },
+ [MetricKey.new_software_quality_high_issues]: { impactSeverities: SoftwareImpactSeverity.High },
+ [MetricKey.new_software_quality_blocker_issues]: {
+ impactSeverities: SoftwareImpactSeverity.Blocker,
+ },
+ [MetricKey.software_quality_info_issues]: { impactSeverities: SoftwareImpactSeverity.Info },
+ [MetricKey.software_quality_low_issues]: { impactSeverities: SoftwareImpactSeverity.Low },
+ [MetricKey.software_quality_medium_issues]: { impactSeverities: SoftwareImpactSeverity.Medium },
+ [MetricKey.software_quality_high_issues]: { impactSeverities: SoftwareImpactSeverity.High },
+ [MetricKey.software_quality_blocker_issues]: { impactSeverities: SoftwareImpactSeverity.Blocker },
+ [MetricKey.new_software_quality_maintainability_issues]: {
+ impactSoftwareQualities: SoftwareQuality.Maintainability,
+ },
+ [MetricKey.new_software_quality_reliability_issues]: {
+ impactSoftwareQualities: SoftwareQuality.Reliability,
+ },
+ [MetricKey.new_software_quality_security_issues]: {
+ impactSoftwareQualities: SoftwareQuality.Security,
+ },
+ [MetricKey.software_quality_maintainability_issues]: {
+ impactSoftwareQualities: SoftwareQuality.Maintainability,
+ },
+ [MetricKey.software_quality_reliability_issues]: {
+ impactSoftwareQualities: SoftwareQuality.Reliability,
+ },
+ [MetricKey.software_quality_security_issues]: {
+ impactSoftwareQualities: SoftwareQuality.Security,
+ },
};
export function isIssueMeasure(metric: string) {