aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web/src/main')
-rw-r--r--server/sonar-web/src/main/js/apps/overview/branches/OverallCodeMeasuresPanel.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx21
-rw-r--r--server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx17
-rw-r--r--server/sonar-web/src/main/js/apps/overview/branches/test-utils.ts9
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx28
-rw-r--r--server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx2
7 files changed, 61 insertions, 21 deletions
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/OverallCodeMeasuresPanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/OverallCodeMeasuresPanel.tsx
index 5530d595dac..d0ab2c0b250 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/OverallCodeMeasuresPanel.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/branches/OverallCodeMeasuresPanel.tsx
@@ -70,6 +70,7 @@ export default function OverallCodeMeasuresPanel(props: Readonly<OverallCodeMeas
<SoftwareImpactMeasureCard
branch={branch}
component={component}
+ conditions={conditions}
softwareQuality={SoftwareQuality.Security}
ratingMetricKey={MetricKey.security_rating}
measures={measures}
@@ -77,6 +78,7 @@ export default function OverallCodeMeasuresPanel(props: Readonly<OverallCodeMeas
<SoftwareImpactMeasureCard
branch={branch}
component={component}
+ conditions={conditions}
softwareQuality={SoftwareQuality.Reliability}
ratingMetricKey={MetricKey.reliability_rating}
measures={measures}
@@ -84,6 +86,7 @@ export default function OverallCodeMeasuresPanel(props: Readonly<OverallCodeMeas
<SoftwareImpactMeasureCard
branch={branch}
component={component}
+ conditions={conditions}
softwareQuality={SoftwareQuality.Maintainability}
ratingMetricKey={MetricKey.sqale_rating}
measures={measures}
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx b/server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx
index 9115a05f775..b98ec5f9d90 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/branches/SoftwareImpactMeasureCard.tsx
@@ -20,9 +20,9 @@
import styled from '@emotion/styled';
import { LinkHighlight, LinkStandalone } from '@sonarsource/echoes-react';
import classNames from 'classnames';
-import { BasicSeparator, LightGreyCard, TextBold, TextSubdued } from 'design-system';
+import { Badge, BasicSeparator, LightGreyCard, TextBold, TextSubdued } from 'design-system';
import * as React from 'react';
-import { useIntl } from 'react-intl';
+import { FormattedMessage, useIntl } from 'react-intl';
import Tooltip from '../../../components/controls/Tooltip';
import { DEFAULT_ISSUES_QUERY } from '../../../components/shared/utils';
import {
@@ -39,14 +39,16 @@ import {
SoftwareQuality,
} from '../../../types/clean-code-taxonomy';
import { MetricKey, MetricType } from '../../../types/metrics';
+import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates';
import { Component, MeasureEnhanced } from '../../../types/types';
import { OverviewDisabledLinkTooltip } from '../components/OverviewDisabledLinkTooltip';
-import { softwareQualityToMeasure } from '../utils';
+import { Status, softwareQualityToMeasure } from '../utils';
import SoftwareImpactMeasureBreakdownCard from './SoftwareImpactMeasureBreakdownCard';
import SoftwareImpactMeasureRating from './SoftwareImpactMeasureRating';
export interface SoftwareImpactBreakdownCardProps {
component: Component;
+ conditions: QualityGateStatusConditionEnhanced[];
softwareQuality: SoftwareQuality;
ratingMetricKey: MetricKey;
measures: MeasureEnhanced[];
@@ -54,7 +56,7 @@ export interface SoftwareImpactBreakdownCardProps {
}
export function SoftwareImpactMeasureCard(props: Readonly<SoftwareImpactBreakdownCardProps>) {
- const { component, softwareQuality, ratingMetricKey, measures, branch } = props;
+ const { component, conditions, softwareQuality, ratingMetricKey, measures, branch } = props;
const intl = useIntl();
@@ -92,12 +94,21 @@ export function SoftwareImpactMeasureCard(props: Readonly<SoftwareImpactBreakdow
intl.formatMessage({ id: 'overview.measures.software_impact.count_tooltip' })
);
+ const failed = conditions.some((c) => c.level === Status.ERROR && c.metric === ratingMetricKey);
+
return (
<LightGreyCard
data-testid={`overview__software-impact-card-${softwareQuality}`}
className="sw-w-1/3 sw-overflow-hidden sw-rounded-2 sw-p-4 sw-flex-col"
>
- <TextBold name={intl.formatMessage({ id: `software_quality.${softwareQuality}` })} />
+ <div className="sw-flex sw-justify-between">
+ <TextBold name={intl.formatMessage({ id: `software_quality.${softwareQuality}` })} />
+ {failed && (
+ <Badge className="sw-h-fit" variant="deleted">
+ <FormattedMessage id="overview.measures.failed_badge" />
+ </Badge>
+ )}
+ </div>
<BasicSeparator className="sw--mx-4" />
<div className="sw-flex sw-flex-col sw-gap-3">
<div className="sw-flex sw-mt-2">
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx
index c76a55708f3..45dddc7b81e 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/ActivityPanel-it.tsx
@@ -46,7 +46,7 @@ it('should render correctly', async () => {
expect(await screen.findAllByText('metric.level.ERROR')).toHaveLength(2);
expect(screen.getAllByText('metric.level.OK')).toHaveLength(2);
- expect(screen.getByRole('status', { name: 'v1.0' })).toBeInTheDocument();
+ expect(screen.getByText('v1.0')).toBeInTheDocument();
expect(screen.getByText(/event.category.OTHER/)).toBeInTheDocument();
expect(screen.getByText(/event.category.DEFINITION_CHANGE/)).toBeInTheDocument();
expect(screen.getByText('event.sqUpgrade10.2')).toBeInTheDocument();
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx
index d4ffff4011f..8a7067c81d2 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-it.tsx
@@ -262,6 +262,21 @@ describe('project overview', () => {
// eslint-disable-next-line jest/expect-expect
it('should render software impact measure cards', async () => {
+ qualityGatesHandler.setQualityGateProjectStatus(
+ mockQualityGateProjectStatus({
+ status: 'ERROR',
+ conditions: [
+ {
+ actualValue: '2',
+ comparator: 'GT',
+ errorThreshold: '1',
+ metricKey: MetricKey.reliability_rating,
+ periodIndex: 1,
+ status: 'ERROR',
+ },
+ ],
+ }),
+ );
const { user, ui } = getPageObjects();
renderBranchOverview();
@@ -288,6 +303,8 @@ describe('project overview', () => {
[SoftwareImpactSeverity.Low]: 1,
},
[false, true, false],
+ undefined,
+ true,
);
ui.expectSoftwareImpactMeasureCard(
SoftwareQuality.Maintainability,
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/test-utils.ts b/server/sonar-web/src/main/js/apps/overview/branches/test-utils.ts
index 21925f6e066..17914108eeb 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/test-utils.ts
+++ b/server/sonar-web/src/main/js/apps/overview/branches/test-utils.ts
@@ -40,7 +40,16 @@ export const getPageObjects = () => {
data?: SoftwareImpactMeasureData,
severitiesActiveState?: boolean[],
branch = 'master',
+ failed = false,
) => {
+ if (failed) {
+ expect(
+ byTestId(`overview__software-impact-card-${softwareQuality}`)
+ .byText('overview.measures.failed_badge')
+ .get(),
+ ).toBeInTheDocument();
+ }
+
if (typeof rating === 'string') {
expect(
byText(rating, { exact: true }).get(ui.softwareImpactMeasureCard(softwareQuality).get()),
diff --git a/server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx b/server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx
index 3167be6de62..a81aab52c17 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx
@@ -65,7 +65,7 @@ it('should display tags', async () => {
it('should display private badge', () => {
const project: Project = { ...PROJECT, visibility: Visibility.Private };
renderProjectCard(project);
- expect(screen.getByLabelText('visibility.private')).toBeInTheDocument();
+ expect(screen.getByText('visibility.private')).toBeInTheDocument();
});
it('should display configure analysis button for logged in user and scan rights', () => {
@@ -81,7 +81,7 @@ it('should not display configure analysis button for logged in user and without
it('should display applications', () => {
renderProjectCard({ ...PROJECT, qualifier: ComponentQualifier.Application });
- expect(screen.getByLabelText('qualifier.APP')).toBeInTheDocument();
+ expect(screen.getAllByText('qualifier.APP')).toHaveLength(2);
});
it('should not display awaiting analysis badge and do not display old measures', () => {
@@ -97,7 +97,7 @@ it('should not display awaiting analysis badge and do not display old measures',
[MetricKey.vulnerabilities]: '6',
},
});
- expect(screen.queryByRole('status', { name: 'projects.awaiting_scan' })).not.toBeInTheDocument();
+ expect(screen.queryByText('projects.awaiting_scan')).not.toBeInTheDocument();
expect(screen.getByText('1')).toBeInTheDocument();
expect(screen.getByText('2')).toBeInTheDocument();
expect(screen.getByText('3')).toBeInTheDocument();
@@ -116,10 +116,10 @@ it('should display awaiting analysis badge and show the old measures', async ()
[MetricKey.vulnerabilities]: '6',
},
});
- expect(screen.getByRole('status', { name: 'projects.awaiting_scan' })).toBeInTheDocument();
- await expect(
- screen.getByRole('status', { name: 'projects.awaiting_scan' }),
- ).toHaveATooltipWithContent('projects.awaiting_scan.description.TRK');
+ expect(screen.getByText('projects.awaiting_scan')).toBeInTheDocument();
+ await expect(screen.getByText('projects.awaiting_scan')).toHaveATooltipWithContent(
+ 'projects.awaiting_scan.description.TRK',
+ );
expect(screen.getByText('4')).toBeInTheDocument();
expect(screen.getByText('5')).toBeInTheDocument();
expect(screen.getByText('6')).toBeInTheDocument();
@@ -136,10 +136,10 @@ it('should display awaiting analysis badge and show the old measures for Applica
[MetricKey.vulnerabilities]: '6',
},
});
- expect(screen.getByRole('status', { name: 'projects.awaiting_scan' })).toBeInTheDocument();
- await expect(
- screen.getByRole('status', { name: 'projects.awaiting_scan' }),
- ).toHaveATooltipWithContent('projects.awaiting_scan.description.APP');
+ expect(screen.getByText('projects.awaiting_scan')).toBeInTheDocument();
+ await expect(screen.getByText('projects.awaiting_scan')).toHaveATooltipWithContent(
+ 'projects.awaiting_scan.description.APP',
+ );
expect(screen.getByText('4')).toBeInTheDocument();
expect(screen.getByText('5')).toBeInTheDocument();
expect(screen.getByText('6')).toBeInTheDocument();
@@ -150,7 +150,7 @@ it('should not display awaiting analysis badge if project is not analyzed', () =
...PROJECT,
analysisDate: undefined,
});
- expect(screen.queryByRole('status', { name: 'projects.awaiting_scan' })).not.toBeInTheDocument();
+ expect(screen.queryByText('projects.awaiting_scan')).not.toBeInTheDocument();
});
it('should not display awaiting analysis badge if project does not have lines of code', () => {
@@ -160,12 +160,12 @@ it('should not display awaiting analysis badge if project does not have lines of
...(({ [MetricKey.ncloc]: _, ...rest }) => rest)(MEASURES),
},
});
- expect(screen.queryByRole('status', { name: 'projects.awaiting_scan' })).not.toBeInTheDocument();
+ expect(screen.queryByText('projects.awaiting_scan')).not.toBeInTheDocument();
});
it('should not display awaiting analysis badge if it is a new code filter', () => {
renderProjectCard(PROJECT, undefined, 'leak');
- expect(screen.queryByRole('status', { name: 'projects.awaiting_scan' })).not.toBeInTheDocument();
+ expect(screen.queryByText('projects.awaiting_scan')).not.toBeInTheDocument();
});
it('should display 3 aplication', () => {
diff --git a/server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx b/server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx
index d116e14daf8..ce90ff69537 100644
--- a/server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx
+++ b/server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx
@@ -71,7 +71,7 @@ describe('rendering', () => {
it('should render correctly for external rule engines', () => {
renderIssue({ issue: mockIssue(true, { externalRuleEngine: 'ESLINT' }) });
- expect(screen.getByRole('status', { name: 'ESLINT' })).toBeInTheDocument();
+ expect(screen.getByText('ESLINT')).toBeInTheDocument();
});
it('should render the SonarLint icon correctly', async () => {