aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-web/design-system/src/components/Badge.tsx7
-rw-r--r--server/sonar-web/design-system/src/components/__tests__/Badge-test.tsx10
-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
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties4
10 files changed, 73 insertions, 30 deletions
diff --git a/server/sonar-web/design-system/src/components/Badge.tsx b/server/sonar-web/design-system/src/components/Badge.tsx
index 54ed4d62289..1746a417d0c 100644
--- a/server/sonar-web/design-system/src/components/Badge.tsx
+++ b/server/sonar-web/design-system/src/components/Badge.tsx
@@ -32,8 +32,7 @@ const variantList: Record<BadgeVariant, ThemeColors> = {
counterFailed: 'badgeCounterFailed',
};
-interface BadgeProps {
- children: string | number;
+interface BadgeProps extends React.PropsWithChildren {
className?: string;
title?: string;
variant?: BadgeVariant;
@@ -41,9 +40,9 @@ interface BadgeProps {
export function Badge({ className, children, title, variant = 'default' }: BadgeProps) {
const commonProps = {
- 'aria-label': title ?? children.toString(),
+ 'aria-label': title,
className,
- role: 'status',
+ role: title ? 'img' : 'presentation',
title,
};
diff --git a/server/sonar-web/design-system/src/components/__tests__/Badge-test.tsx b/server/sonar-web/design-system/src/components/__tests__/Badge-test.tsx
index 97f901852d8..5429ccc2a16 100644
--- a/server/sonar-web/design-system/src/components/__tests__/Badge-test.tsx
+++ b/server/sonar-web/design-system/src/components/__tests__/Badge-test.tsx
@@ -23,10 +23,14 @@ import { Badge } from '../Badge';
it('renders badge correctly', () => {
render(<Badge>foo</Badge>);
- expect(screen.getByRole('status')).toBeInTheDocument();
+ expect(screen.getByText('foo')).toBeInTheDocument();
});
it('renders counter correctly', () => {
- render(<Badge variant="counter">23</Badge>);
- expect(screen.getByRole('status')).toHaveAttribute('aria-label', '23');
+ render(
+ <Badge title="This 23" variant="counter">
+ 23
+ </Badge>,
+ );
+ expect(screen.getByRole('img')).toHaveAccessibleName('This 23');
});
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 () => {
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index 8286d2f65aa..2e222a4f985 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -3930,7 +3930,7 @@ overview.accepted_issues.total=Total accepted issues
overview.high_impact_accepted_issues=High impact accepted issues
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.same_reference.explanation=This branch is configured to use itself as reference branch. It will never have New Code.
+overview.measures.same_reference.explanation=This branch is configured to use itself as a reference branch. It will never have New Code.
overview.measures.bad_reference.explanation=This branch could not be compared to its reference branch. See the SCM or analysis report for more details.
overview.measures.bad_setting.link=This can be fixed in the {setting_link} setting.
overview.measures.security_hotspots_reviewed=Reviewed
@@ -4018,7 +4018,7 @@ overview.sonarlint_ad.details_3=Repair flagged issues in real-time with quick fi
overview.sonarlint_ad.details_4=12 major IDE's supported (including key JetBrains and Microsoft IDE's
overview.sonarlint_ad.details_5=Free forever
overview.sonarlint_ad.learn_more=Learn more about SonarLint
-overview.sonarlint_ad.close_promotion=Close SonarLint romotion
+overview.sonarlint_ad.close_promotion=Close SonarLint promotion
overview.badges.get_badge=Badges
overview.badges.title=Get project badges