From 42f203d478ffff0c9210340c127bab54db72754d Mon Sep 17 00:00:00 2001 From: Philippe Perrin Date: Tue, 18 Feb 2020 17:30:25 +0100 Subject: [PATCH] SONAR-12718 User can get a permalink to the hotspot --- .../security-hotspots/SecurityHotspotsApp.tsx | 3 +- .../SecurityHotspotsAppRenderer.tsx | 7 +- .../SecurityHotspotsAppRenderer-test.tsx | 3 +- .../SecurityHotspotsApp-test.tsx.snap | 24 +++- .../SecurityHotspotsAppRenderer-test.tsx.snap | 47 ++++++- .../components/FilterBar.tsx | 6 +- .../components/HotspotViewer.tsx | 8 +- .../components/HotspotViewerRenderer.tsx | 22 +++- .../components/__tests__/FilterBar-test.tsx | 14 +- .../__tests__/HotspotViewer-test.tsx | 2 + .../__tests__/HotspotViewerRenderer-test.tsx | 5 +- .../__snapshots__/HotspotViewer-test.tsx.snap | 46 +++++++ .../HotspotViewerRenderer-test.tsx.snap | 120 ++++++++++++++++-- .../src/main/js/helpers/testMocks.ts | 3 +- .../resources/org/sonar/l10n/core.properties | 1 + 15 files changed, 279 insertions(+), 32 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx index c2a81755b4d..5367fb99884 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx @@ -30,7 +30,6 @@ import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../helpe import { getStandards } from '../../helpers/security-standard'; import { isLoggedIn } from '../../helpers/users'; import { BranchLike } from '../../types/branch-like'; -import { ComponentQualifier } from '../../types/component'; import { HotspotFilters, HotspotResolution, @@ -330,11 +329,11 @@ export class SecurityHotspotsApp extends React.PureComponent { return ( 0)} loading={loading} loadingMeasure={loadingMeasure} diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx index 51b2558f12b..c9d8b687f84 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx @@ -35,11 +35,11 @@ import './styles.css'; export interface SecurityHotspotsAppRendererProps { branchLike?: BranchLike; + component: T.Component; filters: HotspotFilters; hotspots: RawHotspot[]; hotspotsReviewedMeasure?: string; hotspotsTotal?: number; - isProject: boolean; isStaticListOfHotspots: boolean; loading: boolean; loadingMeasure: boolean; @@ -56,10 +56,10 @@ export interface SecurityHotspotsAppRendererProps { export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRendererProps) { const { branchLike, + component, hotspots, hotspotsReviewedMeasure, hotspotsTotal, - isProject, isStaticListOfHotspots, loading, loadingMeasure, @@ -72,9 +72,9 @@ export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRe return (
{ function shallowRender(props: Partial = {}) { return shallow( diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx index 37ba943c2bc..2a23816f1ba 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx @@ -26,6 +26,7 @@ import HotspotViewerRenderer from './HotspotViewerRenderer'; interface Props { branchLike?: BranchLike; + component: T.Component; hotspotKey: string; onUpdateHotspot: (hotspotKey: string) => Promise; securityCategories: T.StandardSecurityCategories; @@ -55,7 +56,7 @@ export default class HotspotViewer extends React.PureComponent { this.mounted = false; } - fetchHotspot() { + fetchHotspot = () => { this.setState({ loading: true }); return getSecurityHotspotDetails(this.props.hotspotKey) .then(hotspot => { @@ -65,7 +66,7 @@ export default class HotspotViewer extends React.PureComponent { return hotspot; }) .catch(() => this.mounted && this.setState({ loading: false })); - } + }; handleHotspotUpdate = () => { return this.fetchHotspot().then((hotspot?: Hotspot) => { @@ -76,12 +77,13 @@ export default class HotspotViewer extends React.PureComponent { }; render() { - const { branchLike, securityCategories } = this.props; + const { branchLike, component, securityCategories } = this.props; const { hotspot, loading } = this.state; return ( Promise; @@ -36,7 +42,15 @@ export interface HotspotViewerRendererProps { } export default function HotspotViewerRenderer(props: HotspotViewerRendererProps) { - const { branchLike, hotspot, loading, securityCategories } = props; + const { branchLike, component, hotspot, loading, securityCategories } = props; + + const permalink = getPathUrlAsString( + getComponentSecurityHotspotsUrl(component.key, { + ...getBranchLikeQuery(branchLike), + hotspots: hotspot?.key + }), + false + ); return ( @@ -44,7 +58,11 @@ export default function HotspotViewerRenderer(props: HotspotViewerRendererProps)
-

{hotspot.message}

+ {hotspot.message} + + + {translate('hotspots.get_permalink')} +
{translate('category')}: diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx index 31dce745ea4..da016ade85b 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/FilterBar-test.tsx @@ -21,7 +21,8 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import RadioToggle from 'sonar-ui-common/components/controls/RadioToggle'; import Select from 'sonar-ui-common/components/controls/Select'; -import { mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks'; +import { mockComponent, mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks'; +import { ComponentQualifier } from '../../../../types/component'; import { HotspotStatusFilter } from '../../../../types/security-hotspots'; import { AssigneeFilterOption, FilterBar, FilterBarProps } from '../FilterBar'; @@ -32,9 +33,12 @@ it('should render correctly', () => { expect(shallowRender({ hotspotsReviewedMeasure: '23.30' })).toMatchSnapshot( 'with hotspots reviewed measure' ); - expect(shallowRender({ currentUser: mockLoggedInUser(), isProject: false })).toMatchSnapshot( - 'non-project' - ); + expect( + shallowRender({ + currentUser: mockLoggedInUser(), + component: mockComponent({ qualifier: ComponentQualifier.Application }) + }) + ).toMatchSnapshot('non-project'); }); it('should render correctly when the list of hotspot is static', () => { @@ -101,13 +105,13 @@ it('should trigger onChange for leak period', () => { function shallowRender(props: Partial = {}) { return shallow( { function shallowRender(props?: Partial) { return shallow( { @@ -46,6 +47,8 @@ it('should render correctly', () => { function shallowRender(props?: Partial) { return shallow( -

+ '3' is a magic number. -

+ + + + + hotspots.get_permalink + +
-

+ '3' is a magic number. -

+ + + + + hotspots.get_permalink + +
-

+ '3' is a magic number. -

+ + + + + hotspots.get_permalink + +
-

+ '3' is a magic number. -

+ + + + + hotspots.get_permalink + +
-

+ '3' is a magic number. -

+ + + + + hotspots.get_permalink + +
= {}): T.AlmApplication { return { @@ -277,7 +278,7 @@ export function mockComponent(overrides: Partial = {}): T.Component key: 'my-project', name: 'MyProject', organization: 'foo', - qualifier: 'TRK', + qualifier: ComponentQualifier.Project, qualityGate: { isDefault: true, key: '30', name: 'Sonar way' }, qualityProfiles: [ { 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 f4c01c35339..f19013aa7ac 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -685,6 +685,7 @@ hotspots.status_option.FIXED=Fixed hotspots.status_option.FIXED.description=The code has been modified to follow recommended secure coding practices. hotspots.status_option.SAFE=Safe hotspots.status_option.SAFE.description=The code is not at risk and doesn't need to be modified. +hotspots.get_permalink=Get Permalink hotspot.filters.title=Filters hotspot.filters.assignee.assigned_to_me=Assigned to me -- 2.39.5