diff options
author | Pascal Mugnier <pascal.mugnier@sonarsource.com> | 2018-10-22 14:40:40 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-10-25 20:21:01 +0200 |
commit | f068d7b2430a1cd2b05da22b6fd885231d3baec5 (patch) | |
tree | 656613bf72255a25b5ffd43f195c359436b359c2 | |
parent | 3c6746a4fb3f375e81fbe44d4994206cd73de48b (diff) | |
download | sonarqube-f068d7b2430a1cd2b05da22b6fd885231d3baec5.tar.gz sonarqube-f068d7b2430a1cd2b05da22b6fd885231d3baec5.zip |
SONAR-11369 Update UI using WS mock
7 files changed, 716 insertions, 45 deletions
diff --git a/server/sonar-web/src/main/js/api/security-reports.ts b/server/sonar-web/src/main/js/api/security-reports.ts index 2747ea7536f..74006076097 100644 --- a/server/sonar-web/src/main/js/api/security-reports.ts +++ b/server/sonar-web/src/main/js/api/security-reports.ts @@ -27,5 +27,15 @@ export function getSecurityHotspots(data: { includeDistribution?: boolean; branch?: string; }): Promise<{ categories: Array<SecurityHotspot> }> { - return getJSON('/api/security_reports/show', data).catch(throwGlobalError); + return getJSON('/api/security_reports/show', data) + .then(data => { + /* MOCK, must be removed after backend implementation */ + data.categories = data.categories.map((v: SecurityHotspot, index: number) => { + v.activeRules = index; + v.totalRules = 200; + return v; + }); + return data; + }) + .catch(throwGlobalError); } diff --git a/server/sonar-web/src/main/js/app/types.ts b/server/sonar-web/src/main/js/app/types.ts index 658d67ebed8..20827b40e4e 100644 --- a/server/sonar-web/src/main/js/app/types.ts +++ b/server/sonar-web/src/main/js/app/types.ts @@ -298,11 +298,13 @@ export function isSameHomePage(a: HomePage, b: HomePage) { } export interface SecurityHotspot { + activeRules: number; category?: string; cwe?: string; distribution?: Array<SecurityHotspot>; openSecurityHotspots: number; toReviewSecurityHotspots: number; + totalRules: number; vulnerabilities: number; vulnerabilityRating?: number; wontFixSecurityHotspots: number; diff --git a/server/sonar-web/src/main/js/apps/securityReports/components/VulnerabilityList.tsx b/server/sonar-web/src/main/js/apps/securityReports/components/VulnerabilityList.tsx index d3cbb28a78d..e566a2405fb 100755 --- a/server/sonar-web/src/main/js/apps/securityReports/components/VulnerabilityList.tsx +++ b/server/sonar-web/src/main/js/apps/securityReports/components/VulnerabilityList.tsx @@ -41,7 +41,7 @@ import { getRatingTooltip } from '../../../helpers/measures'; interface Props { branchLike?: BranchLike; component: Component; - findings: Array<SecurityHotspot>; + findings: SecurityHotspot[]; showCWE: boolean; type: 'owaspTop10' | 'sansTop25' | 'cwe'; } @@ -140,6 +140,7 @@ export default class VulnerabilityList extends React.PureComponent<Props, State> : null; const title = getRatingTooltip('security_rating', finding.vulnerabilityRating || 1); + const hasActiveRules = finding.activeRules > 0; return ( <React.Fragment key={finding.category || finding.cwe}> <tr> @@ -147,60 +148,72 @@ export default class VulnerabilityList extends React.PureComponent<Props, State> {this.getName(finding, isCWE ? 'cwe' : type)} </td> <td className="text-right"> - <div className="display-inline-flex-center"> - <Link - to={getComponentIssuesUrl(component.key, { - ...params, - types: IssueType.Vulnerability, - resolved: 'false' - })}> - {finding.vulnerabilities} - </Link> - <Tooltip overlay={title}> + {!hasActiveRules && '-'} + {hasActiveRules && ( + <div className="display-inline-flex-center"> <Link - className="link-no-underline spacer-left" to={getComponentIssuesUrl(component.key, { ...params, types: IssueType.Vulnerability, resolved: 'false' })}> - <Rating value={finding.vulnerabilityRating || 1} /> + {finding.vulnerabilities} </Link> - </Tooltip> - </div> + <Tooltip overlay={title}> + <Link + className="link-no-underline spacer-left" + to={getComponentIssuesUrl(component.key, { + ...params, + types: IssueType.Vulnerability, + resolved: 'false' + })}> + <Rating value={finding.vulnerabilityRating || 1} /> + </Link> + </Tooltip> + </div> + )} </td> <td className="text-right security-column-separator"> - <Link - to={getComponentIssuesUrl(component.key, { - ...params, - types: IssueType.Hotspot, - resolved: 'false', - statuses: 'OPEN,REOPENED' - })}> - {finding.openSecurityHotspots} - </Link> + {!hasActiveRules && '-'} + {hasActiveRules && ( + <Link + to={getComponentIssuesUrl(component.key, { + ...params, + types: IssueType.Hotspot, + resolved: 'false', + statuses: 'OPEN,REOPENED' + })}> + {finding.openSecurityHotspots} + </Link> + )} </td> <td className="text-right"> - <Link - to={getComponentIssuesUrl(component.key, { - ...params, - types: IssueType.Hotspot, - resolutions: 'FIXED', - statuses: 'RESOLVED' - })}> - {finding.toReviewSecurityHotspots} - </Link> + {!hasActiveRules && '-'} + {hasActiveRules && ( + <Link + to={getComponentIssuesUrl(component.key, { + ...params, + types: IssueType.Hotspot, + resolutions: 'FIXED', + statuses: 'RESOLVED' + })}> + {finding.toReviewSecurityHotspots} + </Link> + )} </td> <td className="text-right"> - <Link - to={getComponentIssuesUrl(component.key, { - ...params, - types: IssueType.Hotspot, - resolutions: 'WONTFIX', - statuses: 'RESOLVED' - })}> - {finding.wontFixSecurityHotspots} - </Link> + {!hasActiveRules && '-'} + {hasActiveRules && ( + <Link + to={getComponentIssuesUrl(component.key, { + ...params, + types: IssueType.Hotspot, + resolutions: 'WONTFIX', + statuses: 'RESOLVED' + })}> + {finding.wontFixSecurityHotspots} + </Link> + )} </td> </tr> {subFindings} diff --git a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/App-test.tsx index f2ed7089863..cdc43e9abdf 100644 --- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/App-test.tsx +++ b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/App-test.tsx @@ -41,6 +41,8 @@ jest.mock('../../../../api/security-reports', () => ({ return Promise.resolve({ categories: [ { + activeRules: 1, + totalRules: 1, category: 'a1', vulnerabilities: 2, vulnerabiliyRating: 5, @@ -50,6 +52,8 @@ jest.mock('../../../../api/security-reports', () => ({ distribution }, { + activeRules: 1, + totalRules: 1, category: 'a2', vulnerabilities: 3, vulnerabiliyRating: 3, diff --git a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/VulnerabilityList-test.tsx b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/VulnerabilityList-test.tsx index 32f1efeaa98..06f6ed58ae1 100644 --- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/VulnerabilityList-test.tsx +++ b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/VulnerabilityList-test.tsx @@ -33,6 +33,8 @@ jest.mock('../../../../helpers/standards.json', () => ({ const component = { key: 'foo', name: 'Foo', qualifier: 'TRK' } as Component; const findings = [ { + activeRules: 1, + totalRules: 1, category: 'a1', vulnerabilities: 2, vulnerabilityRating: 5, @@ -41,6 +43,8 @@ const findings = [ wontFixSecurityHotspots: 0, distribution: [ { + activeRules: 1, + totalRules: 1, cwe: '42', vulnerabilities: 1, vulnerabilityRating: 1, @@ -51,6 +55,52 @@ const findings = [ ] }, { + activeRules: 1, + totalRules: 2, + category: 'a2', + vulnerabilities: 2, + vulnerabilityRating: 5, + toReviewSecurityHotspots: 2, + openSecurityHotspots: 10, + wontFixSecurityHotspots: 0, + distribution: [ + { + activeRules: 1, + totalRules: 1, + cwe: '42', + vulnerabilities: 1, + vulnerabilityRating: 1, + toReviewSecurityHotspots: 2, + openSecurityHotspots: 10, + wontFixSecurityHotspots: 0 + } + ] + }, + { + activeRules: 0, + totalRules: 1, + category: 'a3', + vulnerabilities: 2, + vulnerabilityRating: 5, + toReviewSecurityHotspots: 2, + openSecurityHotspots: 10, + wontFixSecurityHotspots: 0, + distribution: [ + { + activeRules: 1, + totalRules: 1, + cwe: '42', + vulnerabilities: 1, + vulnerabilityRating: 1, + toReviewSecurityHotspots: 2, + openSecurityHotspots: 10, + wontFixSecurityHotspots: 0 + } + ] + }, + { + activeRules: 1, + totalRules: 1, category: 'unknown', vulnerabilities: 3, vulnerabilityRating: 3, @@ -69,7 +119,7 @@ it('renders', () => { type="owaspTop10" /> ); - expect(wrapper.find('tr').length).toBe(4); + expect(wrapper.find('tr').length).toBe(6); expect(wrapper).toMatchSnapshot(); }); @@ -77,6 +127,6 @@ it('renders with cwe', () => { const wrapper = shallow( <VulnerabilityList component={component} findings={findings} showCWE={true} type="owaspTop10" /> ); - expect(wrapper.find('tr').length).toBe(5); + expect(wrapper.find('tr').length).toBe(9); expect(wrapper).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap index abab05f553e..f61e0fc1a5d 100644 --- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap @@ -215,6 +215,7 @@ exports[`handle checkbox for cwe display 2`] = ` findings={ Array [ Object { + "activeRules": 1, "category": "a1", "distribution": Array [ Object { @@ -236,14 +237,17 @@ exports[`handle checkbox for cwe display 2`] = ` ], "openSecurityHotspots": 10, "toReviewSecurityHotspots": 2, + "totalRules": 1, "vulnerabilities": 2, "vulnerabiliyRating": 5, "wontFixSecurityHotspots": 0, }, Object { + "activeRules": 1, "category": "a2", "openSecurityHotspots": 100, "toReviewSecurityHotspots": 8, + "totalRules": 1, "vulnerabilities": 3, "vulnerabiliyRating": 3, "wontFixSecurityHotspots": 10, diff --git a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/VulnerabilityList-test.tsx.snap b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/VulnerabilityList-test.tsx.snap index d296ead10a7..5c19bde0e7c 100644 --- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/VulnerabilityList-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/VulnerabilityList-test.tsx.snap @@ -193,6 +193,167 @@ exports[`renders 1`] = ` </tr> </React.Fragment> <React.Fragment + key="a2" + > + <tr> + <td + className="" + > + <React.Fragment> + A2 + </React.Fragment> + </td> + <td + className="text-right" + > + <div + className="display-inline-flex-center" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + 2 + </Link> + <Tooltip + overlay="metric.security_rating.tooltip.E" + > + <Link + className="link-no-underline spacer-left" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + <Rating + value={5} + /> + </Link> + </Tooltip> + </div> + </td> + <td + className="text-right security-column-separator" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "statuses": "OPEN,REOPENED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 10 + </Link> + </td> + <td + className="text-right" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolutions": "FIXED", + "statuses": "RESOLVED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 2 + </Link> + </td> + <td + className="text-right" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolutions": "WONTFIX", + "statuses": "RESOLVED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 0 + </Link> + </td> + </tr> + </React.Fragment> + <React.Fragment + key="a3" + > + <tr> + <td + className="" + > + <React.Fragment> + A3 + </React.Fragment> + </td> + <td + className="text-right" + > + - + </td> + <td + className="text-right security-column-separator" + > + - + </td> + <td + className="text-right" + > + - + </td> + <td + className="text-right" + > + - + </td> + </tr> + </React.Fragment> + <React.Fragment key="unknown" > <tr> @@ -651,6 +812,433 @@ exports[`renders with cwe 1`] = ` </React.Fragment> </React.Fragment> <React.Fragment + key="a2" + > + <tr> + <td + className="" + > + <React.Fragment> + A2 + </React.Fragment> + </td> + <td + className="text-right" + > + <div + className="display-inline-flex-center" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + 2 + </Link> + <Tooltip + overlay="metric.security_rating.tooltip.E" + > + <Link + className="link-no-underline spacer-left" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + <Rating + value={5} + /> + </Link> + </Tooltip> + </div> + </td> + <td + className="text-right security-column-separator" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "statuses": "OPEN,REOPENED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 10 + </Link> + </td> + <td + className="text-right" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolutions": "FIXED", + "statuses": "RESOLVED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 2 + </Link> + </td> + <td + className="text-right" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "id": "foo", + "owaspTop10": "a2", + "resolutions": "WONTFIX", + "statuses": "RESOLVED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 0 + </Link> + </td> + </tr> + <React.Fragment + key="42" + > + <tr> + <td + className="cwe-title-cell" + > + <React.Fragment> + CWE-42 + </React.Fragment> + </td> + <td + className="text-right" + > + <div + className="display-inline-flex-center" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + 1 + </Link> + <Tooltip + overlay="metric.security_rating.tooltip.A" + > + <Link + className="link-no-underline spacer-left" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + <Rating + value={1} + /> + </Link> + </Tooltip> + </div> + </td> + <td + className="text-right security-column-separator" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a2", + "resolved": "false", + "statuses": "OPEN,REOPENED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 10 + </Link> + </td> + <td + className="text-right" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a2", + "resolutions": "FIXED", + "statuses": "RESOLVED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 2 + </Link> + </td> + <td + className="text-right" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a2", + "resolutions": "WONTFIX", + "statuses": "RESOLVED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 0 + </Link> + </td> + </tr> + </React.Fragment> + </React.Fragment> + <React.Fragment + key="a3" + > + <tr> + <td + className="" + > + <React.Fragment> + A3 + </React.Fragment> + </td> + <td + className="text-right" + > + - + </td> + <td + className="text-right security-column-separator" + > + - + </td> + <td + className="text-right" + > + - + </td> + <td + className="text-right" + > + - + </td> + </tr> + <React.Fragment + key="42" + > + <tr> + <td + className="cwe-title-cell" + > + <React.Fragment> + CWE-42 + </React.Fragment> + </td> + <td + className="text-right" + > + <div + className="display-inline-flex-center" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a3", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + 1 + </Link> + <Tooltip + overlay="metric.security_rating.tooltip.A" + > + <Link + className="link-no-underline spacer-left" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a3", + "resolved": "false", + "types": "VULNERABILITY", + }, + } + } + > + <Rating + value={1} + /> + </Link> + </Tooltip> + </div> + </td> + <td + className="text-right security-column-separator" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a3", + "resolved": "false", + "statuses": "OPEN,REOPENED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 10 + </Link> + </td> + <td + className="text-right" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a3", + "resolutions": "FIXED", + "statuses": "RESOLVED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 2 + </Link> + </td> + <td + className="text-right" + > + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/issues", + "query": Object { + "cwe": "42", + "id": "foo", + "owaspTop10": "a3", + "resolutions": "WONTFIX", + "statuses": "RESOLVED", + "types": "SECURITY_HOTSPOT", + }, + } + } + > + 0 + </Link> + </td> + </tr> + </React.Fragment> + </React.Fragment> + <React.Fragment key="unknown" > <tr> |