} from '../../helpers/testMocks';
import {
ASSIGNEE_ME,
+ IssueResolution,
+ IssueScope,
+ IssueSeverity,
+ IssueStatus,
IssueType,
RawFacet,
RawIssue,
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',
],
},
],
+ resolution: IssueResolution.WontFix,
+ scope: IssueScope.Main,
+ tags: ['tag0', 'tag1'],
}),
snippets: keyBy(
[
component: 'foo:test1.js',
message: 'FlowIssue',
type: IssueType.CodeSmell,
+ severity: IssueSeverity.Minor,
rule: 'simpleRuleId',
textRange: {
startLine: 10,
],
},
],
+ tags: ['tag1'],
}),
snippets: keyBy(
[
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: {},
},
endOffset: 1,
},
ruleDescriptionContextKey: 'spring',
+ resolution: IssueResolution.Unresolved,
+ status: IssueStatus.Open,
}),
snippets: keyBy(
[
startOffset: 0,
endOffset: 1,
},
+ resolution: IssueResolution.Fixed,
+ status: IssueStatus.Confirmed,
}),
snippets: keyBy(
[
key: 'issue4',
component: 'foo:test2.js',
message: 'Issue with tags',
- rule: 'external_eslint_repo:no-div-regex',
+ rule: 'other',
textRange: {
startLine: 25,
endLine: 25,
ruleDescriptionContextKey: 'spring',
ruleStatus: 'DEPRECATED',
quickFixAvailable: true,
+ tags: ['unused'],
+ project: 'org.project2',
+ assignee: 'email1@sonarsource.com',
+ author: 'email3@sonarsource.com',
}),
snippets: keyBy(
[
});
};
- handleSearchIssues = (query: RequestData): Promise<RawIssuesResponse> => {
- const facets = (query.facets ?? '').split(',').map((name: string) => {
+ mockFacetDetailResponse = (facetsQuery: string): RawFacet[] => {
+ return facetsQuery.split(',').map((name: string): RawFacet => {
if (name === 'owaspTop10-2021') {
return this.owasp2021FacetList();
}
+ if (name === 'tags') {
+ return {
+ property: name,
+ values: [
+ {
+ val: 'unused',
+ count: 12842,
+ },
+ {
+ val: 'confusing',
+ count: 124,
+ },
+ ],
+ };
+ }
+ if (name === 'projects') {
+ return {
+ property: name,
+ values: [
+ { val: 'org.project1', count: 14685 },
+ { val: 'org.project2', count: 3890 },
+ ],
+ };
+ }
+ if (name === 'assignees') {
+ return {
+ property: name,
+ values: [
+ { val: 'email1@sonarsource.com', count: 675 },
+ { val: 'email2@sonarsource.com', count: 531 },
+ ],
+ };
+ }
+ if (name === 'author') {
+ return {
+ property: name,
+ values: [
+ { val: 'email3@sonarsource.com', count: 421 },
+ { val: 'email4@sonarsource.com', count: 123 },
+ ],
+ };
+ }
+ if (name === 'rules') {
+ return {
+ property: name,
+ values: [
+ { val: 'simpleRuleId', count: 8816 },
+ { val: 'advancedRuleId', count: 2060 },
+ { val: 'other', count: 1324 },
+ ],
+ };
+ }
if (name === 'languages') {
return {
property: name,
values: [],
};
});
+ };
+
+ handleSearchIssues = (query: RequestData): Promise<RawIssuesResponse> => {
+ const facets = this.mockFacetDetailResponse((query.facets ?? '') as string);
// Filter list (only supports assignee, type and severity)
const filteredList = this.list
}
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
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' },
+ ],
});
};
};
const resolutionMap: Dict<string> = {
- wontfix: 'WONTFIX',
- falsepositive: 'FALSE-POSITIVE',
+ wontfix: IssueResolution.WontFix,
+ falsepositive: IssueResolution.FalsePositive,
};
return this.getActionsResponse(
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' }),
};
});
});
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 () => {
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
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [
{
"component": "main.js",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [
{
"component": "main.js",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [
{
"component": "main.js",
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';
stats: Dict<number> | undefined;
}
-const RESOLUTIONS = ['', 'FALSE-POSITIVE', 'FIXED', 'REMOVED', 'WONTFIX'];
+const RESOLUTIONS = [
+ IssueResolution.Unresolved,
+ IssueResolution.FalsePositive,
+ IssueResolution.Fixed,
+ IssueResolution.Removed,
+ IssueResolution.WontFix,
+];
export default class ResolutionFacet extends React.PureComponent<Props> {
property = 'resolutions';
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { Query } from '../../utils';
-import AssigneeFacet from '../AssigneeFacet';
-
-it('should render', () => {
- expect(shallowRender({ assignees: ['foo'] })).toMatchSnapshot();
-});
-
-it('should select unassigned', () => {
- expect(shallowRender({ assigned: false }).find('ListStyleFacet').prop('values')).toEqual(['']);
-});
-
-it('should call onChange', () => {
- const onChange = jest.fn();
- const wrapper = shallowRender({ assignees: ['foo'], onChange });
- const itemOnClick = wrapper.find('ListStyleFacet').prop<Function>('onItemClick');
-
- itemOnClick('');
- expect(onChange).toHaveBeenLastCalledWith({ assigned: false, assignees: [] });
-
- itemOnClick('bar');
- expect(onChange).toHaveBeenLastCalledWith({ assigned: true, assignees: ['bar'] });
-
- itemOnClick('baz', true);
- expect(onChange).toHaveBeenLastCalledWith({ assigned: true, assignees: ['baz', 'foo'] });
-});
-
-describe('test behavior', () => {
- const instance = shallowRender({
- assignees: ['foo', 'baz'],
- referencedUsers: {
- foo: { active: false, login: 'foo' },
- baz: { active: true, login: 'baz', name: 'Name Baz' },
- },
- }).instance();
-
- it('should correctly render assignee name', () => {
- expect(instance.getAssigneeName('')).toBe('unassigned');
- expect(instance.getAssigneeName('bar')).toBe('bar');
- expect(instance.getAssigneeName('baz')).toBe('Name Baz');
- expect(instance.getAssigneeName('foo')).toBe('user.x_deleted.foo');
- });
-
- it('should correctly render facet item', () => {
- expect(instance.renderFacetItem('')).toBe('unassigned');
- expect(instance.renderFacetItem('bar')).toBe('bar');
- expect(instance.renderFacetItem('baz')).toMatchSnapshot();
- expect(instance.renderFacetItem('foo')).toMatchSnapshot();
- });
-
- it('should correctly render search result correctly', () => {
- expect(
- instance.renderSearchResult({ active: true, login: 'bar', name: 'Name Bar' }, 'ba')
- ).toMatchSnapshot();
- expect(instance.renderSearchResult({ active: false, login: 'foo' }, 'fo')).toMatchSnapshot();
- });
-});
-
-function shallowRender(props?: Partial<AssigneeFacet['props']>) {
- return shallow<AssigneeFacet>(
- <AssigneeFacet
- assigned={true}
- assignees={[]}
- fetching={false}
- loadSearchResultCount={jest.fn()}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={true}
- query={{} as Query}
- referencedUsers={{ foo: { avatar: 'avatart-foo', login: 'name-foo', name: 'Name Foo' } }}
- stats={{ '': 5, foo: 13, bar: 7, baz: 6 }}
- {...props}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import ListStyleFacet from '../../../../components/facet/ListStyleFacet';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { Query } from '../../utils';
-import AuthorFacet from '../AuthorFacet';
-
-it('should render correctly', () => {
- const wrapper = shallowRender();
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should notify of search result count correctly', () => {
- const loadSearchResultCount = jest.fn();
-
- const wrapper = shallowRender({ loadSearchResultCount });
-
- wrapper.find(ListStyleFacet).props().loadSearchResultCount!(['1', '2']);
-
- expect(loadSearchResultCount).toHaveBeenCalled();
-});
-
-function shallowRender(props: Partial<AuthorFacet['props']> = {}) {
- return shallow<AuthorFacet>(
- <AuthorFacet
- component={mockComponent()}
- fetching={false}
- loadSearchResultCount={jest.fn()}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={true}
- query={{} as Query}
- stats={{}}
- author={[]}
- {...props}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { IntlShape } from 'react-intl';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { ComponentQualifier } from '../../../../types/component';
-import { CreationDateFacet } from '../CreationDateFacet';
-
-it('should render correctly', () => {
- expect(shallowRender({ open: false })).toMatchSnapshot('closed');
- expect(shallowRender()).toMatchSnapshot('clear');
- expect(shallowRender({ createdAt: '2019.05.21T13:33:00Z' })).toMatchSnapshot('created at');
- expect(
- shallowRender({
- createdAfter: new Date('2019.04.29T13:33:00Z'),
- createdAfterIncludesTime: true,
- })
- ).toMatchSnapshot('created after');
- expect(
- shallowRender({
- createdAfter: new Date('2019.04.29T13:33:00Z'),
- createdAfterIncludesTime: true,
- })
- ).toMatchSnapshot('created after timestamp');
- expect(shallowRender({ component: mockComponent() })).toMatchSnapshot('project');
- expect(
- shallowRender({ component: mockComponent({ qualifier: ComponentQualifier.Portfolio }) })
- ).toMatchSnapshot('portfolio');
-});
-
-it.each([
- ['week', '1w'],
- ['month', '1m'],
- ['year', '1y'],
-])('should render correctly for createdInLast %s', (_, createdInLast) => {
- expect(shallowRender({ component: mockComponent(), createdInLast })).toMatchSnapshot();
-});
-
-function shallowRender(props?: Partial<CreationDateFacet['props']>) {
- return shallow<CreationDateFacet>(
- <CreationDateFacet
- component={undefined}
- fetching={false}
- createdAfter={undefined}
- createdAfterIncludesTime={false}
- createdAt=""
- createdBefore={undefined}
- createdInLast=""
- inNewCodePeriod={false}
- intl={
- {
- formatDate: (date: string) => 'formatted.' + date,
- } as IntlShape
- }
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={true}
- stats={undefined}
- {...props}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { getDirectories } from '../../../../api/components';
-import ListStyleFacet from '../../../../components/facet/ListStyleFacet';
-import { mockBranch } from '../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { TreeComponentWithPath } from '../../../../types/component';
-import { Query } from '../../utils';
-import DirectoryFacet from '../DirectoryFacet';
-
-jest.mock('../../../../api/components', () => ({
- getDirectories: jest.fn().mockResolvedValue({ components: [] }),
-}));
-
-beforeEach(() => jest.clearAllMocks());
-
-const branch = mockBranch();
-const component = mockComponent();
-
-it('should render correctly', () => {
- const wrapper = shallowRender();
- const instance = wrapper.instance();
- expect(wrapper).toMatchSnapshot();
- expect(
- instance.renderSearchResult({ path: 'foo/bar' } as TreeComponentWithPath, 'foo')
- ).toMatchSnapshot();
- expect(instance.renderFacetItem('foo/bar')).toMatchSnapshot();
-});
-
-it('should properly search for directory', () => {
- const wrapper = shallowRender();
-
- const query = 'foo';
-
- wrapper.find(ListStyleFacet).props().onSearch(query);
-
- expect(getDirectories).toHaveBeenCalledWith({
- branch: branch.name,
- component: component.key,
- q: query,
- ps: 30,
- p: undefined,
- });
-});
-
-describe("ListStyleFacet's callback props", () => {
- const wrapper = shallowRender();
- const instance = wrapper.instance();
-
- it('#getSearchResultText()', () => {
- expect(instance.getSearchResultText({ path: 'bar' } as TreeComponentWithPath)).toBe('bar');
- });
-
- it('#getSearchResultKey()', () => {
- expect(instance.getSearchResultKey({ path: 'foo/bar' } as TreeComponentWithPath)).toBe(
- 'foo/bar'
- );
- });
-
- it('#getFacetItemText()', () => {
- expect(instance.getFacetItemText('foo/bar')).toBe('foo/bar');
- });
-});
-
-function shallowRender(props: Partial<DirectoryFacet['props']> = {}) {
- return shallow<DirectoryFacet>(
- <DirectoryFacet
- branchLike={branch}
- componentKey={component.key}
- directories={['foo/', 'bar/baz/']}
- fetching={false}
- loadSearchResultCount={jest.fn()}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={false}
- query={{} as Query}
- stats={undefined}
- {...props}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { getFiles } from '../../../../api/components';
-import ListStyleFacet from '../../../../components/facet/ListStyleFacet';
-import { mockBranch } from '../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { TreeComponentWithPath } from '../../../../types/component';
-import { Query } from '../../utils';
-import FileFacet from '../FileFacet';
-
-jest.mock('../../../../api/components', () => ({
- getFiles: jest.fn().mockResolvedValue({ components: [] }),
-}));
-
-beforeEach(() => jest.clearAllMocks());
-
-const branch = mockBranch();
-const component = mockComponent();
-
-const PATH = 'foo/bar.js';
-
-it('should render correctly', () => {
- const wrapper = shallowRender();
- const instance = wrapper.instance();
- expect(wrapper).toMatchSnapshot();
- expect(
- instance.renderSearchResult({ path: PATH } as TreeComponentWithPath, 'bar')
- ).toMatchSnapshot();
- expect(instance.renderFacetItem('fooUuid')).toMatchSnapshot();
-});
-
-it('should properly search for file', () => {
- const wrapper = shallowRender();
-
- const query = 'foo';
-
- wrapper.find(ListStyleFacet).props().onSearch(query);
-
- expect(getFiles).toHaveBeenCalledWith({
- branch: branch.name,
- component: component.key,
- q: query,
- ps: 30,
- p: undefined,
- });
-});
-
-describe("ListStyleFacet's callback props", () => {
- const wrapper = shallowRender();
- const instance = wrapper.instance();
-
- it('#getSearchResultText()', () => {
- expect(instance.getSearchResultText({ path: PATH } as TreeComponentWithPath)).toBe(
- 'foo/bar.js'
- );
- });
-
- it('#getSearchResultKey()', () => {
- expect(instance.getSearchResultKey({ key: 'bar', path: 'bar' } as TreeComponentWithPath)).toBe(
- 'bar'
- );
- });
-
- it('#getFacetItemText()', () => {
- expect(instance.getFacetItemText('bar')).toBe('bar');
- });
-});
-
-function shallowRender(props: Partial<FileFacet['props']> = {}) {
- return shallow<FileFacet>(
- <FileFacet
- branchLike={branch}
- componentKey={component.key}
- fetching={false}
- files={['foo', 'bar']}
- loadSearchResultCount={jest.fn()}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={false}
- query={{} as Query}
- stats={undefined}
- {...props}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { render, screen } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-
-import * as React from 'react';
-import PeriodFilter, { PeriodFilterProps } from '../PeriodFilter';
-
-it('should filter when clicked', async () => {
- const user = userEvent.setup();
- const onChange = jest.fn();
-
- renderPeriodFilter({ onChange });
-
- await user.click(screen.getByText('issues.new_code'));
-
- expect(onChange).toHaveBeenCalledWith({
- createdAfter: undefined,
- createdAt: undefined,
- createdBefore: undefined,
- createdInLast: undefined,
- inNewCodePeriod: true,
- });
-});
-
-function renderPeriodFilter(overrides: Partial<PeriodFilterProps> = {}) {
- return render(
- <PeriodFilter
- fetching={false}
- newCodeSelected={false}
- onChange={jest.fn()}
- stats={{}}
- {...overrides}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import { keyBy } from 'lodash';
-import * as React from 'react';
-import { getTree, searchProjects } from '../../../../api/components';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { ComponentQualifier } from '../../../../types/component';
-import { ReferencedComponent } from '../../../../types/issues';
-import { Query } from '../../utils';
-import ProjectFacet from '../ProjectFacet';
-
-jest.mock('../../../../api/components', () => ({
- getTree: jest.fn().mockResolvedValue({ baseComponent: {}, components: [], paging: {} }),
- searchProjects: jest.fn().mockResolvedValue({
- components: [],
- facets: [],
- paging: {},
- }),
-}));
-
-beforeEach(() => jest.clearAllMocks());
-
-it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should callback to load search results', () => {
- const loadSearchResultCount = jest.fn();
- const wrapper = shallowRender({ loadSearchResultCount });
- wrapper.instance().loadSearchResultCount([
- { key: '1', name: 'first' },
- { key: '2', name: 'seecond' },
- ]);
-
- expect(loadSearchResultCount).toHaveBeenCalledWith('projects', { projects: ['1', '2'] });
-});
-
-it('should handle search for projects globally', async () => {
- const wrapper = shallowRender();
- const query = 'my project';
-
- await wrapper.instance().handleSearch(query);
-
- expect(searchProjects).toHaveBeenCalled();
- expect(getTree).not.toHaveBeenCalled();
-});
-
-it('should handle search for projects in portfolio', async () => {
- const wrapper = shallowRender({
- component: mockComponent({ qualifier: ComponentQualifier.Portfolio }),
- });
- const query = 'my project';
-
- await wrapper.instance().handleSearch(query);
-
- expect(searchProjects).not.toHaveBeenCalled();
- expect(getTree).toHaveBeenCalled();
-});
-
-describe("ListStyleFacet's renderers", () => {
- const components: ReferencedComponent[] = [
- { key: 'projectKey', name: 'First Project Name', uuid: '141324' },
- { key: 'projectKey2', name: 'Second Project Name', uuid: '643878' },
- ];
- const referencedComponents = keyBy(components, (c) => c.key);
- const wrapper = shallowRender({ referencedComponents });
- const instance = wrapper.instance();
-
- it('should include getProjectName', () => {
- expect(instance.getProjectName(components[0].key)).toBe(components[0].name);
- expect(instance.getProjectName('nonexistent')).toBe('nonexistent');
- });
-
- it('should include renderFacetItem', () => {
- expect(instance.renderFacetItem(components[0].key)).toMatchSnapshot();
- });
-
- it('should include renderSearchResult', () => {
- expect(instance.renderSearchResult(components[0], 'First')).toMatchSnapshot();
- });
-});
-
-function shallowRender(props: Partial<ProjectFacet['props']> = {}) {
- return shallow<ProjectFacet>(
- <ProjectFacet
- component={undefined}
- fetching={false}
- loadSearchResultCount={jest.fn()}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={false}
- projects={[]}
- query={{} as Query}
- referencedComponents={{}}
- stats={undefined}
- {...props}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { searchRules } from '../../../../api/rules';
-import { mockReferencedRule } from '../../../../helpers/mocks/issues';
-import { mockRule } from '../../../../helpers/testMocks';
-import { Query } from '../../utils';
-import RuleFacet from '../RuleFacet';
-
-jest.mock('../../../../api/rules', () => ({
- searchRules: jest.fn().mockResolvedValue({}),
-}));
-
-it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should handle search', async () => {
- const wrapper = shallowRender();
-
- const query = 'query';
-
- await wrapper.instance().handleSearch(query);
-
- expect(searchRules).toHaveBeenCalledWith(
- expect.objectContaining({ languages: 'js,java', q: query })
- );
-});
-
-describe('ListStyleFacet Renderers', () => {
- const referencedRules = { r1: mockReferencedRule() };
- const instance = shallowRender({ referencedRules }).instance();
-
- it('should include renderFacetItem', () => {
- const rule = referencedRules.r1;
- expect(instance.getRuleName('r1')).toBe(`(${rule.langName}) ${rule.name}`);
- expect(instance.getRuleName('nonexistent')).toBe('nonexistent');
- });
-
- it('should include renderSearchResult', () => {
- const rule = mockRule();
- expect(instance.renderSearchResult(rule)).toBe(`(${rule.langName}) ${rule.name}`);
- expect(instance.renderSearchResult(mockRule({ langName: '' }))).toBe(rule.name);
- });
-});
-
-function shallowRender(props: Partial<RuleFacet['props']> = {}) {
- return shallow<RuleFacet>(
- <RuleFacet
- fetching={true}
- languages={['js', 'java']}
- loadSearchResultCount={jest.fn()}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={false}
- query={{} as Query}
- referencedRules={{}}
- rules={['r1']}
- stats={{}}
- {...props}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow, ShallowWrapper } from 'enzyme';
-import * as React from 'react';
-import FacetHeader from '../../../../components/facet/FacetHeader';
-import FacetItem from '../../../../components/facet/FacetItem';
-import { IssueScope } from '../../../../types/issues';
-import ScopeFacet, { ScopeFacetProps } from '../ScopeFacet';
-
-it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot('default');
- expect(shallowRender({ open: true })).toMatchSnapshot('open');
- expect(shallowRender({ open: true, scopes: [IssueScope.Main] })).toMatchSnapshot('active facet');
- expect(shallowRender({ open: true, stats: { [IssueScope.Main]: 0 } })).toMatchSnapshot(
- 'disabled facet'
- );
-});
-
-it('should correctly handle facet header clicks', () => {
- const onChange = jest.fn();
- const onToggle = jest.fn();
- const wrapper = shallowRender({ onChange, onToggle });
-
- wrapper.find(FacetHeader).props().onClear!();
- expect(onChange).toHaveBeenCalledWith({ scopes: [] });
-
- wrapper.find(FacetHeader).props().onClick!();
- expect(onToggle).toHaveBeenCalledWith('scopes');
-});
-
-it('should correctly handle facet item clicks', () => {
- const wrapper = shallowRender({ open: true, scopes: [IssueScope.Main] });
- const onChange = jest.fn(({ scopes }) => wrapper.setProps({ scopes }));
- wrapper.setProps({ onChange });
-
- clickFacetItem(wrapper, IssueScope.Test);
- expect(onChange).toHaveBeenLastCalledWith({ scopes: [IssueScope.Test] });
-
- clickFacetItem(wrapper, IssueScope.Test);
- expect(onChange).toHaveBeenLastCalledWith({ scopes: [] });
-
- clickFacetItem(wrapper, IssueScope.Test, true);
- clickFacetItem(wrapper, IssueScope.Main, true);
- expect(onChange).toHaveBeenLastCalledWith({
- scopes: expect.arrayContaining([IssueScope.Main, IssueScope.Test]),
- });
-
- clickFacetItem(wrapper, IssueScope.Test, true);
- expect(onChange).toHaveBeenLastCalledWith({ scopes: [IssueScope.Main] });
-});
-
-function clickFacetItem(
- wrapper: ShallowWrapper<ScopeFacetProps>,
- scope: IssueScope,
- multiple = false
-) {
- return wrapper
- .find(FacetItem)
- .filterWhere((f) => f.key() === scope)
- .props()
- .onClick(scope, multiple);
-}
-
-function shallowRender(props: Partial<ScopeFacetProps> = {}) {
- return shallow<ScopeFacetProps>(
- <ScopeFacet
- fetching={true}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={false}
- scopes={[]}
- stats={{}}
- {...props}
- />
- );
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import { screen } from '@testing-library/react';
+import * as React from 'react';
+import { mockComponent } from '../../../../helpers/mocks/component';
+import { mockQuery } from '../../../../helpers/mocks/issues';
+import { mockAppState } from '../../../../helpers/testMocks';
+import { renderComponent } from '../../../../helpers/testReactTestingUtils';
+import { ComponentQualifier } from '../../../../types/component';
+import { GlobalSettingKeys } from '../../../../types/settings';
+import { Sidebar } from '../Sidebar';
+
+it('should render correct facets for Application', () => {
+ renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.Application }) });
+ expect(screen.getAllByRole('button').map((button) => button.textContent)).toStrictEqual([
+ 'issues.facet.types',
+ 'issues.facet.severities',
+ 'issues.facet.scopes',
+ 'issues.facet.resolutions',
+ 'issues.facet.statuses',
+ 'issues.facet.standards',
+ 'issues.facet.createdAt',
+ 'issues.facet.languages',
+ 'issues.facet.rules',
+ 'issues.facet.tags',
+ 'issues.facet.projects',
+ 'issues.facet.assignees',
+ 'clear',
+ 'issues.facet.authors',
+ ]);
+});
+
+it('should render correct facets for Portfolio', () => {
+ renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.Portfolio }) });
+ expect(screen.getAllByRole('button').map((button) => button.textContent)).toStrictEqual([
+ 'issues.facet.types',
+ 'issues.facet.severities',
+ 'issues.facet.scopes',
+ 'issues.facet.resolutions',
+ 'issues.facet.statuses',
+ 'issues.facet.standards',
+ 'issues.facet.createdAt',
+ 'issues.facet.languages',
+ 'issues.facet.rules',
+ 'issues.facet.tags',
+ 'issues.facet.projects',
+ 'issues.facet.assignees',
+ 'clear',
+ 'issues.facet.authors',
+ ]);
+});
+
+it('should render correct facets for SubPortfolio', () => {
+ renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.SubPortfolio }) });
+ expect(screen.getAllByRole('button').map((button) => button.textContent)).toStrictEqual([
+ 'issues.facet.types',
+ 'issues.facet.severities',
+ 'issues.facet.scopes',
+ 'issues.facet.resolutions',
+ 'issues.facet.statuses',
+ 'issues.facet.standards',
+ 'issues.facet.createdAt',
+ 'issues.facet.languages',
+ 'issues.facet.rules',
+ 'issues.facet.tags',
+ 'issues.facet.projects',
+ 'issues.facet.assignees',
+ 'clear',
+ 'issues.facet.authors',
+ ]);
+});
+
+it.each([
+ ['week', '1w'],
+ ['month', '1m'],
+ ['year', '1y'],
+])('should render correctly for createdInLast %s', (name, createdInLast) => {
+ renderSidebar({ component: mockComponent(), query: mockQuery({ createdInLast }) });
+
+ const text = {
+ week: 'issues.facet.createdAt.last_week',
+ month: 'issues.facet.createdAt.last_month',
+ year: 'issues.facet.createdAt.last_year',
+ }[name] as string;
+ expect(screen.getByText(text)).toBeInTheDocument();
+});
+
+function renderSidebar(props: Partial<Sidebar['props']> = {}) {
+ return renderComponent(
+ <Sidebar
+ appState={mockAppState({
+ settings: { [GlobalSettingKeys.DeveloperAggregatedInfoDisabled]: 'false' },
+ })}
+ component={mockComponent()}
+ createdAfterIncludesTime={false}
+ facets={{}}
+ loadSearchResultCount={jest.fn()}
+ loadingFacets={{}}
+ myIssues={false}
+ onFacetToggle={jest.fn()}
+ onFilterChange={jest.fn()}
+ openFacets={{}}
+ query={mockQuery()}
+ referencedComponentsById={{}}
+ referencedComponentsByKey={{}}
+ referencedLanguages={{}}
+ referencedRules={{}}
+ referencedUsers={{}}
+ {...props}
+ />
+ );
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow, ShallowWrapper } from 'enzyme';
-import { flatten } from 'lodash';
-import * as React from 'react';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { mockAppState } from '../../../../helpers/testMocks';
-import { ComponentQualifier } from '../../../../types/component';
-import { GlobalSettingKeys } from '../../../../types/settings';
-import { Query } from '../../utils';
-import { Sidebar } from '../Sidebar';
-
-it('should render facets for global page', () => {
- expect(renderSidebar()).toMatchSnapshot();
-});
-
-it('should render facets for project', () => {
- expect(renderSidebar({ component: mockComponent() })).toMatchSnapshot();
-});
-
-it.each([
- [ComponentQualifier.Application],
- [ComponentQualifier.Portfolio],
- [ComponentQualifier.SubPortfolio],
-])('should render facets for %p', (qualifier) => {
- expect(renderSidebar({ component: mockComponent({ qualifier }) })).toMatchSnapshot();
-});
-
-it('should render facets when my issues are selected', () => {
- expect(renderSidebar({ myIssues: true })).toMatchSnapshot();
-});
-
-it('should not render developer nominative facets when asked not to', () => {
- expect(
- renderSidebar({
- appState: mockAppState({
- settings: { [GlobalSettingKeys.DeveloperAggregatedInfoDisabled]: 'true' },
- }),
- })
- ).toMatchSnapshot();
-});
-
-const renderSidebar = (props?: Partial<Sidebar['props']>) => {
- return flatten(
- mapChildren(
- shallow<Sidebar>(
- <Sidebar
- appState={mockAppState({
- settings: { [GlobalSettingKeys.DeveloperAggregatedInfoDisabled]: 'false' },
- })}
- component={undefined}
- createdAfterIncludesTime={false}
- facets={{}}
- loadSearchResultCount={jest.fn()}
- loadingFacets={{}}
- myIssues={false}
- onFacetToggle={jest.fn()}
- onFilterChange={jest.fn()}
- openFacets={{}}
- query={{ types: [''] } as Query}
- referencedComponentsById={{}}
- referencedComponentsByKey={{}}
- referencedLanguages={{}}
- referencedRules={{}}
- referencedUsers={{}}
- {...props}
- />
- )
- )
- );
-
- function mapChildren(wrapper: ShallowWrapper) {
- return wrapper.children().map((node) => {
- if (typeof node.type() === 'symbol') {
- return node.children().map((n) => n.name());
- }
- return node.name();
- });
- }
-};
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import ListStyleFacetFooter from '../../../../components/facet/ListStyleFacetFooter';
-import { getStandards } from '../../../../helpers/security-standard';
-import { click } from '../../../../helpers/testUtils';
-import { Query } from '../../utils';
-import StandardFacet from '../StandardFacet';
-
-jest.mock('../../../../helpers/security-standard', () => ({
- ...jest.requireActual('../../../../helpers/security-standard'),
- getStandards: jest.fn().mockResolvedValue({
- owaspTop10: {
- a1: {
- title: 'Injection',
- },
- a2: {
- title: 'Broken Authentication',
- },
- },
- 'owaspTop10-2021': {
- a1: {
- title: 'Injection',
- },
- a2: {
- title: 'Broken Authentication',
- },
- },
- cwe: {
- unknown: {
- title: 'No CWE associated',
- },
- '1004': {
- title: "Sensitive Cookie Without 'HttpOnly' Flag",
- },
- },
- sonarsourceSecurity: {
- 'sql-injection': {
- title: 'SQL Injection',
- },
- 'command-injection': {
- title: 'Command Injection',
- },
- },
- }),
-}));
-
-it('should render closed', () => {
- expect(shallowRender()).toMatchSnapshot();
- expect(getStandards).not.toHaveBeenCalled();
-});
-
-it('should toggle standards facet', () => {
- const onToggle = jest.fn();
- const wrapper = shallowRender({ onToggle });
- click(wrapper.children('FacetHeader'));
- expect(onToggle).toHaveBeenCalledWith('standards');
-});
-
-it('should clear standards facet', () => {
- const onChange = jest.fn();
- const wrapper = shallowRender({ onChange });
- wrapper.children('FacetHeader').prop<Function>('onClear')();
- expect(onChange).toHaveBeenCalledWith({
- cwe: [],
- owaspTop10: [],
- 'owaspTop10-2021': [],
- sonarsourceSecurity: [],
- standards: [],
- });
-});
-
-it('should render sub-facets', () => {
- expect(
- shallowRender({
- cwe: ['42'],
- cweOpen: true,
- cweStats: { 42: 5, 173: 3 },
- open: true,
- owaspTop10: ['a3'],
- owaspTop10Open: true,
- owaspTop10Stats: { a1: 15, a3: 5 },
- sonarsourceSecurity: ['sql-injection'],
- sonarsourceSecurityOpen: true,
- sonarsourceSecurityStats: { 'sql-injection': 12 },
- })
- ).toMatchSnapshot();
- expect(getStandards).toHaveBeenCalled();
-});
-
-it('should show sonarsource facet more button', () => {
- const wrapper = shallowRender({
- open: true,
- sonarsourceSecurity: ['traceability', 'permission', 'others'],
- sonarsourceSecurityOpen: true,
- sonarsourceSecurityStats: {
- 'buffer-overflow': 3,
- 'sql-injection': 3,
- rce: 3,
- 'object-injection': 3,
- 'command-injection': 3,
- 'path-traversal-injection': 3,
- 'ldap-injection': 3,
- 'xpath-injection': 3,
- 'expression-lang-injection': 3,
- 'log-injection': 3,
- xxe: 3,
- xss: 3,
- dos: 3,
- ssrf: 3,
- csrf: 3,
- 'http-response-splitting': 3,
- 'open-redirect': 3,
- 'weak-cryptography': 3,
- auth: 3,
- 'insecure-conf': 3,
- 'file-manipulation': 3,
- 'encrypt-data': 3,
- traceability: 3,
- permission: 3,
- others: 3,
- },
- });
-
- expect(wrapper.find(ListStyleFacetFooter).exists()).toBe(true);
-
- wrapper.setState({ showFullSonarSourceList: true });
- expect(wrapper.find(ListStyleFacetFooter).exists()).toBe(false);
-});
-
-it('should render empty sub-facet', () => {
- expect(
- shallowRender({
- open: true,
- 'owaspTop10-2021': [],
- 'owaspTop10-2021Open': true,
- 'owaspTop10-2021Stats': {},
- }).find('FacetBox[property="owaspTop10-2021"]')
- ).toMatchSnapshot();
-});
-
-it('should select items', () => {
- const onChange = jest.fn();
- const wrapper = shallowRender({
- cwe: ['42'],
- cweOpen: true,
- cweStats: { 42: 5, 173: 3 },
- onChange,
- open: true,
- owaspTop10: ['a3'],
- owaspTop10Open: true,
- owaspTop10Stats: { a1: 15, a3: 5 },
- sonarsourceSecurity: ['command-injection'],
- sonarsourceSecurityOpen: true,
- sonarsourceSecurityStats: { 'sql-injection': 10 },
- });
-
- selectAndCheck('owaspTop10', 'a1');
- selectAndCheck('owaspTop10', 'a1', true, ['a1', 'a3']);
- selectAndCheck('sonarsourceSecurity', 'sql-injection');
-
- function selectAndCheck(facet: string, value: string, multiple = false, expectedValue = [value]) {
- wrapper
- .find(`FacetBox[property="${facet}"]`)
- .find(`FacetItem[value="${value}"]`)
- .prop<Function>('onClick')(value, multiple);
- expect(onChange).toHaveBeenLastCalledWith({ [facet]: expectedValue });
- }
-});
-
-it('should toggle sub-facets', () => {
- const onToggle = jest.fn();
- const wrapper = shallowRender({ onToggle, open: true });
- click(wrapper.find('FacetBox[property="owaspTop10"]').children('FacetHeader'));
- expect(onToggle).toHaveBeenLastCalledWith('owaspTop10');
- click(wrapper.find('FacetBox[property="sonarsourceSecurity"]').children('FacetHeader'));
- expect(onToggle).toHaveBeenLastCalledWith('sonarsourceSecurity');
-});
-
-it('should display correct selection', () => {
- const wrapper = shallowRender({
- open: true,
- owaspTop10: ['a1', 'a3'],
- 'owaspTop10-2021': ['a1', 'a2'],
- cwe: ['42', '1111', 'unknown'],
- sonarsourceSecurity: ['sql-injection', 'others'],
- });
- checkValues('standards', [
- 'SONAR SQL Injection',
- 'Others',
- 'OWASP A1 - a1 title',
- 'OWASP A3',
- 'OWASP A1 - a1 title',
- 'OWASP A2',
- 'CWE-42 - cwe-42 title',
- 'CWE-1111',
- 'Unknown CWE',
- ]);
- checkValues('owaspTop10', ['A1 - a1 title', 'A3']);
- checkValues('owaspTop10-2021', ['A1 - a1 title', 'A2']);
- checkValues('sonarsourceSecurity', ['SQL Injection', 'Others']);
-
- function checkValues(property: string, values: string[]) {
- expect(
- wrapper.find(`FacetBox[property="${property}"]`).children('FacetHeader').prop('values')
- ).toEqual(values);
- }
-});
-
-function shallowRender(props: Partial<StandardFacet['props']> = {}) {
- const wrapper = shallow(
- <StandardFacet
- cwe={[]}
- cweOpen={false}
- cweStats={{}}
- fetchingCwe={false}
- fetchingOwaspTop10={false}
- fetchingOwaspTop10-2021={false}
- fetchingSonarSourceSecurity={false}
- loadSearchResultCount={jest.fn()}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={false}
- owaspTop10={[]}
- owaspTop10Open={false}
- owaspTop10Stats={{}}
- owaspTop10-2021={[]}
- owaspTop10-2021Open={false}
- owaspTop10-2021Stats={{}}
- query={{} as Query}
- sonarsourceSecurity={[]}
- sonarsourceSecurityOpen={false}
- sonarsourceSecurityStats={{}}
- {...props}
- />
- );
- wrapper.setState({
- standards: {
- owaspTop10: { a1: { title: 'a1 title' } },
- 'owaspTop10-2021': { a1: { title: 'a1 title' } },
- cwe: { 42: { title: 'cwe-42 title' }, unknown: { title: 'Unknown CWE' } },
- sonarsourceSecurity: {
- 'sql-injection': { title: 'SQL Injection' },
- others: { title: 'Others' },
- },
- },
- });
- return wrapper;
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { click } from '../../../../helpers/testUtils';
-import StatusFacet from '../StatusFacet';
-
-it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should toggle status facet', () => {
- const onToggle = jest.fn();
- const wrapper = shallowRender({ onToggle });
- click(wrapper.children('FacetHeader'));
- expect(onToggle).toHaveBeenCalledWith('statuses');
-});
-
-it('should clear status facet', () => {
- const onChange = jest.fn();
- const wrapper = shallowRender({ onChange, statuses: ['CONFIRMED'] });
- wrapper.children('FacetHeader').prop<Function>('onClear')();
- expect(onChange).toHaveBeenCalledWith({ statuses: [] });
-});
-
-it('should select a status', () => {
- const onChange = jest.fn();
- const wrapper = shallowRender({ onChange });
- clickAndCheck('OPEN');
- clickAndCheck('CONFIRMED', true, ['CONFIRMED', 'OPEN']);
- clickAndCheck('CLOSED');
-
- function clickAndCheck(status: string, multiple = false, expected = [status]) {
- wrapper.find(`FacetItemsList`).find(`FacetItem[value="${status}"]`).prop<Function>('onClick')(
- status,
- multiple
- );
- expect(onChange).toHaveBeenLastCalledWith({ statuses: expected });
- wrapper.setProps({ statuses: expected });
- }
-});
-
-function shallowRender(props: Partial<StatusFacet['props']> = {}) {
- return shallow(
- <StatusFacet
- fetching={false}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- open={true}
- stats={{
- OPEN: 104,
- CONFIRMED: 8,
- REOPENED: 0,
- RESOLVED: 0,
- CLOSED: 8,
- }}
- statuses={[]}
- {...props}
- />
- );
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { click } from '../../../../helpers/testUtils';
-import TypeFacet from '../TypeFacet';
-
-it('should render open by default', () => {
- expect(shallowRender({ types: ['VULNERABILITY', 'CODE_SMELL'] })).toMatchSnapshot();
-});
-
-it('should toggle type facet', () => {
- const onToggle = jest.fn();
- const wrapper = shallowRender({ onToggle });
- click(wrapper.children('FacetHeader'));
- expect(onToggle).toHaveBeenCalledWith('types');
-});
-
-it('should clear types facet', () => {
- const onChange = jest.fn();
- const wrapper = shallowRender({ onChange, types: ['BUGS'] });
- wrapper.children('FacetHeader').prop<Function>('onClear')();
- expect(onChange).toHaveBeenCalledWith({ types: [] });
-});
-
-it('should select a type', () => {
- const onChange = jest.fn();
- const wrapper = shallowRender({ onChange });
- clickAndCheck('CODE_SMELL');
- clickAndCheck('VULNERABILITY', true, ['CODE_SMELL', 'VULNERABILITY']);
-
- function clickAndCheck(type: string, multiple = false, expected = [type]) {
- wrapper.find(`FacetItemsList`).find(`FacetItem[value="${type}"]`).prop<Function>('onClick')(
- type,
- multiple
- );
- expect(onChange).toHaveBeenLastCalledWith({ types: expected });
- wrapper.setProps({ types: expected });
- }
-});
-
-function shallowRender(props: Partial<TypeFacet['props']> = {}) {
- return shallow(
- <TypeFacet
- fetching={false}
- onChange={jest.fn()}
- onToggle={jest.fn()}
- stats={{ BUG: 0, VULNERABILITY: 2, CODE_SMELL: 5, SECURITY_HOTSPOT: 1 }}
- types={[]}
- {...props}
- />
- );
-}
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<ListStyleFacet
- facetHeader="issues.facet.assignees"
- fetching={false}
- getFacetItemText={[Function]}
- getSearchResultKey={[Function]}
- getSearchResultText={[Function]}
- getSortedItems={[Function]}
- loadSearchResultCount={[Function]}
- maxInitialItems={15}
- maxItems={100}
- minSearchLength={2}
- onChange={[MockFunction]}
- onClear={[Function]}
- onItemClick={[Function]}
- onSearch={[Function]}
- onToggle={[MockFunction]}
- open={true}
- property="assignees"
- query={{}}
- renderFacetItem={[Function]}
- renderSearchResult={[Function]}
- searchPlaceholder="search.search_for_users"
- stats={
- {
- "": 5,
- "bar": 7,
- "baz": 6,
- "foo": 13,
- }
- }
- values={
- [
- "foo",
- ]
- }
-/>
-`;
-
-exports[`test behavior should correctly render facet item 1`] = `
-<React.Fragment>
- <withAppStateContext(Avatar)
- className="little-spacer-right"
- name="Name Baz"
- size={16}
- />
- Name Baz
-</React.Fragment>
-`;
-
-exports[`test behavior should correctly render facet item 2`] = `
-<React.Fragment>
- <withAppStateContext(Avatar)
- className="little-spacer-right"
- name="foo"
- size={16}
- />
- user.x_deleted.foo
-</React.Fragment>
-`;
-
-exports[`test behavior should correctly render search result correctly 1`] = `
-<React.Fragment>
- <withAppStateContext(Avatar)
- className="little-spacer-right"
- name="Name Bar"
- size={16}
- />
- <React.Fragment>
- Name
- <mark>
- Ba
- </mark>
- r
- </React.Fragment>
-</React.Fragment>
-`;
-
-exports[`test behavior should correctly render search result correctly 2`] = `
-<React.Fragment>
- <withAppStateContext(Avatar)
- className="little-spacer-right"
- name="foo"
- size={16}
- />
- <React.Fragment>
- user.x_deleted.
- <mark>
- fo
- </mark>
- o
- </React.Fragment>
-</React.Fragment>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
- facetHeader="issues.facet.authors"
- fetching={false}
- getFacetItemText={[Function]}
- getSearchResultKey={[Function]}
- getSearchResultText={[Function]}
- loadSearchResultCount={[Function]}
- maxInitialItems={15}
- maxItems={100}
- minSearchLength={2}
- onChange={[MockFunction]}
- onSearch={[Function]}
- onToggle={[MockFunction]}
- open={true}
- property="author"
- query={{}}
- renderFacetItem={[Function]}
- renderSearchResult={[Function]}
- searchPlaceholder="search.search_for_authors"
- stats={{}}
- values={[]}
-/>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly for createdInLast month 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "issues.facet.createdAt.last_month",
- ]
- }
- />
- <div>
- <div
- className="search-navigator-date-facet-selection"
- >
- <DateRangeInput
- alignEndDateCalandarRight={true}
- onChange={[Function]}
- value={
- {
- "from": undefined,
- "to": undefined,
- }
- }
- />
- </div>
- <div
- className="spacer-top issues-predefined-periods"
- >
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.all"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.all"
- value=""
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_week"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_week"
- value="1w"
- />
- <FacetItem
- active={true}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_month"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_month"
- value="1m"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_year"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_year"
- value="1y"
- />
- </div>
- </div>
-</FacetBox>
-`;
-
-exports[`should render correctly for createdInLast week 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "issues.facet.createdAt.last_week",
- ]
- }
- />
- <div>
- <div
- className="search-navigator-date-facet-selection"
- >
- <DateRangeInput
- alignEndDateCalandarRight={true}
- onChange={[Function]}
- value={
- {
- "from": undefined,
- "to": undefined,
- }
- }
- />
- </div>
- <div
- className="spacer-top issues-predefined-periods"
- >
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.all"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.all"
- value=""
- />
- <FacetItem
- active={true}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_week"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_week"
- value="1w"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_month"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_month"
- value="1m"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_year"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_year"
- value="1y"
- />
- </div>
- </div>
-</FacetBox>
-`;
-
-exports[`should render correctly for createdInLast year 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "issues.facet.createdAt.last_year",
- ]
- }
- />
- <div>
- <div
- className="search-navigator-date-facet-selection"
- >
- <DateRangeInput
- alignEndDateCalandarRight={true}
- onChange={[Function]}
- value={
- {
- "from": undefined,
- "to": undefined,
- }
- }
- />
- </div>
- <div
- className="spacer-top issues-predefined-periods"
- >
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.all"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.all"
- value=""
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_week"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_week"
- value="1w"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_month"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_month"
- value="1m"
- />
- <FacetItem
- active={true}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_year"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_year"
- value="1y"
- />
- </div>
- </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: clear 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={[]}
- />
- <div>
- <div
- className="search-navigator-date-facet-selection"
- >
- <DateRangeInput
- alignEndDateCalandarRight={true}
- onChange={[Function]}
- value={
- {
- "from": undefined,
- "to": undefined,
- }
- }
- />
- </div>
- <div
- className="spacer-top issues-predefined-periods"
- >
- <FacetItem
- active={true}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.all"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.all"
- value=""
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_week"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_week"
- value="1w"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_month"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_month"
- value="1m"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_year"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_year"
- value="1y"
- />
- </div>
- </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: closed 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={false}
- values={[]}
- />
-</FacetBox>
-`;
-
-exports[`should render correctly: created after 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "formatted.Invalid Date",
- ]
- }
- />
- <div
- className="search-navigator-facet-container"
- >
- <strong>
- after
-
- </strong>
- <DateTimeFormatter
- date={Date { NaN }}
- />
- </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: created after timestamp 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "formatted.Invalid Date",
- ]
- }
- />
- <div
- className="search-navigator-facet-container"
- >
- <strong>
- after
-
- </strong>
- <DateTimeFormatter
- date={Date { NaN }}
- />
- </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: created at 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "formatted.2019.05.21T13:33:00Z",
- ]
- }
- />
- <div
- className="search-navigator-facet-container"
- >
- <DateTimeFormatter
- date="2019.05.21T13:33:00Z"
- />
- <br />
- <span
- className="note"
- >
- <DateFromNow
- date="2019.05.21T13:33:00Z"
- />
- </span>
- </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: portfolio 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={[]}
- />
- <div>
- <div
- className="search-navigator-date-facet-selection"
- >
- <DateRangeInput
- alignEndDateCalandarRight={true}
- onChange={[Function]}
- value={
- {
- "from": undefined,
- "to": undefined,
- }
- }
- />
- </div>
- <div
- className="spacer-top issues-predefined-periods"
- >
- <FacetItem
- active={true}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.all"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.all"
- value=""
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_week"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_week"
- value="1w"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_month"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_month"
- value="1m"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_year"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_year"
- value="1y"
- />
- </div>
- </div>
-</FacetBox>
-`;
-
-exports[`should render correctly: project 1`] = `
-<FacetBox
- property="createdAt"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.createdAt"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={[]}
- />
- <div>
- <div
- className="search-navigator-date-facet-selection"
- >
- <DateRangeInput
- alignEndDateCalandarRight={true}
- onChange={[Function]}
- value={
- {
- "from": undefined,
- "to": undefined,
- }
- }
- />
- </div>
- <div
- className="spacer-top issues-predefined-periods"
- >
- <FacetItem
- active={true}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.all"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.all"
- value=""
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_week"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_week"
- value="1w"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_month"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_month"
- value="1m"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- loading={false}
- name="issues.facet.createdAt.last_year"
- onClick={[Function]}
- tooltip="issues.facet.createdAt.last_year"
- value="1y"
- />
- </div>
- </div>
-</FacetBox>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
- facetHeader="issues.facet.directories"
- fetching={false}
- getFacetItemText={[Function]}
- getSearchResultKey={[Function]}
- getSearchResultText={[Function]}
- loadSearchResultCount={[Function]}
- maxInitialItems={15}
- maxItems={100}
- minSearchLength={3}
- onChange={[MockFunction]}
- onSearch={[Function]}
- onToggle={[MockFunction]}
- open={false}
- property="directories"
- query={{}}
- renderFacetItem={[Function]}
- renderSearchResult={[Function]}
- searchPlaceholder="search.search_for_directories"
- values={
- [
- "foo/",
- "bar/baz/",
- ]
- }
-/>
-`;
-
-exports[`should render correctly 2`] = `
-<React.Fragment>
- <QualifierIcon
- className="little-spacer-right"
- qualifier="DIR"
- />
- <React.Fragment>
- <mark>
- foo
- </mark>
- /bar
- </React.Fragment>
-</React.Fragment>
-`;
-
-exports[`should render correctly 3`] = `
-<React.Fragment>
- <QualifierIcon
- className="little-spacer-right"
- qualifier="DIR"
- />
- foo/bar
-</React.Fragment>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
- facetHeader="issues.facet.files"
- fetching={false}
- getFacetItemText={[Function]}
- getSearchResultKey={[Function]}
- getSearchResultText={[Function]}
- loadSearchResultCount={[Function]}
- maxInitialItems={15}
- maxItems={100}
- minSearchLength={3}
- onChange={[MockFunction]}
- onSearch={[Function]}
- onToggle={[MockFunction]}
- open={false}
- property="files"
- query={{}}
- renderFacetItem={[Function]}
- renderSearchResult={[Function]}
- searchPlaceholder="search.search_for_files"
- values={
- [
- "foo",
- "bar",
- ]
- }
-/>
-`;
-
-exports[`should render correctly 2`] = `
-<React.Fragment>
- <QualifierIcon
- className="little-spacer-right"
- qualifier="FIL"
- />
- <React.Fragment>
- foo
- /
- <React.Fragment>
- <mark>
- bar
- </mark>
- .js
- </React.Fragment>
- </React.Fragment>
-</React.Fragment>
-`;
-
-exports[`should render correctly 3`] = `
-<React.Fragment>
- <QualifierIcon
- className="little-spacer-right"
- qualifier="FIL"
- />
- fooUuid
-</React.Fragment>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ListStyleFacet's renderers should include renderFacetItem 1`] = `
-<span>
- <QualifierIcon
- className="little-spacer-right"
- qualifier="TRK"
- />
- First Project Name
-</span>
-`;
-
-exports[`ListStyleFacet's renderers should include renderSearchResult 1`] = `
-<React.Fragment>
- <QualifierIcon
- className="little-spacer-right"
- qualifier="TRK"
- />
- <React.Fragment>
- <mark>
- First
- </mark>
- Project Name
- </React.Fragment>
-</React.Fragment>
-`;
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
- facetHeader="issues.facet.projects"
- fetching={false}
- getFacetItemText={[Function]}
- getSearchResultKey={[Function]}
- getSearchResultText={[Function]}
- loadSearchResultCount={[Function]}
- maxInitialItems={15}
- maxItems={100}
- minSearchLength={2}
- onChange={[MockFunction]}
- onSearch={[Function]}
- onToggle={[MockFunction]}
- open={false}
- property="projects"
- query={{}}
- renderFacetItem={[Function]}
- renderSearchResult={[Function]}
- searchPlaceholder="search.search_for_projects"
- values={[]}
-/>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ListStyleFacet
- facetHeader="issues.facet.rules"
- fetching={true}
- getFacetItemText={[Function]}
- getSearchResultKey={[Function]}
- getSearchResultText={[Function]}
- loadSearchResultCount={[Function]}
- maxInitialItems={15}
- maxItems={100}
- minSearchLength={2}
- onChange={[MockFunction]}
- onSearch={[Function]}
- onToggle={[MockFunction]}
- open={false}
- property="rules"
- query={{}}
- renderFacetItem={[Function]}
- renderSearchResult={[Function]}
- searchPlaceholder="search.search_for_rules"
- stats={{}}
- values={
- [
- "r1",
- ]
- }
-/>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: active facet 1`] = `
-<FacetBox
- property="scopes"
->
- <FacetHeader
- fetching={true}
- name="issues.facet.scopes"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "issue.scope.MAIN",
- ]
- }
- />
- <FacetItemsList>
- <FacetItem
- active={true}
- halfWidth={false}
- key="MAIN"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <QualifierIcon
- aria-hidden={true}
- className="little-spacer-right"
- qualifier="FIL"
- />
-
- issue.scope.MAIN
- </span>
- }
- onClick={[Function]}
- value="MAIN"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- key="TEST"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <QualifierIcon
- aria-hidden={true}
- className="little-spacer-right"
- qualifier="UTS"
- />
-
- issue.scope.TEST
- </span>
- }
- onClick={[Function]}
- value="TEST"
- />
- </FacetItemsList>
- <MultipleSelectionHint
- options={0}
- values={1}
- />
-</FacetBox>
-`;
-
-exports[`should render correctly: default 1`] = `
-<FacetBox
- property="scopes"
->
- <FacetHeader
- fetching={true}
- name="issues.facet.scopes"
- onClear={[Function]}
- onClick={[Function]}
- open={false}
- values={[]}
- />
-</FacetBox>
-`;
-
-exports[`should render correctly: disabled facet 1`] = `
-<FacetBox
- property="scopes"
->
- <FacetHeader
- fetching={true}
- name="issues.facet.scopes"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={[]}
- />
- <FacetItemsList>
- <FacetItem
- active={false}
- halfWidth={false}
- key="MAIN"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <QualifierIcon
- aria-hidden={true}
- className="little-spacer-right"
- qualifier="FIL"
- />
-
- issue.scope.MAIN
- </span>
- }
- onClick={[Function]}
- stat={0}
- value="MAIN"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- key="TEST"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <QualifierIcon
- aria-hidden={true}
- className="little-spacer-right"
- qualifier="UTS"
- />
-
- issue.scope.TEST
- </span>
- }
- onClick={[Function]}
- value="TEST"
- />
- </FacetItemsList>
- <MultipleSelectionHint
- options={1}
- values={0}
- />
-</FacetBox>
-`;
-
-exports[`should render correctly: open 1`] = `
-<FacetBox
- property="scopes"
->
- <FacetHeader
- fetching={true}
- name="issues.facet.scopes"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={[]}
- />
- <FacetItemsList>
- <FacetItem
- active={false}
- halfWidth={false}
- key="MAIN"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <QualifierIcon
- aria-hidden={true}
- className="little-spacer-right"
- qualifier="FIL"
- />
-
- issue.scope.MAIN
- </span>
- }
- onClick={[Function]}
- value="MAIN"
- />
- <FacetItem
- active={false}
- halfWidth={false}
- key="TEST"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <QualifierIcon
- aria-hidden={true}
- className="little-spacer-right"
- qualifier="UTS"
- />
-
- issue.scope.TEST
- </span>
- }
- onClick={[Function]}
- value="TEST"
- />
- </FacetItemsList>
- <MultipleSelectionHint
- options={0}
- values={0}
- />
-</FacetBox>
-`;
+++ /dev/null
-// 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",
-]
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render closed 1`] = `
-<FacetBox
- property="standards"
->
- <FacetHeader
- name="issues.facet.standards"
- onClear={[Function]}
- onClick={[Function]}
- open={false}
- values={[]}
- />
-</FacetBox>
-`;
-
-exports[`should render empty sub-facet 1`] = `
-<FacetBox
- className="is-inner"
- property="owaspTop10-2021"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.owaspTop10_2021"
- onClick={[Function]}
- open={true}
- values={[]}
- />
- <div
- className="search-navigator-facet-empty little-spacer-top"
- >
- no_results
- </div>
- <MultipleSelectionHint
- options={0}
- values={0}
- />
-</FacetBox>
-`;
-
-exports[`should render sub-facets 1`] = `
-<FacetBox
- property="standards"
->
- <FacetHeader
- name="issues.facet.standards"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "SONAR SQL Injection",
- "OWASP A3",
- "CWE-42 - cwe-42 title",
- ]
- }
- />
- <FacetBox
- className="is-inner"
- property="sonarsourceSecurity"
- >
- <FacetHeader
- fetching={false}
- name="issues.facet.sonarsourceSecurity"
- onClick={[Function]}
- open={true}
- values={
- [
- "SQL Injection",
- ]
- }
- />
- <FacetItemsList>
- <FacetItem
- active={true}
- halfWidth={false}
- key="sql-injection"
- loading={false}
- name="SQL Injection"
- onClick={[Function]}
- stat="12"
- tooltip="SQL Injection"
- value="sql-injection"
- />
- </FacetItemsList>
- <MultipleSelectionHint
- options={1}
- values={1}
- />
- </FacetBox>
- <FacetBox
- className="is-inner"
- property="owaspTop10-2021"
- >
- <FacetHeader
- fetching={false}
- name="issues.facet.owaspTop10_2021"
- onClick={[Function]}
- open={false}
- values={[]}
- />
- </FacetBox>
- <FacetBox
- className="is-inner"
- property="owaspTop10"
- >
- <FacetHeader
- fetching={false}
- name="issues.facet.owaspTop10"
- onClick={[Function]}
- open={true}
- values={
- [
- "A3",
- ]
- }
- />
- <FacetItemsList>
- <FacetItem
- active={false}
- halfWidth={false}
- key="a1"
- loading={false}
- name="A1 - a1 title"
- onClick={[Function]}
- stat="15"
- tooltip="A1 - a1 title"
- value="a1"
- />
- <FacetItem
- active={true}
- halfWidth={false}
- key="a3"
- loading={false}
- name="A3"
- onClick={[Function]}
- stat="5"
- tooltip="A3"
- value="a3"
- />
- </FacetItemsList>
- <MultipleSelectionHint
- options={2}
- values={1}
- />
- </FacetBox>
- <ListStyleFacet
- className="is-inner"
- facetHeader="issues.facet.cwe"
- fetching={false}
- getFacetItemText={[Function]}
- getSearchResultKey={[Function]}
- getSearchResultText={[Function]}
- loadSearchResultCount={[Function]}
- maxInitialItems={15}
- maxItems={100}
- minSearchLength={2}
- onChange={[MockFunction]}
- onSearch={[Function]}
- onToggle={[MockFunction]}
- open={true}
- property="cwe"
- query={{}}
- renderFacetItem={[Function]}
- renderSearchResult={[Function]}
- searchPlaceholder="search.search_for_cwe"
- stats={
- {
- "173": 3,
- "42": 5,
- }
- }
- values={
- [
- "42",
- ]
- }
- />
-</FacetBox>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<FacetBox
- property="statuses"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.statuses"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={[]}
- />
- <FacetItemsList>
- <FacetItem
- active={false}
- halfWidth={true}
- key="OPEN"
- loading={false}
- name={
- <StatusHelper
- status="OPEN"
- />
- }
- onClick={[Function]}
- stat="104"
- tooltip="issue.status.OPEN"
- value="OPEN"
- />
- <FacetItem
- active={false}
- halfWidth={true}
- key="CONFIRMED"
- loading={false}
- name={
- <StatusHelper
- status="CONFIRMED"
- />
- }
- onClick={[Function]}
- stat="8"
- tooltip="issue.status.CONFIRMED"
- value="CONFIRMED"
- />
- <FacetItem
- active={false}
- halfWidth={true}
- key="REOPENED"
- loading={false}
- name={
- <StatusHelper
- status="REOPENED"
- />
- }
- onClick={[Function]}
- stat={0}
- tooltip="issue.status.REOPENED"
- value="REOPENED"
- />
- <FacetItem
- active={false}
- halfWidth={true}
- key="RESOLVED"
- loading={false}
- name={
- <StatusHelper
- status="RESOLVED"
- />
- }
- onClick={[Function]}
- stat={0}
- tooltip="issue.status.RESOLVED"
- value="RESOLVED"
- />
- <FacetItem
- active={false}
- halfWidth={true}
- key="CLOSED"
- loading={false}
- name={
- <StatusHelper
- status="CLOSED"
- />
- }
- onClick={[Function]}
- stat="8"
- tooltip="issue.status.CLOSED"
- value="CLOSED"
- />
- </FacetItemsList>
- <MultipleSelectionHint
- options={5}
- values={0}
- />
-</FacetBox>
-`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render open by default 1`] = `
-<FacetBox
- property="types"
->
- <FacetHeader
- fetching={false}
- name="issues.facet.types"
- onClear={[Function]}
- onClick={[Function]}
- open={true}
- values={
- [
- "issue.type.VULNERABILITY",
- "issue.type.CODE_SMELL",
- ]
- }
- />
- <FacetItemsList>
- <FacetItem
- active={false}
- halfWidth={false}
- key="BUG"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <IssueTypeIcon
- className="little-spacer-right"
- query="BUG"
- />
-
- issue.type.BUG
- </span>
- }
- onClick={[Function]}
- stat={0}
- value="BUG"
- />
- <FacetItem
- active={true}
- halfWidth={false}
- key="VULNERABILITY"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <IssueTypeIcon
- className="little-spacer-right"
- query="VULNERABILITY"
- />
-
- issue.type.VULNERABILITY
- </span>
- }
- onClick={[Function]}
- stat="2"
- value="VULNERABILITY"
- />
- <FacetItem
- active={true}
- halfWidth={false}
- key="CODE_SMELL"
- loading={false}
- name={
- <span
- className="display-flex-center"
- >
- <IssueTypeIcon
- className="little-spacer-right"
- query="CODE_SMELL"
- />
-
- issue.type.CODE_SMELL
- </span>
- }
- onClick={[Function]}
- stat="5"
- value="CODE_SMELL"
- />
- </FacetItemsList>
- <MultipleSelectionHint
- options={4}
- values={2}
- />
-</FacetBox>
-`;
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
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';
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);
}
const canSetType = issue.actions.includes('set_type');
const canSetTags = issue.actions.includes('set_tags');
const hasTransitions = issue.transitions && issue.transitions.length > 0;
- const isSecurityHotspot = issue.type === 'SECURITY_HOTSPOT';
+ const isSecurityHotspot = issue.type === IssueTypeEnum.SecurityHotspot;
return (
<div className={classNames(className, 'issue-actions')}>
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [],
"severity": "MAJOR",
"status": "OPEN",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [
{
"component": "main.js",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [
{
"component": "main.js",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [
{
"component": "main.js",
"projectName": "Foo",
"rule": "javascript:S1067",
"ruleName": "foo",
+ "scope": "MAIN",
"secondaryLocations": [
{
"component": "main.js",
* 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';
...overrides,
};
}
+
+export function mockQuery(overrides: Partial<Query> = {}): Query {
+ return {
+ assigned: false,
+ assignees: [],
+ author: [],
+ createdAfter: undefined,
+ createdAt: '',
+ createdBefore: undefined,
+ createdInLast: '',
+ cwe: [],
+ directories: [],
+ files: [],
+ issues: [],
+ languages: [],
+ owaspTop10: [],
+ 'owaspTop10-2021': [],
+ 'pciDss-3.2': [],
+ 'pciDss-4.0': [],
+ 'owaspAsvs-4.0': [],
+ owaspAsvsLevel: '',
+ projects: [],
+ resolutions: [],
+ resolved: false,
+ rules: [],
+ scopes: [],
+ severities: [],
+ inNewCodePeriod: false,
+ sonarsourceSecurity: [],
+ sort: '',
+ statuses: [],
+ tags: [],
+ types: [],
+ ...overrides,
+ };
+}
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';
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,
};
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',
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',
assignee?: string;
author?: string;
comments?: Array<Comment>;
+ creationDate: string;
component: string;
flows?: Array<{
type?: string;
status: string;
textRange?: TextRange;
type: IssueType;
+ scope: string;
ruleDescriptionContextKey?: string;
ruleStatus?: string;
quickFixAvailable?: boolean;
ruleDescriptionContextKey?: string;
ruleName: string;
ruleStatus?: string;
+ scope: string;
secondaryLocations: FlowLocation[];
severity: string;
status: string;