return result;
}
-export function getMeasuresForProjects(
+export async function getMeasuresForProjects(
projectKeys: string[],
metricKeys: string[],
): Promise<MeasuresForProjects[]> {
- return getJSON('/api/measures/search', {
+ // TODO: Remove this mock (SONAR-21488)
+ const mockedMetrics = metricKeys.filter(
+ (metric) =>
+ ![
+ MetricKey.maintainability_issues,
+ MetricKey.reliability_issues,
+ MetricKey.security_issues,
+ ].includes(metric as MetricKey),
+ );
+
+ const result = await getJSON('/api/measures/search', {
projectKeys: projectKeys.join(),
- metricKeys: metricKeys.join(),
+ metricKeys: mockedMetrics.join(),
}).then((r) => r.measures);
+
+ [
+ MetricKey.maintainability_issues,
+ MetricKey.reliability_issues,
+ MetricKey.security_issues,
+ ].forEach((metric) => {
+ if (metricKeys.includes(metric)) {
+ projectKeys.forEach((projectKey) => {
+ result.push({
+ component: projectKey,
+ metric,
+ value: JSON.stringify({
+ total: 2,
+ }),
+ });
+ });
+ }
+ });
+
+ return result;
}
await user.click(screen.getByText('projects.view.new_code'));
// each project should show "new bugs" instead of "bugs"
- expect(await screen.findAllByLabelText(MetricKey.new_bugs)).toHaveLength(20);
+ expect(await screen.findAllByText(`metric.${MetricKey.new_violations}.description`)).toHaveLength(
+ 20,
+ );
expect(save).toHaveBeenCalledWith(LS_PROJECTS_VIEW, 'leak');
// sort should also be updated
componentQualifier: ComponentQualifier;
}
+function renderNewIssues(props: ProjectCardMeasuresProps) {
+ const { measures, isNewCode } = props;
+
+ if (!isNewCode) {
+ return null;
+ }
+
+ return (
+ <ProjectCardMeasure
+ metricKey={MetricKey.new_violations}
+ label={translate(`metric.${MetricKey.new_violations}.description`)}
+ >
+ <Measure
+ metricKey={MetricKey.new_violations}
+ metricType={MetricType.ShortInteger}
+ value={measures[MetricKey.new_violations]}
+ className="sw-ml-2 sw-body-md-highlight"
+ />
+ </ProjectCardMeasure>
+ );
+}
+
function renderCoverage(props: ProjectCardMeasuresProps) {
const { measures, isNewCode } = props;
const coverageMetric = isNewCode ? MetricKey.new_coverage : MetricKey.coverage;
function renderRatings(props: ProjectCardMeasuresProps) {
const { isNewCode, measures } = props;
+ const measuresByCodeLeak = isNewCode
+ ? []
+ : [
+ {
+ iconLabel: translate(`metric.${MetricKey.security_issues}.short_name`),
+ noShrink: true,
+ metricKey: MetricKey.security_issues,
+ metricRatingKey: MetricKey.security_rating,
+ metricType: MetricType.ShortInteger,
+ },
+ {
+ iconLabel: translate(`metric.${MetricKey.reliability_issues}.short_name`),
+ metricKey: MetricKey.reliability_issues,
+ metricRatingKey: MetricKey.reliability_rating,
+ metricType: MetricType.ShortInteger,
+ },
+ {
+ iconLabel: translate(`metric.${MetricKey.maintainability_issues}.short_name`),
+ metricKey: MetricKey.maintainability_issues,
+ metricRatingKey: MetricKey.sqale_rating,
+ metricType: MetricType.ShortInteger,
+ },
+ ];
+
const measureList = [
- {
- iconLabel: translate('metric.bugs.name'),
- noShrink: true,
- metricKey: isNewCode ? MetricKey.new_bugs : MetricKey.bugs,
- metricRatingKey: isNewCode ? MetricKey.new_reliability_rating : MetricKey.reliability_rating,
- metricType: MetricType.ShortInteger,
- },
- {
- iconLabel: translate('metric.vulnerabilities.name'),
- metricKey: isNewCode ? MetricKey.new_vulnerabilities : MetricKey.vulnerabilities,
- metricRatingKey: isNewCode ? MetricKey.new_security_rating : MetricKey.security_rating,
- metricType: MetricType.ShortInteger,
- },
+ ...measuresByCodeLeak,
{
iconKey: 'security_hotspots',
iconLabel: translate('projects.security_hotspots_reviewed'),
: MetricKey.security_review_rating,
metricType: MetricType.Percent,
},
- {
- iconLabel: translate('metric.code_smells.name'),
- metricKey: isNewCode ? MetricKey.new_code_smells : MetricKey.code_smells,
- metricRatingKey: isNewCode ? MetricKey.new_maintainability_rating : MetricKey.sqale_rating,
- metricType: MetricType.ShortInteger,
- },
];
return measureList.map((measure) => {
const { iconLabel, metricKey, metricRatingKey, metricType } = measure;
const value = formatRating(measures[metricRatingKey]);
+ const measureValue =
+ [
+ MetricKey.security_issues,
+ MetricKey.reliability_issues,
+ MetricKey.maintainability_issues,
+ ].includes(metricKey) && measures[metricKey]
+ ? JSON.parse(measures[metricKey] as string)?.total
+ : measures[metricKey];
+
return (
<ProjectCardMeasure key={metricKey} metricKey={metricKey} label={iconLabel}>
<MetricsRatingBadge label={metricKey} rating={value as MetricsLabel} />
<Measure
metricKey={metricKey}
metricType={metricType}
- value={measures[metricKey]}
+ value={measureValue}
className="sw-ml-2 sw-body-md-highlight"
/>
</ProjectCardMeasure>
}
const measureList = [
+ renderNewIssues(props),
...renderRatings(props),
renderCoverage(props),
renderDuplication(props),
describe('Overall measures', () => {
it('should be rendered properly', () => {
renderProjectCardMeasures();
- expect(screen.getByTitle('metric.bugs.name')).toBeInTheDocument();
+ expect(screen.getByTitle('metric.security_issues.short_name')).toBeInTheDocument();
});
it("should be not be rendered if there's no line of code", () => {
it('should be rendered properly', () => {
renderProjectCardMeasures({}, { isNewCode: true });
expect(screen.getByLabelText(MetricKey.new_security_hotspots_reviewed)).toBeInTheDocument();
+ expect(screen.getByTitle('metric.new_violations.description')).toBeInTheDocument();
});
});
[MetricKey.code_smells]: '132',
[MetricKey.coverage]: '88.3',
[MetricKey.duplicated_lines_density]: '9.8',
+ [MetricKey.maintainability_issues]: JSON.stringify({ total: 10 }),
+ [MetricKey.reliability_issues]: JSON.stringify({ total: 10 }),
+ [MetricKey.security_issues]: JSON.stringify({ total: 10 }),
[MetricKey.ncloc]: '2053',
[MetricKey.reliability_rating]: '1.0',
[MetricKey.security_rating]: '1.0',
[MetricKey.new_code_smells]: '0',
[MetricKey.new_coverage]: '26.55',
[MetricKey.new_duplicated_lines_density]: '0.55',
+ [MetricKey.new_violations]: '10',
[MetricKey.new_lines]: '87',
...measuresOverride,
};
export const METRICS = [
MetricKey.alert_status,
- MetricKey.bugs,
+ MetricKey.reliability_issues,
MetricKey.reliability_rating,
- MetricKey.vulnerabilities,
+ MetricKey.security_issues,
MetricKey.security_rating,
+ MetricKey.maintainability_issues,
+ MetricKey.sqale_rating,
MetricKey.security_hotspots_reviewed,
MetricKey.security_review_rating,
- MetricKey.code_smells,
- MetricKey.sqale_rating,
MetricKey.duplicated_lines_density,
MetricKey.coverage,
MetricKey.ncloc,
export const LEAK_METRICS = [
MetricKey.alert_status,
- MetricKey.new_bugs,
- MetricKey.new_reliability_rating,
- MetricKey.new_vulnerabilities,
- MetricKey.new_security_rating,
+ MetricKey.new_violations,
MetricKey.new_security_hotspots_reviewed,
MetricKey.new_security_review_rating,
- MetricKey.new_code_smells,
- MetricKey.new_maintainability_rating,
MetricKey.new_coverage,
MetricKey.new_duplicated_lines_density,
MetricKey.new_lines,
metric.high_impact_accepted_issues.description=Accepted issues with high impact
metric.maintainability_issues.name=Maintainability Issues
metric.maintainability_issues.description=Maintainability issues
+metric.maintainability_issues.short_name=Maintainability
metric.reliability_issues.name=Reliability Issues
metric.reliability_issues.description=Reliability issues
+metric.reliability_issues.short_name=Reliability
metric.security_issues.name=Security Issues
metric.security_issues.description=Security issues
+metric.security_issues.short_name=Security
#------------------------------------------------------------------------------
#