Browse Source

SONAR-15879 Add warning when not all issues are accessible

tags/9.3.0.51899
Mathieu Suen 2 years ago
parent
commit
8a31770cf4

+ 14
- 1
server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx View File

@@ -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={

server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx → server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesApp-test.tsx View File

@@ -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' } })

server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/App-test.tsx.snap → server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap View File

@@ -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"

+ 3
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -926,6 +926,9 @@ issues.my_issues=My Issues
issues.no_my_issues=There are no issues assigned to you.
issues.no_issues=No Issues. Hooray!
issues.x_more_locations=+ {0} more location(s)
issues.not_all_issue_show=Not all issues are included

issues.not_all_issue_show_why=You do not have access to all projects in this portfolio

#------------------------------------------------------------------------------
#

Loading…
Cancel
Save