]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19036 Facets should update their content even if they are collapsed (#8109)
authorvikvorona <viktor.vorona@sonarsource.com>
Fri, 21 Apr 2023 07:21:18 +0000 (09:21 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 21 Apr 2023 20:02:53 +0000 (20:02 +0000)
server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx
server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx
server/sonar-web/src/main/js/apps/issues/test-utils.tsx

index ec11f62ad5b721ff73d914db3af2867490103b0c..46bedfce13d94b402b7fb09bf41265b6069a2ead 100644 (file)
@@ -620,8 +620,12 @@ export default class IssuesServiceMock {
     });
   };
 
-  mockFacetDetailResponse = (facetsQuery: string): RawFacet[] => {
-    return facetsQuery.split(',').map((name: string): RawFacet => {
+  mockFacetDetailResponse = (query: RequestData): RawFacet[] => {
+    const facets = (query.facets ?? '').split(',');
+    const types: Exclude<IssueType, IssueType.SecurityHotspot>[] = (
+      query.types ?? 'BUG,CODE_SMELL,VULNERABILITY'
+    ).split(',');
+    return facets.map((name: string): RawFacet => {
       if (name === 'owaspTop10-2021') {
         return this.owasp2021FacetList();
       }
@@ -678,16 +682,21 @@ export default class IssuesServiceMock {
         };
       }
       if (name === 'languages') {
+        const counters = {
+          [IssueType.Bug]: { java: 4100, ts: 500 },
+          [IssueType.CodeSmell]: { java: 21000, ts: 2000 },
+          [IssueType.Vulnerability]: { java: 111, ts: 674 },
+        };
         return {
           property: name,
           values: [
             {
               val: 'java',
-              count: 25211,
+              count: types.reduce<number>((acc, type) => acc + counters[type].java, 0),
             },
             {
               val: 'ts',
-              count: 3174,
+              count: types.reduce<number>((acc, type) => acc + counters[type].ts, 0),
             },
           ],
         };
@@ -700,7 +709,7 @@ export default class IssuesServiceMock {
   };
 
   handleSearchIssues = (query: RequestData): Promise<RawIssuesResponse> => {
-    const facets = this.mockFacetDetailResponse((query.facets ?? '') as string);
+    const facets = this.mockFacetDetailResponse(query);
 
     // Filter list (only supports assignee, type and severity)
     const filteredList = this.list
index 212d1d4a38e39b14199c43f66aaaf97aadfdf3c2..e90b41b0a4e5f3fd73d7f54ffc2d9a73fe98b179 100644 (file)
@@ -499,6 +499,33 @@ describe('issues app', () => {
         })
       ).not.toBeInTheDocument();
     });
+
+    it('should update collapsed facets with filter change', async () => {
+      const user = userEvent.setup();
+
+      renderIssueApp();
+
+      await user.click(await ui.languageFacet.find());
+      expect(await ui.languageFacetList.find()).toBeInTheDocument();
+      expect(
+        within(ui.languageFacetList.get()).getByRole('checkbox', { name: 'java' })
+      ).toHaveTextContent('java25short_number_suffix.k');
+      expect(
+        within(ui.languageFacetList.get()).getByRole('checkbox', { name: 'ts' })
+      ).toHaveTextContent('ts3.2short_number_suffix.k');
+
+      await user.click(ui.languageFacet.get());
+      expect(ui.languageFacetList.query()).not.toBeInTheDocument();
+      await user.click(ui.vulnerabilityIssueTypeFilter.get());
+      await user.click(ui.languageFacet.get());
+      expect(await ui.languageFacetList.find()).toBeInTheDocument();
+      expect(
+        within(ui.languageFacetList.get()).getByRole('checkbox', { name: 'java' })
+      ).toHaveTextContent('java111');
+      expect(
+        within(ui.languageFacetList.get()).getByRole('checkbox', { name: 'ts' })
+      ).toHaveTextContent('ts674');
+    });
   });
 });
 
index 1cdb44ae166f8643436d9c54bf7c2ccac3b62010..ffad87ea9bb965964eba1e27348570b90176a4bd 100644 (file)
@@ -33,11 +33,11 @@ import A11ySkipTarget from '../../../components/a11y/A11ySkipTarget';
 import EmptySearch from '../../../components/common/EmptySearch';
 import FiltersHeader from '../../../components/common/FiltersHeader';
 import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper';
-import { Button } from '../../../components/controls/buttons';
 import ButtonToggle from '../../../components/controls/ButtonToggle';
 import Checkbox from '../../../components/controls/Checkbox';
 import HelpTooltip from '../../../components/controls/HelpTooltip';
 import ListFooter from '../../../components/controls/ListFooter';
+import { Button } from '../../../components/controls/buttons';
 import Suggestions from '../../../components/embed-docs-modal/Suggestions';
 import withIndexationGuard from '../../../components/hoc/withIndexationGuard';
 import { Location, Router, withRouter } from '../../../components/hoc/withRouter';
@@ -82,19 +82,19 @@ import ConciseIssuesListHeader from '../conciseIssuesList/ConciseIssuesListHeade
 import Sidebar from '../sidebar/Sidebar';
 import '../styles.css';
 import {
+  Query,
+  STANDARDS,
   areMyIssuesSelected,
   areQueriesEqual,
   getOpen,
   getOpenIssue,
   parseFacets,
   parseQuery,
-  Query,
   saveMyIssues,
   serializeQuery,
   shouldOpenSonarSourceSecurityFacet,
   shouldOpenStandardsChildFacet,
   shouldOpenStandardsFacet,
-  STANDARDS,
 } from '../utils';
 import BulkChangeModal, { MAX_PAGE_SIZE } from './BulkChangeModal';
 import IssueHeader from './IssueHeader';
@@ -503,10 +503,10 @@ export class App extends React.PureComponent<Props, State> {
           if (issues.length > 0) {
             selected = openIssue ? openIssue.key : issues[0].key;
           }
-          this.setState((state) => ({
+          this.setState({
             cannotShowOpenIssue: Boolean(openIssueKey && !openIssue),
             effortTotal,
-            facets: { ...state.facets, ...parseFacets(facets) },
+            facets: parseFacets(facets),
             loading: false,
             locationsNavigator: true,
             issues,
@@ -520,7 +520,7 @@ export class App extends React.PureComponent<Props, State> {
             selected,
             selectedFlowIndex: 0,
             selectedLocationIndex: undefined,
-          }));
+          });
         }
         return issues;
       },
index 5d92bcddc32d5398d53825f85f813494ba155ead..04f53c899df73fe62006e6da3f613b14599ef90c 100644 (file)
@@ -68,6 +68,7 @@ export const ui = {
   clearStatusFacet: byRole('button', { name: 'clear_x_filter.issues.facet.statuses' }),
   openStatusFilter: byRole('checkbox', { name: 'issue.status.OPEN' }),
   confirmedStatusFilter: byRole('checkbox', { name: 'issue.status.CONFIRMED' }),
+  languageFacet: byRole('button', { name: 'issues.facet.languages' }),
   ruleFacet: byRole('button', { name: 'issues.facet.rules' }),
   clearRuleFacet: byRole('button', { name: 'clear_x_filter.issues.facet.rules' }),
   tagFacet: byRole('button', { name: 'issues.facet.tags' }),
@@ -85,6 +86,7 @@ export const ui = {
   clearAllFilters: byRole('button', { name: 'clear_all_filters' }),
 
   ruleFacetList: byRole('list', { name: 'rules' }),
+  languageFacetList: byRole('list', { name: 'languages' }),
   ruleFacetSearch: byRole('searchbox', { name: 'search.search_for_rules' }),
 };