From e811e3183bedf03b78096012c3654da1b2ef414e Mon Sep 17 00:00:00 2001 From: Viktor Vorona Date: Wed, 16 Oct 2024 13:18:21 +0200 Subject: SONAR-23250 Ignore the order of impacts on showing the customization info --- .../coding-rules/__tests__/CodingRuleDetails-it.ts | 38 ++++- .../components/RuleDetailsProfiles.tsx | 171 +++++++++++---------- .../changelog/__tests__/ChangelogContainer-it.tsx | 3 + .../quality-profiles/compare/ComparisonResults.tsx | 9 +- 4 files changed, 126 insertions(+), 95 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRuleDetails-it.ts b/server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRuleDetails-it.ts index a5010470c86..e9b4b398af5 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRuleDetails-it.ts +++ b/server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRuleDetails-it.ts @@ -18,14 +18,15 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { fireEvent, screen } from '@testing-library/react'; +import { byRole } from '~sonar-aligned/helpers/testSelector'; import CodingRulesServiceMock, { RULE_TAGS_MOCK } from '../../../api/mocks/CodingRulesServiceMock'; import SettingsServiceMock from '../../../api/mocks/SettingsServiceMock'; -import { RULE_1 } from '../../../api/mocks/data/ids'; -import { mockCurrentUser, mockLoggedInUser } from '../../../helpers/testMocks'; -import { byRole } from '../../../sonar-aligned/helpers/testSelector'; +import { QP_2, RULE_1, RULE_10 } from '../../../api/mocks/data/ids'; +import { mockCurrentUser, mockLoggedInUser, mockRuleActivation } from '../../../helpers/testMocks'; import { CleanCodeAttribute, CleanCodeAttributeCategory, + SoftwareImpactSeverity, SoftwareQuality, } from '../../../types/clean-code-taxonomy'; import { Feature } from '../../../types/features'; @@ -35,8 +36,8 @@ import { getPageObjects, renderCodingRulesApp } from '../utils-tests'; const rulesHandler = new CodingRulesServiceMock(); const settingsHandler = new SettingsServiceMock(); afterEach(() => { - rulesHandler.reset(); settingsHandler.reset(); + rulesHandler.reset(); }); describe('rendering', () => { @@ -169,6 +170,33 @@ describe('rendering', () => { expect(ui.caycNotificationButton.query()).not.toBeInTheDocument(); }); + + it('should not show customized severity if the order of impacts is different', async () => { + const { ui } = getPageObjects(); + rulesHandler.rulesActivations = { + [RULE_10]: [ + mockRuleActivation({ + qProfile: QP_2, + severity: 'MINOR', + impacts: [ + { + softwareQuality: SoftwareQuality.Reliability, + severity: SoftwareImpactSeverity.High, + }, + { + softwareQuality: SoftwareQuality.Maintainability, + severity: SoftwareImpactSeverity.Low, + }, + ], + }), + ], + }; + renderCodingRulesApp(mockCurrentUser(), 'coding_rules?open=rule10'); + + await ui.detailsloaded(); + + expect(ui.newSeverityCustomizedCell.query()).not.toBeInTheDocument(); + }); }); it('can activate/change/deactivate rule in quality profile', async () => { @@ -240,7 +268,7 @@ it('can activate/change/deactivate rule in quality profile', async () => { it('can activate/change/deactivate rule in quality profile for legacy mode', async () => { const { ui, user } = getPageObjects(); - settingsHandler.set(SettingsKey.MQRMode, 'true'); + settingsHandler.set(SettingsKey.MQRMode, 'false'); rulesHandler.setIsAdmin(); renderCodingRulesApp(mockLoggedInUser(), 'coding_rules?open=rule1', [Feature.PrioritizedRules]); await ui.detailsloaded(); diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsProfiles.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsProfiles.tsx index 52a91e8babc..29b0f06e319 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsProfiles.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsProfiles.tsx @@ -44,7 +44,8 @@ import { useActivateRuleMutation, useDeactivateRuleMutation, } from '../../../queries/quality-profiles'; -import { useIsLegacyCCTMode } from '../../../queries/settings'; +import { useStandardExperienceMode } from '../../../queries/settings'; +import { SoftwareImpact } from '../../../types/clean-code-taxonomy'; import { Dict, RuleActivation, RuleDetails } from '../../../types/types'; import BuiltInQualityProfileBadge from '../../quality-profiles/components/BuiltInQualityProfileBadge'; import ActivatedRuleActions from './ActivatedRuleActions'; @@ -71,7 +72,7 @@ export default function RuleDetailsProfiles(props: Readonly) { const { activations = [], referencedProfiles, ruleDetails, canDeactivateInherited } = props; const { mutate: activateRule } = useActivateRuleMutation(props.onActivate); const { mutate: deactivateRule } = useDeactivateRuleMutation(props.onDeactivate); - const { data: isLegacy } = useIsLegacyCCTMode(); + const { data: isStandardMode } = useStandardExperienceMode(); const canActivate = Object.values(referencedProfiles).some((profile) => Boolean(profile.actions?.edit && profile.language === ruleDetails.lang), @@ -144,6 +145,12 @@ export default function RuleDetailsProfiles(props: Readonly) { ) : null; + const sortImpacts = (a: SoftwareImpact, b: SoftwareImpact) => { + const indexA = softwareQualityOrderMap.get(a.softwareQuality) ?? -1; + const indexB = softwareQualityOrderMap.get(b.softwareQuality) ?? -1; + return indexA - indexB; + }; + return ( @@ -163,73 +170,65 @@ export default function RuleDetailsProfiles(props: Readonly) { {translate('coding_rules.prioritized_rule.title')} )} - {!isLegacy && + {!isStandardMode && activation.impacts && - !isEqual(activation.impacts, ruleDetails.impacts) && ( + !isEqual( + [...activation.impacts].sort(sortImpacts), + [...ruleDetails.impacts].sort(sortImpacts), + ) && ( <> - {[...activation.impacts] - .sort((a, b) => { - const indexA = softwareQualityOrderMap.get(a.softwareQuality) ?? -1; - const indexB = softwareQualityOrderMap.get(b.softwareQuality) ?? -1; - return indexA - indexB; - }) - .map((impact) => { - const ruleImpact = ruleDetails.impacts.find( - (i) => i.softwareQuality === impact.softwareQuality, - ); - if (!ruleImpact || ruleImpact.severity === impact.severity) { - return null; - } - return ( - - - - - ), - recommended: ( - - - - ), - customized: ( - - - - ), - }} - /> - - ); - })} + {[...activation.impacts].sort(sortImpacts).map((impact) => { + const ruleImpact = ruleDetails.impacts.find( + (i) => i.softwareQuality === impact.softwareQuality, + ); + if (!ruleImpact || ruleImpact.severity === impact.severity) { + return null; + } + return ( + + + + + ), + recommended: ( + + + + ), + customized: ( + + + + ), + }} + /> + + ); + })} } > @@ -238,28 +237,30 @@ export default function RuleDetailsProfiles(props: Readonly) { )} - {isLegacy && activation.severity && activation.severity !== ruleDetails.severity && ( - <> - - - - - - ), - customized: ( - - - - ), - }} - /> - - - )} + {isStandardMode && + activation.severity && + activation.severity !== ruleDetails.severity && ( + <> + + + + + + ), + customized: ( + + + + ), + }} + /> + + + )} {profile.isBuiltIn && } diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogContainer-it.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogContainer-it.tsx index b1d4c2b24ff..66b303fb58f 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogContainer-it.tsx +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogContainer-it.tsx @@ -21,6 +21,7 @@ import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { byRole, byText } from '~sonar-aligned/helpers/testSelector'; import QualityProfilesServiceMock from '../../../../api/mocks/QualityProfilesServiceMock'; +import SettingsServiceMock from '../../../../api/mocks/SettingsServiceMock'; import { mockQualityProfileChangelogEvent } from '../../../../helpers/testMocks'; import { renderAppRoutes } from '../../../../helpers/testReactTestingUtils'; import routes from '../../routes'; @@ -28,6 +29,7 @@ import routes from '../../routes'; jest.mock('../../../../api/quality-profiles'); const serviceMock = new QualityProfilesServiceMock(); +const settingsMock = new SettingsServiceMock(); const ui = { row: byRole('row'), cell: byRole('cell'), @@ -75,6 +77,7 @@ afterEach(() => { jest.useRealTimers(); serviceMock.reset(); + settingsMock.reset(); }); it('should see the changelog', async () => { diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.tsx index 1f66dbd9dfb..da85a1fd73c 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.tsx +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.tsx @@ -233,15 +233,14 @@ type RuleCellProps = { function RuleCell({ rule, severity, impacts }: Readonly) { const { data: isStandardMode } = useStandardExperienceMode(); const shouldRenderSeverity = - isStandardMode &&Boolean(severity) && + isStandardMode && + Boolean(severity) && rule.left?.severity && rule.right?.severity && - !isEqual(rule.left.severity, - rule.right.severity); + !isEqual(rule.left.severity, rule.right.severity); const shouldRenderImpacts = rule.impacts || - (rule.left?.impacts && rule.right?.impacts && - !isEqual(rule.left.impacts, rule.right.impacts)); + (rule.left?.impacts && rule.right?.impacts && !isEqual(rule.left.impacts, rule.right.impacts)); return (
-- cgit v1.2.3