aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorWouter Admiraal <wouter.admiraal@sonarsource.com>2019-12-17 16:55:03 +0100
committerSonarTech <sonartech@sonarsource.com>2020-02-10 20:46:14 +0100
commit26f66a70c8de871cc93f234398412966f160b1b8 (patch)
tree708aea302109ba6f9b296001f7b60e36fe80010a /server
parentea0e05cedbe604baa4b9ad50148353d7356237c2 (diff)
downloadsonarqube-26f66a70c8de871cc93f234398412966f160b1b8.tar.gz
sonarqube-26f66a70c8de871cc93f234398412966f160b1b8.zip
Extract metric keys to a global Enum, simplify mocking
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Component-test.tsx.snap16
-rw-r--r--server/sonar-web/src/main/js/apps/code/utils.ts45
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts34
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts47
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/config/domains.ts155
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/overview/__tests__/utils-test.ts12
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx7
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Condition-test.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/ConditionModal-test.tsx20
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Conditions-test.tsx28
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/CopyQualityGateForm-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/ConditionModal-test.tsx.snap38
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Conditions-test.tsx.snap34
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/MeasuresOverlayMeasure.tsx8
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/MeasuresOverlay-test.tsx133
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts50
-rw-r--r--server/sonar-web/src/main/js/helpers/measures.ts31
-rw-r--r--server/sonar-web/src/main/js/helpers/testMocks.ts18
-rw-r--r--server/sonar-web/src/main/js/types/metrics.ts148
21 files changed, 546 insertions, 289 deletions
diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Component-test.tsx.snap b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Component-test.tsx.snap
index 138b237b2e5..2bfb8507609 100644
--- a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Component-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Component-test.tsx.snap
@@ -75,9 +75,9 @@ exports[`should render correctly 1`] = `
}
metric={
Object {
- "id": "coverage",
+ "id": "bugs",
"key": "bugs",
- "name": "Coverage",
+ "name": "Bugs",
"type": "PERCENT",
}
}
@@ -111,9 +111,9 @@ exports[`should render correctly 1`] = `
}
metric={
Object {
- "id": "coverage",
+ "id": "vulnerabilities",
"key": "vulnerabilities",
- "name": "Coverage",
+ "name": "Vulnerabilities",
"type": "PERCENT",
}
}
@@ -205,9 +205,9 @@ exports[`should render correctly for a file 1`] = `
}
metric={
Object {
- "id": "coverage",
+ "id": "bugs",
"key": "bugs",
- "name": "Coverage",
+ "name": "Bugs",
"type": "PERCENT",
}
}
@@ -239,9 +239,9 @@ exports[`should render correctly for a file 1`] = `
}
metric={
Object {
- "id": "coverage",
+ "id": "vulnerabilities",
"key": "vulnerabilities",
- "name": "Coverage",
+ "name": "Vulnerabilities",
"type": "PERCENT",
}
}
diff --git a/server/sonar-web/src/main/js/apps/code/utils.ts b/server/sonar-web/src/main/js/apps/code/utils.ts
index 88f97c1929f..675c33e0a1e 100644
--- a/server/sonar-web/src/main/js/apps/code/utils.ts
+++ b/server/sonar-web/src/main/js/apps/code/utils.ts
@@ -20,6 +20,7 @@
import { getBreadcrumbs, getChildren, getComponent } from '../../api/components';
import { getBranchLikeQuery, isPullRequest } from '../../helpers/branch-like';
import { BranchLike } from '../../types/branch-like';
+import { MetricKey } from '../../types/metrics';
import {
addComponent,
addComponentBreadcrumbs,
@@ -30,34 +31,34 @@ import {
} from './bucket';
const METRICS = [
- 'ncloc',
- 'bugs',
- 'vulnerabilities',
- 'code_smells',
- 'security_hotspots',
- 'coverage',
- 'duplicated_lines_density'
+ MetricKey.ncloc,
+ MetricKey.bugs,
+ MetricKey.vulnerabilities,
+ MetricKey.code_smells,
+ MetricKey.security_hotspots,
+ MetricKey.coverage,
+ MetricKey.duplicated_lines_density
];
-const APPLICATION_METRICS = ['alert_status', ...METRICS];
+const APPLICATION_METRICS = [MetricKey.alert_status, ...METRICS];
const PORTFOLIO_METRICS = [
- 'releasability_rating',
- 'reliability_rating',
- 'security_rating',
- 'security_review_rating',
- 'sqale_rating',
- 'ncloc'
+ MetricKey.releasability_rating,
+ MetricKey.reliability_rating,
+ MetricKey.security_rating,
+ MetricKey.security_review_rating,
+ MetricKey.sqale_rating,
+ MetricKey.ncloc
];
const LEAK_METRICS = [
- 'new_lines',
- 'bugs',
- 'vulnerabilities',
- 'code_smells',
- 'security_hotspots',
- 'new_coverage',
- 'new_duplicated_lines_density'
+ MetricKey.new_lines,
+ MetricKey.bugs,
+ MetricKey.vulnerabilities,
+ MetricKey.code_smells,
+ MetricKey.security_hotspots,
+ MetricKey.new_coverage,
+ MetricKey.new_duplicated_lines_density
];
const PAGE_SIZE = 100;
@@ -107,7 +108,7 @@ export function getCodeMetrics(
) {
if (['VW', 'SVW'].includes(qualifier)) {
const metrics = [...PORTFOLIO_METRICS];
- return options.includeQGStatus ? metrics.concat('alert_status') : metrics;
+ return options.includeQGStatus ? metrics.concat(MetricKey.alert_status) : metrics;
}
if (qualifier === 'APP') {
return [...APPLICATION_METRICS];
diff --git a/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts b/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts
index baec3b1404f..5b59046f0dc 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts
+++ b/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts
@@ -17,13 +17,14 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { MetricKey } from '../../../types/metrics';
import * as utils from '../utils';
const MEASURES = [
{
metric: {
id: '1',
- key: 'lines_to_cover',
+ key: MetricKey.lines_to_cover,
type: 'INT',
name: 'Lines to Cover',
domain: 'Coverage'
@@ -35,7 +36,7 @@ const MEASURES = [
{
metric: {
id: '2',
- key: 'coverage',
+ key: MetricKey.coverage,
type: 'PERCENT',
name: 'Coverage',
domain: 'Coverage'
@@ -47,7 +48,7 @@ const MEASURES = [
{
metric: {
id: '3',
- key: 'duplicated_lines_density',
+ key: MetricKey.duplicated_lines_density,
type: 'PERCENT',
name: 'Duplicated Lines (%)',
domain: 'Duplications'
@@ -62,9 +63,14 @@ describe('filterMeasures', () => {
it('should exclude banned measures', () => {
expect(
utils.filterMeasures([
- { metric: { id: '1', key: 'bugs', name: 'Bugs', type: 'INT' } },
+ { metric: { id: '1', key: MetricKey.bugs, name: 'Bugs', type: 'INT' } },
{
- metric: { id: '2', key: 'critical_violations', name: 'Critical Violations', type: 'INT' }
+ metric: {
+ id: '2',
+ key: MetricKey.critical_violations,
+ name: 'Critical Violations',
+ type: 'INT'
+ }
}
])
).toHaveLength(1);
@@ -76,13 +82,23 @@ describe('sortMeasures', () => {
expect(
utils.sortMeasures('Reliability', [
{
- metric: { id: '1', key: 'reliability_remediation_effort', name: 'new_bugs', type: 'INT' }
+ metric: {
+ id: '1',
+ key: MetricKey.reliability_remediation_effort,
+ name: 'new_bugs',
+ type: 'INT'
+ }
},
{
- metric: { id: '2', key: 'new_reliability_remediation_effort', name: 'bugs', type: 'INT' }
+ metric: {
+ id: '2',
+ key: MetricKey.new_reliability_remediation_effort,
+ name: 'bugs',
+ type: 'INT'
+ }
},
- { metric: { id: '3', key: 'new_bugs', name: 'new_bugs', type: 'INT' } },
- { metric: { id: '4', key: 'bugs', name: 'bugs', type: 'INT' } },
+ { metric: { id: '3', key: MetricKey.new_bugs, name: 'new_bugs', type: 'INT' } },
+ { metric: { id: '4', key: MetricKey.bugs, name: 'bugs', type: 'INT' } },
'overall_category'
])
).toMatchSnapshot();
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.tsx
index c4c40940def..73e6a4c22e5 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.tsx
@@ -30,6 +30,7 @@ import { getBranchLikeQuery, isSameBranchLike } from '../../../helpers/branch-li
import { getPeriodValue, isDiffMetric } from '../../../helpers/measures';
import { getProjectUrl } from '../../../helpers/urls';
import { BranchLike } from '../../../types/branch-like';
+import { MetricKey } from '../../../types/metrics';
import { complementary } from '../config/complementary';
import FilesView from '../drilldown/FilesView';
import TreeMapView from '../drilldown/TreeMapView';
@@ -100,7 +101,7 @@ export default class MeasureContent extends React.PureComponent<Props, State> {
);
const componentKey = this.props.selected || this.props.rootComponent.key;
const baseComponentMetrics = [this.props.requestedMetric.key];
- if (this.props.requestedMetric.key === 'ncloc') {
+ if (this.props.requestedMetric.key === MetricKey.ncloc) {
baseComponentMetrics.push('ncloc_language_distribution');
}
Promise.all([
diff --git a/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts b/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts
index bc87c9bc4ca..faa31be14f1 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts
+++ b/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts
@@ -17,6 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { MetricKey } from '../../../types/metrics';
+
export const bubbles: {
[domain: string]: {
x: string;
@@ -27,30 +29,39 @@ export const bubbles: {
};
} = {
Reliability: {
- x: 'ncloc',
- y: 'reliability_remediation_effort',
- size: 'bugs',
- colors: ['reliability_rating']
+ x: MetricKey.ncloc,
+ y: MetricKey.reliability_remediation_effort,
+ size: MetricKey.bugs,
+ colors: [MetricKey.reliability_rating]
},
Security: {
- x: 'ncloc',
- y: 'security_remediation_effort',
- size: 'vulnerabilities',
- colors: ['security_rating']
+ x: MetricKey.ncloc,
+ y: MetricKey.security_remediation_effort,
+ size: MetricKey.vulnerabilities,
+ colors: [MetricKey.security_rating]
},
Maintainability: {
- x: 'ncloc',
- y: 'sqale_index',
- size: 'code_smells',
- colors: ['sqale_rating']
+ x: MetricKey.ncloc,
+ y: MetricKey.sqale_index,
+ size: MetricKey.code_smells,
+ colors: [MetricKey.sqale_rating]
+ },
+ Coverage: {
+ x: MetricKey.complexity,
+ y: MetricKey.coverage,
+ size: MetricKey.uncovered_lines,
+ yDomain: [100, 0]
+ },
+ Duplications: {
+ x: MetricKey.ncloc,
+ y: MetricKey.duplicated_lines,
+ size: MetricKey.duplicated_blocks
},
- Coverage: { x: 'complexity', y: 'coverage', size: 'uncovered_lines', yDomain: [100, 0] },
- Duplications: { x: 'ncloc', y: 'duplicated_lines', size: 'duplicated_blocks' },
project_overview: {
- x: 'sqale_index',
- y: 'coverage',
- size: 'ncloc',
- colors: ['reliability_rating', 'security_rating'],
+ x: MetricKey.sqale_index,
+ y: MetricKey.coverage,
+ size: MetricKey.ncloc,
+ colors: [MetricKey.reliability_rating, MetricKey.security_rating],
yDomain: [100, 0]
}
};
diff --git a/server/sonar-web/src/main/js/apps/component-measures/config/domains.ts b/server/sonar-web/src/main/js/apps/component-measures/config/domains.ts
index a9a24eca4e4..eb9d15604b2 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/config/domains.ts
+++ b/server/sonar-web/src/main/js/apps/component-measures/config/domains.ts
@@ -17,6 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { MetricKey } from '../../../types/metrics';
+
interface Domains {
[domain: string]: { categories?: string[]; order: string[] };
}
@@ -26,14 +28,14 @@ export const domains: Domains = {
categories: ['new_code_category', 'overall_category'],
order: [
'new_code_category',
- 'new_bugs',
- 'new_reliability_rating',
- 'new_reliability_remediation_effort',
+ MetricKey.new_bugs,
+ MetricKey.new_reliability_rating,
+ MetricKey.new_reliability_remediation_effort,
'overall_category',
- 'bugs',
- 'reliability_rating',
- 'reliability_remediation_effort'
+ MetricKey.bugs,
+ MetricKey.reliability_rating,
+ MetricKey.reliability_remediation_effort
]
},
@@ -41,16 +43,16 @@ export const domains: Domains = {
categories: ['new_code_category', 'overall_category'],
order: [
'new_code_category',
- 'new_vulnerabilities',
- 'new_security_rating',
- 'new_security_remediation_effort',
- 'new_security_hotspots',
+ MetricKey.new_vulnerabilities,
+ MetricKey.new_security_rating,
+ MetricKey.new_security_remediation_effort,
+ MetricKey.new_security_hotspots,
'overall_category',
- 'vulnerabilities',
- 'security_rating',
- 'security_remediation_effort',
- 'security_hotspots'
+ MetricKey.vulnerabilities,
+ MetricKey.security_rating,
+ MetricKey.security_remediation_effort,
+ MetricKey.security_hotspots
]
},
@@ -58,17 +60,17 @@ export const domains: Domains = {
categories: ['new_code_category', 'overall_category'],
order: [
'new_code_category',
- 'new_code_smells',
- 'new_technical_debt',
- 'new_sqale_debt_ratio',
- 'new_maintainability_rating',
+ MetricKey.new_code_smells,
+ MetricKey.new_technical_debt,
+ MetricKey.new_sqale_debt_ratio,
+ MetricKey.new_maintainability_rating,
'overall_category',
- 'code_smells',
- 'sqale_index',
- 'sqale_debt_ratio',
- 'sqale_rating',
- 'effort_to_reach_maintainability_rating_a'
+ MetricKey.code_smells,
+ MetricKey.sqale_index,
+ MetricKey.sqale_debt_ratio,
+ MetricKey.sqale_rating,
+ MetricKey.effort_to_reach_maintainability_rating_a
]
},
@@ -76,31 +78,30 @@ export const domains: Domains = {
categories: ['new_code_category', 'overall_category', 'tests_category'],
order: [
'new_code_category',
- 'new_coverage',
- 'new_lines_to_cover',
- 'new_uncovered_lines',
- 'new_line_coverage',
- 'new_conditions_to_cover',
- 'new_uncovered_conditions',
- 'new_branch_coverage',
+ MetricKey.new_coverage,
+ MetricKey.new_lines_to_cover,
+ MetricKey.new_uncovered_lines,
+ MetricKey.new_line_coverage,
+ MetricKey.new_conditions_to_cover,
+ MetricKey.new_uncovered_conditions,
+ MetricKey.new_branch_coverage,
'overall_category',
- 'coverage',
- 'lines_to_cover',
- 'uncovered_lines',
- 'line_coverage',
- 'conditions_to_cover',
- 'uncovered_conditions',
- 'branch_coverage',
+ MetricKey.coverage,
+ MetricKey.lines_to_cover,
+ MetricKey.uncovered_lines,
+ MetricKey.line_coverage,
+ MetricKey.conditions_to_cover,
+ MetricKey.uncovered_conditions,
+ MetricKey.branch_coverage,
'tests_category',
- 'tests',
- 'test_success',
- 'test_errors',
- 'test_failures',
- 'skipped_tests',
- 'test_success_density',
- 'test_execution_time'
+ MetricKey.tests,
+ MetricKey.test_errors,
+ MetricKey.test_failures,
+ MetricKey.skipped_tests,
+ MetricKey.test_success_density,
+ MetricKey.test_execution_time
]
},
@@ -108,29 +109,29 @@ export const domains: Domains = {
categories: ['new_code_category', 'overall_category'],
order: [
'new_code_category',
- 'new_duplicated_lines_density',
- 'new_duplicated_lines',
- 'new_duplicated_blocks',
+ MetricKey.new_duplicated_lines_density,
+ MetricKey.new_duplicated_lines,
+ MetricKey.new_duplicated_blocks,
'overall_category',
- 'duplicated_lines_density',
- 'duplicated_lines',
- 'duplicated_blocks',
- 'duplicated_files'
+ MetricKey.duplicated_lines_density,
+ MetricKey.duplicated_lines,
+ MetricKey.duplicated_blocks,
+ MetricKey.duplicated_files
]
},
Size: {
order: [
- 'new_lines',
-
- 'ncloc',
- 'lines',
- 'statements',
- 'functions',
- 'classes',
- 'files',
- 'directories'
+ MetricKey.new_lines,
+
+ MetricKey.ncloc,
+ MetricKey.lines,
+ MetricKey.statements,
+ MetricKey.functions,
+ MetricKey.classes,
+ MetricKey.files,
+ MetricKey.directories
]
},
@@ -144,23 +145,23 @@ export const domains: Domains = {
Issues: {
order: [
- 'new_violations',
- 'new_blocker_violations',
- 'new_critical_violations',
- 'new_major_violations',
- 'new_minor_violations',
- 'new_info_violations',
-
- 'violations',
- 'blocker_violations',
- 'critical_violations',
- 'major_violations',
- 'minor_violations',
- 'info_violations',
- 'open_issues',
- 'reopened_issues',
- 'confirmed_issues',
- 'false_positive_issues'
+ MetricKey.new_violations,
+ MetricKey.new_blocker_violations,
+ MetricKey.new_critical_violations,
+ MetricKey.new_major_violations,
+ MetricKey.new_minor_violations,
+ MetricKey.new_info_violations,
+
+ MetricKey.violations,
+ MetricKey.blocker_violations,
+ MetricKey.critical_violations,
+ MetricKey.major_violations,
+ MetricKey.minor_violations,
+ MetricKey.info_violations,
+ MetricKey.open_issues,
+ MetricKey.reopened_issues,
+ MetricKey.confirmed_issues,
+ MetricKey.false_positive_issues
]
}
};
diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.tsx b/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.tsx
index c7904688e52..ff9c186403f 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.tsx
@@ -34,6 +34,7 @@ import { colors } from '../../../app/theme';
import ColorBoxLegend from '../../../components/charts/ColorBoxLegend';
import { isDiffMetric } from '../../../helpers/measures';
import { BranchLike } from '../../../types/branch-like';
+import { MetricKey } from '../../../types/metrics';
import EmptyResult from './EmptyResult';
interface Props {
@@ -207,7 +208,7 @@ export default class TreeMapView extends React.PureComponent<Props, State> {
'component_measures.legend.size_x',
translate(
'metric',
- sizeMeasure && sizeMeasure.metric ? sizeMeasure.metric.key : 'ncloc',
+ sizeMeasure && sizeMeasure.metric ? sizeMeasure.metric.key : MetricKey.ncloc,
'name'
)
)}
diff --git a/server/sonar-web/src/main/js/apps/overview/__tests__/utils-test.ts b/server/sonar-web/src/main/js/apps/overview/__tests__/utils-test.ts
index fced030fc86..927b36415e2 100644
--- a/server/sonar-web/src/main/js/apps/overview/__tests__/utils-test.ts
+++ b/server/sonar-web/src/main/js/apps/overview/__tests__/utils-test.ts
@@ -33,7 +33,7 @@ describe('getThreshold', () => {
getThreshold(
[
{
- metric: mockMetric({ key: 'quality_gate_details' }),
+ metric: mockMetric({ key: MetricKey.quality_gate_details }),
value: 'badly typed json should fail'
}
],
@@ -45,23 +45,23 @@ describe('getThreshold', () => {
});
it('should return the threshold for the right metric', () => {
- expect(getThreshold([mockMeasure()], 'new_coverage')).toBe(85);
- expect(getThreshold([mockMeasure()], 'new_duplicated_lines_density')).toBe(5);
+ expect(getThreshold([mockMeasure()], MetricKey.new_coverage)).toBe(85);
+ expect(getThreshold([mockMeasure()], MetricKey.new_duplicated_lines_density)).toBe(5);
});
});
function mockMeasure() {
return mockMeasureEnhanced({
- metric: mockMetric({ key: 'quality_gate_details' }),
+ metric: mockMetric({ key: MetricKey.quality_gate_details }),
value: JSON.stringify({
conditions: [
mockQualityGateStatusCondition({
- metric: 'new_coverage',
+ metric: MetricKey.new_coverage,
level: 'ERROR',
error: '85'
}),
mockQualityGateStatusCondition({
- metric: 'new_duplicated_lines_density',
+ metric: MetricKey.new_duplicated_lines_density,
level: 'WARNING',
warning: '5'
})
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx
index a9dfbe269ed..8c124a65a98 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx
@@ -26,6 +26,7 @@ import { getLocalizedMetricName, translate } from 'sonar-ui-common/helpers/l10n'
import { isDiffMetric } from 'sonar-ui-common/helpers/measures';
import DocTooltip from '../../../components/docs/DocTooltip';
import { withAppState } from '../../../components/hoc/withAppState';
+import { MetricKey } from '../../../types/metrics';
import Condition from './Condition';
import ConditionModal from './ConditionModal';
@@ -42,7 +43,11 @@ interface Props {
}
const FORBIDDEN_METRIC_TYPES = ['DATA', 'DISTRIB', 'STRING', 'BOOL'];
-const FORBIDDEN_METRICS = ['alert_status', 'releasability_rating', 'security_review_rating'];
+const FORBIDDEN_METRICS: string[] = [
+ MetricKey.alert_status,
+ MetricKey.releasability_rating,
+ MetricKey.security_review_rating
+];
export class Conditions extends React.PureComponent<Props> {
renderConditionsTable = (conditions: T.Condition[], scope: 'new' | 'overall') => {
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Condition-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Condition-test.tsx
index 79fd0689c2d..0e3f8d201ff 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Condition-test.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Condition-test.tsx
@@ -19,7 +19,8 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { mockCondition, mockMetric, mockQualityGate } from '../../../../helpers/testMocks';
+import { mockQualityGate } from '../../../../helpers/mocks/quality-gates';
+import { mockCondition, mockMetric } from '../../../../helpers/testMocks';
import Condition from '../Condition';
it('should render correctly', () => {
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/ConditionModal-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/ConditionModal-test.tsx
index 5816d741f93..ab6e843fb9f 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/ConditionModal-test.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/ConditionModal-test.tsx
@@ -19,7 +19,9 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { mockMetric, mockQualityGate } from '../../../../helpers/testMocks';
+import { mockQualityGate } from '../../../../helpers/mocks/quality-gates';
+import { mockMetric } from '../../../../helpers/testMocks';
+import { MetricKey } from '../../../../types/metrics';
import ConditionModal from '../ConditionModal';
it('should render correctly', () => {
@@ -40,14 +42,12 @@ it('should correctly handle a metric selection', () => {
it('should correctly switch scope', () => {
const wrapper = shallowRender({
metrics: [
- mockMetric({ id: 'new_coverage', key: 'new_coverage', name: 'Coverage on New Code' }),
+ mockMetric({ key: MetricKey.new_coverage }),
mockMetric({
- id: 'new_duplication',
- key: 'new_duplication',
- name: 'Duplication on New Code'
+ key: MetricKey.new_duplicated_lines
}),
mockMetric(),
- mockMetric({ id: 'duplication', key: 'duplication', name: 'Duplication' })
+ mockMetric({ key: MetricKey.duplicated_lines })
]
});
expect(wrapper).toMatchSnapshot();
@@ -64,12 +64,8 @@ function shallowRender(props: Partial<ConditionModal['props']> = {}) {
<ConditionModal
header="header"
metrics={[
- mockMetric({ id: 'new_coverage', key: 'new_coverage', name: 'Coverage on New Code' }),
- mockMetric({
- id: 'new_duplication',
- key: 'new_duplication',
- name: 'Duplication on New Code'
- })
+ mockMetric({ key: MetricKey.new_coverage }),
+ mockMetric({ key: MetricKey.new_duplicated_lines })
]}
onAddCondition={jest.fn()}
onClose={jest.fn()}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Conditions-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Conditions-test.tsx
index c2602951c03..41db990356f 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Conditions-test.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Conditions-test.tsx
@@ -19,7 +19,9 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { mockCondition, mockMetric, mockQualityGate } from '../../../../helpers/testMocks';
+import { mockQualityGate } from '../../../../helpers/mocks/quality-gates';
+import { mockCondition, mockMetric } from '../../../../helpers/testMocks';
+import { MetricKey } from '../../../../types/metrics';
import { Conditions } from '../Conditions';
it('should render correctly', () => {
@@ -30,9 +32,9 @@ it('should render correctly with new code conditions', () => {
const wrapper = shallowRender({
conditions: [
mockCondition(),
- mockCondition({ id: 2, metric: 'duplication' }),
- mockCondition({ id: 3, metric: 'new_coverage' }),
- mockCondition({ id: 4, metric: 'new_duplication' })
+ mockCondition({ id: 2, metric: MetricKey.duplicated_lines }),
+ mockCondition({ id: 3, metric: MetricKey.new_coverage }),
+ mockCondition({ id: 4, metric: MetricKey.new_duplicated_lines })
]
});
expect(wrapper).toMatchSnapshot();
@@ -53,19 +55,15 @@ function shallowRender(props: Partial<Conditions['props']> = {}) {
<Conditions
appState={{ branchesEnabled: true }}
canEdit={false}
- conditions={[mockCondition(), mockCondition({ id: 2, metric: 'duplication' })]}
+ conditions={[mockCondition(), mockCondition({ id: 2, metric: MetricKey.duplicated_lines })]}
metrics={{
- coverage: mockMetric(),
- duplication: mockMetric({ id: 'duplication', key: 'duplication', name: 'Duplication' }),
- new_coverage: mockMetric({
- id: 'new_coverage',
- key: 'new_coverage',
- name: 'Coverage on New Code'
+ [MetricKey.coverage]: mockMetric(),
+ [MetricKey.duplicated_lines]: mockMetric({ key: MetricKey.duplicated_lines }),
+ [MetricKey.new_coverage]: mockMetric({
+ key: MetricKey.new_coverage
}),
- new_duplication: mockMetric({
- id: 'new_duplication',
- key: 'new_duplication',
- name: 'Duplication on New Code'
+ [MetricKey.new_duplicated_lines]: mockMetric({
+ key: MetricKey.new_duplicated_lines
})
}}
onAddCondition={jest.fn()}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/CopyQualityGateForm-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/CopyQualityGateForm-test.tsx
index 2a9b4b4a113..492e8fa6b2f 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/CopyQualityGateForm-test.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/CopyQualityGateForm-test.tsx
@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { mockQualityGate } from '../../../../helpers/testMocks';
+import { mockQualityGate } from '../../../../helpers/mocks/quality-gates';
import CopyQualityGateForm from '../CopyQualityGateForm';
it('should render correctly', () => {
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/ConditionModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/ConditionModal-test.tsx.snap
index 711a500cdf5..d634c60d729 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/ConditionModal-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/ConditionModal-test.tsx.snap
@@ -50,13 +50,13 @@ exports[`should correctly switch scope 1`] = `
Object {
"id": "new_coverage",
"key": "new_coverage",
- "name": "Coverage on New Code",
+ "name": "New_coverage",
"type": "PERCENT",
},
Object {
- "id": "new_duplication",
- "key": "new_duplication",
- "name": "Duplication on New Code",
+ "id": "new_duplicated_lines",
+ "key": "new_duplicated_lines",
+ "name": "New_duplicated_lines",
"type": "PERCENT",
},
]
@@ -121,9 +121,9 @@ exports[`should correctly switch scope 2`] = `
"type": "PERCENT",
},
Object {
- "id": "duplication",
- "key": "duplication",
- "name": "Duplication",
+ "id": "duplicated_lines",
+ "key": "duplicated_lines",
+ "name": "Duplicated_lines",
"type": "PERCENT",
},
]
@@ -184,13 +184,13 @@ exports[`should correctly switch scope 3`] = `
Object {
"id": "new_coverage",
"key": "new_coverage",
- "name": "Coverage on New Code",
+ "name": "New_coverage",
"type": "PERCENT",
},
Object {
- "id": "new_duplication",
- "key": "new_duplication",
- "name": "Duplication on New Code",
+ "id": "new_duplicated_lines",
+ "key": "new_duplicated_lines",
+ "name": "New_duplicated_lines",
"type": "PERCENT",
},
]
@@ -251,13 +251,13 @@ exports[`should render correctly 1`] = `
Object {
"id": "new_coverage",
"key": "new_coverage",
- "name": "Coverage on New Code",
+ "name": "New_coverage",
"type": "PERCENT",
},
Object {
- "id": "new_duplication",
- "key": "new_duplication",
- "name": "Duplication on New Code",
+ "id": "new_duplicated_lines",
+ "key": "new_duplicated_lines",
+ "name": "New_duplicated_lines",
"type": "PERCENT",
},
]
@@ -299,13 +299,13 @@ exports[`should render correctly 2`] = `
Object {
"id": "new_coverage",
"key": "new_coverage",
- "name": "Coverage on New Code",
+ "name": "New_coverage",
"type": "PERCENT",
},
Object {
- "id": "new_duplication",
- "key": "new_duplication",
- "name": "Duplication on New Code",
+ "id": "new_duplicated_lines",
+ "key": "new_duplicated_lines",
+ "name": "New_duplicated_lines",
"type": "PERCENT",
},
]
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Conditions-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Conditions-test.tsx.snap
index d3db47fc642..e5019f06076 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Conditions-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Conditions-test.tsx.snap
@@ -89,16 +89,16 @@ exports[`should render correctly 1`] = `
Object {
"error": "10",
"id": 2,
- "metric": "duplication",
+ "metric": "duplicated_lines",
"op": "LT",
}
}
key="2"
metric={
Object {
- "id": "duplication",
- "key": "duplication",
- "name": "Duplication",
+ "id": "duplicated_lines",
+ "key": "duplicated_lines",
+ "name": "Duplicated_lines",
"type": "PERCENT",
}
}
@@ -210,7 +210,7 @@ exports[`should render correctly with new code conditions 1`] = `
Object {
"id": "new_coverage",
"key": "new_coverage",
- "name": "Coverage on New Code",
+ "name": "New_coverage",
"type": "PERCENT",
}
}
@@ -229,16 +229,16 @@ exports[`should render correctly with new code conditions 1`] = `
Object {
"error": "10",
"id": 4,
- "metric": "new_duplication",
+ "metric": "new_duplicated_lines",
"op": "LT",
}
}
key="4"
metric={
Object {
- "id": "new_duplication",
- "key": "new_duplication",
- "name": "Duplication on New Code",
+ "id": "new_duplicated_lines",
+ "key": "new_duplicated_lines",
+ "name": "New_duplicated_lines",
"type": "PERCENT",
}
}
@@ -328,16 +328,16 @@ exports[`should render correctly with new code conditions 1`] = `
Object {
"error": "10",
"id": 2,
- "metric": "duplication",
+ "metric": "duplicated_lines",
"op": "LT",
}
}
key="2"
metric={
Object {
- "id": "duplication",
- "key": "duplication",
- "name": "Duplication",
+ "id": "duplicated_lines",
+ "key": "duplicated_lines",
+ "name": "Duplicated_lines",
"type": "PERCENT",
}
}
@@ -464,16 +464,16 @@ exports[`should render the add conditions button and modal 1`] = `
Object {
"error": "10",
"id": 2,
- "metric": "duplication",
+ "metric": "duplicated_lines",
"op": "LT",
}
}
key="2"
metric={
Object {
- "id": "duplication",
- "key": "duplication",
- "name": "Duplication",
+ "id": "duplicated_lines",
+ "key": "duplicated_lines",
+ "name": "Duplicated_lines",
"type": "PERCENT",
}
}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/MeasuresOverlayMeasure.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/MeasuresOverlayMeasure.tsx
index 0ff4afc2ba8..52450c42784 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/MeasuresOverlayMeasure.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/MeasuresOverlayMeasure.tsx
@@ -20,6 +20,7 @@
import * as React from 'react';
import IssueTypeIcon from 'sonar-ui-common/components/icons/IssueTypeIcon';
import { getLocalizedMetricName } from 'sonar-ui-common/helpers/l10n';
+import { isMetricKey, MetricKey } from '../../../types/metrics';
import Measure from '../../measure/Measure';
export interface MeasureWithMetric {
@@ -38,9 +39,10 @@ export default function MeasuresOverlayMeasure({ measure }: Props) {
data-metric={measure.metric.key}
key={measure.metric.key}>
<span className="measure-name">
- {['bugs', 'vulnerabilities', 'code_smells'].includes(measure.metric.key) && (
- <IssueTypeIcon className="little-spacer-right" query={measure.metric.key} />
- )}
+ {isMetricKey(measure.metric.key) &&
+ [MetricKey.bugs, MetricKey.vulnerabilities, MetricKey.code_smells].includes(
+ measure.metric.key
+ ) && <IssueTypeIcon className="little-spacer-right" query={measure.metric.key} />}
{getLocalizedMetricName(measure.metric)}
</span>
<span className="measure-value">
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/MeasuresOverlay-test.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/MeasuresOverlay-test.tsx
index 2017997e0a6..ef77fc3c614 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/MeasuresOverlay-test.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/MeasuresOverlay-test.tsx
@@ -21,6 +21,7 @@ import { shallow } from 'enzyme';
import * as React from 'react';
import { click, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { mockBranch } from '../../../../helpers/mocks/branch-like';
+import { MetricKey } from '../../../../types/metrics';
import MeasuresOverlay from '../MeasuresOverlay';
jest.mock('../../../../api/issues', () => ({
@@ -60,78 +61,78 @@ jest.mock('../../../../api/issues', () => ({
jest.mock('../../../../api/measures', () => ({
getMeasures: () =>
Promise.resolve([
- { metric: 'vulnerabilities', value: '0' },
- { metric: 'complexity', value: '1' },
- { metric: 'test_errors', value: '1' },
- { metric: 'comment_lines_density', value: '20.0' },
- { metric: 'wont_fix_issues', value: '0' },
- { metric: 'uncovered_lines', value: '1' },
- { metric: 'functions', value: '1' },
- { metric: 'duplicated_files', value: '1' },
- { metric: 'duplicated_blocks', value: '3' },
- { metric: 'line_coverage', value: '75.0' },
- { metric: 'duplicated_lines_density', value: '0.0' },
- { metric: 'comment_lines', value: '2' },
- { metric: 'ncloc', value: '8' },
- { metric: 'reliability_rating', value: '1.0' },
- { metric: 'false_positive_issues', value: '0' },
- { metric: 'reliability_remediation_effort', value: '0' },
- { metric: 'code_smells', value: '2' },
- { metric: 'security_rating', value: '1.0' },
- { metric: 'test_success_density', value: '100.0' },
- { metric: 'cognitive_complexity', value: '0' },
- { metric: 'files', value: '1' },
- { metric: 'duplicated_lines', value: '0' },
- { metric: 'lines', value: '18' },
- { metric: 'classes', value: '1' },
- { metric: 'bugs', value: '0' },
- { metric: 'lines_to_cover', value: '4' },
- { metric: 'sqale_index', value: '40' },
- { metric: 'sqale_debt_ratio', value: '16.7' },
- { metric: 'coverage', value: '75.0' },
- { metric: 'security_remediation_effort', value: '0' },
- { metric: 'statements', value: '3' },
- { metric: 'skipped_tests', value: '0' },
- { metric: 'test_failures', value: '0' },
- { metric: 'violations', value: '1' }
+ { metric: MetricKey.vulnerabilities, value: '0' },
+ { metric: MetricKey.complexity, value: '1' },
+ { metric: MetricKey.test_errors, value: '1' },
+ { metric: MetricKey.comment_lines_density, value: '20.0' },
+ { metric: MetricKey.wont_fix_issues, value: '0' },
+ { metric: MetricKey.uncovered_lines, value: '1' },
+ { metric: MetricKey.functions, value: '1' },
+ { metric: MetricKey.duplicated_files, value: '1' },
+ { metric: MetricKey.duplicated_blocks, value: '3' },
+ { metric: MetricKey.line_coverage, value: '75.0' },
+ { metric: MetricKey.duplicated_lines_density, value: '0.0' },
+ { metric: MetricKey.comment_lines, value: '2' },
+ { metric: MetricKey.ncloc, value: '8' },
+ { metric: MetricKey.reliability_rating, value: '1.0' },
+ { metric: MetricKey.false_positive_issues, value: '0' },
+ { metric: MetricKey.reliability_remediation_effort, value: '0' },
+ { metric: MetricKey.code_smells, value: '2' },
+ { metric: MetricKey.security_rating, value: '1.0' },
+ { metric: MetricKey.test_success_density, value: '100.0' },
+ { metric: MetricKey.cognitive_complexity, value: '0' },
+ { metric: MetricKey.files, value: '1' },
+ { metric: MetricKey.duplicated_lines, value: '0' },
+ { metric: MetricKey.lines, value: '18' },
+ { metric: MetricKey.classes, value: '1' },
+ { metric: MetricKey.bugs, value: '0' },
+ { metric: MetricKey.lines_to_cover, value: '4' },
+ { metric: MetricKey.sqale_index, value: '40' },
+ { metric: MetricKey.sqale_debt_ratio, value: '16.7' },
+ { metric: MetricKey.coverage, value: '75.0' },
+ { metric: MetricKey.security_remediation_effort, value: '0' },
+ { metric: MetricKey.statements, value: '3' },
+ { metric: MetricKey.skipped_tests, value: '0' },
+ { metric: MetricKey.test_failures, value: '0' },
+ { metric: MetricKey.violations, value: '1' }
])
}));
jest.mock('../../../../api/metrics', () => ({
getAllMetrics: () =>
Promise.resolve([
- { key: 'vulnerabilities', type: 'INT', domain: 'Security' },
- { key: 'complexity', type: 'INT', domain: 'Complexity' },
- { key: 'test_errors', type: 'INT', domain: 'Tests' },
- { key: 'comment_lines_density', type: 'PERCENT', domain: 'Size' },
- { key: 'wont_fix_issues', type: 'INT', domain: 'Issues' },
- { key: 'uncovered_lines', type: 'INT', domain: 'Coverage' },
- { key: 'functions', type: 'INT', domain: 'Size' },
- { key: 'duplicated_files', type: 'INT', domain: 'Duplications' },
- { key: 'duplicated_blocks', type: 'INT', domain: 'Duplications' },
- { key: 'line_coverage', type: 'PERCENT', domain: 'Coverage' },
- { key: 'duplicated_lines_density', type: 'PERCENT', domain: 'Duplications' },
- { key: 'comment_lines', type: 'INT', domain: 'Size' },
- { key: 'ncloc', type: 'INT', domain: 'Size' },
- { key: 'reliability_rating', type: 'RATING', domain: 'Reliability' },
- { key: 'false_positive_issues', type: 'INT', domain: 'Issues' },
- { key: 'code_smells', type: 'INT', domain: 'Maintainability' },
- { key: 'security_rating', type: 'RATING', domain: 'Security' },
- { key: 'test_success_density', type: 'PERCENT', domain: 'Tests' },
- { key: 'cognitive_complexity', type: 'INT', domain: 'Complexity' },
- { key: 'files', type: 'INT', domain: 'Size' },
- { key: 'duplicated_lines', type: 'INT', domain: 'Duplications' },
- { key: 'lines', type: 'INT', domain: 'Size' },
- { key: 'classes', type: 'INT', domain: 'Size' },
- { key: 'bugs', type: 'INT', domain: 'Reliability' },
- { key: 'lines_to_cover', type: 'INT', domain: 'Coverage' },
- { key: 'sqale_index', type: 'WORK_DUR', domain: 'Maintainability' },
- { key: 'sqale_debt_ratio', type: 'PERCENT', domain: 'Maintainability' },
- { key: 'coverage', type: 'PERCENT', domain: 'Coverage' },
- { key: 'statements', type: 'INT', domain: 'Size' },
- { key: 'skipped_tests', type: 'INT', domain: 'Tests' },
- { key: 'test_failures', type: 'INT', domain: 'Tests' },
- { key: 'violations', type: 'INT', domain: 'Issues' },
+ { key: MetricKey.vulnerabilities, type: 'INT', domain: 'Security' },
+ { key: MetricKey.complexity, type: 'INT', domain: 'Complexity' },
+ { key: MetricKey.test_errors, type: 'INT', domain: 'Tests' },
+ { key: MetricKey.comment_lines_density, type: 'PERCENT', domain: 'Size' },
+ { key: MetricKey.wont_fix_issues, type: 'INT', domain: 'Issues' },
+ { key: MetricKey.uncovered_lines, type: 'INT', domain: 'Coverage' },
+ { key: MetricKey.functions, type: 'INT', domain: 'Size' },
+ { key: MetricKey.duplicated_files, type: 'INT', domain: 'Duplications' },
+ { key: MetricKey.duplicated_blocks, type: 'INT', domain: 'Duplications' },
+ { key: MetricKey.line_coverage, type: 'PERCENT', domain: 'Coverage' },
+ { key: MetricKey.duplicated_lines_density, type: 'PERCENT', domain: 'Duplications' },
+ { key: MetricKey.comment_lines, type: 'INT', domain: 'Size' },
+ { key: MetricKey.ncloc, type: 'INT', domain: 'Size' },
+ { key: MetricKey.reliability_rating, type: 'RATING', domain: 'Reliability' },
+ { key: MetricKey.false_positive_issues, type: 'INT', domain: 'Issues' },
+ { key: MetricKey.code_smells, type: 'INT', domain: 'Maintainability' },
+ { key: MetricKey.security_rating, type: 'RATING', domain: 'Security' },
+ { key: MetricKey.test_success_density, type: 'PERCENT', domain: 'Tests' },
+ { key: MetricKey.cognitive_complexity, type: 'INT', domain: 'Complexity' },
+ { key: MetricKey.files, type: 'INT', domain: 'Size' },
+ { key: MetricKey.duplicated_lines, type: 'INT', domain: 'Duplications' },
+ { key: MetricKey.lines, type: 'INT', domain: 'Size' },
+ { key: MetricKey.classes, type: 'INT', domain: 'Size' },
+ { key: MetricKey.bugs, type: 'INT', domain: 'Reliability' },
+ { key: MetricKey.lines_to_cover, type: 'INT', domain: 'Coverage' },
+ { key: MetricKey.sqale_index, type: 'WORK_DUR', domain: 'Maintainability' },
+ { key: MetricKey.sqale_debt_ratio, type: 'PERCENT', domain: 'Maintainability' },
+ { key: MetricKey.coverage, type: 'PERCENT', domain: 'Coverage' },
+ { key: MetricKey.statements, type: 'INT', domain: 'Size' },
+ { key: MetricKey.skipped_tests, type: 'INT', domain: 'Tests' },
+ { key: MetricKey.test_failures, type: 'INT', domain: 'Tests' },
+ { key: MetricKey.violations, type: 'INT', domain: 'Issues' },
// next two must be filtered out
{ key: 'data', type: 'DATA' },
{ key: 'hidden', hidden: true }
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts
new file mode 100644
index 00000000000..ea9bffaf05a
--- /dev/null
+++ b/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import { enhanceConditionWithMeasure } from '../measures';
+import { mockQualityGateStatusCondition } from '../mocks/quality-gates';
+import { mockMeasureEnhanced, mockMetric } from '../testMocks';
+
+describe('enhanceConditionWithMeasure', () => {
+ it('should correctly map enhance conditions with measure data', () => {
+ const measures = [
+ mockMeasureEnhanced({ metric: mockMetric({ key: 'bugs' }), periods: undefined }),
+ mockMeasureEnhanced({ metric: mockMetric({ key: 'new_bugs' }) })
+ ];
+
+ expect(
+ enhanceConditionWithMeasure(mockQualityGateStatusCondition({ metric: 'bugs' }), measures)
+ ).toMatchObject({
+ measure: expect.objectContaining({ metric: expect.objectContaining({ key: 'bugs' }) })
+ });
+
+ expect(
+ enhanceConditionWithMeasure(mockQualityGateStatusCondition({ metric: 'new_bugs' }), measures)
+ ).toMatchObject({
+ measure: expect.objectContaining({
+ metric: expect.objectContaining({ key: 'new_bugs' })
+ }),
+ period: 1
+ });
+ });
+
+ it('should return undefined if no match can be found', () => {
+ expect(enhanceConditionWithMeasure(mockQualityGateStatusCondition(), [])).toBeUndefined();
+ });
+});
diff --git a/server/sonar-web/src/main/js/helpers/measures.ts b/server/sonar-web/src/main/js/helpers/measures.ts
index 283ebfdf7bd..0c180278b2c 100644
--- a/server/sonar-web/src/main/js/helpers/measures.ts
+++ b/server/sonar-web/src/main/js/helpers/measures.ts
@@ -20,9 +20,14 @@
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
import { formatMeasure } from 'sonar-ui-common/helpers/measures';
import { isDefined } from 'sonar-ui-common/helpers/types';
+import { MetricKey } from '../types/metrics';
+import {
+ QualityGateStatusCondition,
+ QualityGateStatusConditionEnhanced
+} from '../types/quality-gates';
/** Return a localized metric name */
-export function localizeMetric(metricKey: string): string {
+export function localizeMetric(metricKey: MetricKey | string): string {
return translate('metric', metricKey, 'name');
}
@@ -48,6 +53,22 @@ export function enhanceMeasuresWithMetrics(
.filter(isDefined);
}
+export function enhanceConditionWithMeasure(
+ condition: QualityGateStatusCondition,
+ measures: T.MeasureEnhanced[]
+): QualityGateStatusConditionEnhanced | undefined {
+ const measure = measures.find(m => m.metric.key === condition.metric);
+
+ // Make sure we have a period index. This is necessary when dealing with
+ // applications.
+ let { period } = condition;
+ if (measure && measure.periods && !period) {
+ period = measure.periods[0].index;
+ }
+
+ return measure && { ...condition, period, measure };
+}
+
/** Get period value of a measure */
export function getPeriodValue(
measure: T.Measure | T.MeasureEnhanced,
@@ -68,7 +89,7 @@ export function isPeriodBestValue(
}
/** Check if metric is differential */
-export function isDiffMetric(metricKey: string): boolean {
+export function isDiffMetric(metricKey: MetricKey | string): boolean {
return metricKey.indexOf('new_') === 0;
}
@@ -124,7 +145,7 @@ function getMaintainabilityRatingTooltip(rating: number): string {
);
}
-export function getRatingTooltip(metricKey: string, value: number | string): string {
+export function getRatingTooltip(metricKey: MetricKey | string, value: number | string): string {
const ratingLetter = formatMeasure(value, 'RATING');
const finalMetricKey = isDiffMetric(metricKey) ? metricKey.substr(4) : metricKey;
@@ -138,6 +159,6 @@ export function getDisplayMetrics(metrics: T.Metric[]) {
return metrics.filter(metric => !metric.hidden && !['DATA', 'DISTRIB'].includes(metric.type));
}
-export function findMeasure(measures: T.Measure[], metric: string) {
- return measures.find(measure => measure.metric === metric);
+export function findMeasure(measures: T.MeasureEnhanced[], metric: MetricKey | string) {
+ return measures.find(measure => measure.metric.key === metric);
}
diff --git a/server/sonar-web/src/main/js/helpers/testMocks.ts b/server/sonar-web/src/main/js/helpers/testMocks.ts
index 9b43cec23f3..b9f034fff2a 100644
--- a/server/sonar-web/src/main/js/helpers/testMocks.ts
+++ b/server/sonar-web/src/main/js/helpers/testMocks.ts
@@ -451,13 +451,17 @@ export function mockLocation(overrides: Partial<Location> = {}): Location {
};
}
-export function mockMetric(overrides: Partial<T.Metric> = {}): T.Metric {
- return {
- id: 'coverage',
- key: 'coverage',
- name: 'Coverage',
- type: 'PERCENT',
- ...overrides
+export function mockMetric(
+ overrides: Partial<Pick<T.Metric, 'key' | 'name' | 'type'>> = {}
+): T.Metric {
+ const key = overrides.key || 'coverage';
+ const name = overrides.name || key[0].toUpperCase() + key.substr(1);
+ const type = overrides.type || 'PERCENT';
+ return {
+ id: key,
+ key,
+ name,
+ type
};
}
diff --git a/server/sonar-web/src/main/js/types/metrics.ts b/server/sonar-web/src/main/js/types/metrics.ts
new file mode 100644
index 00000000000..f205a778f11
--- /dev/null
+++ b/server/sonar-web/src/main/js/types/metrics.ts
@@ -0,0 +1,148 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+export enum MetricKey {
+ alert_status = 'alert_status',
+ blocker_violations = 'blocker_violations',
+ branch_coverage = 'branch_coverage',
+ bugs = 'bugs',
+ burned_budget = 'burned_budget',
+ business_value = 'business_value',
+ class_complexity = 'class_complexity',
+ classes = 'classes',
+ code_smells = 'code_smells',
+ cognitive_complexity = 'cognitive_complexity',
+ comment_lines = 'comment_lines',
+ comment_lines_data = 'comment_lines_data',
+ comment_lines_density = 'comment_lines_density',
+ complexity = 'complexity',
+ complexity_in_classes = 'complexity_in_classes',
+ complexity_in_functions = 'complexity_in_functions',
+ conditions_to_cover = 'conditions_to_cover',
+ confirmed_issues = 'confirmed_issues',
+ coverage = 'coverage',
+ critical_violations = 'critical_violations',
+ development_cost = 'development_cost',
+ directories = 'directories',
+ duplicated_blocks = 'duplicated_blocks',
+ duplicated_files = 'duplicated_files',
+ duplicated_lines = 'duplicated_lines',
+ duplicated_lines_density = 'duplicated_lines_density',
+ duplications_data = 'duplications_data',
+ effort_to_reach_maintainability_rating_a = 'effort_to_reach_maintainability_rating_a',
+ executable_lines_data = 'executable_lines_data',
+ false_positive_issues = 'false_positive_issues',
+ file_complexity = 'file_complexity',
+ file_complexity_distribution = 'file_complexity_distribution',
+ filename_size = 'filename_size',
+ filename_size_rating = 'filename_size_rating',
+ files = 'files',
+ function_complexity = 'function_complexity',
+ function_complexity_distribution = 'function_complexity_distribution',
+ functions = 'functions',
+ generated_lines = 'generated_lines',
+ generated_ncloc = 'generated_ncloc',
+ info_violations = 'info_violations',
+ last_change_on_maintainability_rating = 'last_change_on_maintainability_rating',
+ last_change_on_releasability_rating = 'last_change_on_releasability_rating',
+ last_change_on_reliability_rating = 'last_change_on_reliability_rating',
+ last_change_on_security_rating = 'last_change_on_security_rating',
+ last_change_on_security_review_rating = 'last_change_on_security_review_rating',
+ last_commit_date = 'last_commit_date',
+ leak_projects = 'leak_projects',
+ line_coverage = 'line_coverage',
+ lines = 'lines',
+ lines_to_cover = 'lines_to_cover',
+ maintainability_rating_effort = 'maintainability_rating_effort',
+ major_violations = 'major_violations',
+ minor_violations = 'minor_violations',
+ ncloc = 'ncloc',
+ ncloc_data = 'ncloc_data',
+ ncloc_language_distribution = 'ncloc_language_distribution',
+ new_blocker_violations = 'new_blocker_violations',
+ new_branch_coverage = 'new_branch_coverage',
+ new_bugs = 'new_bugs',
+ new_code_smells = 'new_code_smells',
+ new_conditions_to_cover = 'new_conditions_to_cover',
+ new_coverage = 'new_coverage',
+ new_critical_violations = 'new_critical_violations',
+ new_development_cost = 'new_development_cost',
+ new_duplicated_blocks = 'new_duplicated_blocks',
+ new_duplicated_lines = 'new_duplicated_lines',
+ new_duplicated_lines_density = 'new_duplicated_lines_density',
+ new_info_violations = 'new_info_violations',
+ new_line_coverage = 'new_line_coverage',
+ new_lines = 'new_lines',
+ new_lines_to_cover = 'new_lines_to_cover',
+ new_maintainability_rating = 'new_maintainability_rating',
+ new_major_violations = 'new_major_violations',
+ new_minor_violations = 'new_minor_violations',
+ new_reliability_rating = 'new_reliability_rating',
+ new_reliability_remediation_effort = 'new_reliability_remediation_effort',
+ new_security_hotspots = 'new_security_hotspots',
+ new_security_rating = 'new_security_rating',
+ new_security_remediation_effort = 'new_security_remediation_effort',
+ new_sqale_debt_ratio = 'new_sqale_debt_ratio',
+ new_technical_debt = 'new_technical_debt',
+ new_uncovered_conditions = 'new_uncovered_conditions',
+ new_uncovered_lines = 'new_uncovered_lines',
+ new_violations = 'new_violations',
+ new_vulnerabilities = 'new_vulnerabilities',
+ open_issues = 'open_issues',
+ projects = 'projects',
+ public_api = 'public_api',
+ public_documented_api_density = 'public_documented_api_density',
+ public_undocumented_api = 'public_undocumented_api',
+ quality_gate_details = 'quality_gate_details',
+ quality_profiles = 'quality_profiles',
+ releasability_effort = 'releasability_effort',
+ releasability_rating = 'releasability_rating',
+ reliability_rating = 'reliability_rating',
+ reliability_rating_effort = 'reliability_rating_effort',
+ reliability_remediation_effort = 'reliability_remediation_effort',
+ reopened_issues = 'reopened_issues',
+ security_hotspots = 'security_hotspots',
+ security_rating = 'security_rating',
+ security_rating_effort = 'security_rating_effort',
+ security_remediation_effort = 'security_remediation_effort',
+ security_review_rating = 'security_review_rating',
+ security_review_rating_effort = 'security_review_rating_effort',
+ skipped_tests = 'skipped_tests',
+ sonarjava_feedback = 'sonarjava_feedback',
+ sqale_debt_ratio = 'sqale_debt_ratio',
+ sqale_index = 'sqale_index',
+ sqale_rating = 'sqale_rating',
+ statements = 'statements',
+ team_at_sonarsource = 'team_at_sonarsource',
+ team_size = 'team_size',
+ test_errors = 'test_errors',
+ test_execution_time = 'test_execution_time',
+ test_failures = 'test_failures',
+ test_success_density = 'test_success_density',
+ tests = 'tests',
+ uncovered_conditions = 'uncovered_conditions',
+ uncovered_lines = 'uncovered_lines',
+ violations = 'violations',
+ vulnerabilities = 'vulnerabilities',
+ wont_fix_issues = 'wont_fix_issues'
+}
+
+export function isMetricKey(key: string): key is MetricKey {
+ return (Object.values(MetricKey) as string[]).includes(key);
+}