aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorViktor Vorona <viktor.vorona@sonarsource.com>2024-05-29 17:55:27 +0200
committersonartech <sonartech@sonarsource.com>2024-06-03 20:02:58 +0000
commit411f1d1ae8b2c7128cabfa7a791bc76f5b2f944d (patch)
treea8078395bc1f885b699c0afedaf0f7664525ffa5 /server
parent1d4707b86a5a03f3895cbff760fc9824655d9da2 (diff)
downloadsonarqube-411f1d1ae8b2c7128cabfa7a791bc76f5b2f944d.tar.gz
sonarqube-411f1d1ae8b2c7128cabfa7a791bc76f5b2f944d.zip
SONAR-22224 Disable editing on new metric
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx51
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGate-it.tsx37
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/utils.ts5
-rw-r--r--server/sonar-web/src/main/js/helpers/mocks/metrics.ts11
-rw-r--r--server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts1
7 files changed, 90 insertions, 25 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx
index f01e9c1abda..d17cb066a2a 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx
@@ -23,8 +23,9 @@ import * as React from 'react';
import { translate } from '../../../helpers/l10n';
import { isDiffMetric } from '../../../helpers/measures';
import { useCreateConditionMutation } from '../../../queries/quality-gates';
+import { MetricKey } from '../../../sonar-aligned/types/metrics';
import { Condition, Metric, QualityGate } from '../../../types/types';
-import { getPossibleOperators } from '../utils';
+import { getPossibleOperators, isNonEditableMetric } from '../utils';
import ConditionOperator from './ConditionOperator';
import MetricSelect from './MetricSelect';
import ThresholdInput from './ThresholdInput';
@@ -79,7 +80,7 @@ export default function AddConditionModal({ metrics, onClose, qualityGate }: Rea
const handleMetricChange = (metric: Metric) => {
setSelectedMetric(metric);
setSelectedOperator(undefined);
- setErrorThreshold('');
+ setErrorThreshold(metric.key === MetricKey.prioritized_rule_issues ? '0' : '');
};
const handleOperatorChange = (op: string) => {
@@ -137,6 +138,7 @@ export default function AddConditionModal({ metrics, onClose, qualityGate }: Rea
>
<ThresholdInput
metric={selectedMetric}
+ disabled={isNonEditableMetric(selectedMetric.key as MetricKey)}
name="error"
onChange={handleErrorChange}
value={errorThreshold}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx
index e15de9c0759..d225dc4c5f0 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx
@@ -35,8 +35,13 @@ 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 { MetricKey } from '../../../sonar-aligned/types/metrics';
import { CaycStatus, Condition as ConditionType, Metric, QualityGate } from '../../../types/types';
-import { getLocalizedMetricNameNoDiffMetric, isConditionWithFixedValue } from '../utils';
+import {
+ getLocalizedMetricNameNoDiffMetric,
+ isConditionWithFixedValue,
+ isNonEditableMetric,
+} from '../utils';
import ConditionValue from './ConditionValue';
import EditConditionModal from './EditConditionModal';
@@ -109,27 +114,31 @@ export default function ConditionComponent({
<>
{(!isCaycCompliantAndOverCompliant ||
!isConditionWithFixedValue(condition) ||
- (isCaycCompliantAndOverCompliant && showEdit)) && (
- <>
- <InteractiveIcon
- Icon={PencilIcon}
- aria-label={translateWithParameters('quality_gates.condition.edit', metric.name)}
- data-test="quality-gates__condition-update"
- onClick={handleOpenUpdate}
- className="sw-mr-4"
- size="small"
- />
- {modal && (
- <EditConditionModal
- condition={condition}
- header={translate('quality_gates.update_condition')}
- metric={metric}
- onClose={handleUpdateClose}
- qualityGate={qualityGate}
+ (isCaycCompliantAndOverCompliant && showEdit)) &&
+ !isNonEditableMetric(condition.metric as MetricKey) && (
+ <>
+ <InteractiveIcon
+ Icon={PencilIcon}
+ aria-label={translateWithParameters(
+ 'quality_gates.condition.edit',
+ metric.name,
+ )}
+ data-test="quality-gates__condition-update"
+ onClick={handleOpenUpdate}
+ className="sw-mr-4"
+ size="small"
/>
- )}
- </>
- )}
+ {modal && (
+ <EditConditionModal
+ condition={condition}
+ header={translate('quality_gates.update_condition')}
+ metric={metric}
+ onClose={handleUpdateClose}
+ qualityGate={qualityGate}
+ />
+ )}
+ </>
+ )}
{(!isCaycCompliantAndOverCompliant ||
!condition.isCaycCondition ||
(isCaycCompliantAndOverCompliant && showEdit)) && (
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.tsx
index b832428a495..de3c5df6505 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.tsx
@@ -25,6 +25,7 @@ import { Metric } from '../../../types/types';
interface Props {
name: string;
value: string;
+ disabled?: boolean;
metric: Metric;
onChange: (value: string) => void;
}
@@ -67,7 +68,7 @@ export default class ThresholdInput extends React.PureComponent<Props> {
}
render() {
- const { name, value, metric } = this.props;
+ const { name, value, disabled, metric } = this.props;
if (metric.type === 'RATING') {
return this.renderRatingInput();
@@ -77,6 +78,7 @@ export default class ThresholdInput extends React.PureComponent<Props> {
<InputField
size="small"
data-type={metric.type}
+ disabled={disabled}
id="condition-threshold"
name={name}
onChange={this.handleChange}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGate-it.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGate-it.tsx
index 31b58311c5d..d3230d5eb5b 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGate-it.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGate-it.tsx
@@ -20,7 +20,7 @@
import { screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import selectEvent from 'react-select-event';
-import { byRole, byTestId } from '~sonar-aligned/helpers/testSelector';
+import { byLabelText, byRole, byTestId } from '~sonar-aligned/helpers/testSelector';
import { QualityGatesServiceMock } from '../../../../api/mocks/QualityGatesServiceMock';
import UsersServiceMock from '../../../../api/mocks/UsersServiceMock';
import { searchProjects, searchUsers } from '../../../../api/quality-gates';
@@ -556,6 +556,41 @@ it('should not display CaYC condition simplification tour for users who dismisse
expect(byRole('alertdialog').query()).not.toBeInTheDocument();
});
+it('should not allow to change value of prioritized_rule_issues', async () => {
+ const user = userEvent.setup();
+ qualityGateHandler.setIsAdmin(true);
+ renderQualityGateApp();
+
+ await user.click(await screen.findByText('SonarSource way - CFamily'));
+
+ await user.click(await screen.findByText('quality_gates.add_condition'));
+
+ const dialog = byRole('dialog');
+
+ await user.click(dialog.byRole('radio', { name: 'quality_gates.conditions.overall_code' }).get());
+ await selectEvent.select(dialog.byRole('combobox').get(), ['Issues from prioritized rules']);
+
+ expect(dialog.byRole('textbox', { name: 'quality_gates.conditions.value' }).get()).toBeDisabled();
+ expect(dialog.byRole('textbox', { name: 'quality_gates.conditions.value' }).get()).toHaveValue(
+ '0',
+ );
+
+ await user.click(dialog.byRole('button', { name: 'quality_gates.add_condition' }).get());
+
+ const overallConditions = byTestId('quality-gates__conditions-overall');
+
+ expect(
+ await overallConditions.byRole('cell', { name: 'Issues from prioritized rules' }).find(),
+ ).toBeInTheDocument();
+
+ expect(
+ byLabelText('quality_gates.condition.edit.Issues from prioritized rules').query(),
+ ).not.toBeInTheDocument();
+ expect(
+ byLabelText('quality_gates.condition.delete.Issues from prioritized rules').get(),
+ ).toBeInTheDocument();
+});
+
describe('The Project section', () => {
it('should render list of projects correctly in different tabs', async () => {
const user = userEvent.setup();
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/utils.ts b/server/sonar-web/src/main/js/apps/quality-gates/utils.ts
index cb37ff4039a..ab487e58aa5 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/utils.ts
+++ b/server/sonar-web/src/main/js/apps/quality-gates/utils.ts
@@ -141,11 +141,16 @@ const CAYC_CONDITIONS_WITH_FIXED_VALUE: AllCaycMetricKeys[] = [
MetricKey.new_security_rating,
MetricKey.new_maintainability_rating,
];
+const NON_EDITABLE_CONDITIONS: MetricKey[] = [MetricKey.prioritized_rule_issues];
export function isConditionWithFixedValue(condition: Condition) {
return CAYC_CONDITIONS_WITH_FIXED_VALUE.includes(condition.metric as OptimizedCaycMetricKeys);
}
+export function isNonEditableMetric(metricKey: MetricKey) {
+ return NON_EDITABLE_CONDITIONS.includes(metricKey);
+}
+
export function getCaycConditionMetadata(condition: Condition) {
const foundCondition = OPTIMIZED_CAYC_CONDITIONS[condition.metric as OptimizedCaycMetricKeys];
return {
diff --git a/server/sonar-web/src/main/js/helpers/mocks/metrics.ts b/server/sonar-web/src/main/js/helpers/mocks/metrics.ts
index 60febc0fb71..d191dd1e76b 100644
--- a/server/sonar-web/src/main/js/helpers/mocks/metrics.ts
+++ b/server/sonar-web/src/main/js/helpers/mocks/metrics.ts
@@ -17,6 +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 { MetricKey } from '../../sonar-aligned/types/metrics';
import { Dict, Metric } from '../../types/types';
export const DEFAULT_METRICS: Dict<Metric> = {
@@ -830,6 +831,16 @@ export const DEFAULT_METRICS: Dict<Metric> = {
qualitative: false,
hidden: true,
},
+ [MetricKey.prioritized_rule_issues]: {
+ key: 'prioritized_rule_issues',
+ type: 'INT',
+ name: 'Issues from prioritized rules',
+ description: 'Count of issues that have a flag Prioritized Rule.',
+ domain: 'Issues',
+ direction: -1,
+ qualitative: true,
+ hidden: false,
+ },
projects: {
key: 'projects',
type: 'INT',
diff --git a/server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts b/server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts
index a98e6d016e2..53aed15b4fb 100644
--- a/server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts
+++ b/server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts
@@ -122,6 +122,7 @@ export enum MetricKey {
new_violations_rating = 'new_violations_rating',
new_vulnerabilities = 'new_vulnerabilities',
open_issues = 'open_issues',
+ prioritized_rule_issues = 'prioritized_rule_issues',
projects = 'projects',
public_api = 'public_api',
public_documented_api_density = 'public_documented_api_density',