ADVANCED_RULE,
QP_1,
QP_2,
+ QP_4,
+ QP_5,
RULE_1,
RULE_10,
RULE_11,
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' })],
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())));
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());
// 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());
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();
<RuleDetails
allowCustomRules
canWrite={this.state.canWrite}
+ canDeactivateInherited={this.state.canDeactivateInherited}
onActivate={this.handleRuleActivate}
onDeactivate={this.handleRuleDeactivate}
onDelete={this.handleRuleDelete}
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;
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;
{!ruleDetails.isTemplate && (
<RuleDetailsProfiles
activations={this.state.actives}
+ canDeactivateInherited={canDeactivateInherited}
onActivate={this.handleActivate}
onDeactivate={this.handleDeactivate}
referencedProfiles={referencedProfiles}
interface Props {
activations: RuleActivation[] | undefined;
+ canDeactivateInherited?: boolean;
onActivate: () => Promise<void>;
onDeactivate: () => Promise<void>;
referencedProfiles: Dict<Profile>;
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}
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 {