diff options
author | Mathieu Suen <mathieu.suen@sonarsource.com> | 2022-01-05 10:37:27 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-01-20 20:02:43 +0000 |
commit | 8a31770cf438f06857632c07958c6021e33d01c2 (patch) | |
tree | 46809943728994fe77756a64acdd162c3c0ab6c4 /server/sonar-web/src/main/js | |
parent | 3b37a05131ca2a4cf23f6888824258c8e0a423be (diff) | |
download | sonarqube-8a31770cf438f06857632c07958c6021e33d01c2.tar.gz sonarqube-8a31770cf438f06857632c07958c6021e33d01c2.zip |
SONAR-15879 Add warning when not all issues are accessible
Diffstat (limited to 'server/sonar-web/src/main/js')
-rw-r--r-- | server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx | 15 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesApp-test.tsx (renamed from server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx) | 48 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/App-test.tsx.snap) | 125 |
3 files changed, 186 insertions, 2 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx index daf950c8c91..091dde02396 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx @@ -29,6 +29,7 @@ import FiltersHeader from '../../../components/common/FiltersHeader'; import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper'; import { Button } from '../../../components/controls/buttons'; import Checkbox from '../../../components/controls/Checkbox'; +import HelpTooltip from '../../../components/controls/HelpTooltip'; import ListFooter from '../../../components/controls/ListFooter'; import { Location, Router } from '../../../components/hoc/withRouter'; import '../../../components/search-navigator.css'; @@ -50,6 +51,7 @@ import { } from '../../../helpers/pages'; import { serializeDate } from '../../../helpers/query'; import { BranchLike } from '../../../types/branch-like'; +import { ComponentQualifier, isPortfolioLike } from '../../../types/component'; import { Facet, FetchIssuesPromise, @@ -85,7 +87,7 @@ import MyIssuesFilter from './MyIssuesFilter'; import NoIssues from './NoIssues'; import NoMyIssues from './NoMyIssues'; import PageActions from './PageActions'; -] + interface Props { branchLike?: BranchLike; component?: T.Component; @@ -946,6 +948,8 @@ export default class App extends React.PureComponent<Props, State> { } renderSide(openIssue: T.Issue | undefined) { + const { canBrowseAllChildProjects, qualifier = ComponentQualifier.Project } = + this.props.component || {}; return ( <ScreenPositionHelper className="layout-page-side-outer"> {({ top }) => ( @@ -954,6 +958,15 @@ export default class App extends React.PureComponent<Props, State> { className="layout-page-side" style={{ top }}> <div className="layout-page-side-inner"> + {!canBrowseAllChildProjects && isPortfolioLike(qualifier) && ( + <Alert className="big-spacer-top big-spacer-right" variant="warning"> + {translate('issues.not_all_issue_show')} + <HelpTooltip + className="spacer-left" + overlay={translate('issues.not_all_issue_show_why')} + /> + </Alert> + )} <A11ySkipTarget anchor="issues_sidebar" label={ diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesApp-test.tsx index c46853dced1..ec5f4e5e767 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesApp-test.tsx @@ -39,6 +39,7 @@ import { mockRouter } from '../../../../helpers/testMocks'; import { KEYCODE_MAP, keydown, waitAndUpdate } from '../../../../helpers/testUtils'; +import { ComponentQualifier } from '../../../../types/component'; import { disableLocationsNavigator, enableLocationsNavigator, @@ -47,8 +48,8 @@ import { selectPreviousFlow, selectPreviousLocation } from '../../actions'; -import App from '../IssuesApp'; import BulkChangeModal from '../BulkChangeModal'; +import App from '../IssuesApp'; jest.mock('../../../../helpers/pages', () => ({ addSideBarClass: jest.fn(), @@ -111,6 +112,17 @@ afterEach(() => { }); }); +it('should show warnning when not all projects are accessible', () => { + const wrapper = shallowRender({ + component: mockComponent({ + canBrowseAllChildProjects: false, + qualifier: ComponentQualifier.Portfolio + }) + }); + const rootNode = shallow(wrapper.instance().renderSide(undefined)); + expect(rootNode).toMatchSnapshot(); +}); + it('should render a list of issue', async () => { const wrapper = shallowRender(); await waitAndUpdate(wrapper); @@ -122,6 +134,26 @@ it('should render a list of issue', async () => { expect(addWhitePageClass).toBeCalled(); }); +it('should handle my issue change properly', () => { + const push = jest.fn(); + const wrapper = shallowRender({ router: mockRouter({ push }) }); + wrapper.instance().handleMyIssuesChange(true); + + expect(push).toBeCalledWith({ + pathname: '/issues', + query: { + id: 'foo', + myIssues: 'true' + } + }); +}); + +it('should load search result count correcly', async () => { + const wrapper = shallowRender(); + const count = await wrapper.instance().loadSearchResultCount('severities', {}); + expect(count).toStrictEqual({ MINOR: 4 }); +}); + it('should not render for anonymous user', () => { shallowRender({ currentUser: mockCurrentUser({ isLoggedIn: false }), @@ -130,6 +162,20 @@ it('should not render for anonymous user', () => { expect(handleRequiredAuthentication).toBeCalled(); }); +it('should handle reset properly', () => { + const push = jest.fn(); + const wrapper = shallowRender({ router: mockRouter({ push }) }); + wrapper.instance().handleReset(); + expect(push).toBeCalledWith({ + pathname: '/issues', + query: { + id: 'foo', + myIssues: undefined, + resolved: 'false' + } + }); +}); + it('should open standard facets for vulnerabilities and hotspots', () => { const wrapper = shallowRender({ location: mockLocation({ pathname: '/issues', query: { types: 'VULNERABILITY' } }) diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap index aa9a378fa01..5d9e05830a4 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/App-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap @@ -20,6 +20,131 @@ exports[`should check max 500 issues 1`] = ` </Button> `; +exports[`should show warnning when not all projects are accessible 1`] = ` +<div + className="layout-page-side-outer" +> + <section + aria-label="filters" + className="layout-page-side" + style={ + Object { + "top": 0, + } + } + > + <div + className="layout-page-side-inner" + > + <Alert + className="big-spacer-top big-spacer-right" + variant="warning" + > + issues.not_all_issue_show + <HelpTooltip + className="spacer-left" + overlay="issues.not_all_issue_show_why" + /> + </Alert> + <A11ySkipTarget + anchor="issues_sidebar" + label="issues.skip_to_filters" + weight={10} + /> + <div + className="layout-page-filters" + > + <MyIssuesFilter + myIssues={false} + onMyIssuesChange={[Function]} + /> + <FiltersHeader + displayReset={true} + onReset={[Function]} + /> + <Connect(Sidebar) + component={ + Object { + "breadcrumbs": Array [], + "canBrowseAllChildProjects": false, + "key": "my-project", + "name": "MyProject", + "qualifier": "VW", + "qualityGate": Object { + "isDefault": true, + "key": "30", + "name": "Sonar way", + }, + "qualityProfiles": Array [ + Object { + "deleted": false, + "key": "my-qp", + "language": "ts", + "name": "Sonar way", + }, + ], + "tags": Array [], + } + } + createdAfterIncludesTime={false} + facets={Object {}} + loadSearchResultCount={[Function]} + loadingFacets={Object {}} + myIssues={false} + onFacetToggle={[Function]} + onFilterChange={[Function]} + openFacets={ + Object { + "owaspTop10": false, + "sansTop25": false, + "severities": true, + "sonarsourceSecurity": false, + "standards": false, + "types": true, + } + } + query={ + Object { + "assigned": true, + "assignees": Array [], + "author": Array [], + "createdAfter": undefined, + "createdAt": "", + "createdBefore": undefined, + "createdInLast": "", + "cwe": Array [], + "directories": Array [], + "files": Array [], + "issues": Array [], + "languages": Array [], + "owaspTop10": Array [], + "projects": Array [], + "resolutions": Array [], + "resolved": true, + "rules": Array [], + "sansTop25": Array [], + "scopes": Array [], + "severities": Array [], + "sinceLeakPeriod": false, + "sonarsourceSecurity": Array [], + "sort": "", + "statuses": Array [], + "tags": Array [], + "types": Array [], + } + } + referencedComponentsById={Object {}} + referencedComponentsByKey={Object {}} + referencedLanguages={Object {}} + referencedRules={Object {}} + referencedUsers={Object {}} + /> + </div> + </div> + </section> +</div> +`; + exports[`should switch to source view if an issue is selected 1`] = ` <div className="layout-page issues" |