aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2018-08-21 11:31:32 +0200
committersonartech <sonartech@sonarsource.com>2018-09-19 10:51:41 +0200
commit1b6dcc529ae3ef54db0cfe7ac80c926d20799d56 (patch)
treefe41e3815cf2d343ac34a3d6a45643707508e4c9 /server
parent0ba8c56c9a7cddf225720f224e66b267f9bbf528 (diff)
downloadsonarqube-1b6dcc529ae3ef54db0cfe7ac80c926d20799d56.tar.gz
sonarqube-1b6dcc529ae3ef54db0cfe7ac80c926d20799d56.zip
SONAR-11164 Add measures page for short-lived branches and PR
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts2
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/App.tsx146
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.tsx14
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/MeasuresEmpty.tsx29
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx14
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.tsx20
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.tsx.snap39
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.tsx25
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx17
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/DomainFacet-test.tsx37
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/Sidebar-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/utils.ts29
13 files changed, 267 insertions, 108 deletions
diff --git a/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts b/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts
index 74987c7eaa5..a3d14ff95c4 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts
+++ b/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts
@@ -102,7 +102,7 @@ describe('groupByDomains', () => {
describe('parseQuery', () => {
it('should correctly parse the url query', () => {
expect(utils.parseQuery({})).toEqual({
- metric: 'project_overview',
+ metric: utils.DEFAULT_METRIC,
selected: '',
view: utils.DEFAULT_VIEW
});
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx
index ff78d3a724a..236c96619a2 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx
@@ -22,10 +22,21 @@ import * as key from 'keymaster';
import { InjectedRouter } from 'react-router';
import Helmet from 'react-helmet';
import MeasureContentContainer from './MeasureContentContainer';
+import MeasuresEmpty from './MeasuresEmpty';
import MeasureOverviewContainer from './MeasureOverviewContainer';
import Sidebar from '../sidebar/Sidebar';
import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper';
-import { isProjectOverview, hasBubbleChart, parseQuery, serializeQuery, Query } from '../utils';
+import {
+ isProjectOverview,
+ hasBubbleChart,
+ parseQuery,
+ serializeQuery,
+ Query,
+ hasFullMeasures,
+ getMeasuresPageMetricKeys,
+ groupByDomains,
+ sortMeasures
+} from '../utils';
import { isSameBranchLike, getBranchLikeQuery } from '../../../helpers/branches';
import Suggestions from '../../../app/components/embed-docs-modal/Suggestions';
import {
@@ -33,14 +44,13 @@ import {
translateWithParameters,
translate
} from '../../../helpers/l10n';
-import { getDisplayMetrics } from '../../../helpers/measures';
import { RawQuery } from '../../../helpers/query';
import {
BranchLike,
ComponentMeasure,
+ CurrentUser,
MeasureEnhanced,
Metric,
- CurrentUser,
Period
} from '../../../app/types';
import '../../../components/search-navigator.css';
@@ -117,8 +127,8 @@ export default class App extends React.PureComponent<Props, State> {
fetchMeasures = ({ branchLike, component, fetchMeasures, metrics }: Props) => {
this.setState({ loading: true });
- const filteredKeys = getDisplayMetrics(Object.values(metrics)).map(metric => metric.key);
+ const filteredKeys = getMeasuresPageMetricKeys(metrics, branchLike);
fetchMeasures(component.key, filteredKeys, branchLike).then(
({ measures, leakPeriod }) => {
if (this.mounted) {
@@ -139,6 +149,34 @@ export default class App extends React.PureComponent<Props, State> {
);
};
+ getHelmetTitle = (query: Query, displayOverview: boolean, metric?: Metric) => {
+ if (displayOverview && query.metric) {
+ return isProjectOverview(query.metric)
+ ? translate('component_measures.overview.project_overview.facet')
+ : translateWithParameters(
+ 'component_measures.domain_x_overview',
+ getLocalizedMetricDomain(query.metric)
+ );
+ }
+ return metric ? metric.name : translate('layout.measures');
+ };
+
+ getSelectedMetric = (query: Query, displayOverview: boolean) => {
+ if (displayOverview) {
+ return undefined;
+ }
+ const metric = this.props.metrics[query.metric];
+ if (!metric) {
+ const domainMeasures = groupByDomains(this.state.measures);
+ const firstMeasure =
+ domainMeasures[0] && sortMeasures(domainMeasures[0].name, domainMeasures[0].measures)[0];
+ if (firstMeasure && typeof firstMeasure !== 'string') {
+ return firstMeasure.metric;
+ }
+ }
+ return metric;
+ };
+
updateQuery = (newQuery: Partial<Query>) => {
const query = serializeQuery({
...parseQuery(this.props.location.query),
@@ -154,16 +192,51 @@ export default class App extends React.PureComponent<Props, State> {
});
};
- getHelmetTitle = (metric?: Metric) => {
- if (metric && hasBubbleChart(metric.key)) {
- return isProjectOverview(metric.key)
- ? translate('component_measures.overview.project_overview.facet')
- : translateWithParameters(
- 'component_measures.domain_x_overview',
- getLocalizedMetricDomain(metric.key)
- );
+ renderContent = (displayOverview: boolean, query: Query, metric?: Metric) => {
+ const { branchLike, component, fetchMeasures, metrics } = this.props;
+ const { leakPeriod, measures } = this.state;
+
+ if (measures.length === 0) {
+ return <MeasuresEmpty />;
}
- return metric ? metric.name : translate('layout.measures');
+
+ if (displayOverview) {
+ return (
+ <MeasureOverviewContainer
+ branchLike={branchLike}
+ className="layout-page-main"
+ currentUser={this.props.currentUser}
+ domain={query.metric}
+ leakPeriod={leakPeriod}
+ metrics={metrics}
+ rootComponent={component}
+ router={this.props.router}
+ selected={query.selected}
+ updateQuery={this.updateQuery}
+ />
+ );
+ }
+
+ if (!metric) {
+ return <MeasuresEmpty />;
+ }
+
+ return (
+ <MeasureContentContainer
+ branchLike={branchLike}
+ className="layout-page-main"
+ currentUser={this.props.currentUser}
+ fetchMeasures={fetchMeasures}
+ leakPeriod={leakPeriod}
+ metric={metric}
+ metrics={metrics}
+ rootComponent={component}
+ router={this.props.router}
+ selected={query.selected}
+ updateQuery={this.updateQuery}
+ view={query.view}
+ />
+ );
};
render() {
@@ -171,14 +244,16 @@ export default class App extends React.PureComponent<Props, State> {
if (isLoading) {
return <i className="spinner spinner-margin" />;
}
- const { branchLike, component, fetchMeasures, metrics } = this.props;
- const { leakPeriod } = this.state;
+ const { branchLike } = this.props;
+ const { measures } = this.state;
const query = parseQuery(this.props.location.query);
- const metric = metrics[query.metric];
+ const hasOverview = hasFullMeasures(branchLike);
+ const displayOverview = hasOverview && hasBubbleChart(query.metric);
+ const metric = this.getSelectedMetric(query, displayOverview);
return (
<div className="layout-page" id="component-measures">
<Suggestions suggestions="component_measures" />
- <Helmet title={this.getHelmetTitle(metric)} />
+ <Helmet title={this.getHelmetTitle(query, displayOverview, metric)} />
<ScreenPositionHelper className="layout-page-side-outer">
{({ top }) => (
@@ -186,8 +261,9 @@ export default class App extends React.PureComponent<Props, State> {
<div className="layout-page-side-inner">
<div className="layout-page-filters">
<Sidebar
- measures={this.state.measures}
- selectedMetric={query.metric}
+ hasOverview={hasOverview}
+ measures={measures}
+ selectedMetric={metric ? metric.key : query.metric}
updateQuery={this.updateQuery}
/>
</div>
@@ -196,37 +272,7 @@ export default class App extends React.PureComponent<Props, State> {
)}
</ScreenPositionHelper>
- {metric && (
- <MeasureContentContainer
- branchLike={branchLike}
- className="layout-page-main"
- currentUser={this.props.currentUser}
- fetchMeasures={fetchMeasures}
- leakPeriod={leakPeriod}
- metric={metric}
- metrics={metrics}
- rootComponent={component}
- router={this.props.router}
- selected={query.selected}
- updateQuery={this.updateQuery}
- view={query.view}
- />
- )}
- {!metric &&
- hasBubbleChart(query.metric) && (
- <MeasureOverviewContainer
- branchLike={branchLike}
- className="layout-page-main"
- currentUser={this.props.currentUser}
- domain={query.metric}
- leakPeriod={leakPeriod}
- metrics={metrics}
- rootComponent={component}
- router={this.props.router}
- selected={query.selected}
- updateQuery={this.updateQuery}
- />
- )}
+ {this.renderContent(displayOverview, query, metric)}
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.tsx
index 61840e12d62..2d524d52332 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.tsx
@@ -28,7 +28,8 @@ import Tooltip from '../../../components/controls/Tooltip';
import { getLocalizedMetricName, translate } from '../../../helpers/l10n';
import { getMeasureHistoryUrl } from '../../../helpers/urls';
import { isDiffMetric } from '../../../helpers/measures';
-import { MeasureEnhanced, Metric, ComponentMeasure, BranchLike, Period } from '../../../app/types';
+import { BranchLike, ComponentMeasure, MeasureEnhanced, Metric, Period } from '../../../app/types';
+import { hasFullMeasures } from '../utils';
interface Props {
branchLike?: BranchLike;
@@ -42,7 +43,9 @@ interface Props {
export default function MeasureHeader(props: Props) {
const { branchLike, component, leakPeriod, measure, metric, secondaryMeasure } = props;
const isDiff = isDiffMetric(metric.key);
- const hasHistory = component.qualifier !== 'FIL' && component.qualifier !== 'UTS';
+ const hasHistory =
+ component.qualifier !== 'FIL' && component.qualifier !== 'UTS' && hasFullMeasures(branchLike);
+ const displayLeak = hasFullMeasures(branchLike);
return (
<div className="measure-details-header big-spacer-bottom">
<div className="measure-details-primary">
@@ -79,9 +82,10 @@ export default function MeasureHeader(props: Props) {
)}
</div>
<div className="measure-details-primary-actions">
- {leakPeriod && (
- <LeakPeriodLegend className="spacer-left" component={component} period={leakPeriod} />
- )}
+ {displayLeak &&
+ leakPeriod && (
+ <LeakPeriodLegend className="spacer-left" component={component} period={leakPeriod} />
+ )}
</div>
</div>
{secondaryMeasure &&
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasuresEmpty.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/MeasuresEmpty.tsx
new file mode 100644
index 00000000000..ea25a2d2f69
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasuresEmpty.tsx
@@ -0,0 +1,29 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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 { translate } from '../../../helpers/l10n';
+
+export default function MeasuresEmpty() {
+ return (
+ <div className="layout-page-main">
+ <div className="note text-center">{translate('component_measures.empty')}</div>
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx
index f0202595073..c6505527b5e 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx
@@ -21,6 +21,7 @@
import * as React from 'react';
import { shallow } from 'enzyme';
import App from '../App';
+import { waitAndUpdate } from '../../../../helpers/testUtils';
const COMPONENT = { key: 'foo', name: 'Foo', qualifier: 'TRK' };
@@ -48,21 +49,24 @@ const PROPS = {
component: COMPONENT,
currentUser: { isLoggedIn: false },
location: { pathname: '/component_measures', query: { metric: 'coverage' } },
- fetchMeasures: jest.fn().mockResolvedValue({ component: COMPONENT, measures: [] }),
+ fetchMeasures: jest.fn().mockResolvedValue({
+ component: COMPONENT,
+ measures: [{ metric: 'coverage', value: '80.0' }]
+ }),
fetchMetrics: jest.fn(),
metrics: METRICS,
metricsKey: ['lines_to_cover', 'coverage', 'duplicated_lines_density', 'new_bugs'],
router: { push: jest.fn() } as any
};
-it('should render correctly', () => {
+it('should render correctly', async () => {
const wrapper = shallow(<App {...PROPS} />);
expect(wrapper.find('.spinner')).toHaveLength(1);
- wrapper.setState({ loading: false });
+ await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
});
-it('should render a measure overview', () => {
+it('should render a measure overview', async () => {
const wrapper = shallow(
<App
{...PROPS}
@@ -70,6 +74,6 @@ it('should render a measure overview', () => {
/>
);
expect(wrapper.find('.spinner')).toHaveLength(1);
- wrapper.setState({ loading: false });
+ await waitAndUpdate(wrapper);
expect(wrapper.find('MeasureOverviewContainer')).toHaveLength(1);
});
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.tsx
index 965af1b5474..2df222654bd 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.tsx
@@ -81,10 +81,24 @@ it('should render correctly for leak', () => {
).toMatchSnapshot();
});
-it('should render with branch', () => {
- const shortBranch = { isMain: false, name: 'feature', mergeBranch: '', type: 'SHORT' };
+it('should render with long living branch', () => {
+ const longBranch = { isMain: false, name: 'branch-6.7', type: 'LONG' };
expect(
- shallow(<MeasureHeader branchLike={shortBranch} {...PROPS} />).find('Link')
+ shallow(<MeasureHeader branchLike={longBranch} {...PROPS} />).find('Link')
+ ).toMatchSnapshot();
+});
+
+it('should render with short living branch', () => {
+ const shortBranch = { isMain: false, name: 'feature', mergeBranch: 'master', type: 'SHORT' };
+ expect(
+ shallow(
+ <MeasureHeader
+ {...PROPS}
+ branchLike={shortBranch}
+ measure={LEAK_MEASURE}
+ metric={LEAK_METRIC}
+ />
+ )
).toMatchSnapshot();
});
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.tsx.snap b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.tsx.snap
index 2ccafb98328..c74f60aa659 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.tsx.snap
@@ -128,7 +128,7 @@ exports[`should render correctly for leak 1`] = `
</div>
`;
-exports[`should render with branch 1`] = `
+exports[`should render with long living branch 1`] = `
<Link
className="js-show-history spacer-left button button-small"
onlyActiveOnIndex={false}
@@ -137,7 +137,7 @@ exports[`should render with branch 1`] = `
Object {
"pathname": "/project/activity",
"query": Object {
- "branch": "feature",
+ "branch": "branch-6.7",
"custom_metrics": "reliability_rating",
"graph": "custom",
"id": "foo",
@@ -149,6 +149,41 @@ exports[`should render with branch 1`] = `
</Link>
`;
+exports[`should render with short living branch 1`] = `
+<div
+ className="measure-details-header big-spacer-bottom"
+>
+ <div
+ className="measure-details-primary"
+ >
+ <div
+ className="measure-details-metric"
+ >
+ <IssueTypeIcon
+ className="little-spacer-right text-text-bottom"
+ query="new_reliability_rating"
+ />
+ Reliability Rating on New Code
+ <span
+ className="measure-details-value spacer-left"
+ >
+ <strong>
+ <Measure
+ className="domain-measures-leak"
+ metricKey="new_reliability_rating"
+ metricType="RATING"
+ value="3.0"
+ />
+ </strong>
+ </span>
+ </div>
+ <div
+ className="measure-details-primary-actions"
+ />
+ </div>
+</div>
+`;
+
exports[`should work with measure without value 1`] = `
<div
className="measure-details-header big-spacer-bottom"
diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.tsx b/server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.tsx
index 3257089235c..2b62fbeccbb 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.tsx
@@ -41,6 +41,7 @@ import { MeasureEnhanced } from '../../../app/types';
interface Props {
domain: { name: string; measures: MeasureEnhanced[] };
+ hasOverview: boolean;
onChange: (metric: string) => void;
onToggle: (property: string) => void;
open: boolean;
@@ -48,24 +49,28 @@ interface Props {
}
export default class DomainFacet extends React.PureComponent<Props> {
+ getValues = () => {
+ const { domain, selected } = this.props;
+ const measureSelected = domain.measures.find(measure => measure.metric.key === selected);
+ const overviewSelected = domain.name === selected && this.hasOverview(domain.name);
+ if (measureSelected) {
+ return [getLocalizedMetricName(measureSelected.metric)];
+ }
+ return overviewSelected ? [translate('component_measures.domain_overview')] : [];
+ };
+
handleHeaderClick = () => {
this.props.onToggle(this.props.domain.name);
};
hasFacetSelected = (domain: { name: string }, measures: MeasureEnhanced[], selected: string) => {
const measureSelected = measures.find(measure => measure.metric.key === selected);
- const overviewSelected = domain.name === selected && hasBubbleChart(domain.name);
+ const overviewSelected = domain.name === selected && this.hasOverview(domain.name);
return measureSelected || overviewSelected;
};
- getValues = () => {
- const { domain, selected } = this.props;
- const measureSelected = domain.measures.find(measure => measure.metric.key === selected);
- const overviewSelected = domain.name === selected && hasBubbleChart(domain.name);
- if (measureSelected) {
- return [getLocalizedMetricName(measureSelected.metric)];
- }
- return overviewSelected ? [translate('component_measures.domain_overview')] : [];
+ hasOverview = (domain: string) => {
+ return this.props.hasOverview && hasBubbleChart(domain);
};
renderItemFacetStat = (item: MeasureEnhanced) => {
@@ -115,7 +120,7 @@ export default class DomainFacet extends React.PureComponent<Props> {
renderOverviewFacet = () => {
const { domain, selected } = this.props;
- if (!hasBubbleChart(domain.name)) {
+ if (!this.hasOverview(domain.name)) {
return null;
}
return (
diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx b/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx
index 027d3593f4f..09683497982 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx
@@ -24,9 +24,10 @@ import { getDefaultView, groupByDomains, KNOWN_DOMAINS, PROJECT_OVERVEW, Query }
import { MeasureEnhanced } from '../../../app/types';
interface Props {
+ hasOverview: boolean;
measures: MeasureEnhanced[];
selectedMetric: string;
- updateQuery: (query: Query) => void;
+ updateQuery: (query: Partial<Query>) => void;
}
interface State {
@@ -73,16 +74,20 @@ export default class Sidebar extends React.PureComponent<Props, State> {
this.props.updateQuery({ metric, ...this.resetSelection(metric) });
render() {
+ const { hasOverview } = this.props;
return (
<div>
- <ProjectOverviewFacet
- onChange={this.changeMetric}
- selected={this.props.selectedMetric}
- value={PROJECT_OVERVEW}
- />
+ {hasOverview && (
+ <ProjectOverviewFacet
+ onChange={this.changeMetric}
+ selected={this.props.selectedMetric}
+ value={PROJECT_OVERVEW}
+ />
+ )}
{groupByDomains(this.props.measures).map(domain => (
<DomainFacet
domain={domain}
+ hasOverview={hasOverview}
key={domain.name}
onChange={this.changeMetric}
onToggle={this.toggleFacet}
diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/DomainFacet-test.tsx b/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/DomainFacet-test.tsx
index 590536b454c..1c90ccf475e 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/DomainFacet-test.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/DomainFacet-test.tsx
@@ -51,10 +51,11 @@ const DOMAIN = {
};
const PROPS = {
+ domain: DOMAIN,
+ hasOverview: true,
onChange: () => {},
onToggle: () => {},
open: true,
- domain: DOMAIN,
selected: 'foo'
};
@@ -71,6 +72,16 @@ it('should render closed', () => {
expect(wrapper.find('FacetItemsList')).toHaveLength(0);
});
+it('should render without overview', () => {
+ const wrapper = shallow(<DomainFacet {...PROPS} hasOverview={false} />);
+ expect(
+ wrapper
+ .find('FacetItem')
+ .filterWhere(node => node.getElement().key === 'Reliability')
+ .exists()
+ ).toBe(false);
+});
+
it('should not display subtitles of new measures if there is none', () => {
const domain = {
name: 'Reliability',
@@ -82,17 +93,7 @@ it('should not display subtitles of new measures if there is none', () => {
]
};
- expect(
- shallow(
- <DomainFacet
- domain={domain}
- onChange={() => {}}
- onToggle={() => {}}
- open={true}
- selected={'foo'}
- />
- )
- ).toMatchSnapshot();
+ expect(shallow(<DomainFacet {...PROPS} domain={domain} />)).toMatchSnapshot();
});
it('should not display subtitles of new measures if there is none, even on last line', () => {
@@ -106,15 +107,5 @@ it('should not display subtitles of new measures if there is none, even on last
]
};
- expect(
- shallow(
- <DomainFacet
- domain={domain}
- onChange={() => {}}
- onToggle={() => {}}
- open={true}
- selected={'foo'}
- />
- )
- ).toMatchSnapshot();
+ expect(shallow(<DomainFacet {...PROPS} domain={domain} />)).toMatchSnapshot();
});
diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/Sidebar-test.tsx b/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/Sidebar-test.tsx
index 9b629994ac3..4814927ffe5 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/Sidebar-test.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/Sidebar-test.tsx
@@ -61,6 +61,7 @@ const MEASURES = [
];
const PROPS = {
+ hasOverview: true,
measures: MEASURES,
selectedMetric: 'duplicated_lines_density',
updateQuery: () => {}
diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap b/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap
index 09f7788831c..d626c8f7948 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap
@@ -49,6 +49,7 @@ exports[`should display two facets 1`] = `
"name": "Coverage",
}
}
+ hasOverview={true}
key="Coverage"
onChange={[Function]}
onToggle={[Function]}
@@ -80,6 +81,7 @@ exports[`should display two facets 1`] = `
"name": "Duplications",
}
}
+ hasOverview={true}
key="Duplications"
onChange={[Function]}
onToggle={[Function]}
diff --git a/server/sonar-web/src/main/js/apps/component-measures/utils.ts b/server/sonar-web/src/main/js/apps/component-measures/utils.ts
index 74befd184f0..26b41a1a503 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/utils.ts
+++ b/server/sonar-web/src/main/js/apps/component-measures/utils.ts
@@ -25,10 +25,13 @@ import {
ComponentMeasure,
ComponentMeasureEnhanced,
Metric,
- MeasureEnhanced
+ MeasureEnhanced,
+ BranchLike
} from '../../app/types';
import { enhanceMeasure } from '../../components/measure/utils';
import { cleanQuery, parseAsString, RawQuery, serializeString } from '../../helpers/query';
+import { isLongLivingBranch, isMainBranch } from '../../helpers/branches';
+import { getDisplayMetrics } from '../../helpers/measures';
export const PROJECT_OVERVEW = 'project_overview';
export const DEFAULT_VIEW = 'list';
@@ -146,13 +149,33 @@ export function hasTreemap(metric: string, type: string): boolean {
}
export function hasBubbleChart(domainName: string): boolean {
- return bubbles[domainName] != null;
+ return bubbles[domainName] !== undefined;
}
export function hasFacetStat(metric: string): boolean {
return metric !== 'alert_status';
}
+export function hasFullMeasures(branch?: BranchLike) {
+ return !branch || isLongLivingBranch(branch) || isMainBranch(branch);
+}
+
+export function getMeasuresPageMetricKeys(metrics: { [key: string]: Metric }, branch?: BranchLike) {
+ if (!hasFullMeasures(branch)) {
+ return [
+ 'new_coverage',
+ 'new_lines_to_cover',
+ 'new_uncovered_lines',
+ 'new_line_coverage',
+ 'new_conditions_to_cover',
+ 'new_uncovered_conditions',
+ 'new_branch_coverage'
+ ];
+ }
+
+ return getDisplayMetrics(Object.values(metrics)).map(metric => metric.key);
+}
+
export function getBubbleMetrics(domain: string, metrics: { [key: string]: Metric }) {
const conf = bubbles[domain];
return {
@@ -182,7 +205,7 @@ const parseView = (metric: string, rawView?: string) => {
};
export interface Query {
- metric?: string;
+ metric: string;
selected?: string;
view: string;
}