]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18555 Migrate issues app sidebar to RTL
author7PH <benjamin.raymond@sonarsource.com>
Tue, 28 Mar 2023 15:57:12 +0000 (17:57 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 30 Mar 2023 20:03:06 +0000 (20:03 +0000)
41 files changed:
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/crossComponentSourceViewer/__tests__/__snapshots__/CrossComponentSourceViewer-test.tsx.snap
server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AuthorFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/CreationDateFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/DirectoryFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/FileFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/PeriodFilter-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/ProjectFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/RuleFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/ScopeFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StatusFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/TypeFacet-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AuthorFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/CreationDateFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/DirectoryFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/FileFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ProjectFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/RuleFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ScopeFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StatusFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/TypeFacet-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewer-test.tsx.snap
server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineIssueList-test.tsx.snap
server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueView-test.tsx.snap
server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/issue-test.tsx.snap
server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx
server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueActionsBar-test.tsx.snap
server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap
server/sonar-web/src/main/js/helpers/mocks/issues.ts
server/sonar-web/src/main/js/helpers/testMocks.ts
server/sonar-web/src/main/js/types/issues.ts
server/sonar-web/src/main/js/types/types.ts

index ec195133c9a967812224ec9b1b0eee4e29896584..f9f348b8a164584f36d506ae90c878d4dae32f19 100644 (file)
@@ -31,6 +31,10 @@ import {
 } from '../../helpers/testMocks';
 import {
   ASSIGNEE_ME,
+  IssueResolution,
+  IssueScope,
+  IssueSeverity,
+  IssueStatus,
   IssueType,
   RawFacet,
   RawIssue,
@@ -103,6 +107,7 @@ export default class IssuesServiceMock {
         issue: mockRawIssue(false, {
           key: 'issue101',
           component: 'foo:test1.js',
+          creationDate: '2023-01-05T09:36:01+0100',
           message: 'Issue with no location message',
           type: IssueType.Vulnerability,
           rule: 'simpleRuleId',
@@ -140,6 +145,9 @@ export default class IssuesServiceMock {
               ],
             },
           ],
+          resolution: IssueResolution.WontFix,
+          scope: IssueScope.Main,
+          tags: ['tag0', 'tag1'],
         }),
         snippets: keyBy(
           [
@@ -163,6 +171,7 @@ export default class IssuesServiceMock {
           component: 'foo:test1.js',
           message: 'FlowIssue',
           type: IssueType.CodeSmell,
+          severity: IssueSeverity.Minor,
           rule: 'simpleRuleId',
           textRange: {
             startLine: 10,
@@ -233,6 +242,7 @@ export default class IssuesServiceMock {
               ],
             },
           ],
+          tags: ['tag1'],
         }),
         snippets: keyBy(
           [
@@ -256,10 +266,11 @@ export default class IssuesServiceMock {
           component: 'foo:test1.js',
           message: 'Issue on file',
           assignee: mockLoggedInUser().login,
-          type: IssueType.Vulnerability,
+          type: IssueType.CodeSmell,
           rule: 'simpleRuleId',
           textRange: undefined,
           line: undefined,
+          scope: IssueScope.Test,
         }),
         snippets: {},
       },
@@ -338,6 +349,8 @@ export default class IssuesServiceMock {
             endOffset: 1,
           },
           ruleDescriptionContextKey: 'spring',
+          resolution: IssueResolution.Unresolved,
+          status: IssueStatus.Open,
         }),
         snippets: keyBy(
           [
@@ -362,6 +375,8 @@ export default class IssuesServiceMock {
             startOffset: 0,
             endOffset: 1,
           },
+          resolution: IssueResolution.Fixed,
+          status: IssueStatus.Confirmed,
         }),
         snippets: keyBy(
           [
@@ -381,7 +396,7 @@ export default class IssuesServiceMock {
           key: 'issue4',
           component: 'foo:test2.js',
           message: 'Issue with tags',
-          rule: 'external_eslint_repo:no-div-regex',
+          rule: 'other',
           textRange: {
             startLine: 25,
             endLine: 25,
@@ -391,6 +406,10 @@ export default class IssuesServiceMock {
           ruleDescriptionContextKey: 'spring',
           ruleStatus: 'DEPRECATED',
           quickFixAvailable: true,
+          tags: ['unused'],
+          project: 'org.project2',
+          assignee: 'email1@sonarsource.com',
+          author: 'email3@sonarsource.com',
         }),
         snippets: keyBy(
           [
@@ -536,11 +555,63 @@ export default class IssuesServiceMock {
     });
   };
 
-  handleSearchIssues = (query: RequestData): Promise<RawIssuesResponse> => {
-    const facets = (query.facets ?? '').split(',').map((name: string) => {
+  mockFacetDetailResponse = (facetsQuery: string): RawFacet[] => {
+    return facetsQuery.split(',').map((name: string): RawFacet => {
       if (name === 'owaspTop10-2021') {
         return this.owasp2021FacetList();
       }
+      if (name === 'tags') {
+        return {
+          property: name,
+          values: [
+            {
+              val: 'unused',
+              count: 12842,
+            },
+            {
+              val: 'confusing',
+              count: 124,
+            },
+          ],
+        };
+      }
+      if (name === 'projects') {
+        return {
+          property: name,
+          values: [
+            { val: 'org.project1', count: 14685 },
+            { val: 'org.project2', count: 3890 },
+          ],
+        };
+      }
+      if (name === 'assignees') {
+        return {
+          property: name,
+          values: [
+            { val: 'email1@sonarsource.com', count: 675 },
+            { val: 'email2@sonarsource.com', count: 531 },
+          ],
+        };
+      }
+      if (name === 'author') {
+        return {
+          property: name,
+          values: [
+            { val: 'email3@sonarsource.com', count: 421 },
+            { val: 'email4@sonarsource.com', count: 123 },
+          ],
+        };
+      }
+      if (name === 'rules') {
+        return {
+          property: name,
+          values: [
+            { val: 'simpleRuleId', count: 8816 },
+            { val: 'advancedRuleId', count: 2060 },
+            { val: 'other', count: 1324 },
+          ],
+        };
+      }
       if (name === 'languages') {
         return {
           property: name,
@@ -561,6 +632,10 @@ export default class IssuesServiceMock {
         values: [],
       };
     });
+  };
+
+  handleSearchIssues = (query: RequestData): Promise<RawIssuesResponse> => {
+    const facets = this.mockFacetDetailResponse((query.facets ?? '') as string);
 
     // Filter list (only supports assignee, type and severity)
     const filteredList = this.list
@@ -573,9 +648,33 @@ export default class IssuesServiceMock {
         }
         return query.assignees.split(',').includes(item.issue.assignee);
       })
+      .filter((item) => {
+        if (!query.tags) {
+          return true;
+        }
+        if (!item.issue.tags) {
+          return false;
+        }
+        return item.issue.tags.some((tag) => query.tags?.split(',').includes(tag));
+      })
+      .filter(
+        (item) =>
+          !query.createdBefore || new Date(item.issue.creationDate) <= new Date(query.createdBefore)
+      )
+      .filter(
+        (item) =>
+          !query.createdAfter || new Date(item.issue.creationDate) >= new Date(query.createdAfter)
+      )
       .filter((item) => !query.types || query.types.split(',').includes(item.issue.type))
       .filter(
         (item) => !query.severities || query.severities.split(',').includes(item.issue.severity)
+      )
+      .filter((item) => !query.scopes || query.scopes.split(',').includes(item.issue.scope))
+      .filter((item) => !query.statuses || query.statuses.split(',').includes(item.issue.status))
+      .filter((item) => !query.projects || query.projects.split(',').includes(item.issue.project))
+      .filter((item) => !query.rules || query.rules.split(',').includes(item.issue.rule))
+      .filter(
+        (item) => !query.resolutions || query.resolutions.split(',').includes(item.issue.resolution)
       );
 
     // Splice list items according to paging using a fixed page size
@@ -589,12 +688,17 @@ export default class IssuesServiceMock {
       effortTotal: 199629,
       facets,
       issues: listItems.map((line) => line.issue),
-      languages: [],
+      languages: [{ name: 'java' }, { name: 'python' }, { name: 'ts' }],
       paging: mockPaging({
         pageIndex,
         pageSize,
         total: filteredList.length,
       }),
+      users: [
+        { login: 'login0' },
+        { login: 'login1', name: 'Login 1' },
+        { login: 'login2', name: 'Login 2' },
+      ],
     });
   };
 
@@ -638,8 +742,8 @@ export default class IssuesServiceMock {
     };
 
     const resolutionMap: Dict<string> = {
-      wontfix: 'WONTFIX',
-      falsepositive: 'FALSE-POSITIVE',
+      wontfix: IssueResolution.WontFix,
+      falsepositive: IssueResolution.FalsePositive,
     };
 
     return this.getActionsResponse(
index 76629db8f9111a0c3d710ed1651af15483914821..2cef9341265fde5103d0eb89c6c9f5e5c0ae361d 100644 (file)
@@ -64,7 +64,37 @@ const ui = {
   issueItem7: byRole('region', { name: 'Issue with tags' }),
   issueItem8: byRole('region', { name: 'Issue on page 2' }),
 
+  clearIssueTypeFacet: byRole('button', { name: 'clear_x_filter.issues.facet.types' }),
   codeSmellIssueTypeFilter: byRole('checkbox', { name: 'issue.type.CODE_SMELL' }),
+  vulnerabilityIssueTypeFilter: byRole('checkbox', { name: 'issue.type.VULNERABILITY' }),
+  clearSeverityFacet: byRole('button', { name: 'clear_x_filter.issues.facet.severities' }),
+  majorSeverityFilter: byRole('checkbox', { name: 'severity.MAJOR' }),
+  scopeFacet: byRole('button', { name: 'issues.facet.scopes' }),
+  clearScopeFacet: byRole('button', { name: 'clear_x_filter.issues.facet.scopes' }),
+  mainScopeFilter: byRole('checkbox', { name: 'issue.scope.MAIN' }),
+  resolutionFacet: byRole('button', { name: 'issues.facet.resolutions' }),
+  clearResolutionFacet: byRole('button', { name: 'clear_x_filter.issues.facet.resolutions' }),
+  fixedResolutionFilter: byRole('checkbox', { name: 'issue.resolution.FIXED' }),
+  statusFacet: byRole('button', { name: 'issues.facet.statuses' }),
+  creationDateFacet: byRole('button', { name: 'issues.facet.createdAt' }),
+  clearCreationDateFacet: byRole('button', { name: 'clear_x_filter.issues.facet.createdAt' }),
+  clearStatusFacet: byRole('button', { name: 'clear_x_filter.issues.facet.statuses' }),
+  openStatusFilter: byRole('checkbox', { name: 'issue.status.OPEN' }),
+  confirmedStatusFilter: byRole('checkbox', { name: 'issue.status.CONFIRMED' }),
+  ruleFacet: byRole('button', { name: 'issues.facet.rules' }),
+  clearRuleFacet: byRole('button', { name: 'clear_x_filter.issues.facet.rules' }),
+  tagFacet: byRole('button', { name: 'issues.facet.tags' }),
+  clearTagFacet: byRole('button', { name: 'clear_x_filter.issues.facet.tags' }),
+  projectFacet: byRole('button', { name: 'issues.facet.projects' }),
+  clearProjectFacet: byRole('button', { name: 'clear_x_filter.issues.facet.projects' }),
+  assigneeFacet: byRole('button', { name: 'issues.facet.assignees' }),
+  clearAssigneeFacet: byRole('button', { name: 'clear_x_filter.issues.facet.assignees' }),
+  authorFacet: byRole('button', { name: 'issues.facet.authors' }),
+  clearAuthorFacet: byRole('button', { name: 'clear_x_filter.issues.facet.authors' }),
+
+  dateInputMonthSelect: byRole('combobox', { name: 'Month:' }),
+  dateInputYearSelect: byRole('combobox', { name: 'Year:' }),
+
   clearAllFilters: byRole('button', { name: 'clear_all_filters' }),
 };
 
@@ -305,45 +335,170 @@ describe('issues app', () => {
     });
   });
   describe('filtering', () => {
-    it('should allow to reset all facets', async () => {
+    it('should handle filtering from a specific issue properly', async () => {
       const user = userEvent.setup();
       renderIssueApp();
+      await waitOnDataLoaded();
+
+      // Ensure issue type filter is unchecked
+      expect(ui.codeSmellIssueTypeFilter.get()).not.toBeChecked();
+      expect(ui.vulnerabilityIssueTypeFilter.get()).not.toBeChecked();
+      expect(ui.issueItem1.get()).toBeInTheDocument();
+      expect(ui.issueItem2.get()).toBeInTheDocument();
+
+      // Open filter similar issue dropdown for issue 2 (Code smell)
+      await user.click(
+        await within(ui.issueItem2.get()).findByRole('button', {
+          name: 'issue.filter_similar_issues',
+        })
+      );
+      await user.click(
+        await within(ui.issueItem2.get()).findByRole('button', {
+          name: 'issue.type.CODE_SMELL',
+        })
+      );
 
-      await user.click(ui.codeSmellIssueTypeFilter.get());
       expect(ui.codeSmellIssueTypeFilter.get()).toBeChecked();
-      expect(ui.issueItem4.query()).not.toBeInTheDocument();
+      expect(ui.vulnerabilityIssueTypeFilter.get()).not.toBeChecked();
+      expect(ui.issueItem1.query()).not.toBeInTheDocument();
+      expect(ui.issueItem2.get()).toBeInTheDocument();
+      expect(
+        screen.queryByRole('button', { name: 'issues.facet.owaspTop10_2021' })
+      ).not.toBeInTheDocument();
 
+      // Clear filters
       await user.click(ui.clearAllFilters.get());
+
+      // Open filter similar issue dropdown for issue 3 (Vulnerability)
+      await user.click(
+        await within(await ui.issueItem1.find()).findByRole('button', {
+          name: 'issue.filter_similar_issues',
+        })
+      );
+      await user.click(
+        await within(await ui.issueItem1.find()).findByRole('button', {
+          name: 'issue.type.VULNERABILITY',
+        })
+      );
+
       expect(ui.codeSmellIssueTypeFilter.get()).not.toBeChecked();
-      expect(ui.issueItem4.get()).toBeInTheDocument();
+      expect(ui.vulnerabilityIssueTypeFilter.get()).toBeChecked();
+      expect(ui.issueItem1.get()).toBeInTheDocument();
+      expect(ui.issueItem2.query()).not.toBeInTheDocument();
+      // Standards should now be expanded and Owasp should be visible
+      expect(screen.getByRole('button', { name: 'issues.facet.owaspTop10_2021' })).toBeVisible();
     });
 
-    it('should handle filtering from a specific issue properly', async () => {
+    it('should combine sidebar filters properly', async () => {
       const user = userEvent.setup();
       renderIssueApp();
+      await waitOnDataLoaded();
 
-      // Get first issue list item
-      const issueItem = await ui.issueItem2.find();
+      // Select only code smells (should make the first issue disappear)
+      await user.click(ui.codeSmellIssueTypeFilter.get());
 
-      // Ensure issue type filter is unchecked
-      expect(ui.codeSmellIssueTypeFilter.get()).not.toBeChecked();
+      // Select code smells + major severity
+      await user.click(ui.majorSeverityFilter.get());
+
+      // Expand scope and set code smells + major severity + main scope
+      await user.click(ui.scopeFacet.get());
+      await user.click(ui.mainScopeFilter.get());
+
+      // Resolution
+      await user.click(ui.resolutionFacet.get());
+      await user.click(ui.fixedResolutionFilter.get());
+
+      // Stop to check that filters were applied as expected
+      expect(ui.issueItem1.query()).not.toBeInTheDocument();
+      expect(ui.issueItem2.query()).not.toBeInTheDocument();
+      expect(ui.issueItem3.query()).not.toBeInTheDocument();
+      expect(ui.issueItem4.query()).not.toBeInTheDocument();
+      expect(ui.issueItem5.query()).not.toBeInTheDocument();
+      expect(ui.issueItem6.get()).toBeInTheDocument();
+      expect(ui.issueItem7.query()).not.toBeInTheDocument();
+
+      // Status
+      await user.click(ui.statusFacet.get());
+      await user.click(ui.openStatusFilter.get());
+      expect(ui.issueItem6.query()).not.toBeInTheDocument(); // Issue 6 should vanish
+
+      // Ctrl+click on confirmed status
+      await user.keyboard('{Control>}');
+      await user.click(ui.confirmedStatusFilter.get());
+      await user.keyboard('{/Control}');
+      expect(ui.issueItem6.get()).toBeInTheDocument(); // Issue 6 should come back
+
+      // Clear resolution filter
+      await user.click(ui.clearResolutionFacet.get());
+
+      // Rule
+      await user.click(ui.ruleFacet.get());
+      await user.click(screen.getByRole('checkbox', { name: 'other' }));
+
+      // Tag
+      await user.click(ui.tagFacet.get());
+      await user.click(screen.getByRole('checkbox', { name: 'unused' }));
+
+      // Project
+      await user.click(ui.projectFacet.get());
+      await user.click(screen.getByRole('checkbox', { name: 'org.project2' }));
+
+      // Assignee
+      await user.click(ui.assigneeFacet.get());
+      await user.click(screen.getByRole('checkbox', { name: 'email2@sonarsource.com' }));
+      await user.click(screen.getByRole('checkbox', { name: 'email1@sonarsource.com' })); // Change assignee
+
+      // Author
+      await user.click(ui.authorFacet.get());
+      await user.click(screen.getByRole('checkbox', { name: 'email4@sonarsource.com' }));
+      await user.click(screen.getByRole('checkbox', { name: 'email3@sonarsource.com' })); // Change author
+      expect(ui.issueItem1.query()).not.toBeInTheDocument();
+      expect(ui.issueItem2.query()).not.toBeInTheDocument();
+      expect(ui.issueItem3.query()).not.toBeInTheDocument();
+      expect(ui.issueItem4.query()).not.toBeInTheDocument();
+      expect(ui.issueItem5.query()).not.toBeInTheDocument();
+      expect(ui.issueItem6.query()).not.toBeInTheDocument();
+      expect(ui.issueItem7.get()).toBeInTheDocument();
+
+      // Clear filters one by one
+      await user.click(ui.clearIssueTypeFacet.get());
+      await user.click(ui.clearSeverityFacet.get());
+      await user.click(ui.clearScopeFacet.get());
+      await user.click(ui.clearStatusFacet.get());
+      await user.click(ui.clearRuleFacet.get());
+      await user.click(ui.clearTagFacet.get());
+      await user.click(ui.clearProjectFacet.get());
+      await user.click(ui.clearAssigneeFacet.get());
+      await user.click(ui.clearAuthorFacet.get());
+      expect(ui.issueItem1.get()).toBeInTheDocument();
       expect(ui.issueItem2.get()).toBeInTheDocument();
       expect(ui.issueItem3.get()).toBeInTheDocument();
+      expect(ui.issueItem4.get()).toBeInTheDocument();
+      expect(ui.issueItem5.get()).toBeInTheDocument();
+      expect(ui.issueItem6.get()).toBeInTheDocument();
+      expect(ui.issueItem7.get()).toBeInTheDocument();
+    });
 
-      // Open filter similar issue dropdown
-      await user.click(
-        await within(issueItem).findByRole('button', { name: 'issue.filter_similar_issues' })
-      );
+    it('should allow to set creation date', async () => {
+      const user = userEvent.setup();
+      renderIssueApp(mockLoggedInUser());
+      await waitOnDataLoaded();
 
-      // Select type
-      await user.click(
-        await within(issueItem).findByRole('button', { name: 'issue.type.CODE_SMELL' })
-      );
+      // Select a specific date range such that only one issue matches
+      await user.click(ui.creationDateFacet.get());
+      await user.click(screen.getByPlaceholderText('start_date'));
+      await user.selectOptions(ui.dateInputMonthSelect.get(), 'January');
+      await user.selectOptions(ui.dateInputYearSelect.get(), '2023');
+      await user.click(screen.getByText('1'));
+      await user.click(screen.getByText('10'));
 
-      // Ensure issue type filter is now checked
-      expect(ui.codeSmellIssueTypeFilter.get()).toBeChecked();
-      expect(ui.issueItem2.get()).toBeInTheDocument();
+      expect(ui.issueItem1.get()).toBeInTheDocument();
+      expect(ui.issueItem2.query()).not.toBeInTheDocument();
       expect(ui.issueItem3.query()).not.toBeInTheDocument();
+      expect(ui.issueItem4.query()).not.toBeInTheDocument();
+      expect(ui.issueItem5.query()).not.toBeInTheDocument();
+      expect(ui.issueItem6.query()).not.toBeInTheDocument();
+      expect(ui.issueItem7.query()).not.toBeInTheDocument();
     });
 
     it('should allow to only show my issues', async () => {
@@ -449,7 +604,7 @@ describe('issues item', () => {
     issuesHandler.setIsAdmin(true);
     renderIssueApp();
 
-    // Get 'Fix that' issue list item
+    // Get a specific issue list item
     const listItem = within(await screen.findByRole('region', { name: 'Fix that' }));
 
     // Change issue type
index ec71752ca70ca410ba5eff47ccb792057ec26abc..390838a9ebf19712fe2faaf7310f04ad63feaf84 100644 (file)
@@ -106,6 +106,7 @@ exports[`should render correctly 2`] = `
           "projectName": "Foo",
           "rule": "javascript:S1067",
           "ruleName": "foo",
+          "scope": "MAIN",
           "secondaryLocations": [
             {
               "component": "main.js",
@@ -264,6 +265,7 @@ exports[`should render correctly: no component found 1`] = `
           "projectName": "Foo",
           "rule": "javascript:S1067",
           "ruleName": "foo",
+          "scope": "MAIN",
           "secondaryLocations": [
             {
               "component": "main.js",
@@ -393,6 +395,7 @@ exports[`should render correctly: no component found 1`] = `
           "projectName": "Foo",
           "rule": "javascript:S1067",
           "ruleName": "foo",
+          "scope": "MAIN",
           "secondaryLocations": [
             {
               "component": "main.js",
index 3a60a8445f183053a229cc4474a959d2ac655d14..f7a9823e460b46df550d9823b1b2d3119a3a6d84 100644 (file)
@@ -25,6 +25,7 @@ import FacetItem from '../../../components/facet/FacetItem';
 import FacetItemsList from '../../../components/facet/FacetItemsList';
 import MultipleSelectionHint from '../../../components/facet/MultipleSelectionHint';
 import { translate } from '../../../helpers/l10n';
+import { IssueResolution } from '../../../types/issues';
 import { Dict } from '../../../types/types';
 import { formatFacetStat, Query } from '../utils';
 
@@ -38,7 +39,13 @@ interface Props {
   stats: Dict<number> | undefined;
 }
 
-const RESOLUTIONS = ['', 'FALSE-POSITIVE', 'FIXED', 'REMOVED', 'WONTFIX'];
+const RESOLUTIONS = [
+  IssueResolution.Unresolved,
+  IssueResolution.FalsePositive,
+  IssueResolution.Fixed,
+  IssueResolution.Removed,
+  IssueResolution.WontFix,
+];
 
 export default class ResolutionFacet extends React.PureComponent<Props> {
   property = 'resolutions';
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx
deleted file mode 100644 (file)
index 75195ea..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { Query } from '../../utils';
-import AssigneeFacet from '../AssigneeFacet';
-
-it('should render', () => {
-  expect(shallowRender({ assignees: ['foo'] })).toMatchSnapshot();
-});
-
-it('should select unassigned', () => {
-  expect(shallowRender({ assigned: false }).find('ListStyleFacet').prop('values')).toEqual(['']);
-});
-
-it('should call onChange', () => {
-  const onChange = jest.fn();
-  const wrapper = shallowRender({ assignees: ['foo'], onChange });
-  const itemOnClick = wrapper.find('ListStyleFacet').prop<Function>('onItemClick');
-
-  itemOnClick('');
-  expect(onChange).toHaveBeenLastCalledWith({ assigned: false, assignees: [] });
-
-  itemOnClick('bar');
-  expect(onChange).toHaveBeenLastCalledWith({ assigned: true, assignees: ['bar'] });
-
-  itemOnClick('baz', true);
-  expect(onChange).toHaveBeenLastCalledWith({ assigned: true, assignees: ['baz', 'foo'] });
-});
-
-describe('test behavior', () => {
-  const instance = shallowRender({
-    assignees: ['foo', 'baz'],
-    referencedUsers: {
-      foo: { active: false, login: 'foo' },
-      baz: { active: true, login: 'baz', name: 'Name Baz' },
-    },
-  }).instance();
-
-  it('should correctly render assignee name', () => {
-    expect(instance.getAssigneeName('')).toBe('unassigned');
-    expect(instance.getAssigneeName('bar')).toBe('bar');
-    expect(instance.getAssigneeName('baz')).toBe('Name Baz');
-    expect(instance.getAssigneeName('foo')).toBe('user.x_deleted.foo');
-  });
-
-  it('should correctly render facet item', () => {
-    expect(instance.renderFacetItem('')).toBe('unassigned');
-    expect(instance.renderFacetItem('bar')).toBe('bar');
-    expect(instance.renderFacetItem('baz')).toMatchSnapshot();
-    expect(instance.renderFacetItem('foo')).toMatchSnapshot();
-  });
-
-  it('should correctly render search result correctly', () => {
-    expect(
-      instance.renderSearchResult({ active: true, login: 'bar', name: 'Name Bar' }, 'ba')
-    ).toMatchSnapshot();
-    expect(instance.renderSearchResult({ active: false, login: 'foo' }, 'fo')).toMatchSnapshot();
-  });
-});
-
-function shallowRender(props?: Partial<AssigneeFacet['props']>) {
-  return shallow<AssigneeFacet>(
-    <AssigneeFacet
-      assigned={true}
-      assignees={[]}
-      fetching={false}
-      loadSearchResultCount={jest.fn()}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={true}
-      query={{} as Query}
-      referencedUsers={{ foo: { avatar: 'avatart-foo', login: 'name-foo', name: 'Name Foo' } }}
-      stats={{ '': 5, foo: 13, bar: 7, baz: 6 }}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AuthorFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AuthorFacet-test.tsx
deleted file mode 100644 (file)
index b3fdeb4..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import ListStyleFacet from '../../../../components/facet/ListStyleFacet';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { Query } from '../../utils';
-import AuthorFacet from '../AuthorFacet';
-
-it('should render correctly', () => {
-  const wrapper = shallowRender();
-  expect(wrapper).toMatchSnapshot();
-});
-
-it('should notify of search result count correctly', () => {
-  const loadSearchResultCount = jest.fn();
-
-  const wrapper = shallowRender({ loadSearchResultCount });
-
-  wrapper.find(ListStyleFacet).props().loadSearchResultCount!(['1', '2']);
-
-  expect(loadSearchResultCount).toHaveBeenCalled();
-});
-
-function shallowRender(props: Partial<AuthorFacet['props']> = {}) {
-  return shallow<AuthorFacet>(
-    <AuthorFacet
-      component={mockComponent()}
-      fetching={false}
-      loadSearchResultCount={jest.fn()}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={true}
-      query={{} as Query}
-      stats={{}}
-      author={[]}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/CreationDateFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/CreationDateFacet-test.tsx
deleted file mode 100644 (file)
index 84d94c8..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { IntlShape } from 'react-intl';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { ComponentQualifier } from '../../../../types/component';
-import { CreationDateFacet } from '../CreationDateFacet';
-
-it('should render correctly', () => {
-  expect(shallowRender({ open: false })).toMatchSnapshot('closed');
-  expect(shallowRender()).toMatchSnapshot('clear');
-  expect(shallowRender({ createdAt: '2019.05.21T13:33:00Z' })).toMatchSnapshot('created at');
-  expect(
-    shallowRender({
-      createdAfter: new Date('2019.04.29T13:33:00Z'),
-      createdAfterIncludesTime: true,
-    })
-  ).toMatchSnapshot('created after');
-  expect(
-    shallowRender({
-      createdAfter: new Date('2019.04.29T13:33:00Z'),
-      createdAfterIncludesTime: true,
-    })
-  ).toMatchSnapshot('created after timestamp');
-  expect(shallowRender({ component: mockComponent() })).toMatchSnapshot('project');
-  expect(
-    shallowRender({ component: mockComponent({ qualifier: ComponentQualifier.Portfolio }) })
-  ).toMatchSnapshot('portfolio');
-});
-
-it.each([
-  ['week', '1w'],
-  ['month', '1m'],
-  ['year', '1y'],
-])('should render correctly for createdInLast %s', (_, createdInLast) => {
-  expect(shallowRender({ component: mockComponent(), createdInLast })).toMatchSnapshot();
-});
-
-function shallowRender(props?: Partial<CreationDateFacet['props']>) {
-  return shallow<CreationDateFacet>(
-    <CreationDateFacet
-      component={undefined}
-      fetching={false}
-      createdAfter={undefined}
-      createdAfterIncludesTime={false}
-      createdAt=""
-      createdBefore={undefined}
-      createdInLast=""
-      inNewCodePeriod={false}
-      intl={
-        {
-          formatDate: (date: string) => 'formatted.' + date,
-        } as IntlShape
-      }
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={true}
-      stats={undefined}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/DirectoryFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/DirectoryFacet-test.tsx
deleted file mode 100644 (file)
index 4e783ff..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { getDirectories } from '../../../../api/components';
-import ListStyleFacet from '../../../../components/facet/ListStyleFacet';
-import { mockBranch } from '../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { TreeComponentWithPath } from '../../../../types/component';
-import { Query } from '../../utils';
-import DirectoryFacet from '../DirectoryFacet';
-
-jest.mock('../../../../api/components', () => ({
-  getDirectories: jest.fn().mockResolvedValue({ components: [] }),
-}));
-
-beforeEach(() => jest.clearAllMocks());
-
-const branch = mockBranch();
-const component = mockComponent();
-
-it('should render correctly', () => {
-  const wrapper = shallowRender();
-  const instance = wrapper.instance();
-  expect(wrapper).toMatchSnapshot();
-  expect(
-    instance.renderSearchResult({ path: 'foo/bar' } as TreeComponentWithPath, 'foo')
-  ).toMatchSnapshot();
-  expect(instance.renderFacetItem('foo/bar')).toMatchSnapshot();
-});
-
-it('should properly search for directory', () => {
-  const wrapper = shallowRender();
-
-  const query = 'foo';
-
-  wrapper.find(ListStyleFacet).props().onSearch(query);
-
-  expect(getDirectories).toHaveBeenCalledWith({
-    branch: branch.name,
-    component: component.key,
-    q: query,
-    ps: 30,
-    p: undefined,
-  });
-});
-
-describe("ListStyleFacet's callback props", () => {
-  const wrapper = shallowRender();
-  const instance = wrapper.instance();
-
-  it('#getSearchResultText()', () => {
-    expect(instance.getSearchResultText({ path: 'bar' } as TreeComponentWithPath)).toBe('bar');
-  });
-
-  it('#getSearchResultKey()', () => {
-    expect(instance.getSearchResultKey({ path: 'foo/bar' } as TreeComponentWithPath)).toBe(
-      'foo/bar'
-    );
-  });
-
-  it('#getFacetItemText()', () => {
-    expect(instance.getFacetItemText('foo/bar')).toBe('foo/bar');
-  });
-});
-
-function shallowRender(props: Partial<DirectoryFacet['props']> = {}) {
-  return shallow<DirectoryFacet>(
-    <DirectoryFacet
-      branchLike={branch}
-      componentKey={component.key}
-      directories={['foo/', 'bar/baz/']}
-      fetching={false}
-      loadSearchResultCount={jest.fn()}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={false}
-      query={{} as Query}
-      stats={undefined}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/FileFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/FileFacet-test.tsx
deleted file mode 100644 (file)
index cb6715d..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { getFiles } from '../../../../api/components';
-import ListStyleFacet from '../../../../components/facet/ListStyleFacet';
-import { mockBranch } from '../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { TreeComponentWithPath } from '../../../../types/component';
-import { Query } from '../../utils';
-import FileFacet from '../FileFacet';
-
-jest.mock('../../../../api/components', () => ({
-  getFiles: jest.fn().mockResolvedValue({ components: [] }),
-}));
-
-beforeEach(() => jest.clearAllMocks());
-
-const branch = mockBranch();
-const component = mockComponent();
-
-const PATH = 'foo/bar.js';
-
-it('should render correctly', () => {
-  const wrapper = shallowRender();
-  const instance = wrapper.instance();
-  expect(wrapper).toMatchSnapshot();
-  expect(
-    instance.renderSearchResult({ path: PATH } as TreeComponentWithPath, 'bar')
-  ).toMatchSnapshot();
-  expect(instance.renderFacetItem('fooUuid')).toMatchSnapshot();
-});
-
-it('should properly search for file', () => {
-  const wrapper = shallowRender();
-
-  const query = 'foo';
-
-  wrapper.find(ListStyleFacet).props().onSearch(query);
-
-  expect(getFiles).toHaveBeenCalledWith({
-    branch: branch.name,
-    component: component.key,
-    q: query,
-    ps: 30,
-    p: undefined,
-  });
-});
-
-describe("ListStyleFacet's callback props", () => {
-  const wrapper = shallowRender();
-  const instance = wrapper.instance();
-
-  it('#getSearchResultText()', () => {
-    expect(instance.getSearchResultText({ path: PATH } as TreeComponentWithPath)).toBe(
-      'foo/bar.js'
-    );
-  });
-
-  it('#getSearchResultKey()', () => {
-    expect(instance.getSearchResultKey({ key: 'bar', path: 'bar' } as TreeComponentWithPath)).toBe(
-      'bar'
-    );
-  });
-
-  it('#getFacetItemText()', () => {
-    expect(instance.getFacetItemText('bar')).toBe('bar');
-  });
-});
-
-function shallowRender(props: Partial<FileFacet['props']> = {}) {
-  return shallow<FileFacet>(
-    <FileFacet
-      branchLike={branch}
-      componentKey={component.key}
-      fetching={false}
-      files={['foo', 'bar']}
-      loadSearchResultCount={jest.fn()}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={false}
-      query={{} as Query}
-      stats={undefined}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/PeriodFilter-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/PeriodFilter-test.tsx
deleted file mode 100644 (file)
index e45325b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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 { render, screen } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-
-import * as React from 'react';
-import PeriodFilter, { PeriodFilterProps } from '../PeriodFilter';
-
-it('should filter when clicked', async () => {
-  const user = userEvent.setup();
-  const onChange = jest.fn();
-
-  renderPeriodFilter({ onChange });
-
-  await user.click(screen.getByText('issues.new_code'));
-
-  expect(onChange).toHaveBeenCalledWith({
-    createdAfter: undefined,
-    createdAt: undefined,
-    createdBefore: undefined,
-    createdInLast: undefined,
-    inNewCodePeriod: true,
-  });
-});
-
-function renderPeriodFilter(overrides: Partial<PeriodFilterProps> = {}) {
-  return render(
-    <PeriodFilter
-      fetching={false}
-      newCodeSelected={false}
-      onChange={jest.fn()}
-      stats={{}}
-      {...overrides}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/ProjectFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/ProjectFacet-test.tsx
deleted file mode 100644 (file)
index 541bf27..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import { keyBy } from 'lodash';
-import * as React from 'react';
-import { getTree, searchProjects } from '../../../../api/components';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { ComponentQualifier } from '../../../../types/component';
-import { ReferencedComponent } from '../../../../types/issues';
-import { Query } from '../../utils';
-import ProjectFacet from '../ProjectFacet';
-
-jest.mock('../../../../api/components', () => ({
-  getTree: jest.fn().mockResolvedValue({ baseComponent: {}, components: [], paging: {} }),
-  searchProjects: jest.fn().mockResolvedValue({
-    components: [],
-    facets: [],
-    paging: {},
-  }),
-}));
-
-beforeEach(() => jest.clearAllMocks());
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should callback to load search results', () => {
-  const loadSearchResultCount = jest.fn();
-  const wrapper = shallowRender({ loadSearchResultCount });
-  wrapper.instance().loadSearchResultCount([
-    { key: '1', name: 'first' },
-    { key: '2', name: 'seecond' },
-  ]);
-
-  expect(loadSearchResultCount).toHaveBeenCalledWith('projects', { projects: ['1', '2'] });
-});
-
-it('should handle search for projects globally', async () => {
-  const wrapper = shallowRender();
-  const query = 'my project';
-
-  await wrapper.instance().handleSearch(query);
-
-  expect(searchProjects).toHaveBeenCalled();
-  expect(getTree).not.toHaveBeenCalled();
-});
-
-it('should handle search for projects in portfolio', async () => {
-  const wrapper = shallowRender({
-    component: mockComponent({ qualifier: ComponentQualifier.Portfolio }),
-  });
-  const query = 'my project';
-
-  await wrapper.instance().handleSearch(query);
-
-  expect(searchProjects).not.toHaveBeenCalled();
-  expect(getTree).toHaveBeenCalled();
-});
-
-describe("ListStyleFacet's renderers", () => {
-  const components: ReferencedComponent[] = [
-    { key: 'projectKey', name: 'First Project Name', uuid: '141324' },
-    { key: 'projectKey2', name: 'Second Project Name', uuid: '643878' },
-  ];
-  const referencedComponents = keyBy(components, (c) => c.key);
-  const wrapper = shallowRender({ referencedComponents });
-  const instance = wrapper.instance();
-
-  it('should include getProjectName', () => {
-    expect(instance.getProjectName(components[0].key)).toBe(components[0].name);
-    expect(instance.getProjectName('nonexistent')).toBe('nonexistent');
-  });
-
-  it('should include renderFacetItem', () => {
-    expect(instance.renderFacetItem(components[0].key)).toMatchSnapshot();
-  });
-
-  it('should include renderSearchResult', () => {
-    expect(instance.renderSearchResult(components[0], 'First')).toMatchSnapshot();
-  });
-});
-
-function shallowRender(props: Partial<ProjectFacet['props']> = {}) {
-  return shallow<ProjectFacet>(
-    <ProjectFacet
-      component={undefined}
-      fetching={false}
-      loadSearchResultCount={jest.fn()}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={false}
-      projects={[]}
-      query={{} as Query}
-      referencedComponents={{}}
-      stats={undefined}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/RuleFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/RuleFacet-test.tsx
deleted file mode 100644 (file)
index 193b362..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { searchRules } from '../../../../api/rules';
-import { mockReferencedRule } from '../../../../helpers/mocks/issues';
-import { mockRule } from '../../../../helpers/testMocks';
-import { Query } from '../../utils';
-import RuleFacet from '../RuleFacet';
-
-jest.mock('../../../../api/rules', () => ({
-  searchRules: jest.fn().mockResolvedValue({}),
-}));
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should handle search', async () => {
-  const wrapper = shallowRender();
-
-  const query = 'query';
-
-  await wrapper.instance().handleSearch(query);
-
-  expect(searchRules).toHaveBeenCalledWith(
-    expect.objectContaining({ languages: 'js,java', q: query })
-  );
-});
-
-describe('ListStyleFacet Renderers', () => {
-  const referencedRules = { r1: mockReferencedRule() };
-  const instance = shallowRender({ referencedRules }).instance();
-
-  it('should include renderFacetItem', () => {
-    const rule = referencedRules.r1;
-    expect(instance.getRuleName('r1')).toBe(`(${rule.langName}) ${rule.name}`);
-    expect(instance.getRuleName('nonexistent')).toBe('nonexistent');
-  });
-
-  it('should include renderSearchResult', () => {
-    const rule = mockRule();
-    expect(instance.renderSearchResult(rule)).toBe(`(${rule.langName}) ${rule.name}`);
-    expect(instance.renderSearchResult(mockRule({ langName: '' }))).toBe(rule.name);
-  });
-});
-
-function shallowRender(props: Partial<RuleFacet['props']> = {}) {
-  return shallow<RuleFacet>(
-    <RuleFacet
-      fetching={true}
-      languages={['js', 'java']}
-      loadSearchResultCount={jest.fn()}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={false}
-      query={{} as Query}
-      referencedRules={{}}
-      rules={['r1']}
-      stats={{}}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/ScopeFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/ScopeFacet-test.tsx
deleted file mode 100644 (file)
index 5d2f0f3..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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 { shallow, ShallowWrapper } from 'enzyme';
-import * as React from 'react';
-import FacetHeader from '../../../../components/facet/FacetHeader';
-import FacetItem from '../../../../components/facet/FacetItem';
-import { IssueScope } from '../../../../types/issues';
-import ScopeFacet, { ScopeFacetProps } from '../ScopeFacet';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(shallowRender({ open: true })).toMatchSnapshot('open');
-  expect(shallowRender({ open: true, scopes: [IssueScope.Main] })).toMatchSnapshot('active facet');
-  expect(shallowRender({ open: true, stats: { [IssueScope.Main]: 0 } })).toMatchSnapshot(
-    'disabled facet'
-  );
-});
-
-it('should correctly handle facet header clicks', () => {
-  const onChange = jest.fn();
-  const onToggle = jest.fn();
-  const wrapper = shallowRender({ onChange, onToggle });
-
-  wrapper.find(FacetHeader).props().onClear!();
-  expect(onChange).toHaveBeenCalledWith({ scopes: [] });
-
-  wrapper.find(FacetHeader).props().onClick!();
-  expect(onToggle).toHaveBeenCalledWith('scopes');
-});
-
-it('should correctly handle facet item clicks', () => {
-  const wrapper = shallowRender({ open: true, scopes: [IssueScope.Main] });
-  const onChange = jest.fn(({ scopes }) => wrapper.setProps({ scopes }));
-  wrapper.setProps({ onChange });
-
-  clickFacetItem(wrapper, IssueScope.Test);
-  expect(onChange).toHaveBeenLastCalledWith({ scopes: [IssueScope.Test] });
-
-  clickFacetItem(wrapper, IssueScope.Test);
-  expect(onChange).toHaveBeenLastCalledWith({ scopes: [] });
-
-  clickFacetItem(wrapper, IssueScope.Test, true);
-  clickFacetItem(wrapper, IssueScope.Main, true);
-  expect(onChange).toHaveBeenLastCalledWith({
-    scopes: expect.arrayContaining([IssueScope.Main, IssueScope.Test]),
-  });
-
-  clickFacetItem(wrapper, IssueScope.Test, true);
-  expect(onChange).toHaveBeenLastCalledWith({ scopes: [IssueScope.Main] });
-});
-
-function clickFacetItem(
-  wrapper: ShallowWrapper<ScopeFacetProps>,
-  scope: IssueScope,
-  multiple = false
-) {
-  return wrapper
-    .find(FacetItem)
-    .filterWhere((f) => f.key() === scope)
-    .props()
-    .onClick(scope, multiple);
-}
-
-function shallowRender(props: Partial<ScopeFacetProps> = {}) {
-  return shallow<ScopeFacetProps>(
-    <ScopeFacet
-      fetching={true}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={false}
-      scopes={[]}
-      stats={{}}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx
new file mode 100644 (file)
index 0000000..52fdec7
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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 { screen } from '@testing-library/react';
+import * as React from 'react';
+import { mockComponent } from '../../../../helpers/mocks/component';
+import { mockQuery } from '../../../../helpers/mocks/issues';
+import { mockAppState } from '../../../../helpers/testMocks';
+import { renderComponent } from '../../../../helpers/testReactTestingUtils';
+import { ComponentQualifier } from '../../../../types/component';
+import { GlobalSettingKeys } from '../../../../types/settings';
+import { Sidebar } from '../Sidebar';
+
+it('should render correct facets for Application', () => {
+  renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.Application }) });
+  expect(screen.getAllByRole('button').map((button) => button.textContent)).toStrictEqual([
+    'issues.facet.types',
+    'issues.facet.severities',
+    'issues.facet.scopes',
+    'issues.facet.resolutions',
+    'issues.facet.statuses',
+    'issues.facet.standards',
+    'issues.facet.createdAt',
+    'issues.facet.languages',
+    'issues.facet.rules',
+    'issues.facet.tags',
+    'issues.facet.projects',
+    'issues.facet.assignees',
+    'clear',
+    'issues.facet.authors',
+  ]);
+});
+
+it('should render correct facets for Portfolio', () => {
+  renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.Portfolio }) });
+  expect(screen.getAllByRole('button').map((button) => button.textContent)).toStrictEqual([
+    'issues.facet.types',
+    'issues.facet.severities',
+    'issues.facet.scopes',
+    'issues.facet.resolutions',
+    'issues.facet.statuses',
+    'issues.facet.standards',
+    'issues.facet.createdAt',
+    'issues.facet.languages',
+    'issues.facet.rules',
+    'issues.facet.tags',
+    'issues.facet.projects',
+    'issues.facet.assignees',
+    'clear',
+    'issues.facet.authors',
+  ]);
+});
+
+it('should render correct facets for SubPortfolio', () => {
+  renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.SubPortfolio }) });
+  expect(screen.getAllByRole('button').map((button) => button.textContent)).toStrictEqual([
+    'issues.facet.types',
+    'issues.facet.severities',
+    'issues.facet.scopes',
+    'issues.facet.resolutions',
+    'issues.facet.statuses',
+    'issues.facet.standards',
+    'issues.facet.createdAt',
+    'issues.facet.languages',
+    'issues.facet.rules',
+    'issues.facet.tags',
+    'issues.facet.projects',
+    'issues.facet.assignees',
+    'clear',
+    'issues.facet.authors',
+  ]);
+});
+
+it.each([
+  ['week', '1w'],
+  ['month', '1m'],
+  ['year', '1y'],
+])('should render correctly for createdInLast %s', (name, createdInLast) => {
+  renderSidebar({ component: mockComponent(), query: mockQuery({ createdInLast }) });
+
+  const text = {
+    week: 'issues.facet.createdAt.last_week',
+    month: 'issues.facet.createdAt.last_month',
+    year: 'issues.facet.createdAt.last_year',
+  }[name] as string;
+  expect(screen.getByText(text)).toBeInTheDocument();
+});
+
+function renderSidebar(props: Partial<Sidebar['props']> = {}) {
+  return renderComponent(
+    <Sidebar
+      appState={mockAppState({
+        settings: { [GlobalSettingKeys.DeveloperAggregatedInfoDisabled]: 'false' },
+      })}
+      component={mockComponent()}
+      createdAfterIncludesTime={false}
+      facets={{}}
+      loadSearchResultCount={jest.fn()}
+      loadingFacets={{}}
+      myIssues={false}
+      onFacetToggle={jest.fn()}
+      onFilterChange={jest.fn()}
+      openFacets={{}}
+      query={mockQuery()}
+      referencedComponentsById={{}}
+      referencedComponentsByKey={{}}
+      referencedLanguages={{}}
+      referencedRules={{}}
+      referencedUsers={{}}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx
deleted file mode 100644 (file)
index 5ee2326..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 { shallow, ShallowWrapper } from 'enzyme';
-import { flatten } from 'lodash';
-import * as React from 'react';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { mockAppState } from '../../../../helpers/testMocks';
-import { ComponentQualifier } from '../../../../types/component';
-import { GlobalSettingKeys } from '../../../../types/settings';
-import { Query } from '../../utils';
-import { Sidebar } from '../Sidebar';
-
-it('should render facets for global page', () => {
-  expect(renderSidebar()).toMatchSnapshot();
-});
-
-it('should render facets for project', () => {
-  expect(renderSidebar({ component: mockComponent() })).toMatchSnapshot();
-});
-
-it.each([
-  [ComponentQualifier.Application],
-  [ComponentQualifier.Portfolio],
-  [ComponentQualifier.SubPortfolio],
-])('should render facets for %p', (qualifier) => {
-  expect(renderSidebar({ component: mockComponent({ qualifier }) })).toMatchSnapshot();
-});
-
-it('should render facets when my issues are selected', () => {
-  expect(renderSidebar({ myIssues: true })).toMatchSnapshot();
-});
-
-it('should not render developer nominative facets when asked not to', () => {
-  expect(
-    renderSidebar({
-      appState: mockAppState({
-        settings: { [GlobalSettingKeys.DeveloperAggregatedInfoDisabled]: 'true' },
-      }),
-    })
-  ).toMatchSnapshot();
-});
-
-const renderSidebar = (props?: Partial<Sidebar['props']>) => {
-  return flatten(
-    mapChildren(
-      shallow<Sidebar>(
-        <Sidebar
-          appState={mockAppState({
-            settings: { [GlobalSettingKeys.DeveloperAggregatedInfoDisabled]: 'false' },
-          })}
-          component={undefined}
-          createdAfterIncludesTime={false}
-          facets={{}}
-          loadSearchResultCount={jest.fn()}
-          loadingFacets={{}}
-          myIssues={false}
-          onFacetToggle={jest.fn()}
-          onFilterChange={jest.fn()}
-          openFacets={{}}
-          query={{ types: [''] } as Query}
-          referencedComponentsById={{}}
-          referencedComponentsByKey={{}}
-          referencedLanguages={{}}
-          referencedRules={{}}
-          referencedUsers={{}}
-          {...props}
-        />
-      )
-    )
-  );
-
-  function mapChildren(wrapper: ShallowWrapper) {
-    return wrapper.children().map((node) => {
-      if (typeof node.type() === 'symbol') {
-        return node.children().map((n) => n.name());
-      }
-      return node.name();
-    });
-  }
-};
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx
deleted file mode 100644 (file)
index 91d7786..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import ListStyleFacetFooter from '../../../../components/facet/ListStyleFacetFooter';
-import { getStandards } from '../../../../helpers/security-standard';
-import { click } from '../../../../helpers/testUtils';
-import { Query } from '../../utils';
-import StandardFacet from '../StandardFacet';
-
-jest.mock('../../../../helpers/security-standard', () => ({
-  ...jest.requireActual('../../../../helpers/security-standard'),
-  getStandards: jest.fn().mockResolvedValue({
-    owaspTop10: {
-      a1: {
-        title: 'Injection',
-      },
-      a2: {
-        title: 'Broken Authentication',
-      },
-    },
-    'owaspTop10-2021': {
-      a1: {
-        title: 'Injection',
-      },
-      a2: {
-        title: 'Broken Authentication',
-      },
-    },
-    cwe: {
-      unknown: {
-        title: 'No CWE associated',
-      },
-      '1004': {
-        title: "Sensitive Cookie Without 'HttpOnly' Flag",
-      },
-    },
-    sonarsourceSecurity: {
-      'sql-injection': {
-        title: 'SQL Injection',
-      },
-      'command-injection': {
-        title: 'Command Injection',
-      },
-    },
-  }),
-}));
-
-it('should render closed', () => {
-  expect(shallowRender()).toMatchSnapshot();
-  expect(getStandards).not.toHaveBeenCalled();
-});
-
-it('should toggle standards facet', () => {
-  const onToggle = jest.fn();
-  const wrapper = shallowRender({ onToggle });
-  click(wrapper.children('FacetHeader'));
-  expect(onToggle).toHaveBeenCalledWith('standards');
-});
-
-it('should clear standards facet', () => {
-  const onChange = jest.fn();
-  const wrapper = shallowRender({ onChange });
-  wrapper.children('FacetHeader').prop<Function>('onClear')();
-  expect(onChange).toHaveBeenCalledWith({
-    cwe: [],
-    owaspTop10: [],
-    'owaspTop10-2021': [],
-    sonarsourceSecurity: [],
-    standards: [],
-  });
-});
-
-it('should render sub-facets', () => {
-  expect(
-    shallowRender({
-      cwe: ['42'],
-      cweOpen: true,
-      cweStats: { 42: 5, 173: 3 },
-      open: true,
-      owaspTop10: ['a3'],
-      owaspTop10Open: true,
-      owaspTop10Stats: { a1: 15, a3: 5 },
-      sonarsourceSecurity: ['sql-injection'],
-      sonarsourceSecurityOpen: true,
-      sonarsourceSecurityStats: { 'sql-injection': 12 },
-    })
-  ).toMatchSnapshot();
-  expect(getStandards).toHaveBeenCalled();
-});
-
-it('should show sonarsource facet more button', () => {
-  const wrapper = shallowRender({
-    open: true,
-    sonarsourceSecurity: ['traceability', 'permission', 'others'],
-    sonarsourceSecurityOpen: true,
-    sonarsourceSecurityStats: {
-      'buffer-overflow': 3,
-      'sql-injection': 3,
-      rce: 3,
-      'object-injection': 3,
-      'command-injection': 3,
-      'path-traversal-injection': 3,
-      'ldap-injection': 3,
-      'xpath-injection': 3,
-      'expression-lang-injection': 3,
-      'log-injection': 3,
-      xxe: 3,
-      xss: 3,
-      dos: 3,
-      ssrf: 3,
-      csrf: 3,
-      'http-response-splitting': 3,
-      'open-redirect': 3,
-      'weak-cryptography': 3,
-      auth: 3,
-      'insecure-conf': 3,
-      'file-manipulation': 3,
-      'encrypt-data': 3,
-      traceability: 3,
-      permission: 3,
-      others: 3,
-    },
-  });
-
-  expect(wrapper.find(ListStyleFacetFooter).exists()).toBe(true);
-
-  wrapper.setState({ showFullSonarSourceList: true });
-  expect(wrapper.find(ListStyleFacetFooter).exists()).toBe(false);
-});
-
-it('should render empty sub-facet', () => {
-  expect(
-    shallowRender({
-      open: true,
-      'owaspTop10-2021': [],
-      'owaspTop10-2021Open': true,
-      'owaspTop10-2021Stats': {},
-    }).find('FacetBox[property="owaspTop10-2021"]')
-  ).toMatchSnapshot();
-});
-
-it('should select items', () => {
-  const onChange = jest.fn();
-  const wrapper = shallowRender({
-    cwe: ['42'],
-    cweOpen: true,
-    cweStats: { 42: 5, 173: 3 },
-    onChange,
-    open: true,
-    owaspTop10: ['a3'],
-    owaspTop10Open: true,
-    owaspTop10Stats: { a1: 15, a3: 5 },
-    sonarsourceSecurity: ['command-injection'],
-    sonarsourceSecurityOpen: true,
-    sonarsourceSecurityStats: { 'sql-injection': 10 },
-  });
-
-  selectAndCheck('owaspTop10', 'a1');
-  selectAndCheck('owaspTop10', 'a1', true, ['a1', 'a3']);
-  selectAndCheck('sonarsourceSecurity', 'sql-injection');
-
-  function selectAndCheck(facet: string, value: string, multiple = false, expectedValue = [value]) {
-    wrapper
-      .find(`FacetBox[property="${facet}"]`)
-      .find(`FacetItem[value="${value}"]`)
-      .prop<Function>('onClick')(value, multiple);
-    expect(onChange).toHaveBeenLastCalledWith({ [facet]: expectedValue });
-  }
-});
-
-it('should toggle sub-facets', () => {
-  const onToggle = jest.fn();
-  const wrapper = shallowRender({ onToggle, open: true });
-  click(wrapper.find('FacetBox[property="owaspTop10"]').children('FacetHeader'));
-  expect(onToggle).toHaveBeenLastCalledWith('owaspTop10');
-  click(wrapper.find('FacetBox[property="sonarsourceSecurity"]').children('FacetHeader'));
-  expect(onToggle).toHaveBeenLastCalledWith('sonarsourceSecurity');
-});
-
-it('should display correct selection', () => {
-  const wrapper = shallowRender({
-    open: true,
-    owaspTop10: ['a1', 'a3'],
-    'owaspTop10-2021': ['a1', 'a2'],
-    cwe: ['42', '1111', 'unknown'],
-    sonarsourceSecurity: ['sql-injection', 'others'],
-  });
-  checkValues('standards', [
-    'SONAR SQL Injection',
-    'Others',
-    'OWASP A1 - a1 title',
-    'OWASP A3',
-    'OWASP A1 - a1 title',
-    'OWASP A2',
-    'CWE-42 - cwe-42 title',
-    'CWE-1111',
-    'Unknown CWE',
-  ]);
-  checkValues('owaspTop10', ['A1 - a1 title', 'A3']);
-  checkValues('owaspTop10-2021', ['A1 - a1 title', 'A2']);
-  checkValues('sonarsourceSecurity', ['SQL Injection', 'Others']);
-
-  function checkValues(property: string, values: string[]) {
-    expect(
-      wrapper.find(`FacetBox[property="${property}"]`).children('FacetHeader').prop('values')
-    ).toEqual(values);
-  }
-});
-
-function shallowRender(props: Partial<StandardFacet['props']> = {}) {
-  const wrapper = shallow(
-    <StandardFacet
-      cwe={[]}
-      cweOpen={false}
-      cweStats={{}}
-      fetchingCwe={false}
-      fetchingOwaspTop10={false}
-      fetchingOwaspTop10-2021={false}
-      fetchingSonarSourceSecurity={false}
-      loadSearchResultCount={jest.fn()}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={false}
-      owaspTop10={[]}
-      owaspTop10Open={false}
-      owaspTop10Stats={{}}
-      owaspTop10-2021={[]}
-      owaspTop10-2021Open={false}
-      owaspTop10-2021Stats={{}}
-      query={{} as Query}
-      sonarsourceSecurity={[]}
-      sonarsourceSecurityOpen={false}
-      sonarsourceSecurityStats={{}}
-      {...props}
-    />
-  );
-  wrapper.setState({
-    standards: {
-      owaspTop10: { a1: { title: 'a1 title' } },
-      'owaspTop10-2021': { a1: { title: 'a1 title' } },
-      cwe: { 42: { title: 'cwe-42 title' }, unknown: { title: 'Unknown CWE' } },
-      sonarsourceSecurity: {
-        'sql-injection': { title: 'SQL Injection' },
-        others: { title: 'Others' },
-      },
-    },
-  });
-  return wrapper;
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StatusFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StatusFacet-test.tsx
deleted file mode 100644 (file)
index 1f3c1a6..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { click } from '../../../../helpers/testUtils';
-import StatusFacet from '../StatusFacet';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should toggle status facet', () => {
-  const onToggle = jest.fn();
-  const wrapper = shallowRender({ onToggle });
-  click(wrapper.children('FacetHeader'));
-  expect(onToggle).toHaveBeenCalledWith('statuses');
-});
-
-it('should clear status facet', () => {
-  const onChange = jest.fn();
-  const wrapper = shallowRender({ onChange, statuses: ['CONFIRMED'] });
-  wrapper.children('FacetHeader').prop<Function>('onClear')();
-  expect(onChange).toHaveBeenCalledWith({ statuses: [] });
-});
-
-it('should select a status', () => {
-  const onChange = jest.fn();
-  const wrapper = shallowRender({ onChange });
-  clickAndCheck('OPEN');
-  clickAndCheck('CONFIRMED', true, ['CONFIRMED', 'OPEN']);
-  clickAndCheck('CLOSED');
-
-  function clickAndCheck(status: string, multiple = false, expected = [status]) {
-    wrapper.find(`FacetItemsList`).find(`FacetItem[value="${status}"]`).prop<Function>('onClick')(
-      status,
-      multiple
-    );
-    expect(onChange).toHaveBeenLastCalledWith({ statuses: expected });
-    wrapper.setProps({ statuses: expected });
-  }
-});
-
-function shallowRender(props: Partial<StatusFacet['props']> = {}) {
-  return shallow(
-    <StatusFacet
-      fetching={false}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      open={true}
-      stats={{
-        OPEN: 104,
-        CONFIRMED: 8,
-        REOPENED: 0,
-        RESOLVED: 0,
-        CLOSED: 8,
-      }}
-      statuses={[]}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/TypeFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/TypeFacet-test.tsx
deleted file mode 100644 (file)
index 6ef7659..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { click } from '../../../../helpers/testUtils';
-import TypeFacet from '../TypeFacet';
-
-it('should render open by default', () => {
-  expect(shallowRender({ types: ['VULNERABILITY', 'CODE_SMELL'] })).toMatchSnapshot();
-});
-
-it('should toggle type facet', () => {
-  const onToggle = jest.fn();
-  const wrapper = shallowRender({ onToggle });
-  click(wrapper.children('FacetHeader'));
-  expect(onToggle).toHaveBeenCalledWith('types');
-});
-
-it('should clear types facet', () => {
-  const onChange = jest.fn();
-  const wrapper = shallowRender({ onChange, types: ['BUGS'] });
-  wrapper.children('FacetHeader').prop<Function>('onClear')();
-  expect(onChange).toHaveBeenCalledWith({ types: [] });
-});
-
-it('should select a type', () => {
-  const onChange = jest.fn();
-  const wrapper = shallowRender({ onChange });
-  clickAndCheck('CODE_SMELL');
-  clickAndCheck('VULNERABILITY', true, ['CODE_SMELL', 'VULNERABILITY']);
-
-  function clickAndCheck(type: string, multiple = false, expected = [type]) {
-    wrapper.find(`FacetItemsList`).find(`FacetItem[value="${type}"]`).prop<Function>('onClick')(
-      type,
-      multiple
-    );
-    expect(onChange).toHaveBeenLastCalledWith({ types: expected });
-    wrapper.setProps({ types: expected });
-  }
-});
-
-function shallowRender(props: Partial<TypeFacet['props']> = {}) {
-  return shallow(
-    <TypeFacet
-      fetching={false}
-      onChange={jest.fn()}
-      onToggle={jest.fn()}
-      stats={{ BUG: 0, VULNERABILITY: 2, CODE_SMELL: 5, SECURITY_HOTSPOT: 1 }}
-      types={[]}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap
deleted file mode 100644 (file)
index e6f5de2..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<ListStyleFacet
-  facetHeader="issues.facet.assignees"
-  fetching={false}
-  getFacetItemText={[Function]}
-  getSearchResultKey={[Function]}
-  getSearchResultText={[Function]}
-  getSortedItems={[Function]}
-  loadSearchResultCount={[Function]}
-  maxInitialItems={15}
-  maxItems={100}
-  minSearchLength={2}
-  onChange={[MockFunction]}
-  onClear={[Function]}
-  onItemClick={[Function]}
-  onSearch={[Function]}
-  onToggle={[MockFunction]}
-  open={true}
-  property="assignees"
-  query={{}}
-  renderFacetItem={[Function]}
-  renderSearchResult={[Function]}
-  searchPlaceholder="search.search_for_users"
-  stats={
-    {
-      "": 5,
-      "bar": 7,
-      "baz": 6,
-      "foo": 13,
-    }
-  }
-  values={
-    [
-      "foo",
-    ]
-  }
-/>
-`;
-
-exports[`test behavior should correctly render facet item 1`] = `
-<React.Fragment>
-  <withAppStateContext(Avatar)
-    className="little-spacer-right"
-    name="Name Baz"
-    size={16}
-  />
-  Name Baz
-</React.Fragment>
-`;
-
-exports[`test behavior should correctly render facet item 2`] = `
-<React.Fragment>
-  <withAppStateContext(Avatar)
-    className="little-spacer-right"
-    name="foo"
-    size={16}
-  />
-  user.x_deleted.foo
-</React.Fragment>
-`;
-
-exports[`test behavior should correctly render search result correctly 1`] = `
-<React.Fragment>
-  <withAppStateContext(Avatar)
-    className="little-spacer-right"
-    name="Name Bar"
-    size={16}
-  />
-  <React.Fragment>
-    Name 
-    <mark>
-      Ba
-    </mark>
-    r
-  </React.Fragment>
-</React.Fragment>
-`;
-
-exports[`test behavior should correctly render search result correctly 2`] = `
-<React.Fragment>
-  <withAppStateContext(Avatar)
-    className="little-spacer-right"
-    name="foo"
-    size={16}
-  />
-  <React.Fragment>
-    user.x_deleted.
-    <mark>
-      fo
-    </mark>
-    o
-  </React.Fragment>
-</React.Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AuthorFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AuthorFacet-test.tsx.snap
deleted file mode 100644 (file)
index 9d8d336..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
-  facetHeader="issues.facet.authors"
-  fetching={false}
-  getFacetItemText={[Function]}
-  getSearchResultKey={[Function]}
-  getSearchResultText={[Function]}
-  loadSearchResultCount={[Function]}
-  maxInitialItems={15}
-  maxItems={100}
-  minSearchLength={2}
-  onChange={[MockFunction]}
-  onSearch={[Function]}
-  onToggle={[MockFunction]}
-  open={true}
-  property="author"
-  query={{}}
-  renderFacetItem={[Function]}
-  renderSearchResult={[Function]}
-  searchPlaceholder="search.search_for_authors"
-  stats={{}}
-  values={[]}
-/>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/CreationDateFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/CreationDateFacet-test.tsx.snap
deleted file mode 100644 (file)
index 028ee16..0000000
+++ /dev/null
@@ -1,548 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly for createdInLast month 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "issues.facet.createdAt.last_month",
-      ]
-    }
-  />
-  <div>
-    <div
-      className="search-navigator-date-facet-selection"
-    >
-      <DateRangeInput
-        alignEndDateCalandarRight={true}
-        onChange={[Function]}
-        value={
-          {
-            "from": undefined,
-            "to": undefined,
-          }
-        }
-      />
-    </div>
-    <div
-      className="spacer-top issues-predefined-periods"
-    >
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.all"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.all"
-        value=""
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_week"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_week"
-        value="1w"
-      />
-      <FacetItem
-        active={true}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_month"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_month"
-        value="1m"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_year"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_year"
-        value="1y"
-      />
-    </div>
-  </div>
-</FacetBox>
-`;
-
-exports[`should render correctly for createdInLast week 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "issues.facet.createdAt.last_week",
-      ]
-    }
-  />
-  <div>
-    <div
-      className="search-navigator-date-facet-selection"
-    >
-      <DateRangeInput
-        alignEndDateCalandarRight={true}
-        onChange={[Function]}
-        value={
-          {
-            "from": undefined,
-            "to": undefined,
-          }
-        }
-      />
-    </div>
-    <div
-      className="spacer-top issues-predefined-periods"
-    >
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.all"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.all"
-        value=""
-      />
-      <FacetItem
-        active={true}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_week"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_week"
-        value="1w"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_month"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_month"
-        value="1m"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_year"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_year"
-        value="1y"
-      />
-    </div>
-  </div>
-</FacetBox>
-`;
-
-exports[`should render correctly for createdInLast year 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "issues.facet.createdAt.last_year",
-      ]
-    }
-  />
-  <div>
-    <div
-      className="search-navigator-date-facet-selection"
-    >
-      <DateRangeInput
-        alignEndDateCalandarRight={true}
-        onChange={[Function]}
-        value={
-          {
-            "from": undefined,
-            "to": undefined,
-          }
-        }
-      />
-    </div>
-    <div
-      className="spacer-top issues-predefined-periods"
-    >
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.all"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.all"
-        value=""
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_week"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_week"
-        value="1w"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_month"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_month"
-        value="1m"
-      />
-      <FacetItem
-        active={true}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_year"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_year"
-        value="1y"
-      />
-    </div>
-  </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: clear 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={[]}
-  />
-  <div>
-    <div
-      className="search-navigator-date-facet-selection"
-    >
-      <DateRangeInput
-        alignEndDateCalandarRight={true}
-        onChange={[Function]}
-        value={
-          {
-            "from": undefined,
-            "to": undefined,
-          }
-        }
-      />
-    </div>
-    <div
-      className="spacer-top issues-predefined-periods"
-    >
-      <FacetItem
-        active={true}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.all"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.all"
-        value=""
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_week"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_week"
-        value="1w"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_month"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_month"
-        value="1m"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_year"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_year"
-        value="1y"
-      />
-    </div>
-  </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: closed 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={false}
-    values={[]}
-  />
-</FacetBox>
-`;
-
-exports[`should render correctly: created after 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "formatted.Invalid Date",
-      ]
-    }
-  />
-  <div
-    className="search-navigator-facet-container"
-  >
-    <strong>
-      after
-       
-    </strong>
-    <DateTimeFormatter
-      date={Date { NaN }}
-    />
-  </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: created after timestamp 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "formatted.Invalid Date",
-      ]
-    }
-  />
-  <div
-    className="search-navigator-facet-container"
-  >
-    <strong>
-      after
-       
-    </strong>
-    <DateTimeFormatter
-      date={Date { NaN }}
-    />
-  </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: created at 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "formatted.2019.05.21T13:33:00Z",
-      ]
-    }
-  />
-  <div
-    className="search-navigator-facet-container"
-  >
-    <DateTimeFormatter
-      date="2019.05.21T13:33:00Z"
-    />
-    <br />
-    <span
-      className="note"
-    >
-      <DateFromNow
-        date="2019.05.21T13:33:00Z"
-      />
-    </span>
-  </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: portfolio 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={[]}
-  />
-  <div>
-    <div
-      className="search-navigator-date-facet-selection"
-    >
-      <DateRangeInput
-        alignEndDateCalandarRight={true}
-        onChange={[Function]}
-        value={
-          {
-            "from": undefined,
-            "to": undefined,
-          }
-        }
-      />
-    </div>
-    <div
-      className="spacer-top issues-predefined-periods"
-    >
-      <FacetItem
-        active={true}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.all"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.all"
-        value=""
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_week"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_week"
-        value="1w"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_month"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_month"
-        value="1m"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_year"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_year"
-        value="1y"
-      />
-    </div>
-  </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: project 1`] = `
-<FacetBox
-  property="createdAt"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.createdAt"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={[]}
-  />
-  <div>
-    <div
-      className="search-navigator-date-facet-selection"
-    >
-      <DateRangeInput
-        alignEndDateCalandarRight={true}
-        onChange={[Function]}
-        value={
-          {
-            "from": undefined,
-            "to": undefined,
-          }
-        }
-      />
-    </div>
-    <div
-      className="spacer-top issues-predefined-periods"
-    >
-      <FacetItem
-        active={true}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.all"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.all"
-        value=""
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_week"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_week"
-        value="1w"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_month"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_month"
-        value="1m"
-      />
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        loading={false}
-        name="issues.facet.createdAt.last_year"
-        onClick={[Function]}
-        tooltip="issues.facet.createdAt.last_year"
-        value="1y"
-      />
-    </div>
-  </div>
-</FacetBox>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/DirectoryFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/DirectoryFacet-test.tsx.snap
deleted file mode 100644 (file)
index d7c77c1..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
-  facetHeader="issues.facet.directories"
-  fetching={false}
-  getFacetItemText={[Function]}
-  getSearchResultKey={[Function]}
-  getSearchResultText={[Function]}
-  loadSearchResultCount={[Function]}
-  maxInitialItems={15}
-  maxItems={100}
-  minSearchLength={3}
-  onChange={[MockFunction]}
-  onSearch={[Function]}
-  onToggle={[MockFunction]}
-  open={false}
-  property="directories"
-  query={{}}
-  renderFacetItem={[Function]}
-  renderSearchResult={[Function]}
-  searchPlaceholder="search.search_for_directories"
-  values={
-    [
-      "foo/",
-      "bar/baz/",
-    ]
-  }
-/>
-`;
-
-exports[`should render correctly 2`] = `
-<React.Fragment>
-  <QualifierIcon
-    className="little-spacer-right"
-    qualifier="DIR"
-  />
-  <React.Fragment>
-    <mark>
-      foo
-    </mark>
-    /bar
-  </React.Fragment>
-</React.Fragment>
-`;
-
-exports[`should render correctly 3`] = `
-<React.Fragment>
-  <QualifierIcon
-    className="little-spacer-right"
-    qualifier="DIR"
-  />
-  foo/bar
-</React.Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/FileFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/FileFacet-test.tsx.snap
deleted file mode 100644 (file)
index 56d01f3..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
-  facetHeader="issues.facet.files"
-  fetching={false}
-  getFacetItemText={[Function]}
-  getSearchResultKey={[Function]}
-  getSearchResultText={[Function]}
-  loadSearchResultCount={[Function]}
-  maxInitialItems={15}
-  maxItems={100}
-  minSearchLength={3}
-  onChange={[MockFunction]}
-  onSearch={[Function]}
-  onToggle={[MockFunction]}
-  open={false}
-  property="files"
-  query={{}}
-  renderFacetItem={[Function]}
-  renderSearchResult={[Function]}
-  searchPlaceholder="search.search_for_files"
-  values={
-    [
-      "foo",
-      "bar",
-    ]
-  }
-/>
-`;
-
-exports[`should render correctly 2`] = `
-<React.Fragment>
-  <QualifierIcon
-    className="little-spacer-right"
-    qualifier="FIL"
-  />
-  <React.Fragment>
-    foo
-    /
-    <React.Fragment>
-      <mark>
-        bar
-      </mark>
-      .js
-    </React.Fragment>
-  </React.Fragment>
-</React.Fragment>
-`;
-
-exports[`should render correctly 3`] = `
-<React.Fragment>
-  <QualifierIcon
-    className="little-spacer-right"
-    qualifier="FIL"
-  />
-  fooUuid
-</React.Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ProjectFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ProjectFacet-test.tsx.snap
deleted file mode 100644 (file)
index 8502212..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ListStyleFacet's renderers should include renderFacetItem 1`] = `
-<span>
-  <QualifierIcon
-    className="little-spacer-right"
-    qualifier="TRK"
-  />
-  First Project Name
-</span>
-`;
-
-exports[`ListStyleFacet's renderers should include renderSearchResult 1`] = `
-<React.Fragment>
-  <QualifierIcon
-    className="little-spacer-right"
-    qualifier="TRK"
-  />
-  <React.Fragment>
-    <mark>
-      First
-    </mark>
-     Project Name
-  </React.Fragment>
-</React.Fragment>
-`;
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
-  facetHeader="issues.facet.projects"
-  fetching={false}
-  getFacetItemText={[Function]}
-  getSearchResultKey={[Function]}
-  getSearchResultText={[Function]}
-  loadSearchResultCount={[Function]}
-  maxInitialItems={15}
-  maxItems={100}
-  minSearchLength={2}
-  onChange={[MockFunction]}
-  onSearch={[Function]}
-  onToggle={[MockFunction]}
-  open={false}
-  property="projects"
-  query={{}}
-  renderFacetItem={[Function]}
-  renderSearchResult={[Function]}
-  searchPlaceholder="search.search_for_projects"
-  values={[]}
-/>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/RuleFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/RuleFacet-test.tsx.snap
deleted file mode 100644 (file)
index 8ef9b57..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
-  facetHeader="issues.facet.rules"
-  fetching={true}
-  getFacetItemText={[Function]}
-  getSearchResultKey={[Function]}
-  getSearchResultText={[Function]}
-  loadSearchResultCount={[Function]}
-  maxInitialItems={15}
-  maxItems={100}
-  minSearchLength={2}
-  onChange={[MockFunction]}
-  onSearch={[Function]}
-  onToggle={[MockFunction]}
-  open={false}
-  property="rules"
-  query={{}}
-  renderFacetItem={[Function]}
-  renderSearchResult={[Function]}
-  searchPlaceholder="search.search_for_rules"
-  stats={{}}
-  values={
-    [
-      "r1",
-    ]
-  }
-/>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ScopeFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ScopeFacet-test.tsx.snap
deleted file mode 100644 (file)
index 4d536bb..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: active facet 1`] = `
-<FacetBox
-  property="scopes"
->
-  <FacetHeader
-    fetching={true}
-    name="issues.facet.scopes"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "issue.scope.MAIN",
-      ]
-    }
-  />
-  <FacetItemsList>
-    <FacetItem
-      active={true}
-      halfWidth={false}
-      key="MAIN"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <QualifierIcon
-            aria-hidden={true}
-            className="little-spacer-right"
-            qualifier="FIL"
-          />
-           
-          issue.scope.MAIN
-        </span>
-      }
-      onClick={[Function]}
-      value="MAIN"
-    />
-    <FacetItem
-      active={false}
-      halfWidth={false}
-      key="TEST"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <QualifierIcon
-            aria-hidden={true}
-            className="little-spacer-right"
-            qualifier="UTS"
-          />
-           
-          issue.scope.TEST
-        </span>
-      }
-      onClick={[Function]}
-      value="TEST"
-    />
-  </FacetItemsList>
-  <MultipleSelectionHint
-    options={0}
-    values={1}
-  />
-</FacetBox>
-`;
-
-exports[`should render correctly: default 1`] = `
-<FacetBox
-  property="scopes"
->
-  <FacetHeader
-    fetching={true}
-    name="issues.facet.scopes"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={false}
-    values={[]}
-  />
-</FacetBox>
-`;
-
-exports[`should render correctly: disabled facet 1`] = `
-<FacetBox
-  property="scopes"
->
-  <FacetHeader
-    fetching={true}
-    name="issues.facet.scopes"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={[]}
-  />
-  <FacetItemsList>
-    <FacetItem
-      active={false}
-      halfWidth={false}
-      key="MAIN"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <QualifierIcon
-            aria-hidden={true}
-            className="little-spacer-right"
-            qualifier="FIL"
-          />
-           
-          issue.scope.MAIN
-        </span>
-      }
-      onClick={[Function]}
-      stat={0}
-      value="MAIN"
-    />
-    <FacetItem
-      active={false}
-      halfWidth={false}
-      key="TEST"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <QualifierIcon
-            aria-hidden={true}
-            className="little-spacer-right"
-            qualifier="UTS"
-          />
-           
-          issue.scope.TEST
-        </span>
-      }
-      onClick={[Function]}
-      value="TEST"
-    />
-  </FacetItemsList>
-  <MultipleSelectionHint
-    options={1}
-    values={0}
-  />
-</FacetBox>
-`;
-
-exports[`should render correctly: open 1`] = `
-<FacetBox
-  property="scopes"
->
-  <FacetHeader
-    fetching={true}
-    name="issues.facet.scopes"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={[]}
-  />
-  <FacetItemsList>
-    <FacetItem
-      active={false}
-      halfWidth={false}
-      key="MAIN"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <QualifierIcon
-            aria-hidden={true}
-            className="little-spacer-right"
-            qualifier="FIL"
-          />
-           
-          issue.scope.MAIN
-        </span>
-      }
-      onClick={[Function]}
-      value="MAIN"
-    />
-    <FacetItem
-      active={false}
-      halfWidth={false}
-      key="TEST"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <QualifierIcon
-            aria-hidden={true}
-            className="little-spacer-right"
-            qualifier="UTS"
-          />
-           
-          issue.scope.TEST
-        </span>
-      }
-      onClick={[Function]}
-      value="TEST"
-    />
-  </FacetItemsList>
-  <MultipleSelectionHint
-    options={0}
-    values={0}
-  />
-</FacetBox>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap
deleted file mode 100644 (file)
index c15aaf6..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should not render developer nominative facets when asked not to 1`] = `
-[
-  "TypeFacet",
-  "SeverityFacet",
-  "ScopeFacet",
-  "ResolutionFacet",
-  "StatusFacet",
-  "StandardFacet",
-  "injectIntl(CreationDateFacet)",
-  "withLanguagesContext(LanguageFacet)",
-  "RuleFacet",
-  "TagFacet",
-  "ProjectFacet",
-]
-`;
-
-exports[`should render facets for "APP" 1`] = `
-[
-  "PeriodFilter",
-  "TypeFacet",
-  "SeverityFacet",
-  "ScopeFacet",
-  "ResolutionFacet",
-  "StatusFacet",
-  "StandardFacet",
-  "injectIntl(CreationDateFacet)",
-  "withLanguagesContext(LanguageFacet)",
-  "RuleFacet",
-  "TagFacet",
-  "ProjectFacet",
-  "AssigneeFacet",
-  "AuthorFacet",
-]
-`;
-
-exports[`should render facets for "SVW" 1`] = `
-[
-  "TypeFacet",
-  "SeverityFacet",
-  "ScopeFacet",
-  "ResolutionFacet",
-  "StatusFacet",
-  "StandardFacet",
-  "injectIntl(CreationDateFacet)",
-  "withLanguagesContext(LanguageFacet)",
-  "RuleFacet",
-  "TagFacet",
-  "ProjectFacet",
-  "AssigneeFacet",
-  "AuthorFacet",
-]
-`;
-
-exports[`should render facets for "VW" 1`] = `
-[
-  "TypeFacet",
-  "SeverityFacet",
-  "ScopeFacet",
-  "ResolutionFacet",
-  "StatusFacet",
-  "StandardFacet",
-  "injectIntl(CreationDateFacet)",
-  "withLanguagesContext(LanguageFacet)",
-  "RuleFacet",
-  "TagFacet",
-  "ProjectFacet",
-  "AssigneeFacet",
-  "AuthorFacet",
-]
-`;
-
-exports[`should render facets for global page 1`] = `
-[
-  "TypeFacet",
-  "SeverityFacet",
-  "ScopeFacet",
-  "ResolutionFacet",
-  "StatusFacet",
-  "StandardFacet",
-  "injectIntl(CreationDateFacet)",
-  "withLanguagesContext(LanguageFacet)",
-  "RuleFacet",
-  "TagFacet",
-  "ProjectFacet",
-  "AssigneeFacet",
-  "AuthorFacet",
-]
-`;
-
-exports[`should render facets for project 1`] = `
-[
-  "PeriodFilter",
-  "TypeFacet",
-  "SeverityFacet",
-  "ScopeFacet",
-  "ResolutionFacet",
-  "StatusFacet",
-  "StandardFacet",
-  "injectIntl(CreationDateFacet)",
-  "withLanguagesContext(LanguageFacet)",
-  "RuleFacet",
-  "TagFacet",
-  "DirectoryFacet",
-  "FileFacet",
-  "AssigneeFacet",
-  "AuthorFacet",
-]
-`;
-
-exports[`should render facets when my issues are selected 1`] = `
-[
-  "TypeFacet",
-  "SeverityFacet",
-  "ScopeFacet",
-  "ResolutionFacet",
-  "StatusFacet",
-  "StandardFacet",
-  "injectIntl(CreationDateFacet)",
-  "withLanguagesContext(LanguageFacet)",
-  "RuleFacet",
-  "TagFacet",
-  "ProjectFacet",
-  "AuthorFacet",
-]
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap
deleted file mode 100644 (file)
index e1996d2..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render closed 1`] = `
-<FacetBox
-  property="standards"
->
-  <FacetHeader
-    name="issues.facet.standards"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={false}
-    values={[]}
-  />
-</FacetBox>
-`;
-
-exports[`should render empty sub-facet 1`] = `
-<FacetBox
-  className="is-inner"
-  property="owaspTop10-2021"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.owaspTop10_2021"
-    onClick={[Function]}
-    open={true}
-    values={[]}
-  />
-  <div
-    className="search-navigator-facet-empty little-spacer-top"
-  >
-    no_results
-  </div>
-  <MultipleSelectionHint
-    options={0}
-    values={0}
-  />
-</FacetBox>
-`;
-
-exports[`should render sub-facets 1`] = `
-<FacetBox
-  property="standards"
->
-  <FacetHeader
-    name="issues.facet.standards"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "SONAR SQL Injection",
-        "OWASP A3",
-        "CWE-42 - cwe-42 title",
-      ]
-    }
-  />
-  <FacetBox
-    className="is-inner"
-    property="sonarsourceSecurity"
-  >
-    <FacetHeader
-      fetching={false}
-      name="issues.facet.sonarsourceSecurity"
-      onClick={[Function]}
-      open={true}
-      values={
-        [
-          "SQL Injection",
-        ]
-      }
-    />
-    <FacetItemsList>
-      <FacetItem
-        active={true}
-        halfWidth={false}
-        key="sql-injection"
-        loading={false}
-        name="SQL Injection"
-        onClick={[Function]}
-        stat="12"
-        tooltip="SQL Injection"
-        value="sql-injection"
-      />
-    </FacetItemsList>
-    <MultipleSelectionHint
-      options={1}
-      values={1}
-    />
-  </FacetBox>
-  <FacetBox
-    className="is-inner"
-    property="owaspTop10-2021"
-  >
-    <FacetHeader
-      fetching={false}
-      name="issues.facet.owaspTop10_2021"
-      onClick={[Function]}
-      open={false}
-      values={[]}
-    />
-  </FacetBox>
-  <FacetBox
-    className="is-inner"
-    property="owaspTop10"
-  >
-    <FacetHeader
-      fetching={false}
-      name="issues.facet.owaspTop10"
-      onClick={[Function]}
-      open={true}
-      values={
-        [
-          "A3",
-        ]
-      }
-    />
-    <FacetItemsList>
-      <FacetItem
-        active={false}
-        halfWidth={false}
-        key="a1"
-        loading={false}
-        name="A1 - a1 title"
-        onClick={[Function]}
-        stat="15"
-        tooltip="A1 - a1 title"
-        value="a1"
-      />
-      <FacetItem
-        active={true}
-        halfWidth={false}
-        key="a3"
-        loading={false}
-        name="A3"
-        onClick={[Function]}
-        stat="5"
-        tooltip="A3"
-        value="a3"
-      />
-    </FacetItemsList>
-    <MultipleSelectionHint
-      options={2}
-      values={1}
-    />
-  </FacetBox>
-  <ListStyleFacet
-    className="is-inner"
-    facetHeader="issues.facet.cwe"
-    fetching={false}
-    getFacetItemText={[Function]}
-    getSearchResultKey={[Function]}
-    getSearchResultText={[Function]}
-    loadSearchResultCount={[Function]}
-    maxInitialItems={15}
-    maxItems={100}
-    minSearchLength={2}
-    onChange={[MockFunction]}
-    onSearch={[Function]}
-    onToggle={[MockFunction]}
-    open={true}
-    property="cwe"
-    query={{}}
-    renderFacetItem={[Function]}
-    renderSearchResult={[Function]}
-    searchPlaceholder="search.search_for_cwe"
-    stats={
-      {
-        "173": 3,
-        "42": 5,
-      }
-    }
-    values={
-      [
-        "42",
-      ]
-    }
-  />
-</FacetBox>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StatusFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StatusFacet-test.tsx.snap
deleted file mode 100644 (file)
index c311315..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<FacetBox
-  property="statuses"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.statuses"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={[]}
-  />
-  <FacetItemsList>
-    <FacetItem
-      active={false}
-      halfWidth={true}
-      key="OPEN"
-      loading={false}
-      name={
-        <StatusHelper
-          status="OPEN"
-        />
-      }
-      onClick={[Function]}
-      stat="104"
-      tooltip="issue.status.OPEN"
-      value="OPEN"
-    />
-    <FacetItem
-      active={false}
-      halfWidth={true}
-      key="CONFIRMED"
-      loading={false}
-      name={
-        <StatusHelper
-          status="CONFIRMED"
-        />
-      }
-      onClick={[Function]}
-      stat="8"
-      tooltip="issue.status.CONFIRMED"
-      value="CONFIRMED"
-    />
-    <FacetItem
-      active={false}
-      halfWidth={true}
-      key="REOPENED"
-      loading={false}
-      name={
-        <StatusHelper
-          status="REOPENED"
-        />
-      }
-      onClick={[Function]}
-      stat={0}
-      tooltip="issue.status.REOPENED"
-      value="REOPENED"
-    />
-    <FacetItem
-      active={false}
-      halfWidth={true}
-      key="RESOLVED"
-      loading={false}
-      name={
-        <StatusHelper
-          status="RESOLVED"
-        />
-      }
-      onClick={[Function]}
-      stat={0}
-      tooltip="issue.status.RESOLVED"
-      value="RESOLVED"
-    />
-    <FacetItem
-      active={false}
-      halfWidth={true}
-      key="CLOSED"
-      loading={false}
-      name={
-        <StatusHelper
-          status="CLOSED"
-        />
-      }
-      onClick={[Function]}
-      stat="8"
-      tooltip="issue.status.CLOSED"
-      value="CLOSED"
-    />
-  </FacetItemsList>
-  <MultipleSelectionHint
-    options={5}
-    values={0}
-  />
-</FacetBox>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/TypeFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/TypeFacet-test.tsx.snap
deleted file mode 100644 (file)
index d5f48e2..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render open by default 1`] = `
-<FacetBox
-  property="types"
->
-  <FacetHeader
-    fetching={false}
-    name="issues.facet.types"
-    onClear={[Function]}
-    onClick={[Function]}
-    open={true}
-    values={
-      [
-        "issue.type.VULNERABILITY",
-        "issue.type.CODE_SMELL",
-      ]
-    }
-  />
-  <FacetItemsList>
-    <FacetItem
-      active={false}
-      halfWidth={false}
-      key="BUG"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <IssueTypeIcon
-            className="little-spacer-right"
-            query="BUG"
-          />
-           
-          issue.type.BUG
-        </span>
-      }
-      onClick={[Function]}
-      stat={0}
-      value="BUG"
-    />
-    <FacetItem
-      active={true}
-      halfWidth={false}
-      key="VULNERABILITY"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <IssueTypeIcon
-            className="little-spacer-right"
-            query="VULNERABILITY"
-          />
-           
-          issue.type.VULNERABILITY
-        </span>
-      }
-      onClick={[Function]}
-      stat="2"
-      value="VULNERABILITY"
-    />
-    <FacetItem
-      active={true}
-      halfWidth={false}
-      key="CODE_SMELL"
-      loading={false}
-      name={
-        <span
-          className="display-flex-center"
-        >
-          <IssueTypeIcon
-            className="little-spacer-right"
-            query="CODE_SMELL"
-          />
-           
-          issue.type.CODE_SMELL
-        </span>
-      }
-      onClick={[Function]}
-      stat="5"
-      value="CODE_SMELL"
-    />
-  </FacetItemsList>
-  <MultipleSelectionHint
-    options={4}
-    values={2}
-  />
-</FacetBox>
-`;
index 1469fa0fce8ee1b6a0ea34c0ef7b1e7928af495c..8688bd62ed34d38a9d482b8fa507ead8c43dff1f 100644 (file)
@@ -93,6 +93,7 @@ exports[`should render correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -128,6 +129,7 @@ exports[`should render correctly 1`] = `
               "projectName": "Foo",
               "rule": "javascript:S1067",
               "ruleName": "foo",
+              "scope": "MAIN",
               "secondaryLocations": [],
               "severity": "MAJOR",
               "status": "OPEN",
index 231134d60512043d34950d795d9ddd83ac893da6..11e954e8499b637f319b96b7c04b854967c20dfd 100644 (file)
@@ -33,6 +33,7 @@ exports[`should render issues 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [],
         "severity": "MAJOR",
         "status": "OPEN",
index 849ce18835131f512fa668cec87276aae9b2678f..bb33e7066d4e2a6cca6bf05621a5223353f7d5a2 100644 (file)
@@ -27,6 +27,7 @@ exports[`should render hotspots correctly 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [],
         "severity": "MAJOR",
         "status": "OPEN",
@@ -64,6 +65,7 @@ exports[`should render hotspots correctly 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [],
         "severity": "MAJOR",
         "status": "OPEN",
@@ -125,6 +127,7 @@ exports[`should render issues correctly 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [],
         "severity": "MAJOR",
         "status": "OPEN",
@@ -176,6 +179,7 @@ exports[`should render issues correctly 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [],
         "severity": "MAJOR",
         "status": "OPEN",
index 78a0638669c50749077ea9284dda7ef2bacde38c..655c1f6880582f57fd853607d3ca10351963bc9a 100644 (file)
@@ -37,6 +37,7 @@ exports[`should render issues correctly 1`] = `
       "projectName": "Foo",
       "rule": "javascript:S1067",
       "ruleName": "foo",
+      "scope": "MAIN",
       "secondaryLocations": [],
       "severity": "MAJOR",
       "status": "OPEN",
index 30fff84a310365c5da6d3a71e4d66da69aa7f9df..3856c5489ddecbb32424792d3e003c8451fa9f5d 100644 (file)
@@ -20,7 +20,7 @@
 import classNames from 'classnames';
 import * as React from 'react';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { IssueResponse } from '../../../types/issues';
+import { IssueResolution, IssueResponse, IssueType as IssueTypeEnum } from '../../../types/issues';
 import { Issue, RawQuery } from '../../../types/types';
 import { updateIssue } from '../actions';
 import IssueAssign from './IssueAssign';
@@ -81,8 +81,8 @@ export default class IssueActionsBar extends React.PureComponent<Props, State> {
   handleTransition = (issue: Issue) => {
     this.props.onChange(issue);
     if (
-      issue.resolution === 'FALSE-POSITIVE' ||
-      (issue.resolution === 'WONTFIX' && issue.type !== 'SECURITY_HOTSPOT')
+      issue.resolution === IssueResolution.FalsePositive ||
+      (issue.resolution === IssueResolution.WontFix && issue.type !== IssueTypeEnum.SecurityHotspot)
     ) {
       this.toggleComment(true, translate('issue.comment.explain_why'), true);
     }
@@ -96,7 +96,7 @@ export default class IssueActionsBar extends React.PureComponent<Props, State> {
     const canSetType = issue.actions.includes('set_type');
     const canSetTags = issue.actions.includes('set_tags');
     const hasTransitions = issue.transitions && issue.transitions.length > 0;
-    const isSecurityHotspot = issue.type === 'SECURITY_HOTSPOT';
+    const isSecurityHotspot = issue.type === IssueTypeEnum.SecurityHotspot;
 
     return (
       <div className={classNames(className, 'issue-actions')}>
index 431197f6a575fe4fd62b2e8534df0944bd562edc..0a5febfcea31ba289d07795a6339656eb64373cb 100644 (file)
@@ -34,6 +34,7 @@ exports[`should render commentable correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -78,6 +79,7 @@ exports[`should render commentable correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -122,6 +124,7 @@ exports[`should render commentable correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -166,6 +169,7 @@ exports[`should render commentable correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -222,6 +226,7 @@ exports[`should render commentable correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -276,6 +281,7 @@ exports[`should render effort correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -319,6 +325,7 @@ exports[`should render effort correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -362,6 +369,7 @@ exports[`should render effort correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -405,6 +413,7 @@ exports[`should render effort correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -461,6 +470,7 @@ exports[`should render effort correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -514,6 +524,7 @@ exports[`should render issue correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -556,6 +567,7 @@ exports[`should render issue correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -598,6 +610,7 @@ exports[`should render issue correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -640,6 +653,7 @@ exports[`should render issue correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -686,6 +700,7 @@ exports[`should render issue correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -739,6 +754,7 @@ exports[`should render security hotspot correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -781,6 +797,7 @@ exports[`should render security hotspot correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -823,6 +840,7 @@ exports[`should render security hotspot correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
@@ -869,6 +887,7 @@ exports[`should render security hotspot correctly 1`] = `
             "projectName": "Foo",
             "rule": "javascript:S1067",
             "ruleName": "foo",
+            "scope": "MAIN",
             "secondaryLocations": [],
             "severity": "MAJOR",
             "status": "OPEN",
index d628602e61866388e6a32d7664fea110dfd181e3..75e63851efb994d49c29030123d56523f070fb8f 100644 (file)
@@ -25,6 +25,7 @@ exports[`should render correctly: default 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [],
         "severity": "MAJOR",
         "status": "OPEN",
@@ -71,6 +72,7 @@ exports[`should render correctly: default 1`] = `
               "projectName": "Foo",
               "rule": "javascript:S1067",
               "ruleName": "foo",
+              "scope": "MAIN",
               "secondaryLocations": [],
               "severity": "MAJOR",
               "status": "OPEN",
@@ -146,6 +148,7 @@ exports[`should render correctly: with filter 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [],
         "severity": "MAJOR",
         "status": "OPEN",
@@ -192,6 +195,7 @@ exports[`should render correctly: with filter 1`] = `
               "projectName": "Foo",
               "rule": "javascript:S1067",
               "ruleName": "foo",
+              "scope": "MAIN",
               "secondaryLocations": [],
               "severity": "MAJOR",
               "status": "OPEN",
@@ -262,6 +266,7 @@ exports[`should render correctly: with filter 1`] = `
               "projectName": "Foo",
               "rule": "javascript:S1067",
               "ruleName": "foo",
+              "scope": "MAIN",
               "secondaryLocations": [],
               "severity": "MAJOR",
               "status": "OPEN",
@@ -358,6 +363,7 @@ exports[`should render correctly: with multi locations 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [
           {
             "component": "main.js",
@@ -472,6 +478,7 @@ exports[`should render correctly: with multi locations 1`] = `
               "projectName": "Foo",
               "rule": "javascript:S1067",
               "ruleName": "foo",
+              "scope": "MAIN",
               "secondaryLocations": [
                 {
                   "component": "main.js",
@@ -634,6 +641,7 @@ exports[`should render correctly: with multi locations and link 1`] = `
         "projectName": "Foo",
         "rule": "javascript:S1067",
         "ruleName": "foo",
+        "scope": "MAIN",
         "secondaryLocations": [
           {
             "component": "main.js",
@@ -748,6 +756,7 @@ exports[`should render correctly: with multi locations and link 1`] = `
               "projectName": "Foo",
               "rule": "javascript:S1067",
               "ruleName": "foo",
+              "scope": "MAIN",
               "secondaryLocations": [
                 {
                   "component": "main.js",
index 6cd3522686be1e11153448759ba7a8516351866f..e77d65a40383dad91b328764fea8a471289c8c69 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { Query } from '../../apps/issues/utils';
 import { ReferencedRule } from '../../types/issues';
 import { IssueChangelog } from '../../types/types';
 
@@ -44,3 +45,39 @@ export function mockIssueChangelog(overrides: Partial<IssueChangelog> = {}): Iss
     ...overrides,
   };
 }
+
+export function mockQuery(overrides: Partial<Query> = {}): Query {
+  return {
+    assigned: false,
+    assignees: [],
+    author: [],
+    createdAfter: undefined,
+    createdAt: '',
+    createdBefore: undefined,
+    createdInLast: '',
+    cwe: [],
+    directories: [],
+    files: [],
+    issues: [],
+    languages: [],
+    owaspTop10: [],
+    'owaspTop10-2021': [],
+    'pciDss-3.2': [],
+    'pciDss-4.0': [],
+    'owaspAsvs-4.0': [],
+    owaspAsvsLevel: '',
+    projects: [],
+    resolutions: [],
+    resolved: false,
+    rules: [],
+    scopes: [],
+    severities: [],
+    inNewCodePeriod: false,
+    sonarsourceSecurity: [],
+    sort: '',
+    statuses: [],
+    tags: [],
+    types: [],
+    ...overrides,
+  };
+}
index 350205aa30ea1ce6711e5086cf28253686581107..758edd11a4d5a311441f58cd5a4f811b14cb49fa 100644 (file)
@@ -25,7 +25,7 @@ import { Location, Router } from '../components/hoc/withRouter';
 import { AppState } from '../types/appstate';
 import { RuleRepository } from '../types/coding-rules';
 import { EditionKey } from '../types/editions';
-import { IssueType, RawIssue } from '../types/issues';
+import { IssueScope, IssueSeverity, IssueStatus, IssueType, RawIssue } from '../types/issues';
 import { Language } from '../types/languages';
 import { DumpStatus, DumpTask } from '../types/project-dump';
 import { TaskStatuses } from '../types/tasks';
@@ -286,13 +286,15 @@ export function mockRawIssue(withLocations = false, overrides: Partial<RawIssue>
     actions: [],
     component: 'main.js',
     key: 'AVsae-CQS-9G3txfbFN2',
+    creationDate: '2023-01-15T09:36:01+0100',
     line: 25,
     project: 'myproject',
     rule: 'javascript:S1067',
-    severity: 'MAJOR',
-    status: 'OPEN',
+    severity: IssueSeverity.Major,
+    status: IssueStatus.Open,
     textRange: { startLine: 25, endLine: 26, startOffset: 0, endOffset: 15 },
     type: IssueType.CodeSmell,
+    scope: IssueScope.Main,
     ...overrides,
   };
 
@@ -334,9 +336,10 @@ export function mockIssue(withLocations = false, overrides: Partial<Issue> = {})
     projectName: 'Foo',
     rule: 'javascript:S1067',
     ruleName: 'foo',
+    scope: IssueScope.Main,
     secondaryLocations: [],
-    severity: 'MAJOR',
-    status: 'OPEN',
+    severity: IssueSeverity.Major,
+    status: IssueStatus.Open,
     textRange: { startLine: 25, endLine: 26, startOffset: 0, endOffset: 15 },
     transitions: [],
     type: 'BUG',
index 72e67a7638c1023a29a14b6d6ea5fc5b79e56963..c5dea846e5691efb107bc8758557747c58f4a938 100644 (file)
@@ -29,11 +29,27 @@ export enum IssueType {
   SecurityHotspot = 'SECURITY_HOTSPOT',
 }
 
+export enum IssueSeverity {
+  Blocker = 'BLOCKER',
+  Minor = 'MINOR',
+  Critical = 'CRITICAL',
+  Info = 'INFO',
+  Major = 'MAJOR',
+}
+
 export enum IssueScope {
   Main = 'MAIN',
   Test = 'TEST',
 }
 
+export enum IssueResolution {
+  Unresolved = '',
+  FalsePositive = 'FALSE-POSITIVE',
+  Fixed = 'FIXED',
+  Removed = 'REMOVED',
+  WontFix = 'WONTFIX',
+}
+
 export enum IssueStatus {
   Open = 'OPEN',
   Confirmed = 'CONFIRMED',
@@ -76,6 +92,7 @@ export interface RawIssue {
   assignee?: string;
   author?: string;
   comments?: Array<Comment>;
+  creationDate: string;
   component: string;
   flows?: Array<{
     type?: string;
@@ -93,6 +110,7 @@ export interface RawIssue {
   status: string;
   textRange?: TextRange;
   type: IssueType;
+  scope: string;
   ruleDescriptionContextKey?: string;
   ruleStatus?: string;
   quickFixAvailable?: boolean;
index 2f57f4a4f789a672a2e77cb09f9bfaf9e26707d6..36cc2434a555097924c52ae01506b78451729a1c 100644 (file)
@@ -268,6 +268,7 @@ export interface Issue {
   ruleDescriptionContextKey?: string;
   ruleName: string;
   ruleStatus?: string;
+  scope: string;
   secondaryLocations: FlowLocation[];
   severity: string;
   status: string;