]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-12632 SONAR-12648 Update Pull Request dashboard
authorWouter Admiraal <wouter.admiraal@sonarsource.com>
Thu, 19 Dec 2019 09:45:39 +0000 (10:45 +0100)
committerSonarTech <sonartech@sonarsource.com>
Mon, 10 Feb 2020 19:46:15 +0000 (20:46 +0100)
- Rename component to PullRequestOverview for better consistency
- Update all measure and condition related logic to cater for the
  quality gate condition components
- Move sub-components to the shared folder, to make them re-usable.
- SONAR-12648 Change Metrics title to Measures

32 files changed:
server/sonar-web/src/main/js/app/styles/init/type.css
server/sonar-web/src/main/js/apps/overview/components/IssueLabel.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/IssueRating.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/MeasurementLabel.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueRating-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/__tests__/MeasurementLabel-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueRating-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/MeasurementLabel-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/pullRequests/AfterMergeEstimate.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/IssueLabel.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/IssueRating.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/LargeQualityGateBadge.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/MeasurementLabel.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/pullRequests/ReviewApp.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/AfterMergeEstimate-test.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/IssueLabel-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/IssueRating-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/LargeQualityGateBadge-test.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/MeasurementLabel-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/ReviewApp-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/AfterMergeEstimate-test.tsx.snap
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/IssueLabel-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/IssueRating-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/LargeQualityGateBadge-test.tsx.snap
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/MeasurementLabel-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/PullRequestOverview-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/ReviewApp-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/overview/utils.ts

index 320be2e34c45eafa623d337c9ec7262c7bc95892..b04036497ff95f8e1c1c53946f94369fa1cd14c8 100644 (file)
@@ -253,10 +253,18 @@ small,
   text-transform: none;
 }
 
+.text-light {
+  font-weight: 300 !important;
+}
+
 .text-normal {
   font-weight: normal !important;
 }
 
+.text-bold {
+  font-weight: bold !important;
+}
+
 .text-muted {
   color: var(--secondFontColor);
 }
diff --git a/server/sonar-web/src/main/js/apps/overview/components/IssueLabel.tsx b/server/sonar-web/src/main/js/apps/overview/components/IssueLabel.tsx
new file mode 100644 (file)
index 0000000..1460880
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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 * as React from 'react';
+import { Link } from 'react-router';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { formatMeasure, localizeMetric } from 'sonar-ui-common/helpers/measures';
+import DocTooltip from '../../../components/docs/DocTooltip';
+import { getLeakValue } from '../../../components/measure/utils';
+import { getBranchLikeQuery } from '../../../helpers/branch-like';
+import { findMeasure } from '../../../helpers/measures';
+import { getComponentIssuesUrl } from '../../../helpers/urls';
+import { BranchLike } from '../../../types/branch-like';
+import { getIssueIconClass, getIssueMetricKey, IssueType } from '../utils';
+
+export interface IssueLabelProps {
+  branchLike?: BranchLike;
+  component: T.Component;
+  docTooltip?: Promise<{ default: string }>;
+  measures: T.MeasureEnhanced[];
+  type: IssueType;
+  useDiffMetric?: boolean;
+}
+
+export function IssueLabel(props: IssueLabelProps) {
+  const { branchLike, component, docTooltip, measures, type, useDiffMetric = false } = props;
+  const metric = getIssueMetricKey(type, useDiffMetric);
+  const measure = findMeasure(measures, metric);
+  const iconClass = getIssueIconClass(type);
+
+  let value;
+  if (measure) {
+    value = useDiffMetric ? getLeakValue(measure) : measure.value;
+  }
+
+  const params = {
+    ...getBranchLikeQuery(branchLike),
+    resolved: 'false',
+    types: type,
+    sinceLeakPeriod: useDiffMetric ? 'true' : 'false'
+  };
+
+  return (
+    <>
+      {value === undefined ? (
+        <span aria-label={translate('no_data')} className="overview-measures-empty-value" />
+      ) : (
+        <Link
+          className="overview-measures-value text-light"
+          to={getComponentIssuesUrl(component.key, params)}>
+          {formatMeasure(value, 'SHORT_INT')}
+        </Link>
+      )}
+      {React.createElement(iconClass, { className: 'big-spacer-left little-spacer-right' })}
+      {localizeMetric(metric)}
+      {docTooltip && <DocTooltip className="little-spacer-left" doc={docTooltip} />}
+    </>
+  );
+}
+
+export default React.memo(IssueLabel);
diff --git a/server/sonar-web/src/main/js/apps/overview/components/IssueRating.tsx b/server/sonar-web/src/main/js/apps/overview/components/IssueRating.tsx
new file mode 100644 (file)
index 0000000..9379a40
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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 * as React from 'react';
+import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
+import Rating from 'sonar-ui-common/components/ui/Rating';
+import { getLeakValue, getRatingTooltip } from '../../../components/measure/utils';
+import DrilldownLink from '../../../components/shared/DrilldownLink';
+import { findMeasure } from '../../../helpers/measures';
+import { BranchLike } from '../../../types/branch-like';
+import { getIssueRatingMetricKey, getIssueRatingName, IssueType } from '../utils';
+
+export interface IssueRatingProps {
+  branchLike?: BranchLike;
+  component: T.Component;
+  measures: T.MeasureEnhanced[];
+  type: IssueType;
+  useDiffMetric?: boolean;
+}
+
+export function IssueRating(props: IssueRatingProps) {
+  const { branchLike, component, measures, type, useDiffMetric = false } = props;
+  const rating = getIssueRatingMetricKey(type, useDiffMetric);
+  const measure = findMeasure(measures, rating);
+
+  if (!rating || !measure) {
+    return null;
+  }
+
+  const value = useDiffMetric ? getLeakValue(measure) : measure.value;
+  const tooltip = value && getRatingTooltip(rating, Number(value));
+
+  return (
+    <>
+      <span className="flex-1 big-spacer-right text-right">{getIssueRatingName(type)}</span>
+      <Tooltip overlay={tooltip}>
+        <span>
+          <DrilldownLink
+            branchLike={branchLike}
+            className="link-no-underline"
+            component={component.key}
+            metric={rating}>
+            <Rating value={value} />
+          </DrilldownLink>
+        </span>
+      </Tooltip>
+    </>
+  );
+}
+
+export default React.memo(IssueRating);
diff --git a/server/sonar-web/src/main/js/apps/overview/components/MeasurementLabel.tsx b/server/sonar-web/src/main/js/apps/overview/components/MeasurementLabel.tsx
new file mode 100644 (file)
index 0000000..3de85a1
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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 * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import {
+  formatMeasure,
+  getMinDecimalsCountToBeDistinctFromThreshold
+} from 'sonar-ui-common/helpers/measures';
+import { getLeakValue } from '../../../components/measure/utils';
+import DrilldownLink from '../../../components/shared/DrilldownLink';
+import { findMeasure } from '../../../helpers/measures';
+import { BranchLike } from '../../../types/branch-like';
+import {
+  getMeasurementIconClass,
+  getMeasurementLabelKeys,
+  getMeasurementLinesMetricKey,
+  getMeasurementMetricKey,
+  getThreshold,
+  MeasurementType
+} from '../utils';
+
+interface Props {
+  branchLike?: BranchLike;
+  centered?: boolean;
+  component: T.Component;
+  measures: T.MeasureEnhanced[];
+  type: MeasurementType;
+  useDiffMetric?: boolean;
+}
+
+export default class MeasurementLabel extends React.Component<Props> {
+  getLabelText = () => {
+    const { branchLike, component, measures, type, useDiffMetric = false } = this.props;
+    const { expandedLabelKey, labelKey } = getMeasurementLabelKeys(type, useDiffMetric);
+    const linesMetric = getMeasurementLinesMetricKey(type, useDiffMetric);
+    const measure = findMeasure(measures, linesMetric);
+
+    if (!measure) {
+      return translate(labelKey);
+    } else {
+      const value = useDiffMetric ? getLeakValue(measure) : measure.value;
+
+      return (
+        <FormattedMessage
+          defaultMessage={translate(expandedLabelKey)}
+          id={expandedLabelKey}
+          values={{
+            count: (
+              <DrilldownLink
+                branchLike={branchLike}
+                className="big"
+                component={component.key}
+                metric={linesMetric}>
+                {formatMeasure(value, 'SHORT_INT')}
+              </DrilldownLink>
+            )
+          }}
+        />
+      );
+    }
+  };
+
+  render() {
+    const { branchLike, centered, component, measures, type, useDiffMetric = false } = this.props;
+    const iconClass = getMeasurementIconClass(type);
+    const metric = getMeasurementMetricKey(type, useDiffMetric);
+    const measure = findMeasure(measures, metric);
+
+    let value;
+    if (measure) {
+      value = useDiffMetric ? getLeakValue(measure) : measure.value;
+    }
+
+    if (value === undefined) {
+      return (
+        <div className="display-flex-center">
+          <span aria-label={translate('no_data')} className="overview-measures-empty-value" />
+          <span className="big-spacer-left">{this.getLabelText()}</span>
+        </div>
+      );
+    }
+
+    const icon = React.createElement(iconClass, { size: 'big', value: Number(value) });
+    const link = (
+      <DrilldownLink
+        branchLike={branchLike}
+        className="overview-measures-value text-light"
+        component={component.key}
+        metric={metric}>
+        {formatMeasure(value, 'PERCENT', {
+          decimals: getMinDecimalsCountToBeDistinctFromThreshold(
+            parseFloat(value),
+            getThreshold(measures, metric)
+          )
+        })}
+      </DrilldownLink>
+    );
+    const label = this.getLabelText();
+
+    return centered ? (
+      <div className="display-flex-column flex-1">
+        <div className="display-flex-center display-flex-justify-center">
+          <span className="big-spacer-right">{icon}</span>
+          {link}
+        </div>
+        <div className="spacer-top text-center">{label}</div>
+      </div>
+    ) : (
+      <div className="display-flex-center">
+        <span className="big-spacer-right">{icon}</span>
+        <div className="display-flex-column">
+          <span>{link}</span>
+          <span className="spacer-top">{label}</span>
+        </div>
+      </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx b/server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueLabel-test.tsx
new file mode 100644 (file)
index 0000000..17b9f42
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
+import { mockComponent, mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
+import { MetricKey } from '../../../../types/metrics';
+import { IssueType } from '../../utils';
+import { IssueLabel, IssueLabelProps } from '../IssueLabel';
+
+it('should render correctly for bugs', () => {
+  const measures = [
+    mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) }),
+    mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_bugs }) })
+  ];
+  expect(shallowRender({ measures })).toMatchSnapshot();
+  expect(shallowRender({ measures, useDiffMetric: true })).toMatchSnapshot();
+});
+
+it('should render correctly for code smells', () => {
+  const type = IssueType.CodeSmell;
+  const measures = [
+    mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.code_smells }) }),
+    mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_code_smells }) })
+  ];
+  expect(shallowRender({ measures, type })).toMatchSnapshot();
+  expect(shallowRender({ measures, type, useDiffMetric: true })).toMatchSnapshot();
+});
+
+it('should render correctly for vulnerabilities', () => {
+  const type = IssueType.Vulnerability;
+  const measures = [
+    mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.vulnerabilities }) }),
+    mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_vulnerabilities }) })
+  ];
+  expect(shallowRender({ measures, type })).toMatchSnapshot();
+  expect(shallowRender({ measures, type, useDiffMetric: true })).toMatchSnapshot();
+});
+
+it('should render correctly for hotspots', () => {
+  const docTooltip = Promise.resolve({ default: 'tooltip text' });
+  const type = IssueType.SecurityHotspot;
+  const measures = [
+    mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.security_hotspots }) }),
+    mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_security_hotspots }) })
+  ];
+  expect(
+    shallowRender({
+      docTooltip,
+      measures,
+      type
+    })
+  ).toMatchSnapshot();
+  expect(
+    shallowRender({
+      docTooltip,
+      measures,
+      type,
+      useDiffMetric: true
+    })
+  ).toMatchSnapshot();
+});
+
+it('should render correctly if no values are present', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<IssueLabelProps> = {}) {
+  return shallow(
+    <IssueLabel
+      branchLike={mockPullRequest()}
+      component={mockComponent()}
+      measures={[]}
+      type={IssueType.Bug}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueRating-test.tsx b/server/sonar-web/src/main/js/apps/overview/components/__tests__/IssueRating-test.tsx
new file mode 100644 (file)
index 0000000..a464765
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
+import { mockComponent, mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
+import { MetricKey } from '../../../../types/metrics';
+import { IssueType } from '../../utils';
+import { IssueRating, IssueRatingProps } from '../IssueRating';
+
+it('should render correctly for bugs', () => {
+  expect(shallowRender()).toMatchSnapshot();
+  expect(shallowRender({ useDiffMetric: true })).toMatchSnapshot();
+});
+
+it('should render correctly for code smells', () => {
+  expect(shallowRender({ type: IssueType.CodeSmell })).toMatchSnapshot();
+  expect(shallowRender({ type: IssueType.CodeSmell, useDiffMetric: true })).toMatchSnapshot();
+});
+
+it('should render correctly for vulnerabilities', () => {
+  expect(shallowRender({ type: IssueType.Vulnerability })).toMatchSnapshot();
+  expect(shallowRender({ type: IssueType.Vulnerability, useDiffMetric: true })).toMatchSnapshot();
+});
+
+it('should render correctly if no values are present', () => {
+  expect(
+    shallowRender({
+      measures: [mockMeasureEnhanced({ metric: mockMetric({ key: 'NONE' }) })]
+    }).type()
+  ).toBeNull();
+});
+
+function shallowRender(props: Partial<IssueRatingProps> = {}) {
+  return shallow(
+    <IssueRating
+      branchLike={mockPullRequest()}
+      component={mockComponent()}
+      measures={[
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_reliability_rating }) }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.reliability_rating }) }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_maintainability_rating }) }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.sqale_rating }) }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_security_rating }) }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.security_rating }) })
+      ]}
+      type={IssueType.Bug}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/MeasurementLabel-test.tsx b/server/sonar-web/src/main/js/apps/overview/components/__tests__/MeasurementLabel-test.tsx
new file mode 100644 (file)
index 0000000..944e278
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
+import { mockComponent, mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
+import { MetricKey } from '../../../../types/metrics';
+import { MeasurementType } from '../../utils';
+import MeasurementLabel from '../MeasurementLabel';
+
+it('should render correctly for coverage', () => {
+  expect(shallowRender()).toMatchSnapshot();
+  expect(
+    shallowRender({
+      measures: [
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.lines_to_cover }) })
+      ]
+    })
+  ).toMatchSnapshot();
+  expect(
+    shallowRender({
+      measures: [
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_coverage }) }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_lines_to_cover }) })
+      ],
+      useDiffMetric: true
+    })
+  ).toMatchSnapshot();
+});
+
+it('should render correctly for duplications', () => {
+  expect(
+    shallowRender({
+      measures: [
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.duplicated_lines_density }) })
+      ],
+      type: MeasurementType.Duplication
+    })
+  ).toMatchSnapshot();
+  expect(
+    shallowRender({
+      measures: [
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.duplicated_lines_density }) }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.ncloc }) })
+      ],
+      type: MeasurementType.Duplication
+    })
+  ).toMatchSnapshot();
+  expect(
+    shallowRender({
+      measures: [
+        mockMeasureEnhanced({
+          metric: mockMetric({ key: MetricKey.new_duplicated_lines_density })
+        }),
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_lines }) })
+      ],
+      type: MeasurementType.Duplication,
+      useDiffMetric: true
+    })
+  ).toMatchSnapshot();
+});
+
+it('should render correctly with no value', () => {
+  expect(shallowRender({ measures: [] })).toMatchSnapshot();
+});
+
+it('should render correctly when centered', () => {
+  expect(shallowRender({ centered: true })).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<MeasurementLabel['props']> = {}) {
+  return shallow(
+    <MeasurementLabel
+      branchLike={mockPullRequest()}
+      component={mockComponent()}
+      measures={[mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) })]}
+      type={MeasurementType.Coverage}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueLabel-test.tsx.snap
new file mode 100644 (file)
index 0000000..04a4cf7
--- /dev/null
@@ -0,0 +1,246 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for bugs 1`] = `
+<Fragment>
+  <Link
+    className="overview-measures-value text-light"
+    onlyActiveOnIndex={false}
+    style={Object {}}
+    to={
+      Object {
+        "pathname": "/project/issues",
+        "query": Object {
+          "id": "my-project",
+          "pullRequest": "1001",
+          "resolved": "false",
+          "sinceLeakPeriod": "false",
+          "types": "BUG",
+        },
+      }
+    }
+  >
+    1
+  </Link>
+  <BugIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.bugs.name
+</Fragment>
+`;
+
+exports[`should render correctly for bugs 2`] = `
+<Fragment>
+  <Link
+    className="overview-measures-value text-light"
+    onlyActiveOnIndex={false}
+    style={Object {}}
+    to={
+      Object {
+        "pathname": "/project/issues",
+        "query": Object {
+          "id": "my-project",
+          "pullRequest": "1001",
+          "resolved": "false",
+          "sinceLeakPeriod": "true",
+          "types": "BUG",
+        },
+      }
+    }
+  >
+    1
+  </Link>
+  <BugIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.new_bugs.name
+</Fragment>
+`;
+
+exports[`should render correctly for code smells 1`] = `
+<Fragment>
+  <Link
+    className="overview-measures-value text-light"
+    onlyActiveOnIndex={false}
+    style={Object {}}
+    to={
+      Object {
+        "pathname": "/project/issues",
+        "query": Object {
+          "id": "my-project",
+          "pullRequest": "1001",
+          "resolved": "false",
+          "sinceLeakPeriod": "false",
+          "types": "CODE_SMELL",
+        },
+      }
+    }
+  >
+    1
+  </Link>
+  <CodeSmellIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.code_smells.name
+</Fragment>
+`;
+
+exports[`should render correctly for code smells 2`] = `
+<Fragment>
+  <Link
+    className="overview-measures-value text-light"
+    onlyActiveOnIndex={false}
+    style={Object {}}
+    to={
+      Object {
+        "pathname": "/project/issues",
+        "query": Object {
+          "id": "my-project",
+          "pullRequest": "1001",
+          "resolved": "false",
+          "sinceLeakPeriod": "true",
+          "types": "CODE_SMELL",
+        },
+      }
+    }
+  >
+    1
+  </Link>
+  <CodeSmellIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.new_code_smells.name
+</Fragment>
+`;
+
+exports[`should render correctly for hotspots 1`] = `
+<Fragment>
+  <Link
+    className="overview-measures-value text-light"
+    onlyActiveOnIndex={false}
+    style={Object {}}
+    to={
+      Object {
+        "pathname": "/project/issues",
+        "query": Object {
+          "id": "my-project",
+          "pullRequest": "1001",
+          "resolved": "false",
+          "sinceLeakPeriod": "false",
+          "types": "SECURITY_HOTSPOT",
+        },
+      }
+    }
+  >
+    1
+  </Link>
+  <SecurityHotspotIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.security_hotspots.name
+  <DocTooltip
+    className="little-spacer-left"
+    doc={Promise {}}
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for hotspots 2`] = `
+<Fragment>
+  <Link
+    className="overview-measures-value text-light"
+    onlyActiveOnIndex={false}
+    style={Object {}}
+    to={
+      Object {
+        "pathname": "/project/issues",
+        "query": Object {
+          "id": "my-project",
+          "pullRequest": "1001",
+          "resolved": "false",
+          "sinceLeakPeriod": "true",
+          "types": "SECURITY_HOTSPOT",
+        },
+      }
+    }
+  >
+    1
+  </Link>
+  <SecurityHotspotIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.new_security_hotspots.name
+  <DocTooltip
+    className="little-spacer-left"
+    doc={Promise {}}
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for vulnerabilities 1`] = `
+<Fragment>
+  <Link
+    className="overview-measures-value text-light"
+    onlyActiveOnIndex={false}
+    style={Object {}}
+    to={
+      Object {
+        "pathname": "/project/issues",
+        "query": Object {
+          "id": "my-project",
+          "pullRequest": "1001",
+          "resolved": "false",
+          "sinceLeakPeriod": "false",
+          "types": "VULNERABILITY",
+        },
+      }
+    }
+  >
+    1
+  </Link>
+  <VulnerabilityIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.vulnerabilities.name
+</Fragment>
+`;
+
+exports[`should render correctly for vulnerabilities 2`] = `
+<Fragment>
+  <Link
+    className="overview-measures-value text-light"
+    onlyActiveOnIndex={false}
+    style={Object {}}
+    to={
+      Object {
+        "pathname": "/project/issues",
+        "query": Object {
+          "id": "my-project",
+          "pullRequest": "1001",
+          "resolved": "false",
+          "sinceLeakPeriod": "true",
+          "types": "VULNERABILITY",
+        },
+      }
+    }
+  >
+    1
+  </Link>
+  <VulnerabilityIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.new_vulnerabilities.name
+</Fragment>
+`;
+
+exports[`should render correctly if no values are present 1`] = `
+<Fragment>
+  <span
+    aria-label="no_data"
+    className="overview-measures-empty-value"
+  />
+  <BugIcon
+    className="big-spacer-left little-spacer-right"
+  />
+  metric.bugs.name
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueRating-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/IssueRating-test.tsx.snap
new file mode 100644 (file)
index 0000000..45be5c5
--- /dev/null
@@ -0,0 +1,211 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for bugs 1`] = `
+<Fragment>
+  <span
+    className="flex-1 big-spacer-right text-right"
+  >
+    metric_domain.Reliability
+  </span>
+  <Tooltip
+    overlay="metric.reliability_rating.tooltip.A"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="link-no-underline"
+        component="my-project"
+        metric="reliability_rating"
+      >
+        <Rating
+          value="1.0"
+        />
+      </DrilldownLink>
+    </span>
+  </Tooltip>
+</Fragment>
+`;
+
+exports[`should render correctly for bugs 2`] = `
+<Fragment>
+  <span
+    className="flex-1 big-spacer-right text-right"
+  >
+    metric_domain.Reliability
+  </span>
+  <Tooltip
+    overlay="metric.reliability_rating.tooltip.A"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="link-no-underline"
+        component="my-project"
+        metric="new_reliability_rating"
+      >
+        <Rating
+          value="1.0"
+        />
+      </DrilldownLink>
+    </span>
+  </Tooltip>
+</Fragment>
+`;
+
+exports[`should render correctly for code smells 1`] = `
+<Fragment>
+  <span
+    className="flex-1 big-spacer-right text-right"
+  >
+    metric_domain.Maintainability
+  </span>
+  <Tooltip
+    overlay="metric.sqale_rating.tooltip.A.0.0%"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="link-no-underline"
+        component="my-project"
+        metric="sqale_rating"
+      >
+        <Rating
+          value="1.0"
+        />
+      </DrilldownLink>
+    </span>
+  </Tooltip>
+</Fragment>
+`;
+
+exports[`should render correctly for code smells 2`] = `
+<Fragment>
+  <span
+    className="flex-1 big-spacer-right text-right"
+  >
+    metric_domain.Maintainability
+  </span>
+  <Tooltip
+    overlay="metric.sqale_rating.tooltip.A.0.0%"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="link-no-underline"
+        component="my-project"
+        metric="new_maintainability_rating"
+      >
+        <Rating
+          value="1.0"
+        />
+      </DrilldownLink>
+    </span>
+  </Tooltip>
+</Fragment>
+`;
+
+exports[`should render correctly for vulnerabilities 1`] = `
+<Fragment>
+  <span
+    className="flex-1 big-spacer-right text-right"
+  >
+    metric_domain.Security
+  </span>
+  <Tooltip
+    overlay="metric.security_rating.tooltip.A"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="link-no-underline"
+        component="my-project"
+        metric="security_rating"
+      >
+        <Rating
+          value="1.0"
+        />
+      </DrilldownLink>
+    </span>
+  </Tooltip>
+</Fragment>
+`;
+
+exports[`should render correctly for vulnerabilities 2`] = `
+<Fragment>
+  <span
+    className="flex-1 big-spacer-right text-right"
+  >
+    metric_domain.Security
+  </span>
+  <Tooltip
+    overlay="metric.security_rating.tooltip.A"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="link-no-underline"
+        component="my-project"
+        metric="new_security_rating"
+      >
+        <Rating
+          value="1.0"
+        />
+      </DrilldownLink>
+    </span>
+  </Tooltip>
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/MeasurementLabel-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/MeasurementLabel-test.tsx.snap
new file mode 100644 (file)
index 0000000..732fe6a
--- /dev/null
@@ -0,0 +1,412 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for coverage 1`] = `
+<div
+  className="display-flex-center"
+>
+  <span
+    className="big-spacer-right"
+  >
+    <CoverageRating
+      size="big"
+      value={1}
+    />
+  </span>
+  <div
+    className="display-flex-column"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="overview-measures-value text-light"
+        component="my-project"
+        metric="coverage"
+      >
+        1.0%
+      </DrilldownLink>
+    </span>
+    <span
+      className="spacer-top"
+    >
+      metric.coverage.name
+    </span>
+  </div>
+</div>
+`;
+
+exports[`should render correctly for coverage 2`] = `
+<div
+  className="display-flex-center"
+>
+  <span
+    className="big-spacer-right"
+  >
+    <CoverageRating
+      size="big"
+      value={1}
+    />
+  </span>
+  <div
+    className="display-flex-column"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="overview-measures-value text-light"
+        component="my-project"
+        metric="coverage"
+      >
+        1.0%
+      </DrilldownLink>
+    </span>
+    <span
+      className="spacer-top"
+    >
+      <FormattedMessage
+        defaultMessage="overview.coverage_on_X_lines"
+        id="overview.coverage_on_X_lines"
+        values={
+          Object {
+            "count": <DrilldownLink
+              branchLike={
+                Object {
+                  "analysisDate": "2018-01-01",
+                  "base": "master",
+                  "branch": "feature/foo/bar",
+                  "key": "1001",
+                  "target": "master",
+                  "title": "Foo Bar feature",
+                }
+              }
+              className="big"
+              component="my-project"
+              metric="lines_to_cover"
+            >
+              1
+            </DrilldownLink>,
+          }
+        }
+      />
+    </span>
+  </div>
+</div>
+`;
+
+exports[`should render correctly for coverage 3`] = `
+<div
+  className="display-flex-center"
+>
+  <span
+    className="big-spacer-right"
+  >
+    <CoverageRating
+      size="big"
+      value={1}
+    />
+  </span>
+  <div
+    className="display-flex-column"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="overview-measures-value text-light"
+        component="my-project"
+        metric="new_coverage"
+      >
+        1.0%
+      </DrilldownLink>
+    </span>
+    <span
+      className="spacer-top"
+    >
+      <FormattedMessage
+        defaultMessage="overview.coverage_on_X_new_lines"
+        id="overview.coverage_on_X_new_lines"
+        values={
+          Object {
+            "count": <DrilldownLink
+              branchLike={
+                Object {
+                  "analysisDate": "2018-01-01",
+                  "base": "master",
+                  "branch": "feature/foo/bar",
+                  "key": "1001",
+                  "target": "master",
+                  "title": "Foo Bar feature",
+                }
+              }
+              className="big"
+              component="my-project"
+              metric="new_lines_to_cover"
+            >
+              1
+            </DrilldownLink>,
+          }
+        }
+      />
+    </span>
+  </div>
+</div>
+`;
+
+exports[`should render correctly for duplications 1`] = `
+<div
+  className="display-flex-center"
+>
+  <span
+    className="big-spacer-right"
+  >
+    <DuplicationsRating
+      size="big"
+      value={1}
+    />
+  </span>
+  <div
+    className="display-flex-column"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="overview-measures-value text-light"
+        component="my-project"
+        metric="duplicated_lines_density"
+      >
+        1.0%
+      </DrilldownLink>
+    </span>
+    <span
+      className="spacer-top"
+    >
+      metric.duplicated_lines_density.short_name
+    </span>
+  </div>
+</div>
+`;
+
+exports[`should render correctly for duplications 2`] = `
+<div
+  className="display-flex-center"
+>
+  <span
+    className="big-spacer-right"
+  >
+    <DuplicationsRating
+      size="big"
+      value={1}
+    />
+  </span>
+  <div
+    className="display-flex-column"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="overview-measures-value text-light"
+        component="my-project"
+        metric="duplicated_lines_density"
+      >
+        1.0%
+      </DrilldownLink>
+    </span>
+    <span
+      className="spacer-top"
+    >
+      <FormattedMessage
+        defaultMessage="overview.duplications_on_X_lines"
+        id="overview.duplications_on_X_lines"
+        values={
+          Object {
+            "count": <DrilldownLink
+              branchLike={
+                Object {
+                  "analysisDate": "2018-01-01",
+                  "base": "master",
+                  "branch": "feature/foo/bar",
+                  "key": "1001",
+                  "target": "master",
+                  "title": "Foo Bar feature",
+                }
+              }
+              className="big"
+              component="my-project"
+              metric="ncloc"
+            >
+              1
+            </DrilldownLink>,
+          }
+        }
+      />
+    </span>
+  </div>
+</div>
+`;
+
+exports[`should render correctly for duplications 3`] = `
+<div
+  className="display-flex-center"
+>
+  <span
+    className="big-spacer-right"
+  >
+    <DuplicationsRating
+      size="big"
+      value={1}
+    />
+  </span>
+  <div
+    className="display-flex-column"
+  >
+    <span>
+      <DrilldownLink
+        branchLike={
+          Object {
+            "analysisDate": "2018-01-01",
+            "base": "master",
+            "branch": "feature/foo/bar",
+            "key": "1001",
+            "target": "master",
+            "title": "Foo Bar feature",
+          }
+        }
+        className="overview-measures-value text-light"
+        component="my-project"
+        metric="new_duplicated_lines_density"
+      >
+        1.0%
+      </DrilldownLink>
+    </span>
+    <span
+      className="spacer-top"
+    >
+      <FormattedMessage
+        defaultMessage="overview.duplications_on_X_new_lines"
+        id="overview.duplications_on_X_new_lines"
+        values={
+          Object {
+            "count": <DrilldownLink
+              branchLike={
+                Object {
+                  "analysisDate": "2018-01-01",
+                  "base": "master",
+                  "branch": "feature/foo/bar",
+                  "key": "1001",
+                  "target": "master",
+                  "title": "Foo Bar feature",
+                }
+              }
+              className="big"
+              component="my-project"
+              metric="new_lines"
+            >
+              1
+            </DrilldownLink>,
+          }
+        }
+      />
+    </span>
+  </div>
+</div>
+`;
+
+exports[`should render correctly when centered 1`] = `
+<div
+  className="display-flex-column flex-1"
+>
+  <div
+    className="display-flex-center display-flex-justify-center"
+  >
+    <span
+      className="big-spacer-right"
+    >
+      <CoverageRating
+        size="big"
+        value={1}
+      />
+    </span>
+    <DrilldownLink
+      branchLike={
+        Object {
+          "analysisDate": "2018-01-01",
+          "base": "master",
+          "branch": "feature/foo/bar",
+          "key": "1001",
+          "target": "master",
+          "title": "Foo Bar feature",
+        }
+      }
+      className="overview-measures-value text-light"
+      component="my-project"
+      metric="coverage"
+    >
+      1.0%
+    </DrilldownLink>
+  </div>
+  <div
+    className="spacer-top text-center"
+  >
+    metric.coverage.name
+  </div>
+</div>
+`;
+
+exports[`should render correctly with no value 1`] = `
+<div
+  className="display-flex-center"
+>
+  <span
+    aria-label="no_data"
+    className="overview-measures-empty-value"
+  />
+  <span
+    className="big-spacer-left"
+  >
+    metric.coverage.name
+  </span>
+</div>
+`;
index fdf15e9f47b7f1f53bb98c2b1fadc13ce1dd7ac7..ce19d29dc4a4074f5d476719dfe5c1f60767fa79 100644 (file)
@@ -22,16 +22,16 @@ import * as React from 'react';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 import { formatMeasure } from 'sonar-ui-common/helpers/measures';
 import { findMeasure } from '../../../helpers/measures';
-import { MEASUREMENTS_MAP, MeasurementType } from '../utils';
+import { getMeasurementAfterMergeMetricKey, MeasurementType } from '../utils';
 
-interface Props {
+export interface AfterMergeEstimateProps {
   className?: string;
-  measures: T.Measure[];
+  measures: T.MeasureEnhanced[];
   type: MeasurementType;
 }
 
-export default function AfterMergeEstimate({ className, measures, type }: Props) {
-  const { afterMergeMetric } = MEASUREMENTS_MAP[type];
+export function AfterMergeEstimate({ className, measures, type }: AfterMergeEstimateProps) {
+  const afterMergeMetric = getMeasurementAfterMergeMetricKey(type);
 
   const measure = findMeasure(measures, afterMergeMetric);
 
@@ -42,9 +42,11 @@ export default function AfterMergeEstimate({ className, measures, type }: Props)
   return (
     <div className={classNames(className, 'display-flex-center')}>
       <span className="huge">{formatMeasure(measure.value, 'PERCENT')}</span>
-      <span className="label flex-1">
+      <span className="label flex-1 spacer-left text-right">
         {translate('component_measures.facet_category.overall_category.estimated')}
       </span>
     </div>
   );
 }
+
+export default React.memo(AfterMergeEstimate);
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueLabel.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueLabel.tsx
deleted file mode 100644 (file)
index 6753b0e..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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 * as classNames from 'classnames';
-import * as React from 'react';
-import { Link } from 'react-router';
-import { formatMeasure } from 'sonar-ui-common/helpers/measures';
-import DocTooltip from '../../../components/docs/DocTooltip';
-import { getLeakValue } from '../../../components/measure/utils';
-import { getBranchLikeQuery } from '../../../helpers/branch-like';
-import { findMeasure } from '../../../helpers/measures';
-import { getComponentIssuesUrl } from '../../../helpers/urls';
-import { BranchLike } from '../../../types/branch-like';
-import { getMetricName, IssueType, ISSUETYPE_MAP } from '../utils';
-
-export interface Props {
-  branchLike?: BranchLike;
-  className?: string;
-  component: T.Component;
-  docTooltip?: Promise<{ default: string }>;
-  measures: T.Measure[];
-  type: IssueType;
-}
-
-export default function IssueLabel({
-  branchLike,
-  className,
-  component,
-  docTooltip,
-  measures,
-  type
-}: Props) {
-  const { metric, iconClass } = ISSUETYPE_MAP[type];
-  const measure = findMeasure(measures, metric);
-
-  let value;
-  if (measure) {
-    value = getLeakValue(measure);
-  }
-
-  const params = {
-    ...getBranchLikeQuery(branchLike),
-    resolved: 'false',
-    types: type
-  };
-
-  return (
-    <>
-      {value === undefined ? (
-        <span className={classNames(className, 'measure-empty')}>—</span>
-      ) : (
-        <Link className={className} to={getComponentIssuesUrl(component.key, params)}>
-          {formatMeasure(value, 'SHORT_INT')}
-        </Link>
-      )}
-      {React.createElement(iconClass, { className: 'big-spacer-left little-spacer-right' })}
-      {getMetricName(metric)}
-      {docTooltip && <DocTooltip className="little-spacer-left" doc={docTooltip} />}
-    </>
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueRating.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueRating.tsx
deleted file mode 100644 (file)
index 221e05f..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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 * as React from 'react';
-import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
-import Rating from 'sonar-ui-common/components/ui/Rating';
-import { getLeakValue, getRatingTooltip } from '../../../components/measure/utils';
-import DrilldownLink from '../../../components/shared/DrilldownLink';
-import { findMeasure } from '../../../helpers/measures';
-import { BranchLike } from '../../../types/branch-like';
-import { getRatingName, IssueType, ISSUETYPE_MAP } from '../utils';
-
-interface Props {
-  branchLike?: BranchLike;
-  component: T.Component;
-  measures: T.Measure[];
-  type: IssueType;
-}
-
-export default function IssueRating({ branchLike, component, measures, type }: Props) {
-  const { rating } = ISSUETYPE_MAP[type];
-  const measure = findMeasure(measures, rating);
-
-  if (!rating || !measure) {
-    return null;
-  }
-
-  const value = getLeakValue(measure);
-  const tooltip = value && getRatingTooltip(rating, Number(value));
-
-  return (
-    <>
-      <span className="big-spacer-right flex-1">{getRatingName(type)}</span>
-      <Tooltip overlay={tooltip}>
-        <span>
-          <DrilldownLink
-            branchLike={branchLike}
-            className="link-no-underline"
-            component={component.key}
-            metric={rating}>
-            <Rating value={value} />
-          </DrilldownLink>
-        </span>
-      </Tooltip>
-    </>
-  );
-}
index cb5e106c61f8f56809bead97f8228450bd1d4c82..eb7c69748bca0b4fabcf4f379be1b39152ca7864 100644 (file)
@@ -25,7 +25,6 @@ import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip';
 import HelpIcon from 'sonar-ui-common/components/icons/HelpIcon';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 import { colors } from '../../../app/theme';
-import { isSonarCloud } from '../../../helpers/system';
 import { getQualityGatesUrl, getQualityGateUrl } from '../../../helpers/urls';
 
 interface Props {
@@ -33,25 +32,17 @@ interface Props {
   level?: T.Status;
 }
 
-export default function LargeQualityGateBadge({ component, level }: Props) {
+export function LargeQualityGateBadge({ component, level }: Props) {
   const success = level === 'OK';
 
-  let path;
-  if (isSonarCloud()) {
-    path =
-      component.qualityGate === undefined
-        ? getQualityGatesUrl(component.organization)
-        : getQualityGateUrl(component.qualityGate.key, component.organization);
-  } else {
-    path =
-      component.qualityGate === undefined
-        ? getQualityGatesUrl()
-        : getQualityGateUrl(component.qualityGate.key);
-  }
+  const path =
+    component.qualityGate === undefined
+      ? getQualityGatesUrl()
+      : getQualityGateUrl(component.qualityGate.key);
 
   return (
     <div
-      className={classNames('quality-gate-badge-large small', {
+      className={classNames('overview-quality-gate-badge-large small', {
         failed: !success,
         success
       })}>
@@ -73,8 +64,10 @@ export default function LargeQualityGateBadge({ component, level }: Props) {
         </HelpTooltip>
       </div>
       {level !== undefined && (
-        <h4 className="huge-spacer-top huge">{translate('metric.level', level)}</h4>
+        <h3 className="huge-spacer-top huge">{translate('metric.level', level)}</h3>
       )}
     </div>
   );
 }
+
+export default React.memo(LargeQualityGateBadge);
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasurementLabel.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasurementLabel.tsx
deleted file mode 100644 (file)
index b940161..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 * as classNames from 'classnames';
-import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import { formatMeasure } from 'sonar-ui-common/helpers/measures';
-import { getLeakValue } from '../../../components/measure/utils';
-import DrilldownLink from '../../../components/shared/DrilldownLink';
-import { findMeasure } from '../../../helpers/measures';
-import { BranchLike } from '../../../types/branch-like';
-import { MEASUREMENTS_MAP, MeasurementType } from '../utils';
-
-interface Props {
-  branchLike?: BranchLike;
-  className?: string;
-  component: T.Component;
-  measures: T.Measure[];
-  type: MeasurementType;
-}
-
-export default class MeasurementLabel extends React.Component<Props> {
-  getLabelText = () => {
-    const { branchLike, component, measures, type } = this.props;
-    const { expandedLabelKey, linesMetric, labelKey } = MEASUREMENTS_MAP[type];
-
-    const measure = findMeasure(measures, linesMetric);
-    if (!measure) {
-      return translate(labelKey);
-    } else {
-      return (
-        <FormattedMessage
-          defaultMessage={translate(expandedLabelKey)}
-          id={expandedLabelKey}
-          values={{
-            count: (
-              <DrilldownLink branchLike={branchLike} component={component.key} metric={linesMetric}>
-                {formatMeasure(getLeakValue(measure), 'SHORT_INT')}
-              </DrilldownLink>
-            )
-          }}
-        />
-      );
-    }
-  };
-
-  render() {
-    const { branchLike, className, component, measures, type } = this.props;
-    const { iconClass, metric } = MEASUREMENTS_MAP[type];
-
-    const measure = findMeasure(measures, metric);
-
-    let value;
-    if (measure) {
-      value = getLeakValue(measure);
-    }
-
-    return (
-      <>
-        {value === undefined ? (
-          <span className={classNames(className, 'measure-empty')}>—</span>
-        ) : (
-          <>
-            <span className="big-spacer-right">
-              {React.createElement(iconClass, { size: 'big', value: Number(value) })}
-            </span>
-            <DrilldownLink
-              branchLike={branchLike}
-              className={className}
-              component={component.key}
-              metric={metric}>
-              {formatMeasure(value, 'PERCENT')}
-            </DrilldownLink>
-          </>
-        )}
-        <span className="big-spacer-left">{this.getLabelText()}</span>
-      </>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx
new file mode 100644 (file)
index 0000000..38c6b0b
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * 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 * as classNames from 'classnames';
+import * as React from 'react';
+import { connect } from 'react-redux';
+import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { isDefined } from 'sonar-ui-common/helpers/types';
+import { getMeasuresAndMeta } from '../../../api/measures';
+import DocTooltip from '../../../components/docs/DocTooltip';
+import { getBranchLikeQuery } from '../../../helpers/branch-like';
+import { enhanceConditionWithMeasure, enhanceMeasuresWithMetrics } from '../../../helpers/measures';
+import { fetchBranchStatus } from '../../../store/rootActions';
+import { getBranchStatusByBranchLike, Store } from '../../../store/rootReducer';
+import { BranchLike, PullRequest } from '../../../types/branch-like';
+import { QualityGateStatusCondition } from '../../../types/quality-gates';
+import IssueLabel from '../components/IssueLabel';
+import IssueRating from '../components/IssueRating';
+import MeasurementLabel from '../components/MeasurementLabel';
+import QualityGateConditions from '../components/QualityGateConditions';
+import '../styles.css';
+import { IssueType, MeasurementType, PR_METRICS } from '../utils';
+import AfterMergeEstimate from './AfterMergeEstimate';
+import LargeQualityGateBadge from './LargeQualityGateBadge';
+
+interface Props {
+  branchLike: PullRequest;
+  component: T.Component;
+  conditions?: QualityGateStatusCondition[];
+  fetchBranchStatus: (branchLike: BranchLike, projectKey: string) => Promise<void>;
+  ignoredConditions?: boolean;
+  status?: T.Status;
+}
+
+interface State {
+  loading: boolean;
+  measures: T.MeasureEnhanced[];
+}
+
+export class PullRequestOverview extends React.PureComponent<Props, State> {
+  mounted = false;
+
+  state: State = {
+    loading: false,
+    measures: []
+  };
+
+  componentDidMount() {
+    this.mounted = true;
+    this.fetchBranchData();
+  }
+
+  componentWillUnmount() {
+    this.mounted = false;
+  }
+
+  fetchBranchData = () => {
+    const {
+      branchLike,
+      component: { key }
+    } = this.props;
+
+    this.setState({ loading: true });
+
+    Promise.all([
+      getMeasuresAndMeta(key, PR_METRICS, {
+        additionalFields: 'metrics',
+        ...getBranchLikeQuery(branchLike)
+      }),
+      this.props.fetchBranchStatus(branchLike, key)
+    ]).then(
+      ([{ component, metrics }]) => {
+        if (this.mounted && component.measures) {
+          this.setState({
+            loading: false,
+            measures: enhanceMeasuresWithMetrics(component.measures || [], metrics || [])
+          });
+        }
+      },
+      () => {
+        if (this.mounted) {
+          this.setState({ loading: false });
+        }
+      }
+    );
+  };
+
+  render() {
+    const { branchLike, component, conditions, ignoredConditions, status } = this.props;
+    const { loading, measures } = this.state;
+
+    if (loading) {
+      return (
+        <div className="page page-limited">
+          <i className="spinner" />
+        </div>
+      );
+    }
+
+    if (conditions === undefined) {
+      return null;
+    }
+
+    const failedConditions = conditions
+      .filter(condition => condition.level === 'ERROR')
+      .map(c => enhanceConditionWithMeasure(c, measures))
+      .filter(isDefined);
+
+    return (
+      <div className="page page-limited">
+        <div
+          className={classNames('pr-overview', {
+            'has-conditions': failedConditions.length > 0
+          })}>
+          {ignoredConditions && (
+            <Alert className="big-spacer-bottom" display="inline" variant="info">
+              <span className="text-middle">
+                {translate('overview.quality_gate.ignored_conditions')}
+              </span>
+              <HelpTooltip
+                className="spacer-left"
+                overlay={translate('overview.quality_gate.ignored_conditions.tooltip')}
+              />
+            </Alert>
+          )}
+          <div className="display-flex-row">
+            <div className="big-spacer-right">
+              <h2 className="overview-panel-title spacer-bottom small">
+                {translate('overview.quality_gate')}
+                <DocTooltip
+                  className="spacer-left"
+                  doc={import(
+                    /* webpackMode: "eager" */ 'Docs/tooltips/quality-gates/project-homepage-quality-gate.md'
+                  )}
+                />
+              </h2>
+              <LargeQualityGateBadge component={component} level={status} />
+            </div>
+
+            {failedConditions.length > 0 && (
+              <div className="pr-overview-failed-conditions big-spacer-right">
+                <h2 className="overview-panel-title spacer-bottom small">
+                  {translate('overview.failed_conditions')}
+                </h2>
+                <QualityGateConditions
+                  branchLike={branchLike}
+                  collapsible={true}
+                  component={component}
+                  failedConditions={failedConditions}
+                />
+              </div>
+            )}
+
+            <div className="flex-1">
+              <h2 className="overview-panel-title spacer-bottom small">
+                {translate('overview.measures')}
+              </h2>
+
+              <div className="overview-panel-content">
+                {[IssueType.Bug, IssueType.Vulnerability, IssueType.CodeSmell].map(
+                  (type: IssueType) => (
+                    <div className="overview-measures-row display-flex-row" key={type}>
+                      <div className="overview-panel-big-padded flex-1 small display-flex-center">
+                        <IssueLabel
+                          branchLike={branchLike}
+                          component={component}
+                          measures={measures}
+                          type={type}
+                          useDiffMetric={true}
+                        />
+                      </div>
+                      {type === 'VULNERABILITY' && (
+                        <div className="flex-1 small display-flex-center">
+                          <IssueLabel
+                            branchLike={branchLike}
+                            component={component}
+                            docTooltip={import(
+                              /* webpackMode: "eager" */ 'Docs/tooltips/metrics/security-hotspots.md'
+                            )}
+                            measures={measures}
+                            type={IssueType.SecurityHotspot}
+                            useDiffMetric={true}
+                          />
+                        </div>
+                      )}
+                      <div className="overview-panel-big-padded overview-measures-aside display-flex-center">
+                        <IssueRating
+                          branchLike={branchLike}
+                          component={component}
+                          measures={measures}
+                          type={type}
+                          useDiffMetric={true}
+                        />
+                      </div>
+                    </div>
+                  )
+                )}
+
+                {[MeasurementType.Coverage, MeasurementType.Duplication].map(
+                  (type: MeasurementType) => (
+                    <div className="overview-measures-row display-flex-row" key={type}>
+                      <div className="overview-panel-big-padded flex-1 small display-flex-center">
+                        <MeasurementLabel
+                          branchLike={branchLike}
+                          component={component}
+                          measures={measures}
+                          type={type}
+                          useDiffMetric={true}
+                        />
+                      </div>
+
+                      <AfterMergeEstimate
+                        className="overview-panel-big-padded overview-measures-aside text-right overview-measures-emphasis"
+                        measures={measures}
+                        type={type}
+                      />
+                    </div>
+                  )
+                )}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    );
+  }
+}
+
+const mapStateToProps = (state: Store, { branchLike, component }: Props) => {
+  const { conditions, ignoredConditions, status } = getBranchStatusByBranchLike(
+    state,
+    component.key,
+    branchLike
+  );
+  return { conditions, ignoredConditions, status };
+};
+
+const mapDispatchToProps = { fetchBranchStatus: fetchBranchStatus as any };
+
+export default connect(mapStateToProps, mapDispatchToProps)(PullRequestOverview);
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/ReviewApp.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/ReviewApp.tsx
deleted file mode 100644 (file)
index 21e5fc5..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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 * as classNames from 'classnames';
-import * as React from 'react';
-import { connect } from 'react-redux';
-import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip';
-import { Alert } from 'sonar-ui-common/components/ui/Alert';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import { getMeasures } from '../../../api/measures';
-import DocTooltip from '../../../components/docs/DocTooltip';
-import { getBranchLikeQuery } from '../../../helpers/branch-like';
-import { fetchBranchStatus } from '../../../store/rootActions';
-import { getBranchStatusByBranchLike, Store } from '../../../store/rootReducer';
-import { BranchLike } from '../../../types/branch-like';
-import QualityGateConditions from '../qualityGate/QualityGateConditions';
-import '../styles.css';
-import { IssueType, MeasurementType, PR_METRICS } from '../utils';
-import AfterMergeEstimate from './AfterMergeEstimate';
-import IssueLabel from './IssueLabel';
-import IssueRating from './IssueRating';
-import LargeQualityGateBadge from './LargeQualityGateBadge';
-import MeasurementLabel from './MeasurementLabel';
-
-interface OwnProps {
-  branchLike: BranchLike;
-  component: T.Component;
-}
-
-interface StateProps {
-  conditions?: T.QualityGateStatusCondition[];
-  ignoredConditions?: boolean;
-  status?: T.Status;
-}
-
-interface DispatchProps {
-  fetchBranchStatus: (branchLike: BranchLike, projectKey: string) => Promise<void>;
-}
-
-type Props = OwnProps & StateProps & DispatchProps;
-
-interface State {
-  loading: boolean;
-  measures: T.Measure[];
-}
-
-export class ReviewApp extends React.PureComponent<Props, State> {
-  mounted = false;
-
-  state: State = {
-    loading: false,
-    measures: []
-  };
-
-  componentDidMount() {
-    this.mounted = true;
-    this.fetchBranchData();
-  }
-
-  componentWillUnmount() {
-    this.mounted = false;
-  }
-
-  fetchBranchData = () => {
-    const { branchLike, component } = this.props;
-
-    this.setState({ loading: true });
-
-    Promise.all([
-      getMeasures({
-        component: component.key,
-        metricKeys: PR_METRICS.join(),
-        ...getBranchLikeQuery(branchLike)
-      }),
-      this.props.fetchBranchStatus(branchLike, component.key)
-    ]).then(
-      ([measures]) => {
-        if (this.mounted && measures) {
-          this.setState({
-            loading: false,
-            measures
-          });
-        }
-      },
-      () => {
-        if (this.mounted) {
-          this.setState({ loading: false });
-        }
-      }
-    );
-  };
-
-  render() {
-    const { branchLike, component, conditions, ignoredConditions, status } = this.props;
-    const { loading, measures } = this.state;
-
-    if (loading || !conditions) {
-      return (
-        <div className="page page-limited">
-          <i className="spinner" />
-        </div>
-      );
-    }
-
-    const erroredConditions = conditions.filter(condition => condition.level === 'ERROR');
-
-    return (
-      <div className="page page-limited">
-        <div
-          className={classNames('pr-overview', {
-            'has-conditions': erroredConditions.length > 0
-          })}>
-          {ignoredConditions && (
-            <Alert className="big-spacer-bottom" display="inline" variant="info">
-              <span className="text-middle">
-                {translate('overview.quality_gate.ignored_conditions')}
-              </span>
-              <HelpTooltip
-                className="spacer-left"
-                overlay={translate('overview.quality_gate.ignored_conditions.tooltip')}
-              />
-            </Alert>
-          )}
-          <div className="display-flex-row">
-            <div className="pr-overview-quality-gate big-spacer-right">
-              <h3 className="spacer-bottom small">
-                {translate('overview.quality_gate')}
-                <DocTooltip
-                  className="spacer-left"
-                  doc={import(
-                    /* webpackMode: "eager" */ 'Docs/tooltips/quality-gates/project-homepage-quality-gate.md'
-                  )}
-                />
-              </h3>
-              <LargeQualityGateBadge component={component} level={status} />
-            </div>
-
-            {erroredConditions.length > 0 && (
-              <div className="pr-overview-failed-conditions big-spacer-right">
-                <h3 className="spacer-bottom small">{translate('overview.failed_conditions')}</h3>
-                <QualityGateConditions
-                  branchLike={branchLike}
-                  collapsible={true}
-                  component={component}
-                  conditions={erroredConditions}
-                />
-              </div>
-            )}
-
-            <div className="pr-overview-measurements flex-1">
-              <h3 className="spacer-bottom small">{translate('overview.metrics')}</h3>
-
-              {['BUG', 'VULNERABILITY', 'CODE_SMELL'].map((type: IssueType) => (
-                <div className="pr-overview-measurements-row display-flex-row" key={type}>
-                  <div className="pr-overview-measurements-value flex-1 small display-flex-center">
-                    <IssueLabel
-                      branchLike={branchLike}
-                      className="overview-domain-measure-value"
-                      component={component}
-                      measures={measures}
-                      type={type}
-                    />
-                  </div>
-                  {type === 'VULNERABILITY' && (
-                    <div className="pr-overview-measurements-value flex-1 small display-flex-center">
-                      <IssueLabel
-                        branchLike={branchLike}
-                        className="overview-domain-measure-value"
-                        component={component}
-                        docTooltip={import(
-                          /* webpackMode: "eager" */ 'Docs/tooltips/metrics/security-hotspots.md'
-                        )}
-                        measures={measures}
-                        type="SECURITY_HOTSPOT"
-                      />
-                    </div>
-                  )}
-                  <div className="pr-overview-measurements-rating display-flex-center">
-                    <IssueRating
-                      branchLike={branchLike}
-                      component={component}
-                      measures={measures}
-                      type={type}
-                    />
-                  </div>
-                </div>
-              ))}
-
-              {['COVERAGE', 'DUPLICATION'].map((type: MeasurementType) => (
-                <div className="pr-overview-measurements-row display-flex-row" key={type}>
-                  <div className="pr-overview-measurements-value flex-1 small display-flex-center">
-                    <MeasurementLabel
-                      branchLike={branchLike}
-                      className="overview-domain-measure-value"
-                      component={component}
-                      measures={measures}
-                      type={type}
-                    />
-                  </div>
-
-                  <AfterMergeEstimate
-                    className="pr-overview-measurements-estimate"
-                    measures={measures}
-                    type={type}
-                  />
-                </div>
-              ))}
-            </div>
-          </div>
-        </div>
-      </div>
-    );
-  }
-}
-
-const mapStateToProps = (state: Store, { branchLike, component }: OwnProps) => {
-  const { conditions, ignoredConditions, status } = getBranchStatusByBranchLike(
-    state,
-    component.key,
-    branchLike
-  );
-  return { conditions, ignoredConditions, status };
-};
-
-const mapDispatchToProps = { fetchBranchStatus: fetchBranchStatus as any };
-
-export default connect(mapStateToProps, mapDispatchToProps)(ReviewApp);
index 656a26f2075daa8adeb2eb76830fdc6e92d6dd7c..6e99380f4668307adbba265af06de52907d07867 100644 (file)
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
-import { mockMeasure } from '../../../../helpers/testMocks';
-import AfterMergeEstimate from '../AfterMergeEstimate';
+import { mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
+import { MetricKey } from '../../../../types/metrics';
+import { MeasurementType } from '../../utils';
+import { AfterMergeEstimate, AfterMergeEstimateProps } from '../AfterMergeEstimate';
 
 it('should render correctly for coverage', () => {
-  expect(shallowRender({ measures: [mockMeasure({ metric: 'coverage' })] })).toMatchSnapshot();
+  expect(shallowRender()).toMatchSnapshot();
 });
 
 it('should render correctly for duplications', () => {
   expect(
     shallowRender({
-      measures: [mockMeasure({ metric: 'duplicated_lines_density' })],
-      type: 'DUPLICATION'
+      measures: [
+        mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.duplicated_lines_density }) })
+      ],
+      type: MeasurementType.Duplication
     })
   ).toMatchSnapshot();
 });
 
 it('should render correctly with no value', () => {
-  expect(shallowRender()).toMatchSnapshot();
+  expect(shallowRender({ measures: [] })).toMatchSnapshot();
 });
 
-function shallowRender(props = {}) {
-  return shallow(<AfterMergeEstimate measures={[mockMeasure()]} type="COVERAGE" {...props} />);
+function shallowRender(props: Partial<AfterMergeEstimateProps> = {}) {
+  return shallow(
+    <AfterMergeEstimate
+      measures={[mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) })]}
+      type={MeasurementType.Coverage}
+      {...props}
+    />
+  );
 }
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/IssueLabel-test.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/IssueLabel-test.tsx
deleted file mode 100644 (file)
index 271b63c..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
-import { mockComponent, mockMeasure } from '../../../../helpers/testMocks';
-import IssueLabel, { Props } from '../IssueLabel';
-
-it('should render correctly for bugs', () => {
-  expect(
-    shallowRender({
-      measures: [mockMeasure({ metric: 'new_bugs' })]
-    })
-  ).toMatchSnapshot();
-});
-
-it('should render correctly for code smells', () => {
-  expect(
-    shallowRender({
-      measures: [mockMeasure({ metric: 'new_code_smells' })],
-      type: 'CODE_SMELL'
-    })
-  ).toMatchSnapshot();
-});
-
-it('should render correctly for vulnerabilities', () => {
-  expect(
-    shallowRender({
-      measures: [mockMeasure({ metric: 'new_vulnerabilities' })],
-      type: 'VULNERABILITY'
-    })
-  ).toMatchSnapshot();
-});
-
-it('should render correctly for hotspots', () => {
-  expect(
-    shallowRender({
-      docTooltip: Promise.resolve({ default: 'tooltip text' }),
-      measures: [mockMeasure({ metric: 'new_security_hotspots' })],
-      type: 'SECURITY_HOTSPOT'
-    })
-  ).toMatchSnapshot();
-});
-
-it('should render correctly if no values are present', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-function shallowRender(props: Partial<Props> = {}) {
-  return shallow(
-    <IssueLabel
-      branchLike={mockPullRequest()}
-      component={mockComponent()}
-      measures={[]}
-      type="BUG"
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/IssueRating-test.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/IssueRating-test.tsx
deleted file mode 100644 (file)
index 0142aeb..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
-import { mockComponent, mockMeasure } from '../../../../helpers/testMocks';
-import IssueRating from '../IssueRating';
-
-it('should render correctly for bugs', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should render correctly for code smells', () => {
-  expect(shallowRender({ type: 'CODE_SMELL' })).toMatchSnapshot();
-});
-
-it('should render correctly for vulnerabilities', () => {
-  expect(shallowRender({ type: 'VULNERABILITY' })).toMatchSnapshot();
-});
-
-it('should render correctly if no values are present', () => {
-  expect(shallowRender({ measures: [mockMeasure({ metric: 'NONE' })] })).toMatchSnapshot();
-});
-
-function shallowRender(props = {}) {
-  return shallow(
-    <IssueRating
-      branchLike={mockPullRequest()}
-      component={mockComponent()}
-      measures={[
-        mockMeasure({ metric: 'new_reliability_rating' }),
-        mockMeasure({ metric: 'new_maintainability_rating' }),
-        mockMeasure({ metric: 'new_security_rating' })
-      ]}
-      type="BUG"
-      {...props}
-    />
-  );
-}
index 1a119cf9b23617992b2436683ee3ae21f31a05ca..0cf7f78e0d6e40e76287da2cf575827790961cfc 100644 (file)
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
-import { isSonarCloud } from '../../../../helpers/system';
 import { mockComponent } from '../../../../helpers/testMocks';
-import LargeQualityGateBadge from '../LargeQualityGateBadge';
-
-jest.mock('../../../../helpers/system', () => ({
-  isSonarCloud: jest.fn()
-}));
+import { LargeQualityGateBadge } from '../LargeQualityGateBadge';
 
 it('should render correctly for SQ', () => {
-  (isSonarCloud as jest.Mock).mockReturnValue(false);
-
   expect(shallowRender()).toMatchSnapshot();
   expect(shallowRender({ level: 'OK' })).toMatchSnapshot();
 });
 
-it('should render the link correctly for SC', () => {
-  (isSonarCloud as jest.Mock).mockReturnValue(true);
-  expect(shallowRender()).toMatchSnapshot();
-});
-
 function shallowRender(props = {}) {
   return shallow(<LargeQualityGateBadge component={mockComponent()} level="ERROR" {...props} />);
 }
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/MeasurementLabel-test.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/MeasurementLabel-test.tsx
deleted file mode 100644 (file)
index 7e81f62..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockBranch } from '../../../../helpers/mocks/branch-like';
-import { mockComponent, mockMeasure } from '../../../../helpers/testMocks';
-import MeasurementLabel from '../MeasurementLabel';
-
-it('should render correctly for coverage', () => {
-  expect(shallowRender()).toMatchSnapshot();
-  expect(
-    shallowRender({
-      measures: [
-        mockMeasure({ metric: 'new_coverage' }),
-        mockMeasure({ metric: 'new_lines_to_cover' })
-      ]
-    })
-  ).toMatchSnapshot();
-});
-
-it('should render correctly for duplications', () => {
-  expect(
-    shallowRender({
-      measures: [mockMeasure({ metric: 'new_duplicated_lines_density' })],
-      type: 'DUPLICATION'
-    })
-  ).toMatchSnapshot();
-});
-
-it('should render correctly with no value', () => {
-  expect(shallowRender({ measures: [mockMeasure({ metric: 'NONE' })] })).toMatchSnapshot();
-});
-
-function shallowRender(props: Partial<MeasurementLabel['props']> = {}) {
-  return shallow(
-    <MeasurementLabel
-      branchLike={mockBranch()}
-      component={mockComponent()}
-      measures={[mockMeasure({ metric: 'new_coverage' })]}
-      type="COVERAGE"
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-test.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-test.tsx
new file mode 100644 (file)
index 0000000..1c2c1cb
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
+import { getMeasuresAndMeta } from '../../../../api/measures';
+import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
+import { mockQualityGateStatusCondition } from '../../../../helpers/mocks/quality-gates';
+import { mockComponent } from '../../../../helpers/testMocks';
+import { PullRequestOverview } from '../PullRequestOverview';
+
+jest.mock('../../../../api/measures', () => {
+  const { mockMeasure, mockMetric } = require.requireActual('../../../../helpers/testMocks');
+  return {
+    getMeasuresAndMeta: jest.fn().mockResolvedValue({
+      component: {
+        measures: [
+          mockMeasure({ metric: 'new_bugs' }),
+          mockMeasure({ metric: 'new_vulnerabilities' }),
+          mockMeasure({ metric: 'new_code_smells' }),
+          mockMeasure({ metric: 'new_security_hotspots' })
+        ]
+      },
+      metrics: [
+        mockMetric({ key: 'new_bugs', name: 'new_bugs', id: 'new_bugs' }),
+        mockMetric({
+          key: 'new_vulnerabilities',
+          name: 'new_vulnerabilities',
+          id: 'new_vulnerabilities'
+        }),
+        mockMetric({ key: 'new_code_smells', name: 'new_code_smells', id: 'new_code_smells' }),
+        mockMetric({
+          key: 'new_security_hotspots',
+          name: 'new_security_hotspots',
+          id: 'new_security_hotspots'
+        })
+      ]
+    })
+  };
+});
+
+beforeEach(() => {
+  jest.clearAllMocks();
+});
+
+it('should render correctly for a passed QG', async () => {
+  const fetchBranchStatus = jest.fn();
+
+  const wrapper = shallowRender({ fetchBranchStatus, status: 'OK' });
+
+  wrapper.setProps({ conditions: [] });
+
+  await waitAndUpdate(wrapper);
+  expect(wrapper).toMatchSnapshot();
+
+  expect(wrapper.find('QualityGateConditions').exists()).toBe(false);
+
+  expect(getMeasuresAndMeta).toBeCalled();
+  expect(fetchBranchStatus).toBeCalled();
+});
+
+it('should render correctly if conditions are ignored', async () => {
+  const wrapper = shallowRender({ conditions: [], ignoredConditions: true });
+  await waitAndUpdate(wrapper);
+  expect(wrapper.find('Alert').exists()).toBe(true);
+});
+
+it('should render correctly for a failed QG', async () => {
+  const wrapper = shallowRender({
+    status: 'ERROR',
+    conditions: [
+      mockQualityGateStatusCondition({
+        error: '1.0',
+        level: 'OK',
+        metric: 'new_bugs',
+        period: 1
+      }),
+      mockQualityGateStatusCondition({
+        error: '1.0',
+        metric: 'new_code_smells',
+        period: 1
+      })
+    ]
+  });
+  await waitAndUpdate(wrapper);
+  expect(wrapper).toMatchSnapshot();
+});
+
+it('should correctly handle a WS failure', async () => {
+  (getMeasuresAndMeta as jest.Mock).mockRejectedValueOnce({});
+  const fetchBranchStatus = jest.fn().mockRejectedValue({});
+  const wrapper = shallowRender({ fetchBranchStatus });
+
+  await waitAndUpdate(wrapper);
+  expect(wrapper.type()).toBeNull();
+});
+
+function shallowRender(props: Partial<PullRequestOverview['props']> = {}) {
+  return shallow(
+    <PullRequestOverview
+      branchLike={mockPullRequest()}
+      component={mockComponent()}
+      fetchBranchStatus={jest.fn()}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/ReviewApp-test.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/ReviewApp-test.tsx
deleted file mode 100644 (file)
index 18d0689..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
-import { getMeasures } from '../../../../api/measures';
-import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
-import { mockComponent, mockQualityGateStatusCondition } from '../../../../helpers/testMocks';
-import { ReviewApp } from '../ReviewApp';
-
-jest.mock('../../../../api/measures', () => {
-  const { mockMeasure } = require.requireActual('../../../../helpers/testMocks');
-  return {
-    getMeasures: jest
-      .fn()
-      .mockResolvedValue([
-        mockMeasure({ metric: 'new_bugs ' }),
-        mockMeasure({ metric: 'new_vulnerabilities' }),
-        mockMeasure({ metric: 'new_code_smells' }),
-        mockMeasure({ metric: 'new_security_hotspots' })
-      ])
-  };
-});
-
-beforeEach(() => {
-  jest.clearAllMocks();
-});
-
-it('should render correctly for a passed QG', async () => {
-  const fetchBranchStatus = jest.fn();
-
-  const wrapper = shallowRender({ fetchBranchStatus, status: 'OK' });
-
-  wrapper.setProps({ conditions: [] });
-
-  await waitAndUpdate(wrapper);
-  expect(wrapper).toMatchSnapshot();
-
-  expect(wrapper.find('QualityGateConditions').exists()).toBe(false);
-
-  expect(getMeasures).toBeCalled();
-  expect(fetchBranchStatus).toBeCalled();
-});
-
-it('should render correctly if conditions are ignored', async () => {
-  const wrapper = shallowRender({ conditions: [], ignoredConditions: true });
-  await waitAndUpdate(wrapper);
-  expect(wrapper.find('Alert').exists()).toBe(true);
-});
-
-it('should render correctly for a failed QG', async () => {
-  const wrapper = shallowRender({
-    status: 'ERROR',
-    conditions: [
-      mockQualityGateStatusCondition({
-        error: '1.0',
-        level: 'OK',
-        metric: 'new_bugs',
-        period: 1
-      }),
-      mockQualityGateStatusCondition({
-        error: '1.0',
-        metric: 'new_code_smells',
-        period: 1
-      })
-    ]
-  });
-  await waitAndUpdate(wrapper);
-  expect(wrapper).toMatchSnapshot();
-
-  expect(wrapper.find('QualityGateConditions').exists()).toBe(true);
-});
-
-it('should correctly handle a WS failure', async () => {
-  (getMeasures as jest.Mock).mockRejectedValue({});
-  const fetchBranchStatus = jest.fn().mockRejectedValue({});
-  const wrapper = shallowRender({ fetchBranchStatus });
-
-  await waitAndUpdate(wrapper);
-  expect(wrapper).toMatchSnapshot();
-});
-
-function shallowRender(props: Partial<ReviewApp['props']> = {}) {
-  return shallow(
-    <ReviewApp
-      branchLike={mockPullRequest()}
-      component={mockComponent()}
-      fetchBranchStatus={jest.fn()}
-      {...props}
-    />
-  );
-}
index 274d006d8cd35d3d307d5c83e39883096f30a196..fd304d0e75460ed3cb31b75dcb215583cd307bcd 100644 (file)
@@ -10,7 +10,7 @@ exports[`should render correctly for coverage 1`] = `
     1.0%
   </span>
   <span
-    className="label flex-1"
+    className="label flex-1 spacer-left text-right"
   >
     component_measures.facet_category.overall_category.estimated
   </span>
@@ -27,7 +27,7 @@ exports[`should render correctly for duplications 1`] = `
     1.0%
   </span>
   <span
-    className="label flex-1"
+    className="label flex-1 spacer-left text-right"
   >
     component_measures.facet_category.overall_category.estimated
   </span>
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/IssueLabel-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/IssueLabel-test.tsx.snap
deleted file mode 100644 (file)
index f2ec995..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly for bugs 1`] = `
-<Fragment>
-  <Link
-    onlyActiveOnIndex={false}
-    style={Object {}}
-    to={
-      Object {
-        "pathname": "/project/issues",
-        "query": Object {
-          "id": "my-project",
-          "pullRequest": "1001",
-          "resolved": "false",
-          "types": "BUG",
-        },
-      }
-    }
-  >
-    1
-  </Link>
-  <BugIcon
-    className="big-spacer-left little-spacer-right"
-  />
-  overview.metric.new_bugs
-</Fragment>
-`;
-
-exports[`should render correctly for code smells 1`] = `
-<Fragment>
-  <Link
-    onlyActiveOnIndex={false}
-    style={Object {}}
-    to={
-      Object {
-        "pathname": "/project/issues",
-        "query": Object {
-          "id": "my-project",
-          "pullRequest": "1001",
-          "resolved": "false",
-          "types": "CODE_SMELL",
-        },
-      }
-    }
-  >
-    1
-  </Link>
-  <CodeSmellIcon
-    className="big-spacer-left little-spacer-right"
-  />
-  overview.metric.new_code_smells
-</Fragment>
-`;
-
-exports[`should render correctly for hotspots 1`] = `
-<Fragment>
-  <Link
-    onlyActiveOnIndex={false}
-    style={Object {}}
-    to={
-      Object {
-        "pathname": "/project/issues",
-        "query": Object {
-          "id": "my-project",
-          "pullRequest": "1001",
-          "resolved": "false",
-          "types": "SECURITY_HOTSPOT",
-        },
-      }
-    }
-  >
-    1
-  </Link>
-  <SecurityHotspotIcon
-    className="big-spacer-left little-spacer-right"
-  />
-  overview.metric.new_security_hotspots
-  <DocTooltip
-    className="little-spacer-left"
-    doc={Promise {}}
-  />
-</Fragment>
-`;
-
-exports[`should render correctly for vulnerabilities 1`] = `
-<Fragment>
-  <Link
-    onlyActiveOnIndex={false}
-    style={Object {}}
-    to={
-      Object {
-        "pathname": "/project/issues",
-        "query": Object {
-          "id": "my-project",
-          "pullRequest": "1001",
-          "resolved": "false",
-          "types": "VULNERABILITY",
-        },
-      }
-    }
-  >
-    1
-  </Link>
-  <VulnerabilityIcon
-    className="big-spacer-left little-spacer-right"
-  />
-  overview.metric.new_vulnerabilities
-</Fragment>
-`;
-
-exports[`should render correctly if no values are present 1`] = `
-<Fragment>
-  <span
-    className="measure-empty"
-  >
-    â€”
-  </span>
-  <BugIcon
-    className="big-spacer-left little-spacer-right"
-  />
-  overview.metric.new_bugs
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/IssueRating-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/IssueRating-test.tsx.snap
deleted file mode 100644 (file)
index 7025894..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly for bugs 1`] = `
-<Fragment>
-  <span
-    className="big-spacer-right flex-1"
-  >
-    metric_domain.Reliability
-  </span>
-  <Tooltip
-    overlay="metric.reliability_rating.tooltip.A"
-  >
-    <span>
-      <DrilldownLink
-        branchLike={
-          Object {
-            "analysisDate": "2018-01-01",
-            "base": "master",
-            "branch": "feature/foo/bar",
-            "key": "1001",
-            "target": "master",
-            "title": "Foo Bar feature",
-          }
-        }
-        className="link-no-underline"
-        component="my-project"
-        metric="new_reliability_rating"
-      >
-        <Rating
-          value="1.0"
-        />
-      </DrilldownLink>
-    </span>
-  </Tooltip>
-</Fragment>
-`;
-
-exports[`should render correctly for code smells 1`] = `
-<Fragment>
-  <span
-    className="big-spacer-right flex-1"
-  >
-    metric_domain.Maintainability
-  </span>
-  <Tooltip
-    overlay="metric.sqale_rating.tooltip.A.0.0%"
-  >
-    <span>
-      <DrilldownLink
-        branchLike={
-          Object {
-            "analysisDate": "2018-01-01",
-            "base": "master",
-            "branch": "feature/foo/bar",
-            "key": "1001",
-            "target": "master",
-            "title": "Foo Bar feature",
-          }
-        }
-        className="link-no-underline"
-        component="my-project"
-        metric="new_maintainability_rating"
-      >
-        <Rating
-          value="1.0"
-        />
-      </DrilldownLink>
-    </span>
-  </Tooltip>
-</Fragment>
-`;
-
-exports[`should render correctly for vulnerabilities 1`] = `
-<Fragment>
-  <span
-    className="big-spacer-right flex-1"
-  >
-    metric_domain.Security
-  </span>
-  <Tooltip
-    overlay="metric.security_rating.tooltip.A"
-  >
-    <span>
-      <DrilldownLink
-        branchLike={
-          Object {
-            "analysisDate": "2018-01-01",
-            "base": "master",
-            "branch": "feature/foo/bar",
-            "key": "1001",
-            "target": "master",
-            "title": "Foo Bar feature",
-          }
-        }
-        className="link-no-underline"
-        component="my-project"
-        metric="new_security_rating"
-      >
-        <Rating
-          value="1.0"
-        />
-      </DrilldownLink>
-    </span>
-  </Tooltip>
-</Fragment>
-`;
-
-exports[`should render correctly if no values are present 1`] = `""`;
index 6fdbae1eb7db7c02e3b20fcb70cd8ec39c7d2bc3..517bbf540bedd0d2e9030405c8500cfda599d584 100644 (file)
@@ -2,7 +2,7 @@
 
 exports[`should render correctly for SQ 1`] = `
 <div
-  className="quality-gate-badge-large small failed"
+  className="overview-quality-gate-badge-large small failed"
 >
   <div
     className="display-flex-center"
@@ -40,17 +40,17 @@ exports[`should render correctly for SQ 1`] = `
       />
     </HelpTooltip>
   </div>
-  <h4
+  <h3
     className="huge-spacer-top huge"
   >
     metric.level.ERROR
-  </h4>
+  </h3>
 </div>
 `;
 
 exports[`should render correctly for SQ 2`] = `
 <div
-  className="quality-gate-badge-large small success"
+  className="overview-quality-gate-badge-large small success"
 >
   <div
     className="display-flex-center"
@@ -88,58 +88,10 @@ exports[`should render correctly for SQ 2`] = `
       />
     </HelpTooltip>
   </div>
-  <h4
+  <h3
     className="huge-spacer-top huge"
   >
     metric.level.OK
-  </h4>
-</div>
-`;
-
-exports[`should render the link correctly for SC 1`] = `
-<div
-  className="quality-gate-badge-large small failed"
->
-  <div
-    className="display-flex-center"
-  >
-    <span>
-      overview.on_new_code_long
-    </span>
-    <HelpTooltip
-      className="little-spacer-left"
-      overlay={
-        <FormattedMessage
-          defaultMessage="overview.quality_gate.conditions_on_new_code"
-          id="overview.quality_gate.conditions_on_new_code"
-          values={
-            Object {
-              "link": <Link
-                onlyActiveOnIndex={false}
-                style={Object {}}
-                to={
-                  Object {
-                    "pathname": "/organizations/foo/quality_gates/show/30",
-                  }
-                }
-              >
-                overview.quality_gate
-              </Link>,
-            }
-          }
-        />
-      }
-    >
-      <HelpIcon
-        fill="rgba(255,255,255,0.62)"
-        size={12}
-      />
-    </HelpTooltip>
-  </div>
-  <h4
-    className="huge-spacer-top huge"
-  >
-    metric.level.ERROR
-  </h4>
+  </h3>
 </div>
 `;
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/MeasurementLabel-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/MeasurementLabel-test.tsx.snap
deleted file mode 100644 (file)
index 6c1396c..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly for coverage 1`] = `
-<Fragment>
-  <span
-    className="big-spacer-right"
-  >
-    <CoverageRating
-      size="big"
-      value={1}
-    />
-  </span>
-  <DrilldownLink
-    branchLike={
-      Object {
-        "analysisDate": "2018-01-01",
-        "excludedFromPurge": true,
-        "isMain": false,
-        "name": "branch-6.7",
-      }
-    }
-    component="my-project"
-    metric="new_coverage"
-  >
-    1.0%
-  </DrilldownLink>
-  <span
-    className="big-spacer-left"
-  >
-    overview.metric.coverage
-  </span>
-</Fragment>
-`;
-
-exports[`should render correctly for coverage 2`] = `
-<Fragment>
-  <span
-    className="big-spacer-right"
-  >
-    <CoverageRating
-      size="big"
-      value={1}
-    />
-  </span>
-  <DrilldownLink
-    branchLike={
-      Object {
-        "analysisDate": "2018-01-01",
-        "excludedFromPurge": true,
-        "isMain": false,
-        "name": "branch-6.7",
-      }
-    }
-    component="my-project"
-    metric="new_coverage"
-  >
-    1.0%
-  </DrilldownLink>
-  <span
-    className="big-spacer-left"
-  >
-    <FormattedMessage
-      defaultMessage="overview.coverage_on_X_lines"
-      id="overview.coverage_on_X_lines"
-      values={
-        Object {
-          "count": <DrilldownLink
-            branchLike={
-              Object {
-                "analysisDate": "2018-01-01",
-                "excludedFromPurge": true,
-                "isMain": false,
-                "name": "branch-6.7",
-              }
-            }
-            component="my-project"
-            metric="new_lines_to_cover"
-          >
-            1
-          </DrilldownLink>,
-        }
-      }
-    />
-  </span>
-</Fragment>
-`;
-
-exports[`should render correctly for duplications 1`] = `
-<Fragment>
-  <span
-    className="big-spacer-right"
-  >
-    <DuplicationsRating
-      size="big"
-      value={1}
-    />
-  </span>
-  <DrilldownLink
-    branchLike={
-      Object {
-        "analysisDate": "2018-01-01",
-        "excludedFromPurge": true,
-        "isMain": false,
-        "name": "branch-6.7",
-      }
-    }
-    component="my-project"
-    metric="new_duplicated_lines_density"
-  >
-    1.0%
-  </DrilldownLink>
-  <span
-    className="big-spacer-left"
-  >
-    overview.metric.duplications
-  </span>
-</Fragment>
-`;
-
-exports[`should render correctly with no value 1`] = `
-<Fragment>
-  <span
-    className="measure-empty"
-  >
-    â€”
-  </span>
-  <span
-    className="big-spacer-left"
-  >
-    overview.metric.coverage
-  </span>
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/PullRequestOverview-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/PullRequestOverview-test.tsx.snap
new file mode 100644 (file)
index 0000000..3d778f2
--- /dev/null
@@ -0,0 +1,2599 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for a failed QG 1`] = `
+<div
+  className="page page-limited"
+>
+  <div
+    className="pr-overview has-conditions"
+  >
+    <div
+      className="display-flex-row"
+    >
+      <div
+        className="big-spacer-right"
+      >
+        <h2
+          className="overview-panel-title spacer-bottom small"
+        >
+          overview.quality_gate
+          <DocTooltip
+            className="spacer-left"
+            doc={Promise {}}
+          />
+        </h2>
+        <Memo(LargeQualityGateBadge)
+          component={
+            Object {
+              "breadcrumbs": Array [],
+              "key": "my-project",
+              "name": "MyProject",
+              "organization": "foo",
+              "qualifier": "TRK",
+              "qualityGate": Object {
+                "isDefault": true,
+                "key": "30",
+                "name": "Sonar way",
+              },
+              "qualityProfiles": Array [
+                Object {
+                  "deleted": false,
+                  "key": "my-qp",
+                  "language": "ts",
+                  "name": "Sonar way",
+                },
+              ],
+              "tags": Array [],
+            }
+          }
+          level="ERROR"
+        />
+      </div>
+      <div
+        className="pr-overview-failed-conditions big-spacer-right"
+      >
+        <h2
+          className="overview-panel-title spacer-bottom small"
+        >
+          overview.failed_conditions
+        </h2>
+        <Memo(QualityGateConditions)
+          branchLike={
+            Object {
+              "analysisDate": "2018-01-01",
+              "base": "master",
+              "branch": "feature/foo/bar",
+              "key": "1001",
+              "target": "master",
+              "title": "Foo Bar feature",
+            }
+          }
+          collapsible={true}
+          component={
+            Object {
+              "breadcrumbs": Array [],
+              "key": "my-project",
+              "name": "MyProject",
+              "organization": "foo",
+              "qualifier": "TRK",
+              "qualityGate": Object {
+                "isDefault": true,
+                "key": "30",
+                "name": "Sonar way",
+              },
+              "qualityProfiles": Array [
+                Object {
+                  "deleted": false,
+                  "key": "my-qp",
+                  "language": "ts",
+                  "name": "Sonar way",
+                },
+              ],
+              "tags": Array [],
+            }
+          }
+          failedConditions={
+            Array [
+              Object {
+                "actual": "10",
+                "error": "1.0",
+                "level": "ERROR",
+                "measure": Object {
+                  "bestValue": true,
+                  "metric": Object {
+                    "id": "new_code_smells",
+                    "key": "new_code_smells",
+                    "name": "new_code_smells",
+                    "type": "PERCENT",
+                  },
+                  "periods": Array [
+                    Object {
+                      "bestValue": true,
+                      "index": 1,
+                      "value": "1.0",
+                    },
+                  ],
+                  "value": "1.0",
+                },
+                "metric": "new_code_smells",
+                "op": "GT",
+                "period": 1,
+              },
+            ]
+          }
+        />
+      </div>
+      <div
+        className="flex-1"
+      >
+        <h2
+          className="overview-panel-title spacer-bottom small"
+        >
+          overview.measures
+        </h2>
+        <div
+          className="overview-panel-content"
+        >
+          <div
+            className="overview-measures-row display-flex-row"
+            key="BUG"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <Memo(IssueLabel)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="BUG"
+                useDiffMetric={true}
+              />
+            </div>
+            <div
+              className="overview-panel-big-padded overview-measures-aside display-flex-center"
+            >
+              <Memo(IssueRating)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="BUG"
+                useDiffMetric={true}
+              />
+            </div>
+          </div>
+          <div
+            className="overview-measures-row display-flex-row"
+            key="VULNERABILITY"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <Memo(IssueLabel)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="VULNERABILITY"
+                useDiffMetric={true}
+              />
+            </div>
+            <div
+              className="flex-1 small display-flex-center"
+            >
+              <Memo(IssueLabel)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                docTooltip={Promise {}}
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="SECURITY_HOTSPOT"
+                useDiffMetric={true}
+              />
+            </div>
+            <div
+              className="overview-panel-big-padded overview-measures-aside display-flex-center"
+            >
+              <Memo(IssueRating)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="VULNERABILITY"
+                useDiffMetric={true}
+              />
+            </div>
+          </div>
+          <div
+            className="overview-measures-row display-flex-row"
+            key="CODE_SMELL"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <Memo(IssueLabel)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="CODE_SMELL"
+                useDiffMetric={true}
+              />
+            </div>
+            <div
+              className="overview-panel-big-padded overview-measures-aside display-flex-center"
+            >
+              <Memo(IssueRating)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="CODE_SMELL"
+                useDiffMetric={true}
+              />
+            </div>
+          </div>
+          <div
+            className="overview-measures-row display-flex-row"
+            key="COVERAGE"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <MeasurementLabel
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="COVERAGE"
+                useDiffMetric={true}
+              />
+            </div>
+            <Memo(AfterMergeEstimate)
+              className="overview-panel-big-padded overview-measures-aside text-right overview-measures-emphasis"
+              measures={
+                Array [
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_bugs",
+                      "key": "new_bugs",
+                      "name": "new_bugs",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_vulnerabilities",
+                      "key": "new_vulnerabilities",
+                      "name": "new_vulnerabilities",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_code_smells",
+                      "key": "new_code_smells",
+                      "name": "new_code_smells",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_security_hotspots",
+                      "key": "new_security_hotspots",
+                      "name": "new_security_hotspots",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                ]
+              }
+              type="COVERAGE"
+            />
+          </div>
+          <div
+            className="overview-measures-row display-flex-row"
+            key="DUPLICATION"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <MeasurementLabel
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="DUPLICATION"
+                useDiffMetric={true}
+              />
+            </div>
+            <Memo(AfterMergeEstimate)
+              className="overview-panel-big-padded overview-measures-aside text-right overview-measures-emphasis"
+              measures={
+                Array [
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_bugs",
+                      "key": "new_bugs",
+                      "name": "new_bugs",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_vulnerabilities",
+                      "key": "new_vulnerabilities",
+                      "name": "new_vulnerabilities",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_code_smells",
+                      "key": "new_code_smells",
+                      "name": "new_code_smells",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_security_hotspots",
+                      "key": "new_security_hotspots",
+                      "name": "new_security_hotspots",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                ]
+              }
+              type="DUPLICATION"
+            />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
+
+exports[`should render correctly for a passed QG 1`] = `
+<div
+  className="page page-limited"
+>
+  <div
+    className="pr-overview"
+  >
+    <div
+      className="display-flex-row"
+    >
+      <div
+        className="big-spacer-right"
+      >
+        <h2
+          className="overview-panel-title spacer-bottom small"
+        >
+          overview.quality_gate
+          <DocTooltip
+            className="spacer-left"
+            doc={Promise {}}
+          />
+        </h2>
+        <Memo(LargeQualityGateBadge)
+          component={
+            Object {
+              "breadcrumbs": Array [],
+              "key": "my-project",
+              "name": "MyProject",
+              "organization": "foo",
+              "qualifier": "TRK",
+              "qualityGate": Object {
+                "isDefault": true,
+                "key": "30",
+                "name": "Sonar way",
+              },
+              "qualityProfiles": Array [
+                Object {
+                  "deleted": false,
+                  "key": "my-qp",
+                  "language": "ts",
+                  "name": "Sonar way",
+                },
+              ],
+              "tags": Array [],
+            }
+          }
+          level="OK"
+        />
+      </div>
+      <div
+        className="flex-1"
+      >
+        <h2
+          className="overview-panel-title spacer-bottom small"
+        >
+          overview.measures
+        </h2>
+        <div
+          className="overview-panel-content"
+        >
+          <div
+            className="overview-measures-row display-flex-row"
+            key="BUG"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <Memo(IssueLabel)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="BUG"
+                useDiffMetric={true}
+              />
+            </div>
+            <div
+              className="overview-panel-big-padded overview-measures-aside display-flex-center"
+            >
+              <Memo(IssueRating)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="BUG"
+                useDiffMetric={true}
+              />
+            </div>
+          </div>
+          <div
+            className="overview-measures-row display-flex-row"
+            key="VULNERABILITY"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <Memo(IssueLabel)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="VULNERABILITY"
+                useDiffMetric={true}
+              />
+            </div>
+            <div
+              className="flex-1 small display-flex-center"
+            >
+              <Memo(IssueLabel)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                docTooltip={Promise {}}
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="SECURITY_HOTSPOT"
+                useDiffMetric={true}
+              />
+            </div>
+            <div
+              className="overview-panel-big-padded overview-measures-aside display-flex-center"
+            >
+              <Memo(IssueRating)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="VULNERABILITY"
+                useDiffMetric={true}
+              />
+            </div>
+          </div>
+          <div
+            className="overview-measures-row display-flex-row"
+            key="CODE_SMELL"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <Memo(IssueLabel)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="CODE_SMELL"
+                useDiffMetric={true}
+              />
+            </div>
+            <div
+              className="overview-panel-big-padded overview-measures-aside display-flex-center"
+            >
+              <Memo(IssueRating)
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="CODE_SMELL"
+                useDiffMetric={true}
+              />
+            </div>
+          </div>
+          <div
+            className="overview-measures-row display-flex-row"
+            key="COVERAGE"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <MeasurementLabel
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="COVERAGE"
+                useDiffMetric={true}
+              />
+            </div>
+            <Memo(AfterMergeEstimate)
+              className="overview-panel-big-padded overview-measures-aside text-right overview-measures-emphasis"
+              measures={
+                Array [
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_bugs",
+                      "key": "new_bugs",
+                      "name": "new_bugs",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_vulnerabilities",
+                      "key": "new_vulnerabilities",
+                      "name": "new_vulnerabilities",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_code_smells",
+                      "key": "new_code_smells",
+                      "name": "new_code_smells",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_security_hotspots",
+                      "key": "new_security_hotspots",
+                      "name": "new_security_hotspots",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                ]
+              }
+              type="COVERAGE"
+            />
+          </div>
+          <div
+            className="overview-measures-row display-flex-row"
+            key="DUPLICATION"
+          >
+            <div
+              className="overview-panel-big-padded flex-1 small display-flex-center"
+            >
+              <MeasurementLabel
+                branchLike={
+                  Object {
+                    "analysisDate": "2018-01-01",
+                    "base": "master",
+                    "branch": "feature/foo/bar",
+                    "key": "1001",
+                    "target": "master",
+                    "title": "Foo Bar feature",
+                  }
+                }
+                component={
+                  Object {
+                    "breadcrumbs": Array [],
+                    "key": "my-project",
+                    "name": "MyProject",
+                    "organization": "foo",
+                    "qualifier": "TRK",
+                    "qualityGate": Object {
+                      "isDefault": true,
+                      "key": "30",
+                      "name": "Sonar way",
+                    },
+                    "qualityProfiles": Array [
+                      Object {
+                        "deleted": false,
+                        "key": "my-qp",
+                        "language": "ts",
+                        "name": "Sonar way",
+                      },
+                    ],
+                    "tags": Array [],
+                  }
+                }
+                measures={
+                  Array [
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_bugs",
+                        "key": "new_bugs",
+                        "name": "new_bugs",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_vulnerabilities",
+                        "key": "new_vulnerabilities",
+                        "name": "new_vulnerabilities",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_code_smells",
+                        "key": "new_code_smells",
+                        "name": "new_code_smells",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                    Object {
+                      "bestValue": true,
+                      "metric": Object {
+                        "id": "new_security_hotspots",
+                        "key": "new_security_hotspots",
+                        "name": "new_security_hotspots",
+                        "type": "PERCENT",
+                      },
+                      "periods": Array [
+                        Object {
+                          "bestValue": true,
+                          "index": 1,
+                          "value": "1.0",
+                        },
+                      ],
+                      "value": "1.0",
+                    },
+                  ]
+                }
+                type="DUPLICATION"
+                useDiffMetric={true}
+              />
+            </div>
+            <Memo(AfterMergeEstimate)
+              className="overview-panel-big-padded overview-measures-aside text-right overview-measures-emphasis"
+              measures={
+                Array [
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_bugs",
+                      "key": "new_bugs",
+                      "name": "new_bugs",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_vulnerabilities",
+                      "key": "new_vulnerabilities",
+                      "name": "new_vulnerabilities",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_code_smells",
+                      "key": "new_code_smells",
+                      "name": "new_code_smells",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                  Object {
+                    "bestValue": true,
+                    "metric": Object {
+                      "id": "new_security_hotspots",
+                      "key": "new_security_hotspots",
+                      "name": "new_security_hotspots",
+                      "type": "PERCENT",
+                    },
+                    "periods": Array [
+                      Object {
+                        "bestValue": true,
+                        "index": 1,
+                        "value": "1.0",
+                      },
+                    ],
+                    "value": "1.0",
+                  },
+                ]
+              }
+              type="DUPLICATION"
+            />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/ReviewApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/ReviewApp-test.tsx.snap
deleted file mode 100644 (file)
index 6637671..0000000
+++ /dev/null
@@ -1,2138 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should correctly handle a WS failure 1`] = `
-<div
-  className="page page-limited"
->
-  <i
-    className="spinner"
-  />
-</div>
-`;
-
-exports[`should render correctly for a failed QG 1`] = `
-<div
-  className="page page-limited"
->
-  <div
-    className="pr-overview has-conditions"
-  >
-    <div
-      className="display-flex-row"
-    >
-      <div
-        className="pr-overview-quality-gate big-spacer-right"
-      >
-        <h3
-          className="spacer-bottom small"
-        >
-          overview.quality_gate
-          <DocTooltip
-            className="spacer-left"
-            doc={Promise {}}
-          />
-        </h3>
-        <LargeQualityGateBadge
-          component={
-            Object {
-              "breadcrumbs": Array [],
-              "key": "my-project",
-              "name": "MyProject",
-              "organization": "foo",
-              "qualifier": "TRK",
-              "qualityGate": Object {
-                "isDefault": true,
-                "key": "30",
-                "name": "Sonar way",
-              },
-              "qualityProfiles": Array [
-                Object {
-                  "deleted": false,
-                  "key": "my-qp",
-                  "language": "ts",
-                  "name": "Sonar way",
-                },
-              ],
-              "tags": Array [],
-            }
-          }
-          level="ERROR"
-        />
-      </div>
-      <div
-        className="pr-overview-failed-conditions big-spacer-right"
-      >
-        <h3
-          className="spacer-bottom small"
-        >
-          overview.failed_conditions
-        </h3>
-        <QualityGateConditions
-          branchLike={
-            Object {
-              "analysisDate": "2018-01-01",
-              "base": "master",
-              "branch": "feature/foo/bar",
-              "key": "1001",
-              "target": "master",
-              "title": "Foo Bar feature",
-            }
-          }
-          collapsible={true}
-          component={
-            Object {
-              "breadcrumbs": Array [],
-              "key": "my-project",
-              "name": "MyProject",
-              "organization": "foo",
-              "qualifier": "TRK",
-              "qualityGate": Object {
-                "isDefault": true,
-                "key": "30",
-                "name": "Sonar way",
-              },
-              "qualityProfiles": Array [
-                Object {
-                  "deleted": false,
-                  "key": "my-qp",
-                  "language": "ts",
-                  "name": "Sonar way",
-                },
-              ],
-              "tags": Array [],
-            }
-          }
-          conditions={
-            Array [
-              Object {
-                "actual": "10",
-                "error": "1.0",
-                "level": "ERROR",
-                "metric": "new_code_smells",
-                "op": "GT",
-                "period": 1,
-              },
-            ]
-          }
-        />
-      </div>
-      <div
-        className="pr-overview-measurements flex-1"
-      >
-        <h3
-          className="spacer-bottom small"
-        >
-          overview.metrics
-        </h3>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="BUG"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <IssueLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="BUG"
-            />
-          </div>
-          <div
-            className="pr-overview-measurements-rating display-flex-center"
-          >
-            <IssueRating
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="BUG"
-            />
-          </div>
-        </div>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="VULNERABILITY"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <IssueLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="VULNERABILITY"
-            />
-          </div>
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <IssueLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              docTooltip={Promise {}}
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="SECURITY_HOTSPOT"
-            />
-          </div>
-          <div
-            className="pr-overview-measurements-rating display-flex-center"
-          >
-            <IssueRating
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="VULNERABILITY"
-            />
-          </div>
-        </div>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="CODE_SMELL"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <IssueLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="CODE_SMELL"
-            />
-          </div>
-          <div
-            className="pr-overview-measurements-rating display-flex-center"
-          >
-            <IssueRating
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="CODE_SMELL"
-            />
-          </div>
-        </div>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="COVERAGE"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <MeasurementLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="COVERAGE"
-            />
-          </div>
-          <AfterMergeEstimate
-            className="pr-overview-measurements-estimate"
-            measures={
-              Array [
-                Object {
-                  "bestValue": true,
-                  "metric": "new_bugs ",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_vulnerabilities",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_code_smells",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_security_hotspots",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-              ]
-            }
-            type="COVERAGE"
-          />
-        </div>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="DUPLICATION"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <MeasurementLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="DUPLICATION"
-            />
-          </div>
-          <AfterMergeEstimate
-            className="pr-overview-measurements-estimate"
-            measures={
-              Array [
-                Object {
-                  "bestValue": true,
-                  "metric": "new_bugs ",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_vulnerabilities",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_code_smells",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_security_hotspots",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-              ]
-            }
-            type="DUPLICATION"
-          />
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`should render correctly for a passed QG 1`] = `
-<div
-  className="page page-limited"
->
-  <div
-    className="pr-overview"
-  >
-    <div
-      className="display-flex-row"
-    >
-      <div
-        className="pr-overview-quality-gate big-spacer-right"
-      >
-        <h3
-          className="spacer-bottom small"
-        >
-          overview.quality_gate
-          <DocTooltip
-            className="spacer-left"
-            doc={Promise {}}
-          />
-        </h3>
-        <LargeQualityGateBadge
-          component={
-            Object {
-              "breadcrumbs": Array [],
-              "key": "my-project",
-              "name": "MyProject",
-              "organization": "foo",
-              "qualifier": "TRK",
-              "qualityGate": Object {
-                "isDefault": true,
-                "key": "30",
-                "name": "Sonar way",
-              },
-              "qualityProfiles": Array [
-                Object {
-                  "deleted": false,
-                  "key": "my-qp",
-                  "language": "ts",
-                  "name": "Sonar way",
-                },
-              ],
-              "tags": Array [],
-            }
-          }
-          level="OK"
-        />
-      </div>
-      <div
-        className="pr-overview-measurements flex-1"
-      >
-        <h3
-          className="spacer-bottom small"
-        >
-          overview.metrics
-        </h3>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="BUG"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <IssueLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="BUG"
-            />
-          </div>
-          <div
-            className="pr-overview-measurements-rating display-flex-center"
-          >
-            <IssueRating
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="BUG"
-            />
-          </div>
-        </div>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="VULNERABILITY"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <IssueLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="VULNERABILITY"
-            />
-          </div>
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <IssueLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              docTooltip={Promise {}}
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="SECURITY_HOTSPOT"
-            />
-          </div>
-          <div
-            className="pr-overview-measurements-rating display-flex-center"
-          >
-            <IssueRating
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="VULNERABILITY"
-            />
-          </div>
-        </div>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="CODE_SMELL"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <IssueLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="CODE_SMELL"
-            />
-          </div>
-          <div
-            className="pr-overview-measurements-rating display-flex-center"
-          >
-            <IssueRating
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="CODE_SMELL"
-            />
-          </div>
-        </div>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="COVERAGE"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <MeasurementLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="COVERAGE"
-            />
-          </div>
-          <AfterMergeEstimate
-            className="pr-overview-measurements-estimate"
-            measures={
-              Array [
-                Object {
-                  "bestValue": true,
-                  "metric": "new_bugs ",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_vulnerabilities",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_code_smells",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_security_hotspots",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-              ]
-            }
-            type="COVERAGE"
-          />
-        </div>
-        <div
-          className="pr-overview-measurements-row display-flex-row"
-          key="DUPLICATION"
-        >
-          <div
-            className="pr-overview-measurements-value flex-1 small display-flex-center"
-          >
-            <MeasurementLabel
-              branchLike={
-                Object {
-                  "analysisDate": "2018-01-01",
-                  "base": "master",
-                  "branch": "feature/foo/bar",
-                  "key": "1001",
-                  "target": "master",
-                  "title": "Foo Bar feature",
-                }
-              }
-              className="overview-domain-measure-value"
-              component={
-                Object {
-                  "breadcrumbs": Array [],
-                  "key": "my-project",
-                  "name": "MyProject",
-                  "organization": "foo",
-                  "qualifier": "TRK",
-                  "qualityGate": Object {
-                    "isDefault": true,
-                    "key": "30",
-                    "name": "Sonar way",
-                  },
-                  "qualityProfiles": Array [
-                    Object {
-                      "deleted": false,
-                      "key": "my-qp",
-                      "language": "ts",
-                      "name": "Sonar way",
-                    },
-                  ],
-                  "tags": Array [],
-                }
-              }
-              measures={
-                Array [
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_bugs ",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_vulnerabilities",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_code_smells",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                  Object {
-                    "bestValue": true,
-                    "metric": "new_security_hotspots",
-                    "periods": Array [
-                      Object {
-                        "bestValue": true,
-                        "index": 1,
-                        "value": "1.0",
-                      },
-                    ],
-                    "value": "1.0",
-                  },
-                ]
-              }
-              type="DUPLICATION"
-            />
-          </div>
-          <AfterMergeEstimate
-            className="pr-overview-measurements-estimate"
-            measures={
-              Array [
-                Object {
-                  "bestValue": true,
-                  "metric": "new_bugs ",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_vulnerabilities",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_code_smells",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-                Object {
-                  "bestValue": true,
-                  "metric": "new_security_hotspots",
-                  "periods": Array [
-                    Object {
-                      "bestValue": true,
-                      "index": 1,
-                      "value": "1.0",
-                    },
-                  ],
-                  "value": "1.0",
-                },
-              ]
-            }
-            type="DUPLICATION"
-          />
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-`;
index d7cc776291afc567ba5976d6578ff016f471136d..fa7c0341f9c5989b61de1702a92b8c136d08e901 100644 (file)
@@ -24,145 +24,208 @@ import VulnerabilityIcon from 'sonar-ui-common/components/icons/VulnerabilityIco
 import DuplicationsRating from 'sonar-ui-common/components/ui/DuplicationsRating';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 import CoverageRating from '../../components/ui/CoverageRating';
+import { MetricKey } from '../../types/metrics';
+import { QualityGateStatusConditionEnhanced } from '../../types/quality-gates';
 
-export const METRICS = [
+export const METRICS: string[] = [
   // quality gate
-  'alert_status',
-  'quality_gate_details',
+  MetricKey.alert_status,
+  MetricKey.quality_gate_details, // TODO: still relevant?
 
   // bugs
-  'bugs',
-  'new_bugs',
-  'reliability_rating',
-  'new_reliability_rating',
+  MetricKey.bugs,
+  MetricKey.new_bugs,
+  MetricKey.reliability_rating,
+  MetricKey.new_reliability_rating,
 
   // vulnerabilities
-  'vulnerabilities',
-  'new_vulnerabilities',
-  'security_rating',
-  'new_security_rating',
-  'security_hotspots',
-  'new_security_hotspots',
+  MetricKey.vulnerabilities,
+  MetricKey.new_vulnerabilities,
+  MetricKey.security_rating,
+  MetricKey.new_security_rating,
+  MetricKey.security_hotspots,
+  MetricKey.new_security_hotspots,
 
   // code smells
-  'code_smells',
-  'new_code_smells',
-  'sqale_rating',
-  'new_maintainability_rating',
-  'sqale_index',
-  'new_technical_debt',
+  MetricKey.code_smells,
+  MetricKey.new_code_smells,
+  MetricKey.sqale_rating,
+  MetricKey.new_maintainability_rating,
+  MetricKey.sqale_index,
+  MetricKey.new_technical_debt,
 
   // coverage
-  'coverage',
-  'new_coverage',
-  'new_lines_to_cover',
-  'tests',
+  MetricKey.coverage,
+  MetricKey.new_coverage,
+  MetricKey.lines_to_cover,
+  MetricKey.new_lines_to_cover,
+  MetricKey.tests,
 
   // duplications
-  'duplicated_lines_density',
-  'new_duplicated_lines_density',
-  'duplicated_blocks',
+  MetricKey.duplicated_lines_density,
+  MetricKey.new_duplicated_lines_density,
+  MetricKey.duplicated_blocks,
 
   // size
-  'ncloc',
-  'lines',
-  'ncloc_language_distribution',
-  'projects',
-  'new_lines'
+  MetricKey.ncloc,
+  MetricKey.ncloc_language_distribution,
+  MetricKey.projects,
+  MetricKey.lines,
+  MetricKey.new_lines
 ];
 
-export const PR_METRICS = [
-  'coverage',
-  'new_coverage',
-  'new_lines_to_cover',
-
-  'duplicated_lines_density',
-  'new_duplicated_lines_density',
-  'new_lines',
-  'new_code_smells',
-  'new_maintainability_rating',
-  'new_bugs',
-  'new_reliability_rating',
-  'new_vulnerabilities',
-  'new_security_hotspots',
-  'new_security_rating'
+export const PR_METRICS: string[] = [
+  MetricKey.coverage,
+  MetricKey.new_coverage,
+  MetricKey.new_lines_to_cover,
+
+  MetricKey.duplicated_lines_density,
+  MetricKey.new_duplicated_lines_density,
+  MetricKey.new_lines,
+  MetricKey.new_code_smells,
+  MetricKey.new_maintainability_rating,
+  MetricKey.new_bugs,
+  MetricKey.new_reliability_rating,
+  MetricKey.new_vulnerabilities,
+  MetricKey.new_security_hotspots,
+  MetricKey.new_security_rating
 ];
 
-export const HISTORY_METRICS_LIST = [
-  'bugs',
-  'vulnerabilities',
-  'sqale_index',
-  'duplicated_lines_density',
-  'ncloc',
-  'coverage'
+export const HISTORY_METRICS_LIST: string[] = [
+  MetricKey.bugs,
+  MetricKey.vulnerabilities,
+  MetricKey.sqale_index,
+  MetricKey.duplicated_lines_density,
+  MetricKey.ncloc,
+  MetricKey.coverage
 ];
 
-export type MeasurementType = 'COVERAGE' | 'DUPLICATION';
+export enum MeasurementType {
+  Coverage = 'COVERAGE',
+  Duplication = 'DUPLICATION'
+}
 
-export const MEASUREMENTS_MAP = {
-  COVERAGE: {
-    metric: 'new_coverage',
-    linesMetric: 'new_lines_to_cover',
-    afterMergeMetric: 'coverage',
-    labelKey: 'overview.metric.coverage',
+const MEASUREMENTS_MAP = {
+  [MeasurementType.Coverage]: {
+    metric: MetricKey.coverage,
+    newMetric: MetricKey.new_coverage,
+    linesMetric: MetricKey.lines_to_cover,
+    newLinesMetric: MetricKey.new_lines_to_cover,
+    afterMergeMetric: MetricKey.coverage,
+    labelKey: 'metric.coverage.name',
     expandedLabelKey: 'overview.coverage_on_X_lines',
+    newLinesExpandedLabelKey: 'overview.coverage_on_X_new_lines',
     iconClass: CoverageRating
   },
-  DUPLICATION: {
-    metric: 'new_duplicated_lines_density',
-    linesMetric: 'new_lines',
-    afterMergeMetric: 'duplicated_lines_density',
-    labelKey: 'overview.metric.duplications',
-    expandedLabelKey: 'overview.duplications_on_X',
+  [MeasurementType.Duplication]: {
+    metric: MetricKey.duplicated_lines_density,
+    newMetric: MetricKey.new_duplicated_lines_density,
+    linesMetric: MetricKey.ncloc,
+    newLinesMetric: MetricKey.new_lines,
+    afterMergeMetric: MetricKey.duplicated_lines_density,
+    labelKey: 'metric.duplicated_lines_density.short_name',
+    expandedLabelKey: 'overview.duplications_on_X_lines',
+    newLinesExpandedLabelKey: 'overview.duplications_on_X_new_lines',
     iconClass: DuplicationsRating
   }
 };
 
-export type IssueType = 'CODE_SMELL' | 'VULNERABILITY' | 'BUG' | 'SECURITY_HOTSPOT';
+export enum IssueType {
+  CodeSmell = 'CODE_SMELL',
+  Vulnerability = 'VULNERABILITY',
+  Bug = 'BUG',
+  SecurityHotspot = 'SECURITY_HOTSPOT'
+}
 
-export const ISSUETYPE_MAP = {
-  CODE_SMELL: {
-    metric: 'new_code_smells',
-    rating: 'new_maintainability_rating',
+const ISSUETYPE_MAP = {
+  [IssueType.CodeSmell]: {
+    metric: MetricKey.code_smells,
+    newMetric: MetricKey.new_code_smells,
+    rating: MetricKey.sqale_rating,
+    newRating: MetricKey.new_maintainability_rating,
     ratingName: 'Maintainability',
     iconClass: CodeSmellIcon
   },
-  VULNERABILITY: {
-    metric: 'new_vulnerabilities',
-    rating: 'new_security_rating',
+  [IssueType.Vulnerability]: {
+    metric: MetricKey.vulnerabilities,
+    newMetric: MetricKey.new_vulnerabilities,
+    rating: MetricKey.security_rating,
+    newRating: MetricKey.new_security_rating,
     ratingName: 'Security',
     iconClass: VulnerabilityIcon
   },
-  BUG: {
-    metric: 'new_bugs',
-    rating: 'new_reliability_rating',
+  [IssueType.Bug]: {
+    metric: MetricKey.bugs,
+    newMetric: MetricKey.new_bugs,
+    rating: MetricKey.reliability_rating,
+    newRating: MetricKey.new_reliability_rating,
     ratingName: 'Reliability',
     iconClass: BugIcon
   },
-  SECURITY_HOTSPOT: {
-    metric: 'new_security_hotspots',
+  [IssueType.SecurityHotspot]: {
+    metric: MetricKey.security_hotspots,
+    newMetric: MetricKey.new_security_hotspots,
     rating: '',
+    newRating: '',
     ratingName: '',
     iconClass: SecurityHotspotIcon
   }
 };
 
-export function getMetricName(metricKey: string) {
-  return translate('overview.metric', metricKey);
+export function getIssueRatingName(type: IssueType) {
+  return translate('metric_domain', ISSUETYPE_MAP[type].ratingName);
 }
 
-export function getRatingName(type: IssueType) {
-  return translate('metric_domain', ISSUETYPE_MAP[type].ratingName);
+export function getIssueIconClass(type: IssueType) {
+  return ISSUETYPE_MAP[type].iconClass;
+}
+
+export function getIssueMetricKey(type: IssueType, useDiffMetric: boolean) {
+  return useDiffMetric ? ISSUETYPE_MAP[type].newMetric : ISSUETYPE_MAP[type].metric;
+}
+
+export function getIssueRatingMetricKey(type: IssueType, useDiffMetric: boolean) {
+  return useDiffMetric ? ISSUETYPE_MAP[type].newRating : ISSUETYPE_MAP[type].rating;
+}
+
+export function getMeasurementIconClass(type: MeasurementType) {
+  return MEASUREMENTS_MAP[type].iconClass;
+}
+
+export function getMeasurementMetricKey(type: MeasurementType, useDiffMetric: boolean) {
+  return useDiffMetric ? MEASUREMENTS_MAP[type].newMetric : MEASUREMENTS_MAP[type].metric;
+}
+
+export function getMeasurementAfterMergeMetricKey(type: MeasurementType) {
+  return MEASUREMENTS_MAP[type].afterMergeMetric;
+}
+
+export function getMeasurementLinesMetricKey(type: MeasurementType, useDiffMetric: boolean) {
+  return useDiffMetric ? MEASUREMENTS_MAP[type].newLinesMetric : MEASUREMENTS_MAP[type].linesMetric;
+}
+
+export function getMeasurementLabelKeys(type: MeasurementType, useDiffMetric: boolean) {
+  return {
+    expandedLabelKey: useDiffMetric
+      ? MEASUREMENTS_MAP[type].newLinesExpandedLabelKey
+      : MEASUREMENTS_MAP[type].expandedLabelKey,
+    labelKey: MEASUREMENTS_MAP[type].labelKey
+  };
 }
 
 /*
  * Extract a specific metric's threshold from the quality gate details
  */
-export function getThreshold(measures: T.MeasureEnhanced[], metricKey: string): number | undefined {
-  const detailsMeasure = measures.find(measure => measure.metric.key === 'quality_gate_details');
+export function getThreshold(
+  measures: T.MeasureEnhanced[],
+  metricKey: MetricKey | string
+): number | undefined {
+  const detailsMeasure = measures.find(
+    measure => measure.metric.key === MetricKey.quality_gate_details
+  );
   if (detailsMeasure && detailsMeasure.value) {
     const details = safeParse(detailsMeasure.value);
-    const conditions: T.QualityGateStatusConditionEnhanced[] = details.conditions || [];
+    const conditions: QualityGateStatusConditionEnhanced[] = details.conditions || [];
 
     const condition = conditions.find(c => c.metric === metricKey);
     if (condition) {