aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/coding-rules
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web/src/main/js/apps/coding-rules')
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRules-it.ts53
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/AttributeCategoryFacet.tsx (renamed from server/sonar-web/src/main/js/apps/coding-rules/components/ActivationSeverityFacet.tsx)39
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesApp.tsx15
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/FacetsList.tsx67
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/LanguageFacet.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/ProfileFacet.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/SeverityFacet.tsx69
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/SoftwareQualityFacet.tsx (renamed from server/sonar-web/src/main/js/apps/coding-rules/components/DefaultSeverityFacet.tsx)34
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/query.ts37
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/utils-tests.tsx6
10 files changed, 221 insertions, 101 deletions
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRules-it.ts b/server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRules-it.ts
index 4134304b6c6..a81bc28eee4 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRules-it.ts
+++ b/server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRules-it.ts
@@ -20,7 +20,7 @@
import { act, fireEvent, screen } from '@testing-library/react';
import selectEvent from 'react-select-event';
import CodingRulesServiceMock, { RULE_TAGS_MOCK } from '../../../api/mocks/CodingRulesServiceMock';
-import { RULE_TYPES } from '../../../helpers/constants';
+import { CLEAN_CODE_CATEGORIES, SOFTWARE_QUALITIES } from '../../../helpers/constants';
import { parseDate } from '../../../helpers/dates';
import { mockCurrentUser, mockLoggedInUser } from '../../../helpers/testMocks';
import { dateInputEvent, renderAppRoutes } from '../../../helpers/testReactTestingUtils';
@@ -57,8 +57,12 @@ describe('Rules app list', () => {
1
);
- // Renders type facets
- RULE_TYPES.map((type) => `issue.type.${type}`).forEach((name) =>
+ // Renders clean code categories and software qualities facets
+ CLEAN_CODE_CATEGORIES.map(
+ (category) => `issue.clean_code_attribute_category.${category}`
+ ).forEach((name) => expect(ui.facetItem(name).get()).toBeInTheDocument());
+
+ SOFTWARE_QUALITIES.map((quality) => `issue.software_quality.${quality}`).forEach((name) =>
expect(ui.facetItem(name).get()).toBeInTheDocument()
);
@@ -77,6 +81,7 @@ describe('Rules app list', () => {
ui.availableSinceFacet,
ui.templateFacet,
ui.qpFacet,
+ ui.typeFacet,
].forEach((facet) => {
expect(facet.get()).toHaveAttribute('aria-expanded', 'false');
});
@@ -159,6 +164,31 @@ describe('Rules app list', () => {
await user.click(ui.facetItem('cute').get());
});
expect(ui.ruleListItem.getAll(ui.rulesList.get())).toHaveLength(1);
+
+ // Clear all filters
+ await act(async () => {
+ await user.click(ui.clearAllFiltersButton.get());
+ });
+ expect(ui.ruleListItem.getAll(ui.rulesList.get())).toHaveLength(11);
+
+ // Filter by clean code category
+ await act(async () => {
+ await user.click(ui.facetItem('issue.clean_code_attribute_category.ADAPTABLE').get());
+ });
+ expect(ui.ruleListItem.getAll(ui.rulesList.get())).toHaveLength(10);
+
+ // Filter by software quality
+ await act(async () => {
+ await user.click(ui.facetItem('issue.software_quality.MAINTAINABILITY').get());
+ });
+ expect(ui.ruleListItem.getAll(ui.rulesList.get())).toHaveLength(10);
+
+ // Filter by severity
+ await act(async () => {
+ await user.click(ui.severetiesFacet.get());
+ await user.click(ui.facetItem('severity.HIGH').get());
+ });
+ expect(ui.ruleListItem.getAll(ui.rulesList.get())).toHaveLength(9);
});
it('filter by standards', async () => {
@@ -368,7 +398,8 @@ describe('Rule app details', () => {
ui.ruleCleanCodeAttributeCategory(CleanCodeAttributeCategory.Adaptable).get()
).toBeInTheDocument();
expect(ui.ruleCleanCodeAttribute(CleanCodeAttribute.Clear).get()).toBeInTheDocument();
- expect(ui.ruleSoftwareQuality(SoftwareQuality.Maintainability).get()).toBeInTheDocument();
+ // 1 In Rule details + 1 in facet
+ expect(ui.ruleSoftwareQuality(SoftwareQuality.Maintainability).getAll()).toHaveLength(2);
expect(document.title).toEqual('page_title.template.with_category.coding_rules.page');
expect(screen.getByText('Why')).toBeInTheDocument();
expect(screen.getByText('Because')).toBeInTheDocument();
@@ -683,11 +714,17 @@ describe('redirects', () => {
});
it('should handle hash parameters', async () => {
- renderCodingRulesApp(mockLoggedInUser(), 'coding_rules#languages=c,js|types=BUG');
- // 2 languages
+ const { ui } = getPageObjects();
+
+ renderCodingRulesApp(
+ mockLoggedInUser(),
+ 'coding_rules#languages=c,js|types=BUG|cleanCodeAttributeCategories=ADAPTABLE'
+ );
expect(await screen.findByText('x_selected.2')).toBeInTheDocument();
- expect(screen.getAllByTitle('issue.type.BUG')).toHaveLength(2);
- // Only 3 rules shown
+ expect(screen.getByTitle('issue.type.BUG')).toBeInTheDocument();
+ expect(ui.facetItem('issue.clean_code_attribute_category.ADAPTABLE').get()).toBeChecked();
+
+ // Only 2 rules shown
expect(screen.getByText('x_of_y_shown.2.2')).toBeInTheDocument();
});
});
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationSeverityFacet.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/AttributeCategoryFacet.tsx
index 7754b3efbe3..b0396e8053c 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationSeverityFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/AttributeCategoryFacet.tsx
@@ -18,32 +18,23 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import SeverityHelper from '../../../components/shared/SeverityHelper';
-import { SEVERITIES } from '../../../helpers/constants';
+import { CLEAN_CODE_CATEGORIES } from '../../../helpers/constants';
import { translate } from '../../../helpers/l10n';
import Facet, { BasicProps } from './Facet';
-interface Props extends BasicProps {
- disabled: boolean;
-}
-
-export default class ActivationSeverityFacet extends React.PureComponent<Props> {
- renderName = (severity: string) => <SeverityHelper severity={severity} />;
-
- renderTextName = (severity: string) => translate('severity', severity);
+export default function AttributeCategoryFacet(props: BasicProps) {
+ const renderName = React.useCallback(
+ (attribute: string) => translate('issue.clean_code_attribute_category', attribute),
+ []
+ );
- render() {
- return (
- <Facet
- {...this.props}
- disabled={this.props.disabled}
- disabledHelper={translate('coding_rules.filters.active_severity.inactive')}
- halfWidth
- options={SEVERITIES}
- property="activationSeverities"
- renderName={this.renderName}
- renderTextName={this.renderTextName}
- />
- );
- }
+ return (
+ <Facet
+ {...props}
+ options={CLEAN_CODE_CATEGORIES}
+ property="cleanCodeAttributeCategories"
+ renderName={renderName}
+ renderTextName={renderName}
+ />
+ );
}
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesApp.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesApp.tsx
index 3cef1985e96..3998d0fc355 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesApp.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesApp.tsx
@@ -58,10 +58,8 @@ import {
OpenFacets,
Query,
areQueriesEqual,
- getAppFacet,
getOpen,
getSelected,
- getServerFacet,
hasRuleKey,
parseQuery,
serializeQuery,
@@ -114,7 +112,8 @@ export class CodingRulesApp extends React.PureComponent<Props, State> {
),
sonarsourceSecurity: shouldOpenSonarSourceSecurityFacet({}, query),
standards: shouldOpenStandardsFacet({}, query),
- types: true,
+ cleanCodeAttributeCategories: true,
+ impactSoftwareQualities: true,
},
referencedProfiles: {},
referencedRepositories: {},
@@ -199,8 +198,7 @@ export class CodingRulesApp extends React.PureComponent<Props, State> {
const { openFacets } = this.state;
return Object.keys(openFacets)
.filter((facet: FacetKey) => openFacets[facet])
- .filter((facet: FacetKey) => shouldRequestFacet(facet))
- .map((facet: FacetKey) => getServerFacet(facet));
+ .filter((facet: FacetKey) => shouldRequestFacet(facet));
};
getFieldsToFetch = () => {
@@ -214,6 +212,7 @@ export class CodingRulesApp extends React.PureComponent<Props, State> {
'sysTags',
'tags',
'templateKey',
+ 'cleanCodeAttribute',
];
if (parseQuery(this.props.location.query).profile) {
fields.push('actives', 'params');
@@ -226,7 +225,7 @@ export class CodingRulesApp extends React.PureComponent<Props, State> {
facets: this.getFacetsToFetch().join(),
ps: PAGE_SIZE,
s: 'name',
- ...this.props.location.query,
+ ...serializeQuery(parseQuery(this.props.location.query)),
});
stopLoading = () => {
@@ -299,7 +298,7 @@ export class CodingRulesApp extends React.PureComponent<Props, State> {
};
fetchFacet = (facet: FacetKey) => {
- this.makeFetchRequest({ ps: 1, facets: getServerFacet(facet) }).then(({ facets }) => {
+ this.makeFetchRequest({ ps: 1, facets: facet }).then(({ facets }) => {
if (this.mounted) {
this.setState((state) => ({ facets: { ...state.facets, ...facets }, loading: false }));
}
@@ -711,7 +710,7 @@ function parseFacets(rawFacets: { property: string; values: { count: number; val
for (const rawValue of rawFacet.values) {
values[rawValue.val] = rawValue.count;
}
- facets[getAppFacet(rawFacet.property)] = values;
+ facets[rawFacet.property as FacetKey] = values;
}
return facets;
}
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/FacetsList.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/FacetsList.tsx
index 2d43646bba3..4b8cfe0ca18 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/FacetsList.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/FacetsList.tsx
@@ -21,13 +21,15 @@ import * as React from 'react';
import { Profile } from '../../../api/quality-profiles';
import { Dict } from '../../../types/types';
import { Facets, OpenFacets, Query } from '../query';
-import ActivationSeverityFacet from './ActivationSeverityFacet';
+import AttributeCategoryFacet from './AttributeCategoryFacet';
import AvailableSinceFacet from './AvailableSinceFacet';
-import DefaultSeverityFacet from './DefaultSeverityFacet';
import InheritanceFacet from './InheritanceFacet';
import LanguageFacet from './LanguageFacet';
import ProfileFacet from './ProfileFacet';
+import SoftwareQualityFacet from './SoftwareQualityFacet';
+
import RepositoryFacet from './RepositoryFacet';
+import SeverityFacet from './SeverityFacet';
import { StandardFacet } from './StandardFacet';
import StatusFacet from './StatusFacet';
import TagFacet from './TagFacet';
@@ -54,10 +56,6 @@ export default function FacetsList(props: FacetsListProps) {
props.selectedProfile === undefined ||
!props.selectedProfile.isInherited;
- const activationSeverityDisabled =
- props.query.compareToProfile !== undefined ||
- props.selectedProfile === undefined ||
- !props.query.activation;
return (
<>
<LanguageFacet
@@ -68,18 +66,43 @@ export default function FacetsList(props: FacetsListProps) {
stats={props.facets && props.facets.languages}
values={props.query.languages}
/>
+
+ <AttributeCategoryFacet
+ onChange={props.onFilterChange}
+ onToggle={props.onFacetToggle}
+ open={!!props.openFacets.cleanCodeAttributeCategories}
+ stats={props.facets?.cleanCodeAttributeCategories}
+ values={props.query.cleanCodeAttributeCategories}
+ />
+
+ <SoftwareQualityFacet
+ onChange={props.onFilterChange}
+ onToggle={props.onFacetToggle}
+ open={!!props.openFacets.impactSoftwareQualities}
+ stats={props.facets?.impactSoftwareQualities}
+ values={props.query.impactSoftwareQualities}
+ />
+
+ <SeverityFacet
+ onChange={props.onFilterChange}
+ onToggle={props.onFacetToggle}
+ open={!!props.openFacets.impactSeverities}
+ stats={props.facets?.impactSeverities}
+ values={props.query.impactSeverities}
+ />
+
<TypeFacet
onChange={props.onFilterChange}
onToggle={props.onFacetToggle}
open={!!props.openFacets.types}
- stats={props.facets && props.facets.types}
+ stats={props.facets?.types}
values={props.query.types}
/>
<TagFacet
onChange={props.onFilterChange}
onToggle={props.onFacetToggle}
open={!!props.openFacets.tags}
- stats={props.facets && props.facets.tags}
+ stats={props.facets?.tags}
values={props.query.tags}
/>
<RepositoryFacet
@@ -87,27 +110,21 @@ export default function FacetsList(props: FacetsListProps) {
onToggle={props.onFacetToggle}
open={!!props.openFacets.repositories}
referencedRepositories={props.referencedRepositories}
- stats={props.facets && props.facets.repositories}
+ stats={props.facets?.repositories}
values={props.query.repositories}
/>
- <DefaultSeverityFacet
- onChange={props.onFilterChange}
- onToggle={props.onFacetToggle}
- open={!!props.openFacets.severities}
- stats={props.facets && props.facets.severities}
- values={props.query.severities}
- />
+
<StatusFacet
onChange={props.onFilterChange}
onToggle={props.onFacetToggle}
open={!!props.openFacets.statuses}
- stats={props.facets && props.facets.statuses}
+ stats={props.facets?.statuses}
values={props.query.statuses}
/>
<StandardFacet
cwe={props.query.cwe}
cweOpen={!!props.openFacets.cwe}
- cweStats={props.facets && props.facets.cwe}
+ cweStats={props.facets?.cwe}
fetchingCwe={false}
fetchingOwaspTop10={false}
fetchingOwaspTop10-2021={false}
@@ -117,14 +134,14 @@ export default function FacetsList(props: FacetsListProps) {
open={!!props.openFacets.standards}
owaspTop10={props.query.owaspTop10}
owaspTop10Open={!!props.openFacets.owaspTop10}
- owaspTop10Stats={props.facets && props.facets.owaspTop10}
+ owaspTop10Stats={props.facets?.owaspTop10}
owaspTop10-2021={props.query['owaspTop10-2021']}
owaspTop10-2021Open={!!props.openFacets['owaspTop10-2021']}
- owaspTop10-2021Stats={props.facets && props.facets['owaspTop10-2021']}
+ owaspTop10-2021Stats={props.facets?.['owaspTop10-2021']}
query={props.query}
sonarsourceSecurity={props.query.sonarsourceSecurity}
sonarsourceSecurityOpen={!!props.openFacets.sonarsourceSecurity}
- sonarsourceSecurityStats={props.facets && props.facets.sonarsourceSecurity}
+ sonarsourceSecurityStats={props.facets?.sonarsourceSecurity}
/>
<AvailableSinceFacet
onChange={props.onFilterChange}
@@ -157,14 +174,6 @@ export default function FacetsList(props: FacetsListProps) {
open={!!props.openFacets.inheritance}
value={props.query.inheritance}
/>
- <ActivationSeverityFacet
- disabled={activationSeverityDisabled}
- onChange={props.onFilterChange}
- onToggle={props.onFacetToggle}
- open={!!props.openFacets.activationSeverities}
- stats={props.facets && props.facets.activationSeverities}
- values={props.query.activationSeverities}
- />
</>
)}
</>
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/LanguageFacet.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/LanguageFacet.tsx
index 1e6fc871fbf..81e9b7b44ba 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/LanguageFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/LanguageFacet.tsx
@@ -74,6 +74,7 @@ class LanguageFacet extends React.PureComponent<Props> {
getFacetItemText={this.getLanguageName}
getSearchResultKey={(language) => language.key}
getSearchResultText={(language) => language.name}
+ maxInitialItems={10}
minSearchLength={1}
onChange={this.props.onChange}
onSearch={this.handleSearch}
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/ProfileFacet.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/ProfileFacet.tsx
index 8c9c3247362..f791e997634 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/ProfileFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/ProfileFacet.tsx
@@ -56,7 +56,6 @@ export default class ProfileFacet extends React.PureComponent<Props> {
handleClear = () =>
this.props.onChange({
activation: undefined,
- activationSeverities: [],
compareToProfile: undefined,
inheritance: undefined,
profile: undefined,
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/SeverityFacet.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/SeverityFacet.tsx
new file mode 100644
index 00000000000..cdb4f11e5b9
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/SeverityFacet.tsx
@@ -0,0 +1,69 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import DocumentationTooltip from '../../../components/common/DocumentationTooltip';
+import SoftwareImpactSeverityIcon from '../../../components/icons/SoftwareImpactSeverityIcon';
+import { IMPACT_SEVERITIES } from '../../../helpers/constants';
+import { translate } from '../../../helpers/l10n';
+import Facet, { BasicProps } from './Facet';
+
+export default function SeverityFacet(props: BasicProps) {
+ const renderName = React.useCallback(
+ (severity: string) => (
+ <div className="sw-flex">
+ <SoftwareImpactSeverityIcon severity={severity} />
+ <span className="sw-ml-1">{translate('severity', severity)}</span>
+ </div>
+ ),
+ []
+ );
+
+ const renderTextName = React.useCallback(
+ (severity: string) => translate('severity', severity),
+ []
+ );
+
+ return (
+ <Facet
+ {...props}
+ options={IMPACT_SEVERITIES}
+ property="impactSeverities"
+ renderName={renderName}
+ renderTextName={renderTextName}
+ >
+ <DocumentationTooltip
+ className="spacer-left"
+ placement="right"
+ content={
+ <>
+ <p>{translate('issues.facet.impactSeverities.help.line1')}</p>
+ <p className="sw-mt-2">{translate('issues.facet.impactSeverities.help.line2')}</p>
+ </>
+ }
+ links={[
+ {
+ href: '/user-guide/clean-code',
+ label: translate('learn_more'),
+ },
+ ]}
+ />
+ </Facet>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/DefaultSeverityFacet.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/SoftwareQualityFacet.tsx
index da51af94cd6..59d0da4736b 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/components/DefaultSeverityFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/components/SoftwareQualityFacet.tsx
@@ -17,27 +17,25 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
import * as React from 'react';
-import SeverityHelper from '../../../components/shared/SeverityHelper';
-import { SEVERITIES } from '../../../helpers/constants';
+import { SOFTWARE_QUALITIES } from '../../../helpers/constants';
import { translate } from '../../../helpers/l10n';
import Facet, { BasicProps } from './Facet';
-export default class DefaultSeverityFacet extends React.PureComponent<BasicProps> {
- renderName = (severity: string) => <SeverityHelper severity={severity} />;
-
- renderTextName = (severity: string) => translate('severity', severity);
+export default function SoftwareQualityFacet(props: BasicProps) {
+ const renderName = React.useCallback(
+ (quality: string) => translate('issue.software_quality', quality),
+ []
+ );
- render() {
- return (
- <Facet
- {...this.props}
- halfWidth
- options={SEVERITIES}
- property="severities"
- renderName={this.renderName}
- renderTextName={this.renderTextName}
- />
- );
- }
+ return (
+ <Facet
+ {...props}
+ options={SOFTWARE_QUALITIES}
+ property="impactSoftwareQualities"
+ renderName={renderName}
+ renderTextName={renderName}
+ />
+ );
}
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/query.ts b/server/sonar-web/src/main/js/apps/coding-rules/query.ts
index 540ebece009..eb31bc35298 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/query.ts
+++ b/server/sonar-web/src/main/js/apps/coding-rules/query.ts
@@ -24,20 +24,28 @@ import {
parseAsOptionalBoolean,
parseAsOptionalString,
parseAsString,
+ parseImpactSeverityQuery,
queriesEqual,
serializeDateShort,
serializeOptionalBoolean,
serializeString,
serializeStringArray,
} from '../../helpers/query';
+import {
+ CleanCodeAttributeCategory,
+ SoftwareImpactSeverity,
+ SoftwareQuality,
+} from '../../types/clean-code-taxonomy';
import { Dict, RawQuery, RuleInheritance } from '../../types/types';
export interface Query {
activation: boolean | undefined;
- activationSeverities: string[];
availableSince: Date | undefined;
+ cleanCodeAttributeCategories: CleanCodeAttributeCategory[];
compareToProfile: string | undefined;
cwe: string[];
+ impactSeverities: SoftwareImpactSeverity[];
+ impactSoftwareQualities: SoftwareQuality[];
inheritance: RuleInheritance | undefined;
languages: string[];
owaspTop10: string[];
@@ -78,10 +86,18 @@ export interface Actives {
export function parseQuery(query: RawQuery): Query {
return {
activation: parseAsOptionalBoolean(query.activation),
- activationSeverities: parseAsArray(query.active_severities, parseAsString),
availableSince: parseAsDate(query.available_since),
+ cleanCodeAttributeCategories: parseAsArray<CleanCodeAttributeCategory>(
+ query.cleanCodeAttributeCategories,
+ parseAsString
+ ),
compareToProfile: parseAsOptionalString(query.compareToProfile),
cwe: parseAsArray(query.cwe, parseAsString),
+ impactSeverities: parseImpactSeverityQuery(query.impactSeverities, query.severities),
+ impactSoftwareQualities: parseAsArray<SoftwareQuality>(
+ query.impactSoftwareQualities,
+ parseAsString
+ ),
inheritance: parseAsInheritance(query.inheritance),
languages: parseAsArray(query.languages, parseAsString),
owaspTop10: parseAsArray(query.owaspTop10, parseAsString),
@@ -102,11 +118,13 @@ export function parseQuery(query: RawQuery): Query {
export function serializeQuery(query: Query): RawQuery {
return cleanQuery({
activation: serializeOptionalBoolean(query.activation),
- active_severities: serializeStringArray(query.activationSeverities),
available_since: serializeDateShort(query.availableSince),
+ cleanCodeAttributeCategories: serializeStringArray(query.cleanCodeAttributeCategories),
compareToProfile: serializeString(query.compareToProfile),
cwe: serializeStringArray(query.cwe),
inheritance: serializeInheritance(query.inheritance),
+ impactSeverities: serializeStringArray(query.impactSeverities),
+ impactSoftwareQualities: serializeStringArray(query.impactSoftwareQualities),
is_template: serializeOptionalBoolean(query.template),
languages: serializeStringArray(query.languages),
owaspTop10: serializeStringArray(query.owaspTop10),
@@ -115,7 +133,7 @@ export function serializeQuery(query: Query): RawQuery {
qprofile: serializeString(query.profile),
repositories: serializeStringArray(query.repositories),
rule_key: serializeString(query.ruleKey),
- severities: serializeStringArray(query.severities),
+ severities: undefined,
sonarsourceSecurity: serializeStringArray(query.sonarsourceSecurity),
statuses: serializeStringArray(query.statuses),
tags: serializeStringArray(query.tags),
@@ -141,18 +159,13 @@ export function shouldRequestFacet(facet: string): facet is FacetKey {
'statuses',
'tags',
'types',
+ 'cleanCodeAttributeCategories',
+ 'impactSoftwareQualities',
+ 'impactSeverities',
];
return facetsToRequest.includes(facet);
}
-export function getServerFacet(facet: FacetKey) {
- return facet === 'activationSeverities' ? 'active_severities' : facet;
-}
-
-export function getAppFacet(serverFacet: string): FacetKey {
- return serverFacet === 'active_severities' ? 'activationSeverities' : (serverFacet as FacetKey);
-}
-
export function getOpen(query: RawQuery) {
return query.open;
}
diff --git a/server/sonar-web/src/main/js/apps/coding-rules/utils-tests.tsx b/server/sonar-web/src/main/js/apps/coding-rules/utils-tests.tsx
index 8847ba6f056..dd518f5c590 100644
--- a/server/sonar-web/src/main/js/apps/coding-rules/utils-tests.tsx
+++ b/server/sonar-web/src/main/js/apps/coding-rules/utils-tests.tsx
@@ -41,11 +41,15 @@ const selectors = {
clearAllFiltersButton: byRole('button', { name: 'clear_all_filters' }),
// Facets
+ cleanCodeCategoriesFacet: byRole('button', {
+ name: 'coding_rules.facet.cleanCodeAttributeCategories',
+ }),
languagesFacet: byRole('button', { name: 'coding_rules.facet.languages' }),
typeFacet: byRole('button', { name: 'coding_rules.facet.types' }),
tagsFacet: byRole('button', { name: 'coding_rules.facet.tags' }),
repositoriesFacet: byRole('button', { name: 'coding_rules.facet.repositories' }),
- severetiesFacet: byRole('button', { name: 'coding_rules.facet.severities' }),
+ softwareQualitiesFacet: byRole('button', { name: 'coding_rules.facet.impactSoftwareQualities' }),
+ severetiesFacet: byRole('button', { name: 'coding_rules.facet.impactSeverities' }),
statusesFacet: byRole('button', { name: 'coding_rules.facet.statuses' }),
standardsFacet: byRole('button', { name: 'issues.facet.standards' }),
standardsOwasp2017Top10Facet: byRole('button', { name: 'issues.facet.owaspTop10' }),