From dc18e426d0b215ecc617d713affda19fb6df310b Mon Sep 17 00:00:00 2001 From: Mathieu Suen Date: Thu, 14 Jan 2021 11:30:48 +0100 Subject: [PATCH] SONAR-13376 Reflect QG status when hotspot is update. --- .../security-hotspots/SecurityHotspotsApp.tsx | 18 +++++++++++++-- .../__tests__/SecurityHotspotsApp-test.tsx | 23 ++++++++++++++++++- 2 files changed, 38 insertions(+), 3 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 f91c3d44f91..d9cb36b1760 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 @@ -21,6 +21,7 @@ import { Location } from 'history'; import * as key from 'keymaster'; import { flatMap, range } from 'lodash'; import * as React from 'react'; +import { connect } from 'react-redux'; import { addSideBarClass, removeSideBarClass } from 'sonar-ui-common/helpers/pages'; import { getMeasures } from '../../api/measures'; import { getSecurityHotspotList, getSecurityHotspots } from '../../api/security-hotspots'; @@ -30,6 +31,7 @@ import { getLeakValue } from '../../components/measure/utils'; import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../helpers/branch-like'; import { getStandards } from '../../helpers/security-standard'; import { isLoggedIn } from '../../helpers/users'; +import { fetchBranchStatus } from '../../store/rootActions'; import { BranchLike } from '../../types/branch-like'; import { SecurityStandard, Standards } from '../../types/security'; import { @@ -45,8 +47,11 @@ import { SECURITY_STANDARDS } from './utils'; const HOTSPOT_KEYMASTER_SCOPE = 'hotspots-list'; const PAGE_SIZE = 500; +interface DispatchProps { + fetchBranchStatus: (branchLike: BranchLike, projectKey: string) => void; +} -interface Props { +interface OwnProps { branchLike?: BranchLike; currentUser: T.CurrentUser; component: T.Component; @@ -54,6 +59,8 @@ interface Props { router: Router; } +type Props = DispatchProps & OwnProps; + interface State { filterByCategory?: { standard: SecurityStandard; category: string }; filters: HotspotFilters; @@ -325,8 +332,13 @@ export class SecurityHotspotsApp extends React.PureComponent { handleHotspotUpdate = (hotspotKey: string) => { const { hotspots, hotspotsPageIndex } = this.state; + const { branchLike, component } = this.props; const index = hotspots.findIndex(h => h.key === hotspotKey); + if (isPullRequest(branchLike)) { + this.props.fetchBranchStatus(branchLike, component.key); + } + return Promise.all( range(hotspotsPageIndex).map(p => this.fetchSecurityHotspots(p + 1 /* pages are 1-indexed */)) ) @@ -424,4 +436,6 @@ export class SecurityHotspotsApp extends React.PureComponent { } } -export default withCurrentUser(SecurityHotspotsApp); +const mapDispatchToProps = { fetchBranchStatus }; + +export default withCurrentUser(connect(null, mapDispatchToProps)(SecurityHotspotsApp)); diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx index 5ba2ae3c633..bf65636abc6 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx @@ -233,12 +233,16 @@ it('should handle loading more', async () => { it('should handle hotspot update', async () => { const key = 'hotspotKey'; const hotspots = [mockRawHotspot(), mockRawHotspot({ key })]; + const fetchBranchStatusMock = jest.fn(); + const branchLike = mockPullRequest(); + const componentKey = 'test'; + (getSecurityHotspots as jest.Mock).mockResolvedValueOnce({ hotspots, paging: { pageIndex: 1, total: 1252 } }); - const wrapper = shallowRender(); + let wrapper = shallowRender(); await waitAndUpdate(wrapper); wrapper.setState({ hotspotsPageIndex: 2 }); @@ -272,6 +276,22 @@ it('should handle hotspot update', async () => { ).toBe(selectedHotspotIndex); expect(getMeasures).toBeCalled(); + + (getSecurityHotspots as jest.Mock).mockResolvedValueOnce({ + hotspots, + paging: { pageIndex: 1, total: 1252 } + }); + + wrapper = shallowRender({ + branchLike, + fetchBranchStatus: fetchBranchStatusMock, + component: mockComponent({ key: componentKey }) + }); + await wrapper + .find(SecurityHotspotsAppRenderer) + .props() + .onUpdateHotspot(key); + expect(fetchBranchStatusMock).toBeCalledWith(branchLike, componentKey); }); it('should handle status filter change', async () => { @@ -369,6 +389,7 @@ describe('keyboard navigation', () => { function shallowRender(props: Partial = {}) { return shallow(