diff options
5 files changed, 118 insertions, 2 deletions
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx index 7d1f7457ba7..931289e8965 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx @@ -27,8 +27,10 @@ import { getMeasuresWithPeriod } from '../../../api/measures'; import { getAllMetrics } from '../../../api/metrics'; import Suggestions from '../../../app/components/embed-docs-modal/Suggestions'; import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper'; +import HelpTooltip from '../../../components/controls/HelpTooltip'; import { enhanceMeasure } from '../../../components/measure/utils'; import '../../../components/search-navigator.css'; +import { Alert } from '../../../components/ui/Alert'; import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../../helpers/branch-like'; import { getLocalizedMetricDomain, @@ -43,7 +45,7 @@ import { } from '../../../helpers/pages'; import { fetchBranchStatus } from '../../../store/rootActions'; import { BranchLike } from '../../../types/branch-like'; -import { ComponentQualifier } from '../../../types/component'; +import { ComponentQualifier, isPortfolioLike } from '../../../types/component'; import Sidebar from '../sidebar/Sidebar'; import '../style.css'; import { @@ -286,6 +288,7 @@ export class App extends React.PureComponent<Props, State> { const { branchLike } = this.props; const { measures } = this.state; + const { canBrowseAllChildProjects, qualifier } = this.props.component; const query = parseQuery(this.props.location.query); const showFullMeasures = hasFullMeasures(branchLike); const displayOverview = hasBubbleChart(query.metric); @@ -295,13 +298,24 @@ export class App extends React.PureComponent<Props, State> { <div id="component-measures"> <Suggestions suggestions="component_measures" /> <Helmet defer={false} title={this.getHelmetTitle(query, displayOverview, metric)} /> - {measures.length > 0 ? ( <div className="layout-page"> <ScreenPositionHelper className="layout-page-side-outer"> {({ top }) => ( <div 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('component_measures.not_all_measures_are_shown')} + <HelpTooltip + className="spacer-left" + ariaLabel={translate( + 'component_measures.not_all_measures_are_shown.help' + )} + overlay={translate('component_measures.not_all_measures_are_shown.help')} + /> + </Alert> + )} <div className="layout-page-filters"> <Sidebar measures={measures} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx index c805df0da81..f628d90f0af 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.tsx @@ -20,10 +20,13 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { getMeasuresWithPeriod } from '../../../../api/measures'; +import ScreenPositionHelper from '../../../../components/common/ScreenPositionHelper'; +import { Alert } from '../../../../components/ui/Alert'; import { mockMainBranch, mockPullRequest } from '../../../../helpers/mocks/branch-like'; import { mockComponent } from '../../../../helpers/mocks/component'; import { mockIssue, mockLocation, mockRouter } from '../../../../helpers/testMocks'; import { waitAndUpdate } from '../../../../helpers/testUtils'; +import { ComponentQualifier } from '../../../../types/component'; import { App } from '../App'; jest.mock('../../../../api/metrics', () => ({ @@ -113,6 +116,47 @@ it('should refresh branch status if issues are updated', async () => { expect(fetchBranchStatus).toBeCalledWith(branchLike, 'foo'); }); +it('should render a warning message when user does not have access to all projects whithin a Portfolio', async () => { + const wrapper = shallowRender({ + component: mockComponent({ + qualifier: ComponentQualifier.Portfolio, + canBrowseAllChildProjects: false + }) + }); + await waitAndUpdate(wrapper); + expect(wrapper.find(ScreenPositionHelper).dive()).toMatchSnapshot( + 'Measure menu with warning (ScreenPositionHelper)' + ); +}); + +it.each([ + [ComponentQualifier.Portfolio, true, false], + [ComponentQualifier.Project, false, false], + [ComponentQualifier.Portfolio, false, true] +])( + 'should not render a warning message', + async ( + componentQualifier: ComponentQualifier, + canBrowseAllChildProjects: boolean, + alertIsVisible: boolean + ) => { + const wrapper = shallowRender({ + component: mockComponent({ + qualifier: componentQualifier, + canBrowseAllChildProjects + }) + }); + await waitAndUpdate(wrapper); + expect( + wrapper + .find(ScreenPositionHelper) + .dive() + .find(Alert) + .exists() + ).toBe(alertIsVisible); + } +); + function shallowRender(props: Partial<App['props']> = {}) { return shallow<App>( <App diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap index e71e4a4d989..a702f6768c7 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap @@ -53,6 +53,61 @@ exports[`should render a message when there are no measures 1`] = ` </div> `; +exports[`should render a warning message when user does not have access to all projects whithin a Portfolio: Measure menu with warning (ScreenPositionHelper) 1`] = ` +<div + className="layout-page-side-outer" +> + <div + className="layout-page-side" + style={ + Object { + "top": 0, + } + } + > + <div + className="layout-page-side-inner" + > + <Alert + className="big-spacer-top big-spacer-right" + variant="warning" + > + component_measures.not_all_measures_are_shown + <HelpTooltip + ariaLabel="component_measures.not_all_measures_are_shown.help" + className="spacer-left" + overlay="component_measures.not_all_measures_are_shown.help" + /> + </Alert> + <div + className="layout-page-filters" + > + <Sidebar + measures={ + Array [ + Object { + "leak": undefined, + "metric": Object { + "domain": "Coverage", + "id": "2", + "key": "coverage", + "name": "Coverage", + "type": "PERCENT", + }, + "value": "80.0", + }, + ] + } + selectedMetric="coverage" + showFullMeasures={true} + updateQuery={[Function]} + /> + </div> + </div> + </div> +</div> +`; + exports[`should render correctly 1`] = ` <div id="component-measures" diff --git a/server/sonar-web/src/main/js/types/types.d.ts b/server/sonar-web/src/main/js/types/types.d.ts index 3caa2e0c535..b4700e156fb 100644 --- a/server/sonar-web/src/main/js/types/types.d.ts +++ b/server/sonar-web/src/main/js/types/types.d.ts @@ -173,6 +173,7 @@ declare namespace T { description?: string; isFavorite?: boolean; isRecentlyBrowsed?: boolean; + canBrowseAllChildProjects?: boolean; key: string; match?: string; name: string; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 265842054d1..ee23dc387ed 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3280,6 +3280,8 @@ component_measures.facet_category.overall_category=Overall component_measures.facet_category.overall_category.estimated=Estimated after merge component_measures.facet_category.tests_category=Tests component_measures.bubble_chart.zoom_level=Current zoom level. Scroll on the chart to zoom or unzoom, click here to reset. +component_measures.not_all_measures_are_shown=Not all projects are included +component_measures.not_all_measures_are_shown.help=You do not have access to all projects #------------------------------------------------------------------------------ # |