From: 7PH Date: Tue, 28 Mar 2023 15:57:12 +0000 (+0200) Subject: SONAR-18555 Migrate issues app sidebar to RTL X-Git-Tag: 10.0.0.68432~37 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a35ce4635c89cf21d3aba13be7971575c5070ca7;p=sonarqube.git SONAR-18555 Migrate issues app sidebar to RTL --- diff --git a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts index ec195133c9a..f9f348b8a16 100644 --- a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts +++ b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts @@ -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 => { - 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 => { + 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 = { - wontfix: 'WONTFIX', - falsepositive: 'FALSE-POSITIVE', + wontfix: IssueResolution.WontFix, + falsepositive: IssueResolution.FalsePositive, }; return this.getActionsResponse( diff --git a/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx b/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx index 76629db8f91..2cef9341265 100644 --- a/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx +++ b/server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx @@ -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 diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/CrossComponentSourceViewer-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/CrossComponentSourceViewer-test.tsx.snap index ec71752ca70..390838a9ebf 100644 --- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/CrossComponentSourceViewer-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/CrossComponentSourceViewer-test.tsx.snap @@ -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", diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx index 3a60a8445f1..f7a9823e460 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.tsx @@ -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 | 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 { 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 index 75195eafcd4..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx +++ /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('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) { - return shallow( - - ); -} 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 index b3fdeb4b1ca..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AuthorFacet-test.tsx +++ /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 = {}) { - return shallow( - - ); -} 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 index 84d94c83959..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/CreationDateFacet-test.tsx +++ /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) { - return shallow( - '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 index 4e783ffdf1a..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/DirectoryFacet-test.tsx +++ /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 = {}) { - return shallow( - - ); -} 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 index cb6715d7507..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/FileFacet-test.tsx +++ /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 = {}) { - return shallow( - - ); -} 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 index e45325b0e31..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/PeriodFilter-test.tsx +++ /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 = {}) { - return render( - - ); -} 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 index 541bf2754eb..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/ProjectFacet-test.tsx +++ /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 = {}) { - return shallow( - - ); -} 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 index 193b3624e77..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/RuleFacet-test.tsx +++ /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 = {}) { - return shallow( - - ); -} 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 index 5d2f0f37d25..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/ScopeFacet-test.tsx +++ /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, - scope: IssueScope, - multiple = false -) { - return wrapper - .find(FacetItem) - .filterWhere((f) => f.key() === scope) - .props() - .onClick(scope, multiple); -} - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} 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 index 00000000000..52fdec70fee --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx @@ -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 = {}) { + return renderComponent( + + ); +} 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 index 5ee232665a2..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx +++ /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) => { - return flatten( - mapChildren( - shallow( - - ) - ) - ); - - 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 index 91d7786ded0..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx +++ /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('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('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 = {}) { - const wrapper = shallow( - - ); - 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 index 1f3c1a6c14f..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StatusFacet-test.tsx +++ /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('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('onClick')( - status, - multiple - ); - expect(onChange).toHaveBeenLastCalledWith({ statuses: expected }); - wrapper.setProps({ statuses: expected }); - } -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} 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 index 6ef7659495e..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/TypeFacet-test.tsx +++ /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('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('onClick')( - type, - multiple - ); - expect(onChange).toHaveBeenLastCalledWith({ types: expected }); - wrapper.setProps({ types: expected }); - } -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} 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 index e6f5de2d616..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AssigneeFacet-test.tsx.snap +++ /dev/null @@ -1,96 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render 1`] = ` - -`; - -exports[`test behavior should correctly render facet item 1`] = ` - - - Name Baz - -`; - -exports[`test behavior should correctly render facet item 2`] = ` - - - user.x_deleted.foo - -`; - -exports[`test behavior should correctly render search result correctly 1`] = ` - - - - Name - - Ba - - r - - -`; - -exports[`test behavior should correctly render search result correctly 2`] = ` - - - - user.x_deleted. - - fo - - o - - -`; 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 index 9d8d3369552..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/AuthorFacet-test.tsx.snap +++ /dev/null @@ -1,26 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -`; 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 index 028ee163412..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/CreationDateFacet-test.tsx.snap +++ /dev/null @@ -1,548 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly for createdInLast month 1`] = ` - - -
-
- -
-
- - - - -
-
-
-`; - -exports[`should render correctly for createdInLast week 1`] = ` - - -
-
- -
-
- - - - -
-
-
-`; - -exports[`should render correctly for createdInLast year 1`] = ` - - -
-
- -
-
- - - - -
-
-
-`; - -exports[`should render correctly: clear 1`] = ` - - -
-
- -
-
- - - - -
-
-
-`; - -exports[`should render correctly: closed 1`] = ` - - - -`; - -exports[`should render correctly: created after 1`] = ` - - -
- - after - - - -
-
-`; - -exports[`should render correctly: created after timestamp 1`] = ` - - -
- - after - - - -
-
-`; - -exports[`should render correctly: created at 1`] = ` - - -
- -
- - - -
-
-`; - -exports[`should render correctly: portfolio 1`] = ` - - -
-
- -
-
- - - - -
-
-
-`; - -exports[`should render correctly: project 1`] = ` - - -
-
- -
-
- - - - -
-
-
-`; 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 index d7c77c17c1f..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/DirectoryFacet-test.tsx.snap +++ /dev/null @@ -1,55 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -`; - -exports[`should render correctly 2`] = ` - - - - - foo - - /bar - - -`; - -exports[`should render correctly 3`] = ` - - - foo/bar - -`; 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 index 56d01f38203..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/FileFacet-test.tsx.snap +++ /dev/null @@ -1,59 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -`; - -exports[`should render correctly 2`] = ` - - - - foo - / - - - bar - - .js - - - -`; - -exports[`should render correctly 3`] = ` - - - fooUuid - -`; 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 index 8502212fda3..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ProjectFacet-test.tsx.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ListStyleFacet's renderers should include renderFacetItem 1`] = ` - - - First Project Name - -`; - -exports[`ListStyleFacet's renderers should include renderSearchResult 1`] = ` - - - - - First - - Project Name - - -`; - -exports[`should render correctly 1`] = ` - -`; 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 index 8ef9b574cec..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/RuleFacet-test.tsx.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -`; 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 index 4d536bbdfb8..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/ScopeFacet-test.tsx.snap +++ /dev/null @@ -1,210 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: active facet 1`] = ` - - - - - - - issue.scope.MAIN - - } - onClick={[Function]} - value="MAIN" - /> - - - - issue.scope.TEST - - } - onClick={[Function]} - value="TEST" - /> - - - -`; - -exports[`should render correctly: default 1`] = ` - - - -`; - -exports[`should render correctly: disabled facet 1`] = ` - - - - - - - issue.scope.MAIN - - } - onClick={[Function]} - stat={0} - value="MAIN" - /> - - - - issue.scope.TEST - - } - onClick={[Function]} - value="TEST" - /> - - - -`; - -exports[`should render correctly: open 1`] = ` - - - - - - - issue.scope.MAIN - - } - onClick={[Function]} - value="MAIN" - /> - - - - issue.scope.TEST - - } - onClick={[Function]} - value="TEST" - /> - - - -`; 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 index c15aaf6e7d2..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap +++ /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 index e1996d21b90..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StandardFacet-test.tsx.snap +++ /dev/null @@ -1,180 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render closed 1`] = ` - - - -`; - -exports[`should render empty sub-facet 1`] = ` - - -
- no_results -
- -
-`; - -exports[`should render sub-facets 1`] = ` - - - - - - - - - - - - - - - - - - - - - - -`; 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 index c3113151531..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/StatusFacet-test.tsx.snap +++ /dev/null @@ -1,97 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - - - - - } - onClick={[Function]} - stat="104" - tooltip="issue.status.OPEN" - value="OPEN" - /> - - } - onClick={[Function]} - stat="8" - tooltip="issue.status.CONFIRMED" - value="CONFIRMED" - /> - - } - onClick={[Function]} - stat={0} - tooltip="issue.status.REOPENED" - value="REOPENED" - /> - - } - onClick={[Function]} - stat={0} - tooltip="issue.status.RESOLVED" - value="RESOLVED" - /> - - } - onClick={[Function]} - stat="8" - tooltip="issue.status.CLOSED" - value="CLOSED" - /> - - - -`; 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 index d5f48e2ef5d..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/TypeFacet-test.tsx.snap +++ /dev/null @@ -1,90 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render open by default 1`] = ` - - - - - - - issue.type.BUG - - } - onClick={[Function]} - stat={0} - value="BUG" - /> - - - - issue.type.VULNERABILITY - - } - onClick={[Function]} - stat="2" - value="VULNERABILITY" - /> - - - - issue.type.CODE_SMELL - - } - onClick={[Function]} - stat="5" - value="CODE_SMELL" - /> - - - -`; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewer-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewer-test.tsx.snap index 1469fa0fce8..8688bd62ed3 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewer-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewer-test.tsx.snap @@ -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", diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineIssueList-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineIssueList-test.tsx.snap index 231134d6051..11e954e8499 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineIssueList-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineIssueList-test.tsx.snap @@ -33,6 +33,7 @@ exports[`should render issues 1`] = ` "projectName": "Foo", "rule": "javascript:S1067", "ruleName": "foo", + "scope": "MAIN", "secondaryLocations": [], "severity": "MAJOR", "status": "OPEN", diff --git a/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueView-test.tsx.snap b/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueView-test.tsx.snap index 849ce188351..bb33e7066d4 100644 --- a/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueView-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueView-test.tsx.snap @@ -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", diff --git a/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/issue-test.tsx.snap b/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/issue-test.tsx.snap index 78a0638669c..655c1f68805 100644 --- a/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/issue-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/issue-test.tsx.snap @@ -37,6 +37,7 @@ exports[`should render issues correctly 1`] = ` "projectName": "Foo", "rule": "javascript:S1067", "ruleName": "foo", + "scope": "MAIN", "secondaryLocations": [], "severity": "MAJOR", "status": "OPEN", diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx b/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx index 30fff84a310..3856c5489dd 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx +++ b/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx @@ -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 { 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 { 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 (
diff --git a/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueActionsBar-test.tsx.snap b/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueActionsBar-test.tsx.snap index 431197f6a57..0a5febfcea3 100644 --- a/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueActionsBar-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueActionsBar-test.tsx.snap @@ -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", diff --git a/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap b/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap index d628602e618..75e63851efb 100644 --- a/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap @@ -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", diff --git a/server/sonar-web/src/main/js/helpers/mocks/issues.ts b/server/sonar-web/src/main/js/helpers/mocks/issues.ts index 6cd3522686b..e77d65a4038 100644 --- a/server/sonar-web/src/main/js/helpers/mocks/issues.ts +++ b/server/sonar-web/src/main/js/helpers/mocks/issues.ts @@ -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 = {}): Iss ...overrides, }; } + +export function mockQuery(overrides: Partial = {}): 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, + }; +} diff --git a/server/sonar-web/src/main/js/helpers/testMocks.ts b/server/sonar-web/src/main/js/helpers/testMocks.ts index 350205aa30e..758edd11a4d 100644 --- a/server/sonar-web/src/main/js/helpers/testMocks.ts +++ b/server/sonar-web/src/main/js/helpers/testMocks.ts @@ -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 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 = {}) 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', diff --git a/server/sonar-web/src/main/js/types/issues.ts b/server/sonar-web/src/main/js/types/issues.ts index 72e67a7638c..c5dea846e56 100644 --- a/server/sonar-web/src/main/js/types/issues.ts +++ b/server/sonar-web/src/main/js/types/issues.ts @@ -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; + 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; diff --git a/server/sonar-web/src/main/js/types/types.ts b/server/sonar-web/src/main/js/types/types.ts index 2f57f4a4f78..36cc2434a55 100644 --- a/server/sonar-web/src/main/js/types/types.ts +++ b/server/sonar-web/src/main/js/types/types.ts @@ -268,6 +268,7 @@ export interface Issue { ruleDescriptionContextKey?: string; ruleName: string; ruleStatus?: string; + scope: string; secondaryLocations: FlowLocation[]; severity: string; status: string;