import { getBranchLikeQuery } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
import { formatMeasure, isDiffMetric, localizeMetric } from '../../../helpers/measures';
+import { getOperatorLabel } from '../../../helpers/qualityGates';
import {
getComponentDrilldownUrl,
getComponentIssuesUrl,
const threshold = (condition.level === 'ERROR' ? condition.error : condition.warning) as string;
const actual = (condition.period ? measure.period?.value : measure.value) as string;
- let operator = translate('quality_gates.operator', condition.op);
-
- if (metric.type === MetricType.Rating) {
- operator = translate('quality_gates.operator', condition.op, 'rating');
- }
+ const operator = getOperatorLabel(condition.op, metric);
return this.wrapWithLink(
<div className="sw-flex sw-items-center sw-p-2">
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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 { ButtonPrimary, FormField, Modal, RadioButton } from 'design-system';
+import * as React from 'react';
+import { getLocalizedMetricName, translate } from '../../../helpers/l10n';
+import { isDiffMetric } from '../../../helpers/measures';
+import { useCreateConditionMutation } from '../../../queries/quality-gates';
+import { Condition, Metric, QualityGate } from '../../../types/types';
+import { getPossibleOperators } from '../utils';
+import ConditionOperator from './ConditionOperator';
+import MetricSelect from './MetricSelect';
+import ThresholdInput from './ThresholdInput';
+
+interface Props {
+ metrics: Metric[];
+ onClose: () => void;
+ qualityGate: QualityGate;
+}
+
+const ADD_CONDITION_MODAL_ID = 'add-condition-modal';
+
+export default function AddConditionModal({ metrics, onClose, qualityGate }: Readonly<Props>) {
+ const [errorThreshold, setErrorThreshold] = React.useState('');
+ const [scope, setScope] = React.useState<'new' | 'overall'>('new');
+ const [selectedMetric, setSelectedMetric] = React.useState<Metric | undefined>();
+ const [selectedOperator, setSelectedOperator] = React.useState<string | undefined>();
+ const { mutateAsync: createCondition } = useCreateConditionMutation(qualityGate.name);
+
+ const getSinglePossibleOperator = (metric: Metric) => {
+ const operators = getPossibleOperators(metric);
+ return Array.isArray(operators) ? undefined : operators;
+ };
+
+ const handleFormSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
+ event.preventDefault();
+
+ if (selectedMetric) {
+ const newCondition: Omit<Condition, 'id'> = {
+ metric: selectedMetric.key,
+ op: getSinglePossibleOperator(selectedMetric) ?? selectedOperator,
+ error: errorThreshold,
+ };
+ await createCondition(newCondition);
+ onClose();
+ }
+ };
+
+ const handleScopeChange = (scope: 'new' | 'overall') => {
+ let correspondingMetric;
+
+ if (selectedMetric) {
+ const correspondingMetricKey =
+ scope === 'new' ? `new_${selectedMetric.key}` : selectedMetric.key.replace(/^new_/, '');
+ correspondingMetric = metrics.find((m) => m.key === correspondingMetricKey);
+ }
+
+ setScope(scope);
+ setSelectedMetric(correspondingMetric);
+ };
+
+ const handleMetricChange = (metric: Metric) => {
+ setSelectedMetric(metric);
+ setSelectedOperator(undefined);
+ setErrorThreshold('');
+ };
+
+ const handleOperatorChange = (op: string) => {
+ setSelectedOperator(op);
+ };
+
+ const handleErrorChange = (error: string) => {
+ setErrorThreshold(error);
+ };
+
+ const renderBody = () => {
+ return (
+ <form onSubmit={handleFormSubmit} id={ADD_CONDITION_MODAL_ID}>
+ <FormField label={translate('quality_gates.conditions.where')}>
+ <div className="sw-flex sw-gap-4">
+ <RadioButton checked={scope === 'new'} onCheck={handleScopeChange} value="new">
+ <span data-test="quality-gates__condition-scope-new">
+ {translate('quality_gates.conditions.new_code')}
+ </span>
+ </RadioButton>
+ <RadioButton checked={scope === 'overall'} onCheck={handleScopeChange} value="overall">
+ <span data-test="quality-gates__condition-scope-overall">
+ {translate('quality_gates.conditions.overall_code')}
+ </span>
+ </RadioButton>
+ </div>
+ </FormField>
+
+ <FormField
+ description={selectedMetric && getLocalizedMetricName(selectedMetric)}
+ htmlFor="condition-metric"
+ label={translate('quality_gates.conditions.fails_when')}
+ >
+ <MetricSelect
+ metric={selectedMetric}
+ metricsArray={metrics.filter((m) =>
+ scope === 'new' ? isDiffMetric(m.key) : !isDiffMetric(m.key),
+ )}
+ onMetricChange={handleMetricChange}
+ />
+ </FormField>
+
+ {selectedMetric && (
+ <div className="sw-flex sw-gap-2">
+ <FormField
+ className="sw-mb-0"
+ htmlFor="condition-operator"
+ label={translate('quality_gates.conditions.operator')}
+ >
+ <ConditionOperator
+ metric={selectedMetric}
+ onOperatorChange={handleOperatorChange}
+ op={selectedOperator}
+ />
+ </FormField>
+ <FormField
+ htmlFor="condition-threshold"
+ label={translate('quality_gates.conditions.value')}
+ >
+ <ThresholdInput
+ metric={selectedMetric}
+ name="error"
+ onChange={handleErrorChange}
+ value={errorThreshold}
+ />
+ </FormField>
+ </div>
+ )}
+ </form>
+ );
+ };
+
+ return (
+ <Modal
+ isScrollable={false}
+ isOverflowVisible
+ headerTitle={translate('quality_gates.add_condition')}
+ onClose={onClose}
+ body={renderBody()}
+ primaryButton={
+ <ButtonPrimary
+ autoFocus
+ disabled={selectedMetric === undefined}
+ id="add-condition-button"
+ form={ADD_CONDITION_MODAL_ID}
+ type="submit"
+ >
+ {translate('quality_gates.add_condition')}
+ </ButtonPrimary>
+ }
+ secondaryButtonLabel={translate('close')}
+ />
+ );
+}
import * as React from 'react';
import { useMetrics } from '../../../app/components/metrics/withMetricsContext';
import { getLocalizedMetricName, translate, translateWithParameters } from '../../../helpers/l10n';
+import { getOperatorLabel } from '../../../helpers/qualityGates';
import { useDeleteConditionMutation } from '../../../queries/quality-gates';
-import { MetricType } from '../../../types/metrics';
import { CaycStatus, Condition as ConditionType, Metric, QualityGate } from '../../../types/types';
import { getLocalizedMetricNameNoDiffMetric, isConditionWithFixedValue } from '../utils';
-import ConditionModal from './ConditionModal';
import ConditionValue from './ConditionValue';
+import EditConditionModal from './EditConditionModal';
export enum ConditionChange {
Added = 'added',
const [modal, setModal] = React.useState(false);
const { mutateAsync: deleteCondition } = useDeleteConditionMutation(qualityGate.name);
const metrics = useMetrics();
+ const { op = 'GT' } = condition;
const handleOpenUpdate = () => {
setModal(true);
setDeleteFormOpen(false);
};
- const renderOperator = () => {
- const { op = 'GT' } = condition;
- return metric.type === MetricType.Rating
- ? translate('quality_gates.operator', op, 'rating')
- : translate('quality_gates.operator', op);
- };
-
const isCaycCompliantAndOverCompliant = qualityGate.caycStatus !== CaycStatus.NonCompliant;
return (
{metric.hidden && <TextError className="sw-ml-1" text={translate('deprecated')} />}
</ContentCell>
- <ContentCell className="sw-whitespace-nowrap">{renderOperator()}</ContentCell>
+ <ContentCell className="sw-whitespace-nowrap">{getOperatorLabel(op, metric)}</ContentCell>
<NumericalCell className="sw-whitespace-nowrap">
<ConditionValue
size="small"
/>
{modal && (
- <ConditionModal
+ <EditConditionModal
condition={condition}
header={translate('quality_gates.update_condition')}
metric={metric}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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 { ButtonPrimary, FormField, Modal, RadioButton } from 'design-system';
-import * as React from 'react';
-import { getLocalizedMetricName, translate } from '../../../helpers/l10n';
-import { isDiffMetric } from '../../../helpers/measures';
-import {
- useCreateConditionMutation,
- useUpdateConditionMutation,
-} from '../../../queries/quality-gates';
-import { Condition, Metric, QualityGate } from '../../../types/types';
-import { getPossibleOperators } from '../utils';
-import ConditionOperator from './ConditionOperator';
-import MetricSelect from './MetricSelect';
-import ThresholdInput from './ThresholdInput';
-
-interface Props {
- condition?: Condition;
- metric?: Metric;
- metrics?: Metric[];
- header: string;
- onClose: () => void;
- qualityGate: QualityGate;
-}
-
-const ADD_CONDITION_MODAL_ID = 'add-condition-modal';
-
-export default function ConditionModal({
- condition,
- metric,
- metrics,
- header,
- onClose,
- qualityGate,
-}: Readonly<Props>) {
- const [errorThreshold, setErrorThreshold] = React.useState(condition ? condition.error : '');
- const [scope, setScope] = React.useState<'new' | 'overall'>('new');
- const [selectedMetric, setSelectedMetric] = React.useState<Metric | undefined>(metric);
- const [selectedOperator, setSelectedOperator] = React.useState<string | undefined>(
- condition ? condition.op : undefined,
- );
- const { mutateAsync: createCondition } = useCreateConditionMutation(qualityGate.name);
- const { mutateAsync: updateCondition } = useUpdateConditionMutation(qualityGate.name);
-
- const getSinglePossibleOperator = (metric: Metric) => {
- const operators = getPossibleOperators(metric);
- return Array.isArray(operators) ? undefined : operators;
- };
-
- const handleFormSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
- event.preventDefault();
-
- if (selectedMetric) {
- const newCondition: Omit<Condition, 'id'> = {
- metric: selectedMetric.key,
- op: getSinglePossibleOperator(selectedMetric) ?? selectedOperator,
- error: errorThreshold,
- };
- const submitPromise = condition
- ? updateCondition({ id: condition.id, ...newCondition })
- : createCondition(newCondition);
- await submitPromise;
- onClose();
- }
- };
-
- const handleScopeChange = (scope: 'new' | 'overall') => {
- let correspondingMetric;
-
- if (selectedMetric && metrics) {
- const correspondingMetricKey =
- scope === 'new' ? `new_${selectedMetric.key}` : selectedMetric.key.replace(/^new_/, '');
- correspondingMetric = metrics.find((m) => m.key === correspondingMetricKey);
- }
-
- setScope(scope);
- setSelectedMetric(correspondingMetric);
- };
-
- const handleMetricChange = (metric: Metric) => {
- setSelectedMetric(metric);
- setSelectedOperator(undefined);
- setErrorThreshold('');
- };
-
- const handleOperatorChange = (op: string) => {
- setSelectedOperator(op);
- };
-
- const handleErrorChange = (error: string) => {
- setErrorThreshold(error);
- };
-
- const renderBody = () => {
- return (
- <form id={ADD_CONDITION_MODAL_ID} onSubmit={handleFormSubmit}>
- {metric === undefined && (
- <FormField label={translate('quality_gates.conditions.where')}>
- <div className="sw-flex sw-gap-4">
- <RadioButton checked={scope === 'new'} onCheck={handleScopeChange} value="new">
- <span data-test="quality-gates__condition-scope-new">
- {translate('quality_gates.conditions.new_code')}
- </span>
- </RadioButton>
- <RadioButton
- checked={scope === 'overall'}
- onCheck={handleScopeChange}
- value="overall"
- >
- <span data-test="quality-gates__condition-scope-overall">
- {translate('quality_gates.conditions.overall_code')}
- </span>
- </RadioButton>
- </div>
- </FormField>
- )}
-
- <FormField
- description={metric && getLocalizedMetricName(metric)}
- htmlFor="condition-metric"
- label={translate('quality_gates.conditions.fails_when')}
- >
- {metrics && (
- <MetricSelect
- metric={selectedMetric}
- metricsArray={metrics.filter((m) =>
- scope === 'new' ? isDiffMetric(m.key) : !isDiffMetric(m.key),
- )}
- onMetricChange={handleMetricChange}
- />
- )}
- </FormField>
-
- {selectedMetric && (
- <div className="sw-flex sw-gap-2">
- <FormField
- className="sw-mb-0"
- htmlFor="condition-operator"
- label={translate('quality_gates.conditions.operator')}
- >
- <ConditionOperator
- metric={selectedMetric}
- onOperatorChange={handleOperatorChange}
- op={selectedOperator}
- />
- </FormField>
- <FormField
- htmlFor="condition-threshold"
- label={translate('quality_gates.conditions.value')}
- >
- <ThresholdInput
- metric={selectedMetric}
- name="error"
- onChange={handleErrorChange}
- value={errorThreshold}
- />
- </FormField>
- </div>
- )}
- </form>
- );
- };
-
- return (
- <Modal
- isScrollable={false}
- isOverflowVisible
- headerTitle={header}
- onClose={onClose}
- body={renderBody()}
- primaryButton={
- <ButtonPrimary
- autoFocus
- disabled={selectedMetric === undefined}
- id="add-condition-button"
- form={ADD_CONDITION_MODAL_ID}
- type="submit"
- >
- {header}
- </ButtonPrimary>
- }
- secondaryButtonLabel={translate('close')}
- />
- );
-}
*/
import { InputSelect, Note } from 'design-system';
import * as React from 'react';
-import { translate } from '../../../helpers/l10n';
+import { getOperatorLabel } from '../../../helpers/qualityGates';
import { Metric } from '../../../types/types';
import { getPossibleOperators } from '../utils';
this.props.onOperatorChange(value);
};
- getLabel(op: string, metric: Metric) {
- return metric.type === 'RATING'
- ? translate('quality_gates.operator', op, 'rating')
- : translate('quality_gates.operator', op);
- }
-
render() {
const operators = getPossibleOperators(this.props.metric);
if (Array.isArray(operators)) {
const operatorOptions = operators.map((op) => {
- const label = this.getLabel(op, this.props.metric);
+ const label = getOperatorLabel(op, this.props.metric);
return { label, value: op };
});
);
}
- return <Note className="sw-w-abs-150">{this.getLabel(operators, this.props.metric)}</Note>;
+ return <Note className="sw-w-abs-150">{getOperatorLabel(operators, this.props.metric)}</Note>;
}
}
import { MetricKey } from '../../../types/metrics';
import { CaycStatus, Condition as ConditionType, QualityGate } from '../../../types/types';
import { groupAndSortByPriorityConditions, isQualityGateOptimized } from '../utils';
+import AddConditionModal from './AddConditionModal';
import CaYCConditionsSimplificationGuide from './CaYCConditionsSimplificationGuide';
import CaycCompliantBanner from './CaycCompliantBanner';
import CaycCondition from './CaycCondition';
import CaycFixOptimizeBanner from './CaycFixOptimizeBanner';
-import ConditionModal from './ConditionModal';
import CaycReviewUpdateConditionsModal from './ConditionReviewAndUpdateModal';
import ConditionsTable from './ConditionsTable';
(metric, condition) => metric.key === condition.metric,
);
return (
- <ConditionModal
- header={translate('quality_gates.add_condition')}
- metrics={availableMetrics}
- onClose={onClose}
- qualityGate={qualityGate}
- />
+ <AddConditionModal metrics={availableMetrics} onClose={onClose} qualityGate={qualityGate} />
);
},
[metrics, qualityGate],
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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 { ButtonPrimary, FormField, Highlight, Modal, Note } from 'design-system';
+import { isArray } from 'lodash';
+import * as React from 'react';
+import { getLocalizedMetricName, translate } from '../../../helpers/l10n';
+import { useUpdateConditionMutation } from '../../../queries/quality-gates';
+import { Condition, Metric, QualityGate } from '../../../types/types';
+import { getPossibleOperators } from '../utils';
+import ConditionOperator from './ConditionOperator';
+import ThresholdInput from './ThresholdInput';
+
+interface Props {
+ condition: Condition;
+ metric: Metric;
+ header: string;
+ onClose: () => void;
+ qualityGate: QualityGate;
+}
+
+const EDIT_CONDITION_MODAL_ID = 'edit-condition-modal';
+
+export default function EditConditionModal({
+ condition,
+ metric,
+ onClose,
+ qualityGate,
+}: Readonly<Props>) {
+ const [errorThreshold, setErrorThreshold] = React.useState(condition ? condition.error : '');
+
+ const [selectedOperator, setSelectedOperator] = React.useState<string | undefined>(
+ condition ? condition.op : undefined,
+ );
+ const { mutateAsync: updateCondition } = useUpdateConditionMutation(qualityGate.name);
+
+ const getSinglePossibleOperator = (metric: Metric) => {
+ const operators = getPossibleOperators(metric);
+ return isArray(operators) ? selectedOperator : operators;
+ };
+
+ const handleFormSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
+ event.preventDefault();
+
+ const newCondition: Omit<Condition, 'id'> = {
+ metric: metric.key,
+ op: getSinglePossibleOperator(metric),
+ error: errorThreshold,
+ };
+ await updateCondition({ id: condition.id, ...newCondition });
+ onClose();
+ };
+
+ const handleErrorChange = (error: string) => {
+ setErrorThreshold(error);
+ };
+
+ const handleOperatorChange = (op: string) => {
+ setSelectedOperator(op);
+ };
+
+ const renderBody = () => {
+ return (
+ <form onSubmit={handleFormSubmit} id={EDIT_CONDITION_MODAL_ID}>
+ <span className="sw-flex sw-flex-col sw-w-full sw-mb-6" aria-hidden="true">
+ <Highlight className="sw-mb-2 sw-flex sw-items-center sw-gap-2">
+ <span>{translate('quality_gates.conditions.fails_when')}</span>
+ </Highlight>
+ <Note className="sw-mt-2">{getLocalizedMetricName(metric)}</Note>
+ </span>
+
+ <div className="sw-flex sw-gap-2">
+ <FormField
+ className="sw-mb-0"
+ htmlFor="condition-operator"
+ label={translate('quality_gates.conditions.operator')}
+ >
+ <ConditionOperator
+ metric={metric}
+ onOperatorChange={handleOperatorChange}
+ op={selectedOperator}
+ />
+ </FormField>
+ <FormField
+ htmlFor="condition-threshold"
+ label={translate('quality_gates.conditions.value')}
+ >
+ <ThresholdInput
+ metric={metric}
+ name="error"
+ onChange={handleErrorChange}
+ value={errorThreshold}
+ />
+ </FormField>
+ </div>
+ </form>
+ );
+ };
+
+ return (
+ <Modal
+ isScrollable={false}
+ isOverflowVisible
+ headerTitle={translate('quality_gates.update_condition')}
+ onClose={onClose}
+ body={renderBody()}
+ primaryButton={
+ <ButtonPrimary form={EDIT_CONDITION_MODAL_ID} type="submit">
+ {translate('quality_gates.update_condition')}
+ </ButtonPrimary>
+ }
+ secondaryButtonLabel={translate('close')}
+ />
+ );
+}
import { dismissNotice } from '../../../../api/users';
import { mockLoggedInUser } from '../../../../helpers/testMocks';
import { RenderContext, renderAppRoutes } from '../../../../helpers/testReactTestingUtils';
-import { byRole } from '../../../../helpers/testSelector';
+import { byRole, byTestId } from '../../../../helpers/testSelector';
import { Feature } from '../../../../types/features';
import { CaycStatus } from '../../../../types/types';
import { NoticeType } from '../../../../types/users';
// On new code
await user.click(await screen.findByText('quality_gates.add_condition'));
- let dialog = within(screen.getByRole('dialog'));
+ const dialog = byRole('dialog');
- await user.click(dialog.getByRole('radio', { name: 'quality_gates.conditions.new_code' }));
- await selectEvent.select(dialog.getByRole('combobox'), ['Issues']);
- await user.click(dialog.getByRole('textbox', { name: 'quality_gates.conditions.value' }));
+ await user.click(dialog.byRole('radio', { name: 'quality_gates.conditions.new_code' }).get());
+
+ await selectEvent.select(dialog.byRole('combobox').get(), 'Issues');
+ await user.click(
+ await dialog.byRole('textbox', { name: 'quality_gates.conditions.value' }).find(),
+ );
await user.keyboard('12');
- await user.click(dialog.getByRole('button', { name: 'quality_gates.add_condition' }));
- const newConditions = within(await screen.findByTestId('quality-gates__conditions-new'));
- expect(await newConditions.findByRole('cell', { name: 'Issues' })).toBeInTheDocument();
- expect(await newConditions.findByRole('cell', { name: '12' })).toBeInTheDocument();
+ await user.click(dialog.byRole('button', { name: 'quality_gates.add_condition' }).get());
+ const newConditions = byTestId('quality-gates__conditions-new');
+ expect(await newConditions.byRole('cell', { name: 'Issues' }).find()).toBeInTheDocument();
+ expect(await newConditions.byRole('cell', { name: '12' }).find()).toBeInTheDocument();
// On overall code
await user.click(await screen.findByText('quality_gates.add_condition'));
- dialog = within(screen.getByRole('dialog'));
- await selectEvent.select(dialog.getByRole('combobox'), ['Info Issues']);
- await user.click(dialog.getByRole('radio', { name: 'quality_gates.conditions.overall_code' }));
- await user.click(dialog.getByLabelText('quality_gates.conditions.operator'));
+ await selectEvent.select(dialog.byRole('combobox').get(), ['Info Issues']);
+ await user.click(dialog.byRole('radio', { name: 'quality_gates.conditions.overall_code' }).get());
+ await user.click(dialog.byLabelText('quality_gates.conditions.operator').get());
- await user.click(dialog.getByText('quality_gates.operator.LT'));
- await user.click(dialog.getByRole('textbox', { name: 'quality_gates.conditions.value' }));
+ await user.click(dialog.byText('quality_gates.operator.LT').get());
+ await user.click(dialog.byRole('textbox', { name: 'quality_gates.conditions.value' }).get());
await user.keyboard('42');
- await user.click(dialog.getByRole('button', { name: 'quality_gates.add_condition' }));
+ await user.click(dialog.byRole('button', { name: 'quality_gates.add_condition' }).get());
- const overallConditions = within(await screen.findByTestId('quality-gates__conditions-overall'));
+ const overallConditions = byTestId('quality-gates__conditions-overall');
- expect(await overallConditions.findByRole('cell', { name: 'Info Issues' })).toBeInTheDocument();
- expect(await overallConditions.findByRole('cell', { name: '42' })).toBeInTheDocument();
+ expect(
+ await overallConditions.byRole('cell', { name: 'Info Issues' }).find(),
+ ).toBeInTheDocument();
+ expect(await overallConditions.byRole('cell', { name: '42' }).find()).toBeInTheDocument();
// Select a rating
await user.click(await screen.findByText('quality_gates.add_condition'));
- dialog = within(screen.getByRole('dialog'));
- await user.click(dialog.getByRole('radio', { name: 'quality_gates.conditions.overall_code' }));
- await selectEvent.select(dialog.getByRole('combobox'), ['Maintainability Rating']);
- await user.click(dialog.getByLabelText('quality_gates.conditions.value'));
- await user.click(dialog.getByText('B'));
- await user.click(dialog.getByRole('button', { name: 'quality_gates.add_condition' }));
+ await user.click(dialog.byRole('radio', { name: 'quality_gates.conditions.overall_code' }).get());
+ await selectEvent.select(dialog.byRole('combobox').get(), ['Maintainability Rating']);
+ await user.click(dialog.byLabelText('quality_gates.conditions.value').get());
+ await user.click(dialog.byText('B').get());
+ await user.click(dialog.byRole('button', { name: 'quality_gates.add_condition' }).get());
expect(
- await overallConditions.findByRole('cell', { name: 'Maintainability Rating' }),
+ await overallConditions.byRole('cell', { name: 'Maintainability Rating' }).find(),
).toBeInTheDocument();
- expect(await overallConditions.findByRole('cell', { name: 'B' })).toBeInTheDocument();
+ expect(await overallConditions.byRole('cell', { name: 'B' }).find()).toBeInTheDocument();
});
it('should be able to edit a condition', async () => {
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { MetricKey } from '../types/metrics';
+import { MetricKey, MetricType } from '../types/metrics';
import {
QualityGateApplicationStatusChildProject,
QualityGateProjectStatus,
QualityGateStatusCondition,
} from '../types/quality-gates';
+import { Metric } from '../types/types';
+import { translate } from './l10n';
+
+export function getOperatorLabel(op: string, metric: Metric) {
+ return metric.type === MetricType.Rating
+ ? translate('quality_gates.operator', op, 'rating')
+ : translate('quality_gates.operator', op);
+}
export function extractStatusConditionsFromProjectStatus(
projectStatus: QualityGateProjectStatus,