]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-12721 Display Security Hotspots page on branches and pull requests
authorPhilippe Perrin <philippe.perrin@sonarsource.com>
Wed, 18 Dec 2019 15:26:25 +0000 (16:26 +0100)
committerSonarTech <sonartech@sonarsource.com>
Mon, 13 Jan 2020 19:46:30 +0000 (20:46 +0100)
server/sonar-web/src/main/js/api/security-hotspots.ts
server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsApp.tsx
server/sonar-web/src/main/js/apps/securityHotspots/__tests__/SecurityHotspotsApp-test.tsx
server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsApp-test.tsx.snap
server/sonar-web/src/main/js/apps/securityHotspots/components/HotspotSnippetContainer.tsx
server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/HotspotSnippetContainer-test.tsx
server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/HotspotSnippetContainer-test.tsx.snap

index 9971cdd6c2e2265b4a3c386cbdce47de7df594dc..316166e0f8dcf0c2d4f09b6f38bbf0a1c44f8558 100644 (file)
@@ -19,6 +19,7 @@
  */
 import { getJSON, post } from 'sonar-ui-common/helpers/request';
 import throwGlobalError from '../app/utils/throwGlobalError';
+import { BranchParameters } from '../types/branch-like';
 import {
   DetailedHotspot,
   HotspotSearchResponse,
@@ -29,11 +30,13 @@ export function setSecurityHotspotStatus(data: HotspotSetStatusRequest): Promise
   return post('/api/hotspots/change_status', data).catch(throwGlobalError);
 }
 
-export function getSecurityHotspots(data: {
-  projectKey: string;
-  p: number;
-  ps: number;
-}): Promise<HotspotSearchResponse> {
+export function getSecurityHotspots(
+  data: {
+    projectKey: string;
+    p: number;
+    ps: number;
+  } & BranchParameters
+): Promise<HotspotSearchResponse> {
   return getJSON('/api/hotspots/search', data).catch(throwGlobalError);
 }
 
index 78d3ddf7d530a0845c1e516c8a47fb5be4f0f324..768643395e2e1c34c22dd981808c3407da6c32d5 100644 (file)
@@ -20,6 +20,7 @@
 import * as React from 'react';
 import { addNoFooterPageClass, removeNoFooterPageClass } from 'sonar-ui-common/helpers/pages';
 import { getSecurityHotspots } from '../../api/security-hotspots';
+import { getBranchLikeQuery } from '../../helpers/branch-like';
 import { getStandards } from '../../helpers/security-standard';
 import { BranchLike } from '../../types/branch-like';
 import { HotspotUpdate, RawHotspot } from '../../types/security-hotspots';
@@ -68,9 +69,16 @@ export default class SecurityHotspotsApp extends React.PureComponent<Props, Stat
   }
 
   fetchInitialData() {
+    const { branchLike, component } = this.props;
+
     return Promise.all([
       getStandards(),
-      getSecurityHotspots({ projectKey: this.props.component.key, p: 1, ps: PAGE_SIZE })
+      getSecurityHotspots({
+        projectKey: component.key,
+        p: 1,
+        ps: PAGE_SIZE,
+        ...getBranchLikeQuery(branchLike)
+      })
     ])
       .then(([{ sonarsourceSecurity }, response]) => {
         if (!this.mounted) {
index 1b43fe4cfcc4ad30a73dd31a39e522f072067d2a..9e73887780fee44524def166051130585ba6e2f8 100644 (file)
@@ -22,7 +22,7 @@ import * as React from 'react';
 import { addNoFooterPageClass } from 'sonar-ui-common/helpers/pages';
 import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
 import { getSecurityHotspots } from '../../../api/security-hotspots';
-import { mockMainBranch } from '../../../helpers/mocks/branch-like';
+import { mockBranch } from '../../../helpers/mocks/branch-like';
 import { mockRawHotspot } from '../../../helpers/mocks/security-hotspots';
 import { getStandards } from '../../../helpers/security-standard';
 import { mockComponent } from '../../../helpers/testMocks';
@@ -43,6 +43,8 @@ jest.mock('../../../helpers/security-standard', () => ({
   getStandards: jest.fn()
 }));
 
+const branch = mockBranch();
+
 it('should render correctly', () => {
   expect(shallowRender()).toMatchSnapshot();
 });
@@ -62,7 +64,11 @@ it('should load data correctly', async () => {
 
   expect(addNoFooterPageClass).toBeCalled();
   expect(getStandards).toBeCalled();
-  expect(getSecurityHotspots).toBeCalled();
+  expect(getSecurityHotspots).toBeCalledWith(
+    expect.objectContaining({
+      branch: branch.name
+    })
+  );
 
   await waitAndUpdate(wrapper);
 
@@ -100,6 +106,6 @@ it('should handle hotspot update', async () => {
 
 function shallowRender(props: Partial<SecurityHotspotsApp['props']> = {}) {
   return shallow<SecurityHotspotsApp>(
-    <SecurityHotspotsApp branchLike={mockMainBranch()} component={mockComponent()} {...props} />
+    <SecurityHotspotsApp branchLike={branch} component={mockComponent()} {...props} />
   );
 }
index 56682f1ba2e02308f1f185cee8276ac0dbe86f5f..b2a09e10b46f83d2a7b48b9a353cb7707bafec5c 100644 (file)
@@ -6,8 +6,8 @@ exports[`should render correctly 1`] = `
     Object {
       "analysisDate": "2018-01-01",
       "excludedFromPurge": true,
-      "isMain": true,
-      "name": "master",
+      "isMain": false,
+      "name": "branch-6.7",
     }
   }
   hotspots={Array []}
index bc6839740c06cae19ab0c1470f1cfcbb834452a6..5974f278b7fb3d98f69f600714c0539e9a0244d0 100644 (file)
@@ -77,14 +77,17 @@ export default class HotspotSnippetContainer extends React.Component<Props, Stat
   }
 
   fetchSources() {
-    const { component, textRange } = this.props.hotspot;
+    const {
+      branchLike,
+      hotspot: { component, textRange }
+    } = this.props;
 
     const from = Math.max(1, textRange.startLine - BUFFER_LINES);
     // Add 1 to check for end-of-file:
     const to = textRange.endLine + BUFFER_LINES + 1;
 
     this.setState({ loading: true });
-    return getSources({ key: component.key, from, to })
+    return getSources({ key: component.key, from, to, ...getBranchLikeQuery(branchLike) })
       .then(sourceLines => {
         if (this.mounted) {
           const lastLine = this.checkLastLine(sourceLines, to);
index 4000d8ed8dd0041616347770176d8c14f6d6471d..622840289f8b0ee0b3992b288059c41ec04511d0 100644 (file)
@@ -22,6 +22,7 @@ import { range } from 'lodash';
 import * as React from 'react';
 import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
 import { getSources } from '../../../../api/components';
+import { mockBranch } from '../../../../helpers/mocks/branch-like';
 import { mockDetailledHotspot } from '../../../../helpers/mocks/security-hotspots';
 import { mockSourceLine } from '../../../../helpers/testMocks';
 import HotspotSnippetContainer from '../HotspotSnippetContainer';
@@ -31,6 +32,8 @@ jest.mock('../../../../api/components', () => ({
   getSources: jest.fn().mockResolvedValue([])
 }));
 
+const branch = mockBranch();
+
 it('should render correctly', () => {
   expect(shallowRender()).toMatchSnapshot();
 });
@@ -48,7 +51,11 @@ it('should load sources on mount', async () => {
 
   await waitAndUpdate(wrapper);
 
-  expect(getSources).toBeCalled();
+  expect(getSources).toBeCalledWith(
+    expect.objectContaining({
+      branch: branch.name
+    })
+  );
   expect(wrapper.state().lastLine).toBeUndefined();
   expect(wrapper.state().sourceLines).toHaveLength(12);
 });
@@ -97,6 +104,11 @@ describe('Expansion', () => {
 
     await waitAndUpdate(wrapper);
 
+    expect(getSources).toBeCalledWith(
+      expect.objectContaining({
+        branch: branch.name
+      })
+    );
     expect(wrapper.state().sourceLines).toHaveLength(16);
   });
 
@@ -181,6 +193,6 @@ it('should handle symbol click', () => {
 
 function shallowRender(props?: Partial<HotspotSnippetContainer['props']>) {
   return shallow<HotspotSnippetContainer>(
-    <HotspotSnippetContainer hotspot={mockDetailledHotspot()} {...props} />
+    <HotspotSnippetContainer branchLike={branch} hotspot={mockDetailledHotspot()} {...props} />
   );
 }
index 1d94193a839d70943eca30dd72b696a4a91b8793..0d5e1ad75b43bfb6f16f2c00f8c5b124bd31a245 100644 (file)
@@ -2,6 +2,14 @@
 
 exports[`should render correctly 1`] = `
 <HotspotSnippetContainerRenderer
+  branchLike={
+    Object {
+      "analysisDate": "2018-01-01",
+      "excludedFromPurge": true,
+      "isMain": false,
+      "name": "branch-6.7",
+    }
+  }
   highlightedSymbols={Array []}
   hotspot={
     Object {