diff options
author | Revanshu Paliwal <revanshu.paliwal@sonarsource.com> | 2022-07-21 12:00:13 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-07-22 20:03:01 +0000 |
commit | d64ee92295a48e1ce3c7af7fb7f6425bb38bada0 (patch) | |
tree | 9375f7ecaafc623c0d70e31426c6306ad706724a /server | |
parent | 3dedd84e8151ea9183459c8564c0464179e0bdff (diff) | |
download | sonarqube-d64ee92295a48e1ce3c7af7fb7f6425bb38bada0.tar.gz sonarqube-d64ee92295a48e1ce3c7af7fb7f6425bb38bada0.zip |
SONAR-16598 Fixing extended rule description bug in issue page
Diffstat (limited to 'server')
4 files changed, 36 insertions, 19 deletions
diff --git a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts index 0188a721882..e2da3d0c923 100644 --- a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts +++ b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts @@ -254,6 +254,7 @@ export default class IssuesServiceMock { rule: mockRuleDetails({ key: parameters.key, name: 'Advanced rule', + htmlNote: '<h1>Extended Description</h1>', educationPrinciples: ['defense_in_depth'], descriptionSections: [ { key: RuleDescriptionSections.INTRODUCTION, content: '<h1>Into</h1>' }, diff --git a/server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx b/server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx index b3bf900e1cb..ddabf99750b 100644 --- a/server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx +++ b/server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx @@ -87,11 +87,15 @@ it('should open issue and navigate', async () => { expect(screen.getByText('coding_rules.context.others.description.first')).toBeInTheDocument(); expect(screen.getByText('coding_rules.context.others.description.second')).toBeInTheDocument(); - // Select the resources tab and check its content + // Select the main info tab and check its content expect(screen.getByRole('button', { name: `issue.tabs.more_info` })).toBeInTheDocument(); await user.click(screen.getByRole('button', { name: `issue.tabs.more_info` })); expect(screen.getByRole('heading', { name: 'Link' })).toBeInTheDocument(); + // check for extended description + const extendedDescriptions = screen.getAllByText('Extended Description'); + expect(extendedDescriptions).toHaveLength(1); + // Select the previous issue (with a simple rule) through keyboard shortcut await user.keyboard('{ArrowUp}'); diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssueTabViewer.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssueTabViewer.tsx index 52b264780b6..578c7faec8c 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssueTabViewer.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/IssueTabViewer.tsx @@ -55,22 +55,6 @@ export default class IssueViewerTabs extends React.PureComponent<Props> { !!ruleDetails.educationPrinciples && ruleDetails.educationPrinciples.length > 0; const showNotification = showNotice && hasEducationPrinciples; - if (ruleDetails.htmlNote) { - if (descriptionSectionsByKey[RuleDescriptionSections.RESOURCES] !== undefined) { - // We add the extended description (htmlNote) in the first context, in case there are contexts - // Extended description will get reworked in future - descriptionSectionsByKey[RuleDescriptionSections.RESOURCES][0].content += - '<br/>' + ruleDetails.htmlNote; - } else { - descriptionSectionsByKey[RuleDescriptionSections.RESOURCES] = [ - { - key: RuleDescriptionSections.RESOURCES, - content: ruleDetails.htmlNote - } - ]; - } - } - const rootCauseDescriptionSections = descriptionSectionsByKey[RuleDescriptionSections.DEFAULT] || descriptionSectionsByKey[RuleDescriptionSections.ROOT_CAUSE]; diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx index 79f773c9221..49dc85b3a96 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx @@ -19,7 +19,7 @@ */ import styled from '@emotion/styled'; import classNames from 'classnames'; -import { debounce, keyBy, omit, without } from 'lodash'; +import { debounce, groupBy, keyBy, omit, without } from 'lodash'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { FormattedMessage } from 'react-intl'; @@ -74,6 +74,7 @@ import { import { SecurityStandard } from '../../../types/security'; import { Component, Dict, Issue, Paging, RawQuery, RuleDetails } from '../../../types/types'; import { CurrentUser, UserBase } from '../../../types/users'; +import { RuleDescriptionSections } from '../../coding-rules/rule'; import * as actions from '../actions'; import ConciseIssuesList from '../conciseIssuesList/ConciseIssuesList'; import ConciseIssuesListHeader from '../conciseIssuesList/ConciseIssuesListHeader'; @@ -354,13 +355,40 @@ export class App extends React.PureComponent<Props, State> { } this.setState({ loadingRule: true }); const openRuleDetails = await getRuleDetails({ key: openIssue.rule }) - .then(response => response.rule) + .then(response => { + const ruleDetails = response.rule; + this.addExtendedDescription(ruleDetails); + return ruleDetails; + }) .catch(() => undefined); if (this.mounted) { this.setState({ loadingRule: false, openRuleDetails }); } } + addExtendedDescription = (ruleDetails: RuleDetails) => { + const descriptionSectionsByKey = groupBy( + ruleDetails.descriptionSections, + section => section.key + ); + + if (ruleDetails.htmlNote) { + if (descriptionSectionsByKey[RuleDescriptionSections.RESOURCES] !== undefined) { + // We add the extended description (htmlNote) in the first context, in case there are contexts + // Extended description will get reworked in future + descriptionSectionsByKey[RuleDescriptionSections.RESOURCES][0].content += + '<br/>' + ruleDetails.htmlNote; + } else { + descriptionSectionsByKey[RuleDescriptionSections.RESOURCES] = [ + { + key: RuleDescriptionSections.RESOURCES, + content: ruleDetails.htmlNote + } + ]; + } + } + }; + selectPreviousIssue = () => { const { issues } = this.state; const selectedIndex = this.getSelectedIndex(); |