]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20355 Show deactivate button in rule details as well
authorWouter Admiraal <wouter.admiraal@sonarsource.com>
Thu, 14 Sep 2023 11:15:18 +0000 (13:15 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 14 Sep 2023 20:02:39 +0000 (20:02 +0000)
server/sonar-web/src/main/js/api/mocks/data/rules.ts
server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRules-it.ts
server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesApp.tsx
server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetails.tsx
server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsProfiles.tsx
server/sonar-web/src/main/js/types/settings.ts

index 3b07b24525947b553f79cb7131e23cec4ef3c8a3..f7a1aca3dbf89a34561b77f5e3bbdb34121bd064 100644 (file)
@@ -29,6 +29,8 @@ import {
   ADVANCED_RULE,
   QP_1,
   QP_2,
+  QP_4,
+  QP_5,
   RULE_1,
   RULE_10,
   RULE_11,
@@ -245,7 +247,11 @@ export function mockRuleDetailsList() {
 
 export function mockRulesActivationsInQP() {
   return {
-    [RULE_1]: [mockRuleActivation({ qProfile: QP_1 })],
+    [RULE_1]: [
+      mockRuleActivation({ qProfile: QP_1 }),
+      mockRuleActivation({ qProfile: QP_4 }),
+      mockRuleActivation({ qProfile: QP_5, inherit: 'INHERITED' }),
+    ],
     [RULE_7]: [mockRuleActivation({ qProfile: QP_2 })],
     [RULE_8]: [mockRuleActivation({ qProfile: QP_2 })],
     [RULE_9]: [mockRuleActivation({ qProfile: QP_2, inherit: 'INHERITED' })],
index 8c7625b851d774986b1cf615835e7d61b8f5a45a..6ee951ec91f56e359ca500dcdb815b9f499df1bc 100644 (file)
@@ -544,7 +544,7 @@ describe('Rule app details', () => {
     await act(() => user.click(ui.activateButton.get(ui.activateQPDialog.get())));
     expect(ui.qpLink('QP FooBar').get()).toBeInTheDocument();
 
-    // activate last java rule
+    // Activate last java rule
     await user.click(ui.activateButton.get());
     await user.type(ui.paramInput('1').get(), 'paramInput');
     await act(() => user.click(ui.activateButton.get(ui.activateQPDialog.get())));
@@ -552,7 +552,7 @@ describe('Rule app details', () => {
     expect(ui.qpLink('QP FooBaz').get()).toBeInTheDocument();
 
     // Rule is activated in all quality profiles - show notification in dialog
-    await user.click(ui.activateButton.get());
+    await user.click(ui.activateButton.get(screen.getByRole('main')));
     expect(ui.activaInAllQPs.get()).toBeInTheDocument();
     expect(ui.activateButton.get(ui.activateQPDialog.get())).toBeDisabled();
     await user.click(ui.cancelButton.get());
@@ -560,13 +560,15 @@ describe('Rule app details', () => {
     // Change rule details in quality profile
     await user.click(ui.changeButton('QP FooBaz').get());
     await user.type(ui.paramInput('1').get(), 'New');
-    await act(() => user.click(ui.saveButton.get(ui.changeQPDialog.get())));
-    expect(screen.getByText('paramInputNew')).toBeInTheDocument();
+    await act(async () => {
+      await user.click(ui.saveButton.get(ui.changeQPDialog.get()));
+    });
+    expect(screen.getByText('New')).toBeInTheDocument();
 
     // Revert rule details in quality profile
     await user.click(ui.revertToParentDefinitionButton.get());
     await act(() => user.click(ui.yesButton.get()));
-    expect(screen.queryByText('paramInputNew')).not.toBeInTheDocument();
+    expect(screen.queryByText('New')).not.toBeInTheDocument();
 
     // Deactivate rule in quality profile
     await user.click(ui.deactivateInQPButton('QP FooBar').get());
@@ -574,6 +576,36 @@ describe('Rule app details', () => {
     expect(ui.qpLink('QP FooBar').query()).not.toBeInTheDocument();
   });
 
+  it('can deactivate an inherrited rule', async () => {
+    const { ui, user } = getPageObjects();
+    rulesHandler.setIsAdmin();
+    renderCodingRulesApp(mockLoggedInUser(), 'coding_rules?open=rule1');
+    await ui.appLoaded();
+
+    // Should show 2 deactivate buttons: one for the parent, one for the child profile.
+    expect(ui.deactivateInQPButton('QP FooBarBaz').get()).toBeInTheDocument();
+    expect(ui.deactivateInQPButton('QP FooBaz').get()).toBeInTheDocument();
+
+    // Deactivate rule in inherited quality profile
+    await user.click(ui.deactivateInQPButton('QP FooBaz').get());
+    await act(async () => {
+      await user.click(ui.yesButton.get());
+    });
+    expect(ui.qpLink('QP FooBaz').query()).not.toBeInTheDocument();
+  });
+
+  it('cannot deactivate an inherrited rule if the setting is false', async () => {
+    const { ui } = getPageObjects();
+    rulesHandler.setIsAdmin();
+    settingsHandler.set(SettingsKey.QPAdminCanDisableInheritedRules, 'false');
+    renderCodingRulesApp(mockLoggedInUser(), 'coding_rules?open=rule1');
+    await ui.appLoaded();
+
+    // Should show 1 deactivate button: one for the parent, none for the child profile.
+    expect(ui.deactivateInQPButton('QP FooBarBaz').get()).toBeInTheDocument();
+    expect(ui.deactivateInQPButton('QP FooBaz').query()).not.toBeInTheDocument();
+  });
+
   it('can extend the rule description', async () => {
     const { ui, user } = getPageObjects();
     rulesHandler.setIsAdmin();
index 8ed2bebc61b67abefb7d241473c5c1e96d6cce17..18adffdb470acf843c77883a9389ad9ef5ff16f9 100644 (file)
@@ -655,6 +655,7 @@ export class CodingRulesApp extends React.PureComponent<Props, State> {
                 <RuleDetails
                   allowCustomRules
                   canWrite={this.state.canWrite}
+                  canDeactivateInherited={this.state.canDeactivateInherited}
                   onActivate={this.handleRuleActivate}
                   onDeactivate={this.handleRuleDeactivate}
                   onDelete={this.handleRuleDelete}
index 244b4728a5cea777b72c3628f15dc4b6573f3f3c..eef92663a2dda552a0008ab7827dc55f4f295a9f 100644 (file)
@@ -38,6 +38,7 @@ import RuleDetailsProfiles from './RuleDetailsProfiles';
 interface Props {
   allowCustomRules?: boolean;
   canWrite?: boolean;
+  canDeactivateInherited?: boolean;
   onActivate: (profile: string, rule: string, activation: Activation) => void;
   onDeactivate: (profile: string, rule: string) => void;
   onDelete: (rule: string) => void;
@@ -154,7 +155,7 @@ export default class RuleDetails extends React.PureComponent<Props, State> {
       return <div className="coding-rule-details" />;
     }
 
-    const { allowCustomRules, canWrite, referencedProfiles } = this.props;
+    const { allowCustomRules, canWrite, referencedProfiles, canDeactivateInherited } = this.props;
     const { params = [] } = ruleDetails;
 
     const isCustom = !!ruleDetails.templateKey;
@@ -240,6 +241,7 @@ export default class RuleDetails extends React.PureComponent<Props, State> {
           {!ruleDetails.isTemplate && (
             <RuleDetailsProfiles
               activations={this.state.actives}
+              canDeactivateInherited={canDeactivateInherited}
               onActivate={this.handleActivate}
               onDeactivate={this.handleDeactivate}
               referencedProfiles={referencedProfiles}
index e72f318e7df33e6c6f99d14d8d90e2307bace069..c5f2e31b5ac448982bb9fd301ad7a0b6eddef0f6 100644 (file)
@@ -33,6 +33,7 @@ import RuleInheritanceIcon from './RuleInheritanceIcon';
 
 interface Props {
   activations: RuleActivation[] | undefined;
+  canDeactivateInherited?: boolean;
   onActivate: () => Promise<void>;
   onDeactivate: () => Promise<void>;
   referencedProfiles: Dict<Profile>;
@@ -126,30 +127,30 @@ export default class RuleDetailsProfiles extends React.PureComponent<Props> {
                 rule={ruleDetails}
               />
             )}
-            {hasParent ? (
-              activation.inherit === 'OVERRIDES' &&
-              profile.parentName && (
-                <ConfirmButton
-                  confirmButtonText={translate('yes')}
-                  confirmData={profile.key}
-                  modalBody={translateWithParameters(
-                    'coding_rules.revert_to_parent_definition.confirm',
-                    profile.parentName,
-                  )}
-                  modalHeader={translate('coding_rules.revert_to_parent_definition')}
-                  onConfirm={this.handleRevert}
-                >
-                  {({ onClick }) => (
-                    <Button
-                      className="coding-rules-detail-quality-profile-revert button-red spacer-left"
-                      onClick={onClick}
-                    >
-                      {translate('coding_rules.revert_to_parent_definition')}
-                    </Button>
-                  )}
-                </ConfirmButton>
-              )
-            ) : (
+
+            {hasParent && activation.inherit === 'OVERRIDES' && profile.parentName && (
+              <ConfirmButton
+                confirmButtonText={translate('yes')}
+                confirmData={profile.key}
+                modalBody={translateWithParameters(
+                  'coding_rules.revert_to_parent_definition.confirm',
+                  profile.parentName,
+                )}
+                modalHeader={translate('coding_rules.revert_to_parent_definition')}
+                onConfirm={this.handleRevert}
+              >
+                {({ onClick }) => (
+                  <Button
+                    className="coding-rules-detail-quality-profile-revert button-red spacer-left"
+                    onClick={onClick}
+                  >
+                    {translate('coding_rules.revert_to_parent_definition')}
+                  </Button>
+                )}
+              </ConfirmButton>
+            )}
+
+            {(!hasParent || this.props.canDeactivateInherited) && (
               <ConfirmButton
                 confirmButtonText={translate('yes')}
                 confirmData={profile.key}
index 8444f8112f435f41e1c90d49c824284dd80aa993..7eef37418c3a9f9725d058c367410085a19572b1 100644 (file)
@@ -27,7 +27,7 @@ export const enum SettingsKey {
   PluginRiskConsent = 'sonar.plugins.risk.consent',
   LicenceRemainingLocNotificationThreshold = 'sonar.license.notifications.remainingLocThreshold',
   TokenMaxAllowedLifetime = 'sonar.auth.token.max.allowed.lifetime',
-  QPAdminCanDisableInheritedRules = 'sonar.allowQualityProfileAdminsDisableInheritedRules',
+  QPAdminCanDisableInheritedRules = 'sonar.qualityProfiles.allowDisableInheritedRules',
 }
 
 export enum GlobalSettingKeys {