import withMetricsContext from '../../../app/components/metrics/withMetricsContext';
import DocumentationTooltip from '../../../components/common/DocumentationTooltip';
import { Button } from '../../../components/controls/buttons';
-import ModalButton from '../../../components/controls/ModalButton';
+import ModalButton, { ModalProps } from '../../../components/controls/ModalButton';
import { Alert } from '../../../components/ui/Alert';
import { getLocalizedMetricName, translate } from '../../../helpers/l10n';
import { isDiffMetric } from '../../../helpers/measures';
];
export class Conditions extends React.PureComponent<Props> {
- renderConditionsTable = (conditions: ConditionType[], scope: 'new' | 'overall') => {
- const {
- qualityGate,
- metrics,
- canEdit,
- onRemoveCondition,
- onSaveCondition,
- updatedConditionId,
- } = this.props;
-
+ renderConditionModal = ({ onClose }: ModalProps) => {
+ const { metrics, qualityGate, conditions } = this.props;
+ const availableMetrics = differenceWith(
+ map(metrics, (metric) => metric).filter(
+ (metric) =>
+ !metric.hidden &&
+ !FORBIDDEN_METRIC_TYPES.includes(metric.type) &&
+ !FORBIDDEN_METRICS.includes(metric.key)
+ ),
+ conditions,
+ (metric, condition) => metric.key === condition.metric
+ );
return (
- <ConditionsTable
+ <ConditionModal
+ header={translate('quality_gates.add_condition')}
+ metrics={availableMetrics}
+ onAddCondition={this.props.onAddCondition}
+ onClose={onClose}
qualityGate={qualityGate}
- metrics={metrics}
- canEdit={canEdit}
- onRemoveCondition={onRemoveCondition}
- onSaveCondition={onSaveCondition}
- updatedConditionId={updatedConditionId}
- conditions={getOthersConditions(conditions)}
- scope={scope}
/>
);
};
metric: metrics[condition.metric],
}));
- const availableMetrics = differenceWith(
- map(metrics, (metric) => metric).filter(
- (metric) =>
- !metric.hidden &&
- !FORBIDDEN_METRIC_TYPES.includes(metric.type) &&
- !FORBIDDEN_METRICS.includes(metric.key)
- ),
- conditions,
- (metric, condition) => metric.key === condition.metric
- );
-
return (
<div className="quality-gate-section">
{canEdit && (
<div className="pull-right">
- <ModalButton
- modal={({ onClose }) => (
- <ConditionModal
- header={translate('quality_gates.add_condition')}
- metrics={availableMetrics}
- onAddCondition={this.props.onAddCondition}
- onClose={onClose}
- qualityGate={this.props.qualityGate}
- />
- )}
- >
+ <ModalButton modal={this.renderConditionModal}>
{({ onClick }) => (
<Button data-test="quality-gates__add-condition" onClick={onClick}>
{translate('quality_gates.add_condition')}
render() {
const { qualityGate } = this.props;
const actions = qualityGate.actions || ({} as any);
- const hasNoConditions =
- qualityGate.conditions === undefined || qualityGate.conditions.length === 0;
+ const { isCaycCompliant } = qualityGate;
+
return (
<div className="layout-page-header-panel layout-page-main-header issues-main-header">
<div className="layout-page-header-panel-inner layout-page-main-header-inner">
)}
>
{({ onClick }) => (
- <Button className="little-spacer-left" id="quality-gate-copy" onClick={onClick}>
- {translate('copy')}
- </Button>
+ <Tooltip
+ overlay={
+ !isCaycCompliant ? translate('quality_gates.cannot_copy_no_cayc') : null
+ }
+ >
+ <Button
+ className="little-spacer-left"
+ id="quality-gate-copy"
+ onClick={onClick}
+ disabled={!isCaycCompliant}
+ >
+ {translate('copy')}
+ </Button>
+ </Tooltip>
)}
</ModalButton>
)}
{actions.setAsDefault && (
<Tooltip
overlay={
- hasNoConditions
- ? translate('quality_gates.cannot_set_default_no_conditions')
- : null
+ !isCaycCompliant ? translate('quality_gates.cannot_set_default_no_cayc') : null
}
>
<Button
className="little-spacer-left"
- disabled={hasNoConditions}
+ disabled={!isCaycCompliant}
id="quality-gate-toggle-default"
onClick={this.handleSetAsDefaultClick}
>
});
});
-it('should be able to copy a quality gate', async () => {
+it('should be able to copy a quality gate which is CAYC compliant', async () => {
const user = userEvent.setup();
handler.setIsAdmin(true);
renderQualityGateApp();
+ const notDefaultQualityGate = await screen.findByText('Sonar way');
+ await user.click(notDefaultQualityGate);
const copyButton = await screen.findByRole('button', { name: 'copy' });
await user.click(copyButton);
expect(await screen.findByRole('menuitem', { name: /.* bis/ })).toBeInTheDocument();
});
+it('should not be able to copy a quality gate which is not CAYC compliant', async () => {
+ const user = userEvent.setup();
+ handler.setIsAdmin(true);
+ renderQualityGateApp();
+
+ const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily');
+ await user.click(notDefaultQualityGate);
+
+ const copyButton = await screen.findByRole('button', { name: 'copy' });
+
+ expect(copyButton).toBeDisabled();
+});
+
it('should be able to rename a quality gate', async () => {
const user = userEvent.setup();
handler.setIsAdmin(true);
expect(await screen.findByRole('menuitem', { name: /New Name.*/ })).toBeInTheDocument();
});
-it('should be able to set as default a quality gate', async () => {
+it('should not be able to set as default a quality gate which is not CAYC compliant', async () => {
const user = userEvent.setup();
handler.setIsAdmin(true);
renderQualityGateApp();
const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily');
await user.click(notDefaultQualityGate);
const setAsDefaultButton = screen.getByRole('button', { name: 'set_as_default' });
+ expect(setAsDefaultButton).toBeDisabled();
+});
+
+it('should be able to set as default a quality gate which is CAYC compliant', async () => {
+ const user = userEvent.setup();
+ handler.setIsAdmin(true);
+ renderQualityGateApp();
+
+ const notDefaultQualityGate = await screen.findByText('Sonar way');
+ await user.click(notDefaultQualityGate);
+ const setAsDefaultButton = screen.getByRole('button', { name: 'set_as_default' });
await user.click(setAsDefaultButton);
- expect(screen.getAllByRole('menuitem')[1]).toHaveTextContent('default');
+ expect(screen.getAllByRole('menuitem')[2]).toHaveTextContent('default');
});
it('should be able to add a condition', async () => {
quality_gates.rename=Rename Quality Gate
quality_gates.delete=Delete Quality Gate
quality_gates.copy=Copy Quality Gate
-quality_gates.cannot_set_default_no_conditions=You must configure at least 1 condition before you can make this the default quality gate.
+quality_gates.cannot_set_default_no_cayc=You must make this quality gate Clean as You Code compliant to make this the default quality gate.
+quality_gates.cannot_copy_no_cayc=You must make this quality gate Clean as You Code compliant to copy.
quality_gates.is_default_no_conditions=This is the default quality gate, but it has no configured conditions. Please configure at least 1 condition for this quality gate.
quality_gates.conditions=Conditions
quality_gates.conditions.help=Your project will fail the Quality Gate if it crosses any metric thresholds set for New Code or Overall Code.