aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJay <jeremy.davis@sonarsource.com>2023-12-08 17:09:43 +0100
committersonartech <sonartech@sonarsource.com>2023-12-08 20:03:05 +0000
commit99f771c79563dcb26fbf71cee8a6da2deab7ee8f (patch)
treee26ce017553fd4b9a8639a02a876e9fbf59c17a1 /server
parentf2624c272d3bcea46540937ea6bddb7d691683f0 (diff)
downloadsonarqube-99f771c79563dcb26fbf71cee8a6da2deab7ee8f.tar.gz
sonarqube-99f771c79563dcb26fbf71cee8a6da2deab7ee8f.zip
SONAR-21215 Update PR Overview UI
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/BranchQualityGateConditions.tsx21
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/__tests__/BranchQualityGate-it.tsx8
-rw-r--r--server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCard.tsx (renamed from server/sonar-web/src/main/js/apps/overview/branches/MeasuresCard.tsx)29
-rw-r--r--server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardNumber.tsx (renamed from server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardNumber.tsx)54
-rw-r--r--server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx (renamed from server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardPanel.tsx)35
-rw-r--r--server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPercent.tsx (renamed from server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardPercent.tsx)55
-rw-r--r--server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx24
-rw-r--r--server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx4
8 files changed, 113 insertions, 117 deletions
diff --git a/server/sonar-web/src/main/js/apps/overview/components/BranchQualityGateConditions.tsx b/server/sonar-web/src/main/js/apps/overview/components/BranchQualityGateConditions.tsx
index 22b53b8a9ee..9d0759ccf10 100644
--- a/server/sonar-web/src/main/js/apps/overview/components/BranchQualityGateConditions.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/components/BranchQualityGateConditions.tsx
@@ -18,7 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { ChevronRightIcon, DangerButtonSecondary } from 'design-system';
+import styled from '@emotion/styled';
+import { Badge, ButtonSecondary, themeColor } from 'design-system';
import React from 'react';
import { useIntl } from 'react-intl';
import {
@@ -27,7 +28,7 @@ import {
propsToIssueParams,
} from '../../../components/shared/utils';
import { getBranchLikeQuery } from '../../../helpers/branch-like';
-import { getLocalizedMetricName } from '../../../helpers/l10n';
+import { getLocalizedMetricName, translate } from '../../../helpers/l10n';
import { formatMeasure, getShortType, isDiffMetric } from '../../../helpers/measures';
import {
getComponentDrilldownUrl,
@@ -78,10 +79,14 @@ function FailedQGCondition(
const url = getQGConditionUrl(component.key, condition, branchLike);
return (
- <DangerButtonSecondary className="sw-px-2 sw-py-1 sw-rounded-1/2 sw-body-sm" to={url}>
- <FailedMetric condition={condition} />
- <ChevronRightIcon className="sw-ml-1" />
- </DangerButtonSecondary>
+ <ButtonSecondary className="sw-px-2 sw-py-1 sw-rounded-1/2 sw-body-sm" to={url}>
+ <Badge className="sw-mr-2" variant="deleted">
+ {translate('overview.measures.failed_badge')}
+ </Badge>
+ <SpanDanger>
+ <FailedMetric condition={condition} />
+ </SpanDanger>
+ </ButtonSecondary>
);
}
@@ -209,3 +214,7 @@ function getQGConditionUrl(
listView: true,
});
}
+
+const SpanDanger = styled.span`
+ color: ${themeColor('danger')};
+`;
diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/BranchQualityGate-it.tsx b/server/sonar-web/src/main/js/apps/overview/components/__tests__/BranchQualityGate-it.tsx
index 1731d8793db..5bbb4be19c4 100644
--- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/BranchQualityGate-it.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/BranchQualityGate-it.tsx
@@ -34,7 +34,7 @@ it('renders failed QG', () => {
// Maintainability rating condition
const maintainabilityRatingLink = byRole('link', {
- name: 'overview.failed_condition.x_rating_requiredmetric_domain.Maintainability metric.type.ratingE A',
+ name: 'overview.measures.failed_badge overview.failed_condition.x_rating_requiredmetric_domain.Maintainability metric.type.ratingE A',
}).get();
expect(maintainabilityRatingLink).toBeInTheDocument();
expect(maintainabilityRatingLink).toHaveAttribute(
@@ -44,7 +44,7 @@ it('renders failed QG', () => {
// Security Hotspots rating condition
const securityHotspotsRatingLink = byRole('link', {
- name: 'overview.failed_condition.x_rating_requiredmetric_domain.Security Review metric.type.ratingE A',
+ name: 'overview.measures.failed_badge overview.failed_condition.x_rating_requiredmetric_domain.Security Review metric.type.ratingE A',
}).get();
expect(securityHotspotsRatingLink).toBeInTheDocument();
expect(securityHotspotsRatingLink).toHaveAttribute(
@@ -54,7 +54,7 @@ it('renders failed QG', () => {
// New code smells
const codeSmellsLink = byRole('link', {
- name: 'overview.failed_condition.x_required 5 Code Smells ≤ 1',
+ name: 'overview.measures.failed_badge overview.failed_condition.x_required 5 Code Smells ≤ 1',
}).get();
expect(codeSmellsLink).toBeInTheDocument();
expect(codeSmellsLink).toHaveAttribute(
@@ -64,7 +64,7 @@ it('renders failed QG', () => {
// Conditions to cover
const conditionToCoverLink = byRole('link', {
- name: 'overview.failed_condition.x_required 5 Conditions to cover ≥ 10',
+ name: 'overview.measures.failed_badge overview.failed_condition.x_required 5 Conditions to cover ≥ 10',
}).get();
expect(conditionToCoverLink).toBeInTheDocument();
expect(conditionToCoverLink).toHaveAttribute(
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresCard.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCard.tsx
index 7539c92037a..ae195fceafd 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresCard.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCard.tsx
@@ -18,8 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import styled from '@emotion/styled';
-import classNames from 'classnames';
-import { Card, ContentLink, PageContentFontWrapper, themeColor } from 'design-system';
+import { Badge, Card, ContentLink, themeColor } from 'design-system';
import * as React from 'react';
import { To } from 'react-router-dom';
import { translate, translateWithParameters } from '../../../helpers/l10n';
@@ -41,16 +40,11 @@ export default function MeasuresCard(
const { failed, children, metric, icon, value, url, label, ...rest } = props;
return (
- <StyledCard
- className={classNames(
- 'sw-h-fit sw-p-8 sw-rounded-2 sw-flex sw-justify-between sw-items-center sw-text-base',
- {
- failed,
- },
- )}
+ <Card
+ className="sw-h-fit sw-p-8 sw-rounded-2 sw-flex sw-justify-between sw-items-center sw-text-base"
{...rest}
>
- <PageContentFontWrapper className="sw-flex sw-flex-col sw-gap-1 sw-justify-between">
+ <div className="sw-flex sw-flex-col sw-gap-1 sw-justify-between">
<div className="sw-flex sw-items-center sw-gap-2 sw-font-semibold">
{value ? (
<ContentLink
@@ -68,21 +62,20 @@ export default function MeasuresCard(
<StyledNoValue> — </StyledNoValue>
)}
{translate(label)}
+ {failed && (
+ <Badge className="sw-mt-1/2" variant="deleted">
+ {translate('overview.measures.failed_badge')}
+ </Badge>
+ )}
</div>
{children && <div className="sw-flex sw-flex-col">{children}</div>}
- </PageContentFontWrapper>
+ </div>
{icon && <div>{icon}</div>}
- </StyledCard>
+ </Card>
);
}
const StyledNoValue = styled.span`
color: ${themeColor('pageTitle')};
`;
-
-export const StyledCard = styled(Card)`
- &.failed {
- border-color: ${themeColor('qgCardFailed')};
- }
-`;
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardNumber.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardNumber.tsx
index 340dc2863c9..7f905c97b9e 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardNumber.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardNumber.tsx
@@ -17,53 +17,65 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { TextError } from 'design-system';
+import { LightLabel, TextError } from 'design-system';
import * as React from 'react';
+import { useIntl } from 'react-intl';
import { To } from 'react-router-dom';
import { formatMeasure } from '../../../helpers/measures';
import { MetricKey, MetricType } from '../../../types/metrics';
import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates';
+import { Status } from '../utils';
import MeasuresCard from './MeasuresCard';
interface Props {
- failedConditions: QualityGateStatusConditionEnhanced[];
+ conditions: QualityGateStatusConditionEnhanced[];
label: string;
url: To;
value: string;
- failingConditionMetric: MetricKey;
- requireLabel: string;
+ conditionMetric: MetricKey;
guidingKeyOnError?: string;
}
export default function MeasuresCardNumber(
props: React.PropsWithChildren<Props & React.HTMLAttributes<HTMLDivElement>>,
) {
- const {
- label,
- value,
- failedConditions,
- url,
- failingConditionMetric,
- requireLabel,
- guidingKeyOnError,
- ...rest
- } = props;
+ const { label, value, conditions, url, conditionMetric, guidingKeyOnError, ...rest } = props;
- const failed = Boolean(
- failedConditions.find((condition) => condition.metric === failingConditionMetric),
- );
+ const intl = useIntl();
+
+ const condition = conditions.find((condition) => condition.metric === conditionMetric);
+
+ const conditionFailed = condition?.level === Status.ERROR;
+
+ const requireLabel =
+ condition &&
+ intl.formatMessage(
+ { id: 'overview.quality_gate.required_x' },
+ {
+ operator: condition.op === 'GT' ? '≤' : '≥',
+ value: formatMeasure(condition.error, MetricType.Percent, {
+ decimals: 2,
+ omitExtraDecimalZeros: true,
+ }),
+ },
+ );
return (
<MeasuresCard
url={url}
value={formatMeasure(value, MetricType.ShortInteger)}
- metric={failingConditionMetric}
+ metric={conditionMetric}
label={label}
- failed={failed}
- data-guiding-id={failed ? guidingKeyOnError : undefined}
+ failed={conditionFailed}
+ data-guiding-id={conditionFailed ? guidingKeyOnError : undefined}
{...rest}
>
- {failed && <TextError className="sw-font-regular sw-mt-2" text={requireLabel} />}
+ {requireLabel &&
+ (conditionFailed ? (
+ <TextError className="sw-mt-2 sw-font-regular" text={requireLabel} />
+ ) : (
+ <LightLabel className="sw-mt-2">{requireLabel}</LightLabel>
+ ))}
</MeasuresCard>
);
}
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardPanel.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx
index a909f2d2ed2..5f116e4c822 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardPanel.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx
@@ -19,7 +19,6 @@
*/
import classNames from 'classnames';
import * as React from 'react';
-import { useIntl } from 'react-intl';
import { getLeakValue } from '../../../components/measure/utils';
import { DEFAULT_ISSUES_QUERY } from '../../../components/shared/utils';
import { getBranchLikeQuery } from '../../../helpers/branch-like';
@@ -42,13 +41,11 @@ interface Props {
branchLike?: BranchLike;
component: Component;
measures: MeasureEnhanced[];
- failedConditions: QualityGateStatusConditionEnhanced[];
+ conditions: QualityGateStatusConditionEnhanced[];
}
export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>) {
- const { branchLike, component, measures, failedConditions, className } = props;
-
- const intl = useIntl();
+ const { branchLike, component, measures, conditions, className } = props;
const newViolations = getLeakValue(findMeasure(measures, MetricKey.new_violations)) as string;
const newSecurityHotspots = getLeakValue(
@@ -66,14 +63,8 @@ export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>)
...DEFAULT_ISSUES_QUERY,
})}
value={newViolations}
- failedConditions={failedConditions}
- failingConditionMetric={MetricKey.new_violations}
- requireLabel={intl.formatMessage(
- { id: 'overview.quality_gate.require_fixing' },
- {
- count: newViolations,
- },
- )}
+ conditions={conditions}
+ conditionMetric={MetricKey.new_violations}
guidingKeyOnError="overviewZeroNewIssuesSimplification"
/>
@@ -88,8 +79,8 @@ export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>)
branchLike,
listView: true,
})}
- failedConditions={failedConditions}
- failingConditionMetric={MetricKey.new_coverage}
+ conditions={conditions}
+ conditionMetric={MetricKey.new_coverage}
newLinesMetric={MetricKey.new_lines_to_cover}
afterMergeMetric={MetricKey.coverage}
measures={measures}
@@ -107,14 +98,8 @@ export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>)
...getBranchLikeQuery(branchLike),
})}
value={newSecurityHotspots}
- failedConditions={failedConditions}
- failingConditionMetric={MetricKey.new_security_hotspots_reviewed}
- requireLabel={intl.formatMessage(
- { id: 'overview.quality_gate.require_reviewing' },
- {
- count: newSecurityHotspots,
- },
- )}
+ conditions={conditions}
+ conditionMetric={MetricKey.new_security_hotspots_reviewed}
/>
<MeasuresCardPercent
@@ -128,8 +113,8 @@ export default function MeasuresCardPanel(props: React.PropsWithChildren<Props>)
branchLike,
listView: true,
})}
- failedConditions={failedConditions}
- failingConditionMetric={MetricKey.new_duplicated_lines_density}
+ conditions={conditions}
+ conditionMetric={MetricKey.new_duplicated_lines_density}
newLinesMetric={MetricKey.new_lines}
afterMergeMetric={MetricKey.duplicated_lines_density}
measures={measures}
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardPercent.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPercent.tsx
index fed7c608dc3..a7a9a16172a 100644
--- a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresCardPercent.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPercent.tsx
@@ -35,7 +35,7 @@ import { BranchLike } from '../../../types/branch-like';
import { MetricKey, MetricType } from '../../../types/metrics';
import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates';
import { MeasureEnhanced } from '../../../types/types';
-import { MeasurementType, getMeasurementMetricKey } from '../utils';
+import { MeasurementType, Status, getMeasurementMetricKey } from '../utils';
import MeasuresCard from './MeasuresCard';
interface Props {
@@ -45,8 +45,8 @@ interface Props {
label: string;
url: To;
measures: MeasureEnhanced[];
- failedConditions: QualityGateStatusConditionEnhanced[];
- failingConditionMetric: MetricKey;
+ conditions: QualityGateStatusConditionEnhanced[];
+ conditionMetric: MetricKey;
newLinesMetric: MetricKey;
afterMergeMetric: MetricKey;
}
@@ -61,8 +61,8 @@ export default function MeasuresCardPercent(
label,
url,
measures,
- failedConditions,
- failingConditionMetric,
+ conditions,
+ conditionMetric,
newLinesMetric,
afterMergeMetric,
} = props;
@@ -87,27 +87,21 @@ export default function MeasuresCardPercent(
const afterMergeValue = findMeasure(measures, afterMergeMetric)?.value;
- const failedCondition = failedConditions.find(
- (condition) => condition.metric === failingConditionMetric,
- );
+ const condition = conditions.find((c) => c.metric === conditionMetric);
+ const conditionFailed = condition?.level === Status.ERROR;
- let errorRequireLabel = '';
- if (failedCondition) {
- errorRequireLabel = intl.formatMessage(
+ const requireLabel =
+ condition &&
+ intl.formatMessage(
{ id: 'overview.quality_gate.required_x' },
{
- operator: failedCondition.op === 'GT' ? '≤' : '≥',
- value: formatMeasure(
- failedCondition.level === 'ERROR' ? failedCondition.error : failedCondition.warning,
- MetricType.Percent,
- {
- decimals: 2,
- omitExtraDecimalZeros: true,
- },
- ),
+ operator: condition.op === 'GT' ? '≤' : '≥',
+ value: formatMeasure(condition.error, MetricType.Percent, {
+ decimals: 2,
+ omitExtraDecimalZeros: true,
+ }),
},
);
- }
return (
<MeasuresCard
@@ -115,11 +109,18 @@ export default function MeasuresCardPercent(
metric={metricKey}
url={url}
label={label}
- failed={Boolean(failedCondition)}
+ failed={conditionFailed}
icon={renderIcon(measurementType, value)}
>
- <div className="sw-flex sw-flex-col">
- <LightLabel className="sw-flex sw-items-center sw-gap-1">
+ <>
+ {requireLabel &&
+ (conditionFailed ? (
+ <TextError className="sw-mt-2 sw-font-regular" text={requireLabel} />
+ ) : (
+ <LightLabel className="sw-mt-2">{requireLabel}</LightLabel>
+ ))}
+
+ <LightLabel className="sw-flex sw-items-center sw-gap-1 sw-mt-4">
<FormattedMessage
defaultMessage={translate(newLinesLabel)}
id={newLinesLabel}
@@ -152,11 +153,7 @@ export default function MeasuresCardPercent(
/>
</LightLabel>
)}
-
- {failedCondition && (
- <TextError className="sw-mt-2 sw-font-regular" text={errorRequireLabel} />
- )}
- </div>
+ </>
</MeasuresCard>
);
}
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
index 5c0d965b20c..40cc145f709 100644
--- a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { BasicSeparator, CenteredLayout, Spinner } from 'design-system';
+import { BasicSeparator, CenteredLayout, PageContentFontWrapper, Spinner } from 'design-system';
import { uniq } from 'lodash';
import * as React from 'react';
import { useEffect, useState } from 'react';
@@ -29,13 +29,13 @@ import { isDefined } from '../../../helpers/types';
import { useBranchStatusQuery } from '../../../queries/branch';
import { PullRequest } from '../../../types/branch-like';
import { Component, MeasureEnhanced, QualityGate } from '../../../types/types';
-import MeasuresCardPanel from '../branches/MeasuresCardPanel';
import BranchQualityGate from '../components/BranchQualityGate';
import IgnoredConditionWarning from '../components/IgnoredConditionWarning';
import MetaTopBar from '../components/MetaTopBar';
import ZeroNewIssuesSimplificationGuide from '../components/ZeroNewIssuesSimplificationGuide';
import '../styles.css';
import { PR_METRICS, Status } from '../utils';
+import MeasuresCardPanel from './MeasuresCardPanel';
import SonarLintAd from './SonarLintAd';
interface Props {
@@ -60,11 +60,8 @@ export default function PullRequestOverview(props: Props) {
const metricKeys =
conditions !== undefined
- ? // Also load metrics that apply to failing QG conditions.
- uniq([
- ...PR_METRICS,
- ...conditions.filter((c) => c.level !== Status.OK).map((c) => c.metric),
- ])
+ ? // Also load metrics that apply to QG conditions.
+ uniq([...PR_METRICS, ...conditions.map((c) => c.metric)])
: PR_METRICS;
getMeasuresWithMetrics(component.key, metricKeys, getBranchLikeQuery(branchLike)).then(
@@ -108,14 +105,17 @@ export default function PullRequestOverview(props: Props) {
return null;
}
- const failedConditions = conditions
- .filter((condition) => condition.level === Status.ERROR)
+ const enhancedConditions = conditions
.map((c) => enhanceConditionWithMeasure(c, measures))
.filter(isDefined);
+ const failedConditions = enhancedConditions.filter(
+ (condition) => condition.level === Status.ERROR,
+ );
+
return (
<CenteredLayout>
- <div className="it__pr-overview sw-mt-12 sw-mb-8 sw-grid sw-grid-cols-12">
+ <PageContentFontWrapper className="it__pr-overview sw-mt-12 sw-mb-8 sw-grid sw-grid-cols-12 sw-body-sm">
<div className="sw-col-start-2 sw-col-span-10">
<MetaTopBar branchLike={branchLike} measures={measures} />
<BasicSeparator className="sw-my-4" />
@@ -135,7 +135,7 @@ export default function PullRequestOverview(props: Props) {
className="sw-flex-1"
branchLike={branchLike}
component={component}
- failedConditions={failedConditions}
+ conditions={enhancedConditions}
measures={measures}
/>
@@ -143,7 +143,7 @@ export default function PullRequestOverview(props: Props) {
<SonarLintAd status={status} />
</div>
- </div>
+ </PageContentFontWrapper>
</CenteredLayout>
);
}
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx
index 3a80968c392..2755d3b3abf 100644
--- a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx
@@ -180,12 +180,12 @@ it('should render correctly for a failed QG', async () => {
expect(
byRole('link', {
- name: 'overview.failed_condition.x_required 10.0% duplicated_lines ≤ 1.0%',
+ name: 'overview.measures.failed_badge overview.failed_condition.x_required 10.0% duplicated_lines ≤ 1.0%',
}).get(),
).toBeInTheDocument();
expect(
byRole('link', {
- name: 'overview.failed_condition.x_required 10 new_bugs ≤ 3',
+ name: 'overview.measures.failed_badge overview.failed_condition.x_required 10 new_bugs ≤ 3',
}).get(),
).toBeInTheDocument();
});