Browse Source

SONAR-13391 handle missing newcode

tags/8.4.0.35506
Jeremy 4 years ago
parent
commit
31f4bf3727

+ 2
- 3
server/sonar-web/src/main/js/apps/overview/branches/BranchOverview.tsx View File

qgStatuses qgStatuses
} = this.state; } = this.state;


const leakPeriod = component.qualifier === ComponentQualifier.Application ? appLeak : period;

const projectIsEmpty = const projectIsEmpty =
loadingStatus === false && loadingStatus === false &&
(measures === undefined || (measures === undefined ||
return ( return (
<BranchOverviewRenderer <BranchOverviewRenderer
analyses={analyses} analyses={analyses}
appLeak={appLeak}
branchLike={branchLike} branchLike={branchLike}
component={component} component={component}
graph={graph} graph={graph}
leakPeriod={leakPeriod}
loadingHistory={loadingHistory} loadingHistory={loadingHistory}
loadingStatus={loadingStatus} loadingStatus={loadingStatus}
measures={measures} measures={measures}
measuresHistory={measuresHistory} measuresHistory={measuresHistory}
metrics={metrics} metrics={metrics}
onGraphChange={this.handleGraphChange} onGraphChange={this.handleGraphChange}
period={period}
projectIsEmpty={projectIsEmpty} projectIsEmpty={projectIsEmpty}
qgStatuses={qgStatuses} qgStatuses={qgStatuses}
/> />

+ 9
- 3
server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx View File

import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget'; import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget';
import { ApplicationPeriod } from '../../../types/application'; import { ApplicationPeriod } from '../../../types/application';
import { BranchLike } from '../../../types/branch-like'; import { BranchLike } from '../../../types/branch-like';
import { ComponentQualifier } from '../../../types/component';
import { GraphType, MeasureHistory } from '../../../types/project-activity'; import { GraphType, MeasureHistory } from '../../../types/project-activity';
import { QualityGateStatus } from '../../../types/quality-gates'; import { QualityGateStatus } from '../../../types/quality-gates';
import ActivityPanel from './ActivityPanel'; import ActivityPanel from './ActivityPanel';


export interface BranchOverviewRendererProps { export interface BranchOverviewRendererProps {
analyses?: T.Analysis[]; analyses?: T.Analysis[];
appLeak?: ApplicationPeriod;
branchLike?: BranchLike; branchLike?: BranchLike;
component: T.Component; component: T.Component;
graph?: GraphType; graph?: GraphType;
leakPeriod?: T.Period | ApplicationPeriod;
loadingHistory?: boolean; loadingHistory?: boolean;
loadingStatus?: boolean; loadingStatus?: boolean;
measures?: T.MeasureEnhanced[]; measures?: T.MeasureEnhanced[];
measuresHistory?: MeasureHistory[]; measuresHistory?: MeasureHistory[];
metrics?: T.Metric[]; metrics?: T.Metric[];
onGraphChange: (graph: GraphType) => void; onGraphChange: (graph: GraphType) => void;
period?: T.Period;
projectIsEmpty?: boolean; projectIsEmpty?: boolean;
qgStatuses?: QualityGateStatus[]; qgStatuses?: QualityGateStatus[];
} }
export function BranchOverviewRenderer(props: BranchOverviewRendererProps) { export function BranchOverviewRenderer(props: BranchOverviewRendererProps) {
const { const {
analyses, analyses,
appLeak,
branchLike, branchLike,
component, component,
graph, graph,
leakPeriod,
loadingHistory, loadingHistory,
loadingStatus, loadingStatus,
measures, measures,
measuresHistory = [], measuresHistory = [],
metrics = [], metrics = [],
onGraphChange, onGraphChange,
period,
projectIsEmpty, projectIsEmpty,
qgStatuses qgStatuses
} = props; } = props;


const leakPeriod = component.qualifier === ComponentQualifier.Application ? appLeak : period;

return ( return (
<div className="page page-limited"> <div className="page page-limited">
<div className="overview"> <div className="overview">
<div className="flex-1"> <div className="flex-1">
<div className="display-flex-column"> <div className="display-flex-column">
<MeasuresPanel <MeasuresPanel
appLeak={appLeak}
branchLike={branchLike} branchLike={branchLike}
component={component} component={component}
leakPeriod={leakPeriod}
loading={loadingStatus} loading={loadingStatus}
measures={measures} measures={measures}
period={period}
/> />


<ActivityPanel <ActivityPanel

+ 19
- 99
server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanel.tsx View File

* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import * as React from 'react'; import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
import BoxedTabs from 'sonar-ui-common/components/controls/BoxedTabs'; import BoxedTabs from 'sonar-ui-common/components/controls/BoxedTabs';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { translate } from 'sonar-ui-common/helpers/l10n'; import { translate } from 'sonar-ui-common/helpers/l10n';
import { isDiffMetric } from 'sonar-ui-common/helpers/measures'; import { isDiffMetric } from 'sonar-ui-common/helpers/measures';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { rawSizes } from '../../../app/theme'; import { rawSizes } from '../../../app/theme';
import { findMeasure } from '../../../helpers/measures'; import { findMeasure } from '../../../helpers/measures';
import { ApplicationPeriod } from '../../../types/application'; import { ApplicationPeriod } from '../../../types/application';
import { BranchLike } from '../../../types/branch-like'; import { BranchLike } from '../../../types/branch-like';
import { ComponentQualifier } from '../../../types/component'; import { ComponentQualifier } from '../../../types/component';
import { MetricKey } from '../../../types/metrics'; import { MetricKey } from '../../../types/metrics';
import IssueLabel from '../components/IssueLabel';
import IssueRating from '../components/IssueRating';
import MeasurementLabel from '../components/MeasurementLabel'; import MeasurementLabel from '../components/MeasurementLabel';
import { IssueType, MeasurementType } from '../utils'; import { IssueType, MeasurementType } from '../utils';
import DebtValue from './DebtValue';
import { DrilldownMeasureValue } from './DrilldownMeasureValue'; import { DrilldownMeasureValue } from './DrilldownMeasureValue';
import { LeakPeriodInfo } from './LeakPeriodInfo'; import { LeakPeriodInfo } from './LeakPeriodInfo';
import SecurityHotspotsReviewed from './SecurityHotspotsReviewed';
import MeasuresPanelIssueMeasureRow from './MeasuresPanelIssueMeasureRow';
import MeasuresPanelNoNewCode from './MeasuresPanelNoNewCode';


export interface MeasuresPanelProps { export interface MeasuresPanelProps {
appLeak?: ApplicationPeriod;
branchLike?: BranchLike; branchLike?: BranchLike;
component: T.Component; component: T.Component;
leakPeriod?: T.Period | ApplicationPeriod;
loading?: boolean; loading?: boolean;
measures?: T.MeasureEnhanced[]; measures?: T.MeasureEnhanced[];
period?: T.Period;
} }


export enum MeasuresPanelTabs { export enum MeasuresPanelTabs {
} }


export function MeasuresPanel(props: MeasuresPanelProps) { export function MeasuresPanel(props: MeasuresPanelProps) {
const { branchLike, component, loading, leakPeriod, measures = [] } = props;
const { appLeak, branchLike, component, loading, measures = [], period } = props;


const hasDiffMeasures = measures.some(m => isDiffMetric(m.metric.key)); const hasDiffMeasures = measures.some(m => isDiffMetric(m.metric.key));
const isApp = component.qualifier === ComponentQualifier.Application; const isApp = component.qualifier === ComponentQualifier.Application;
const leakPeriod = isApp ? appLeak : period;


const [tab, selectTab] = React.useState(MeasuresPanelTabs.New); const [tab, selectTab] = React.useState(MeasuresPanelTabs.New);




<div className="overview-panel-content flex-1 bordered"> <div className="overview-panel-content flex-1 bordered">
{!hasDiffMeasures && isNewCodeTab ? ( {!hasDiffMeasures && isNewCodeTab ? (
<div
className="display-flex-center display-flex-justify-center"
style={{ height: 500 }}>
<img
alt="" /* Make screen readers ignore this image; it's purely eye candy. */
className="spacer-right"
height={52}
src={`${getBaseUrl()}/images/source-code.svg`}
/>
<div className="big-spacer-left text-muted" style={{ maxWidth: 500 }}>
<p className="spacer-bottom big-spacer-top big">
{translate('overview.measures.empty_explanation')}
</p>
<p>
<FormattedMessage
defaultMessage={translate('overview.measures.empty_link')}
id="overview.measures.empty_link"
values={{
learn_more_link: (
<Link to="/documentation/user-guide/clean-as-you-code/">
{translate('learn_more')}
</Link>
)
}}
/>
</p>
</div>
</div>
<MeasuresPanelNoNewCode
branchLike={branchLike}
component={component}
period={period}
/>
) : ( ) : (
<> <>
{[ {[
IssueType.SecurityHotspot, IssueType.SecurityHotspot,
IssueType.CodeSmell IssueType.CodeSmell
].map((type: IssueType) => ( ].map((type: IssueType) => (
<div
className="display-flex-row overview-measures-row"
data-test={`overview__measures-${type.toString().toLowerCase()}`}
key={type}>
{type === IssueType.CodeSmell ? (
<>
<div className="overview-panel-big-padded flex-1 small display-flex-center big-spacer-left">
<DebtValue
branchLike={branchLike}
component={component}
measures={measures}
useDiffMetric={isNewCodeTab}
/>
</div>
<div className="flex-1 small display-flex-center">
<IssueLabel
branchLike={branchLike}
component={component}
measures={measures}
type={type}
useDiffMetric={isNewCodeTab}
/>
</div>
</>
) : (
<div className="overview-panel-big-padded flex-1 small display-flex-center big-spacer-left">
<IssueLabel
branchLike={branchLike}
component={component}
docTooltip={
type === IssueType.SecurityHotspot
? import(
/* webpackMode: "eager" */ 'Docs/tooltips/metrics/security-hotspots.md'
)
: undefined
}
measures={measures}
type={type}
useDiffMetric={isNewCodeTab}
/>
</div>
)}
{type === IssueType.SecurityHotspot && (
<div className="flex-1 small display-flex-center">
<SecurityHotspotsReviewed
measures={measures}
useDiffMetric={isNewCodeTab}
/>
</div>
)}
{(!isApp || tab === MeasuresPanelTabs.Overall) && (
<div className="overview-panel-big-padded overview-measures-aside display-flex-center">
<IssueRating
branchLike={branchLike}
component={component}
measures={measures}
type={type}
useDiffMetric={isNewCodeTab}
/>
</div>
)}
</div>
<MeasuresPanelIssueMeasureRow
branchLike={branchLike}
component={component}
isNewCodeTab={isNewCodeTab}
key={type}
measures={measures}
type={type}
/>
))} ))}


<div className="display-flex-row overview-measures-row"> <div className="display-flex-row overview-measures-row">

+ 100
- 0
server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanelIssueMeasureRow.tsx View File

/*
* 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 { BranchLike } from '../../../types/branch-like';
import { ComponentQualifier } from '../../../types/component';
import IssueLabel from '../components/IssueLabel';
import IssueRating from '../components/IssueRating';
import { IssueType } from '../utils';
import DebtValue from './DebtValue';
import SecurityHotspotsReviewed from './SecurityHotspotsReviewed';

export interface MeasuresPanelIssueMeasureRowProps {
branchLike?: BranchLike;
component: T.Component;
isNewCodeTab: boolean;
measures: T.MeasureEnhanced[];
type: IssueType;
}

export default function MeasuresPanelIssueMeasureRow(props: MeasuresPanelIssueMeasureRowProps) {
const { branchLike, component, isNewCodeTab, measures, type } = props;

const isApp = component.qualifier === ComponentQualifier.Application;

return (
<div
className="display-flex-row overview-measures-row"
data-test={`overview__measures-${type.toString().toLowerCase()}`}>
{type === IssueType.CodeSmell ? (
<>
<div className="overview-panel-big-padded flex-1 small display-flex-center big-spacer-left">
<DebtValue
branchLike={branchLike}
component={component}
measures={measures}
useDiffMetric={isNewCodeTab}
/>
</div>
<div className="flex-1 small display-flex-center">
<IssueLabel
branchLike={branchLike}
component={component}
measures={measures}
type={type}
useDiffMetric={isNewCodeTab}
/>
</div>
</>
) : (
<div className="overview-panel-big-padded flex-1 small display-flex-center big-spacer-left">
<IssueLabel
branchLike={branchLike}
component={component}
docTooltip={
type === IssueType.SecurityHotspot
? import(/* webpackMode: "eager" */ 'Docs/tooltips/metrics/security-hotspots.md')
: undefined
}
measures={measures}
type={type}
useDiffMetric={isNewCodeTab}
/>
</div>
)}
{type === IssueType.SecurityHotspot && (
<div className="flex-1 small display-flex-center">
<SecurityHotspotsReviewed measures={measures} useDiffMetric={isNewCodeTab} />
</div>
)}
{(!isApp || !isNewCodeTab) && (
<div className="overview-panel-big-padded overview-measures-aside display-flex-center">
<IssueRating
branchLike={branchLike}
component={component}
measures={measures}
type={type}
useDiffMetric={isNewCodeTab}
/>
</div>
)}
</div>
);
}

+ 102
- 0
server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanelNoNewCode.tsx View File

/*
* 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 { Link } from 'react-router';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { getBranchLikeQuery } from '../../../helpers/branch-like';
import { BranchLike } from '../../../types/branch-like';
import { ComponentQualifier } from '../../../types/component';

export interface MeasuresPanelNoNewCodeProps {
branchLike?: BranchLike;
component: T.Component;
period?: T.Period;
}

export default function MeasuresPanelNoNewCode(props: MeasuresPanelNoNewCodeProps) {
const { branchLike, component, period } = props;

const isApp = component.qualifier === ComponentQualifier.Application;
/*
* If the period is "reference branch"-based, and if there's no date, it means
* that we're not lacking a second analysis, but that we'll never have new code because the
* selected reference branch is itself, or has disappeared for some reason.
* Makes no sense for Apps (project aggregate)
*/
const hasBadNewCodeSetting =
!isApp && !!period && !period.date && period.mode === 'REFERENCE_BRANCH';

const showSettingsLink = !!(component.configuration && component.configuration.showSettings);

return (
<div className="display-flex-center display-flex-justify-center" style={{ height: 500 }}>
<img
alt="" /* Make screen readers ignore this image; it's purely eye candy. */
className="spacer-right"
height={52}
src={`${getBaseUrl()}/images/source-code.svg`}
/>
<div className="big-spacer-left text-muted" style={{ maxWidth: 500 }}>
<p className="spacer-bottom big-spacer-top big">
{hasBadNewCodeSetting
? translate('overview.measures.bad_setting.explanation')
: translate('overview.measures.empty_explanation')}
</p>
{hasBadNewCodeSetting ? (
showSettingsLink && (
<p>
<FormattedMessage
defaultMessage={translate('overview.measures.bad_setting.link')}
id="overview.measures.bad_setting.link"
values={{
setting_link: (
<Link
to={{
pathname: '/project/baseline',
query: { id: component.key, ...getBranchLikeQuery(branchLike) }
}}>
{translate('settings.new_code_period.category')}
</Link>
)
}}
/>
</p>
)
) : (
<p>
<FormattedMessage
defaultMessage={translate('overview.measures.empty_link')}
id="overview.measures.empty_link"
values={{
learn_more_link: (
<Link to="/documentation/user-guide/clean-as-you-code/">
{translate('learn_more')}
</Link>
)
}}
/>
</p>
)}
</div>
</div>
);
}

+ 24
- 3
server/sonar-web/src/main/js/apps/overview/branches/__tests__/MeasuresPanel-test.tsx View File

import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import * as React from 'react'; import * as React from 'react';
import BoxedTabs from 'sonar-ui-common/components/controls/BoxedTabs'; import BoxedTabs from 'sonar-ui-common/components/controls/BoxedTabs';
import { mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent, mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { mockBranch, mockMainBranch } from '../../../../helpers/mocks/branch-like';
import {
mockComponent,
mockMeasureEnhanced,
mockMetric,
mockPeriod
} from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component'; import { ComponentQualifier } from '../../../../types/component';
import { MetricKey } from '../../../../types/metrics'; import { MetricKey } from '../../../../types/metrics';
import { MeasuresPanel, MeasuresPanelProps, MeasuresPanelTabs } from '../MeasuresPanel'; import { MeasuresPanel, MeasuresPanelProps, MeasuresPanelTabs } from '../MeasuresPanel';
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });


it('should render correctly if branch is misconfigured', () => {
const wrapper = shallowRender({
branchLike: mockBranch({ name: 'own-reference' }),
measures: [
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) })
],
period: mockPeriod({ date: undefined, mode: 'REFERENCE_BRANCH', parameter: 'own-reference' })
});
wrapper.find(BoxedTabs).prop<Function>('onSelect')(MeasuresPanelTabs.New);
expect(wrapper).toMatchSnapshot('hide settings');

wrapper.setProps({ component: mockComponent({ configuration: { showSettings: true } }) });
expect(wrapper).toMatchSnapshot('show settings');
});

it('should render correctly if there is no coverage', () => { it('should render correctly if there is no coverage', () => {
expect( expect(
shallowRender({ shallowRender({
}); });


function shallowRender(props: Partial<MeasuresPanelProps> = {}) { function shallowRender(props: Partial<MeasuresPanelProps> = {}) {
return shallow(
return shallow<MeasuresPanelProps>(
<MeasuresPanel <MeasuresPanel
branchLike={mockMainBranch()} branchLike={mockMainBranch()}
component={mockComponent()} component={mockComponent()}

+ 62
- 0
server/sonar-web/src/main/js/apps/overview/branches/__tests__/MeasuresPanelIssueMeasureRow-test.tsx View File

/*
* 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 { mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent, mockMeasureEnhanced, mockMetric } from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component';
import { MetricKey } from '../../../../types/metrics';
import { IssueType } from '../../utils';
import MeasuresPanelIssueMeasureRow, {
MeasuresPanelIssueMeasureRowProps
} from '../MeasuresPanelIssueMeasureRow';

it('should render correctly for projects', () => {
expect(shallowRender({ type: IssueType.Bug })).toMatchSnapshot('Bug');
expect(shallowRender({ type: IssueType.CodeSmell })).toMatchSnapshot('Code Smell');
expect(shallowRender({ type: IssueType.SecurityHotspot })).toMatchSnapshot('Hotspot');
expect(shallowRender({ type: IssueType.Vulnerability })).toMatchSnapshot('Vulnerabilty');
expect(shallowRender({ isNewCodeTab: false })).toMatchSnapshot('Overview');
});

it('should render correctly for apps', () => {
const app = mockComponent({ qualifier: ComponentQualifier.Application });

expect(shallowRender({ component: app })).toMatchSnapshot('new code');
expect(shallowRender({ component: app, isNewCodeTab: false })).toMatchSnapshot('overview');
});

function shallowRender(props: Partial<MeasuresPanelIssueMeasureRowProps> = {}) {
return shallow<MeasuresPanelIssueMeasureRowProps>(
<MeasuresPanelIssueMeasureRow
branchLike={mockMainBranch()}
component={mockComponent()}
isNewCodeTab={true}
measures={[
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_coverage }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.bugs }) }),
mockMeasureEnhanced({ metric: mockMetric({ key: MetricKey.new_bugs }) })
]}
type={IssueType.Bug}
{...props}
/>
);
}

+ 101
- 0
server/sonar-web/src/main/js/apps/overview/branches/__tests__/MeasuresPanelNoNewCode-test.tsx View File

/*
* 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 { mockMainBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent, mockPeriod } from '../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../types/component';
import MeasuresPanelNoNewCode, { MeasuresPanelNoNewCodeProps } from '../MeasuresPanelNoNewCode';

it('should render the default message', () => {
const defaultMessage = `
<div
className="display-flex-center display-flex-justify-center"
style={
Object {
"height": 500,
}
}
>
<img
alt=""
className="spacer-right"
height={52}
src="/images/source-code.svg"
/>
<div
className="big-spacer-left text-muted"
style={
Object {
"maxWidth": 500,
}
}
>
<p
className="spacer-bottom big-spacer-top big"
>
overview.measures.empty_explanation
</p>
<p>
<FormattedMessage
defaultMessage="overview.measures.empty_link"
id="overview.measures.empty_link"
values={
Object {
"learn_more_link": <Link
onlyActiveOnIndex={false}
style={Object {}}
to="/documentation/user-guide/clean-as-you-code/"
>
learn_more
</Link>,
}
}
/>
</p>
</div>
</div>
`;

expect(shallowRender()).toMatchInlineSnapshot(defaultMessage);
expect(
shallowRender({ component: mockComponent({ qualifier: ComponentQualifier.Application }) })
).toMatchInlineSnapshot(defaultMessage);
expect(
shallowRender({ period: mockPeriod({ date: '2018-05-23', mode: 'REFERENCE_BRANCH' }) })
).toMatchInlineSnapshot(defaultMessage);
expect(
shallowRender({ period: mockPeriod({ date: '2018-05-23', mode: 'PREVIOUS_VERSION' }) })
).toMatchInlineSnapshot(defaultMessage);
});

it('should render "bad code setting" explanation', () => {
const period = mockPeriod({ date: undefined, mode: 'REFERENCE_BRANCH' });
expect(shallowRender({ period })).toMatchSnapshot('no link');
expect(
shallowRender({ component: mockComponent({ configuration: { showSettings: true } }), period })
).toMatchSnapshot('with link');
});

function shallowRender(props: Partial<MeasuresPanelNoNewCodeProps> = {}) {
return shallow<MeasuresPanelNoNewCodeProps>(
<MeasuresPanelNoNewCode branchLike={mockMainBranch()} component={mockComponent()} {...props} />
);
}

+ 14
- 14
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/BranchOverview-test.tsx.snap View File

}, },
] ]
} }
appLeak={
Object {
"date": "2017-01-05",
"project": "foo",
"projectName": "Foo",
}
}
branchLike={ branchLike={
Object { Object {
"analysisDate": "2018-01-01", "analysisDate": "2018-01-01",
} }
} }
graph="coverage" graph="coverage"
leakPeriod={
Object {
"date": "2017-01-05",
"project": "foo",
"projectName": "Foo",
}
}
loadingHistory={false} loadingHistory={false}
loadingStatus={false} loadingStatus={false}
measures={ measures={
}, },
] ]
} }
appLeak={
Object {
"date": "2017-01-05",
"project": "foo",
"projectName": "Foo",
}
}
branchLike={ branchLike={
Object { Object {
"analysisDate": "2018-01-01", "analysisDate": "2018-01-01",
} }
} }
graph="coverage" graph="coverage"
leakPeriod={
Object {
"date": "2017-01-05",
"project": "foo",
"projectName": "Foo",
}
}
loadingHistory={false} loadingHistory={false}
loadingStatus={false} loadingStatus={false}
measures={ measures={

+ 2920
- 5512
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/MeasuresPanel-test.tsx.snap
File diff suppressed because it is too large
View File


+ 1750
- 0
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/MeasuresPanelIssueMeasureRow-test.tsx.snap
File diff suppressed because it is too large
View File


+ 89
- 0
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/MeasuresPanelNoNewCode-test.tsx.snap View File

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render "bad code setting" explanation: no link 1`] = `
<div
className="display-flex-center display-flex-justify-center"
style={
Object {
"height": 500,
}
}
>
<img
alt=""
className="spacer-right"
height={52}
src="/images/source-code.svg"
/>
<div
className="big-spacer-left text-muted"
style={
Object {
"maxWidth": 500,
}
}
>
<p
className="spacer-bottom big-spacer-top big"
>
overview.measures.bad_setting.explanation
</p>
</div>
</div>
`;

exports[`should render "bad code setting" explanation: with link 1`] = `
<div
className="display-flex-center display-flex-justify-center"
style={
Object {
"height": 500,
}
}
>
<img
alt=""
className="spacer-right"
height={52}
src="/images/source-code.svg"
/>
<div
className="big-spacer-left text-muted"
style={
Object {
"maxWidth": 500,
}
}
>
<p
className="spacer-bottom big-spacer-top big"
>
overview.measures.bad_setting.explanation
</p>
<p>
<FormattedMessage
defaultMessage="overview.measures.bad_setting.link"
id="overview.measures.bad_setting.link"
values={
Object {
"setting_link": <Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/baseline",
"query": Object {
"id": "my-project",
},
}
}
>
settings.new_code_period.category
</Link>,
}
}
/>
</p>
</div>
</div>
`;

+ 3
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

overview.measures=Measures overview.measures=Measures
overview.measures.empty_explanation=Measures on New Code will appear after the second analysis of this branch. overview.measures.empty_explanation=Measures on New Code will appear after the second analysis of this branch.
overview.measures.empty_link={learn_more_link} about the Clean as You Code approach. overview.measures.empty_link={learn_more_link} about the Clean as You Code approach.
overview.measures.bad_setting.explanation=This branch is configured to use itself as reference branch. It will never have New Code.
overview.measures.bad_setting.link=This can be fixed in the {setting_link} setting.
overview.measures.security_hotspots_reviewed=Reviewed overview.measures.security_hotspots_reviewed=Reviewed


overview.project.no_lines_of_code=This project has no lines of code. overview.project.no_lines_of_code=This project has no lines of code.
# New periods (MMF-1579) # New periods (MMF-1579)
overview.period.number_of_days=From last {0} days overview.period.number_of_days=From last {0} days
overview.period.specific_analysis=Since {0} overview.period.specific_analysis=Since {0}
overview.period.reference_branch=Compared to {0}


overview.gate.ERROR=Failed overview.gate.ERROR=Failed
overview.gate.WARN=Warning overview.gate.WARN=Warning

Loading…
Cancel
Save