aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWouter Admiraal <wouter.admiraal@sonarsource.com>2019-04-30 09:21:47 +0200
committersonartech <sonartech@sonarsource.com>2019-05-07 09:54:29 +0200
commit444b67e5ffe6dc914d40ad1b157cb72aaa591643 (patch)
tree94751adede0868698246a801e3833f8997aff397
parentecee829049b997c943b8c0f9060d940d1d88614c (diff)
downloadsonarqube-444b67e5ffe6dc914d40ad1b157cb72aaa591643.tar.gz
sonarqube-444b67e5ffe6dc914d40ad1b157cb72aaa591643.zip
SONAR-11970 Remove security report code from sonar-web
-rw-r--r--server/sonar-web/src/main/js/api/security-reports.ts30
-rw-r--r--server/sonar-web/src/main/js/app/types.d.ts13
-rw-r--r--server/sonar-web/src/main/js/app/utils/startReactApp.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx20
-rw-r--r--server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx1
-rwxr-xr-xserver/sonar-web/src/main/js/apps/securityReports/components/App.tsx195
-rwxr-xr-xserver/sonar-web/src/main/js/apps/securityReports/components/VulnerabilityList.tsx351
-rw-r--r--server/sonar-web/src/main/js/apps/securityReports/components/__tests__/App-test.tsx212
-rw-r--r--server/sonar-web/src/main/js/apps/securityReports/components/__tests__/VulnerabilityList-test.tsx134
-rw-r--r--server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap697
-rw-r--r--server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/VulnerabilityList-test.tsx.snap1264
-rw-r--r--server/sonar-web/src/main/js/apps/securityReports/style.css38
-rwxr-xr-xserver/sonar-web/src/main/js/apps/securityReports/utils.ts76
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/security-standard-test.ts123
-rw-r--r--server/sonar-web/src/main/js/helpers/security-standard.ts52
15 files changed, 186 insertions, 3024 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
deleted file mode 100644
index d709b33ca7e..00000000000
--- a/server/sonar-web/src/main/js/api/security-reports.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { getJSON } from '../helpers/request';
-import throwGlobalError from '../app/utils/throwGlobalError';
-
-export function getSecurityHotspots(data: {
- project: string;
- standard: T.StandardType;
- includeDistribution?: boolean;
- branch?: string;
-}): Promise<{ categories: T.SecurityHotspot[] }> {
- return getJSON('/api/security_reports/show', data).catch(throwGlobalError);
-}
diff --git a/server/sonar-web/src/main/js/app/types.d.ts b/server/sonar-web/src/main/js/app/types.d.ts
index d97e54174f3..5ec635aab23 100644
--- a/server/sonar-web/src/main/js/app/types.d.ts
+++ b/server/sonar-web/src/main/js/app/types.d.ts
@@ -331,19 +331,6 @@ declare namespace T {
name: string;
}
- export interface SecurityHotspot {
- activeRules: number;
- category?: string;
- cwe?: string;
- distribution?: Array<SecurityHotspot>;
- openSecurityHotspots: number;
- toReviewSecurityHotspots: number;
- totalRules: number;
- vulnerabilities: number;
- vulnerabilityRating?: number;
- wontFixSecurityHotspots: number;
- }
-
export interface Issue {
actions: string[];
assignee?: string;
diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
index 776fe74d0ce..64d954aed09 100644
--- a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
+++ b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
@@ -230,10 +230,6 @@ export default function startReactApp(
)}
/>
<Route path="project/issues" component={Issues} />
- <Route
- path="project/security_reports/:type"
- component={lazyLoad(() => import('../../apps/securityReports/components/App'))}
- />
<RouteWithChildRoutes
path="project/quality_gate"
childRoutes={projectQualityGateRoutes}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx
index 46482c38c93..51dde5811c3 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx
@@ -19,23 +19,23 @@
*/
import * as React from 'react';
import { sortBy, without, omit } from 'lodash';
-import { Query, STANDARDS, formatFacetStat, Facet } from '../utils';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
import FacetBox from '../../../components/facet/FacetBox';
import FacetHeader from '../../../components/facet/FacetHeader';
-import { translate } from '../../../helpers/l10n';
-import FacetItemsList from '../../../components/facet/FacetItemsList';
import FacetItem from '../../../components/facet/FacetItem';
+import FacetItemsList from '../../../components/facet/FacetItemsList';
+import ListStyleFacet from '../../../components/facet/ListStyleFacet';
+import MultipleSelectionHint from '../../../components/facet/MultipleSelectionHint';
+import { translate } from '../../../helpers/l10n';
+import { highlightTerm } from '../../../helpers/search';
import {
+ getStandards,
+ renderCWECategory,
renderOwaspTop10Category,
renderSansTop25Category,
- renderCWECategory,
renderSonarSourceSecurityCategory
-} from '../../securityReports/utils';
-import DeferredSpinner from '../../../components/common/DeferredSpinner';
-import ListStyleFacet from '../../../components/facet/ListStyleFacet';
-import MultipleSelectionHint from '../../../components/facet/MultipleSelectionHint';
-import { highlightTerm } from '../../../helpers/search';
-import { getStandards } from '../../../helpers/security-standard';
+} from '../../../helpers/security-standard';
+import { Query, STANDARDS, formatFacetStat, Facet } from '../utils';
interface Props {
cwe: string[];
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx
index 487b2d43349..0140d9d8c87 100644
--- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx
@@ -25,6 +25,7 @@ import { Query } from '../../utils';
import { getStandards } from '../../../../helpers/security-standard';
jest.mock('../../../../helpers/security-standard', () => ({
+ ...require.requireActual('../../../../helpers/security-standard'),
getStandards: jest.fn().mockResolvedValue({
owaspTop10: {
a1: {
diff --git a/server/sonar-web/src/main/js/apps/securityReports/components/App.tsx b/server/sonar-web/src/main/js/apps/securityReports/components/App.tsx
deleted file mode 100755
index 37c049a0c86..00000000000
--- a/server/sonar-web/src/main/js/apps/securityReports/components/App.tsx
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import Helmet from 'react-helmet';
-import { Link } from 'react-router';
-import VulnerabilityList from './VulnerabilityList';
-import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget';
-import { Alert } from '../../../components/ui/Alert';
-import Checkbox from '../../../components/controls/Checkbox';
-import DeferredSpinner from '../../../components/common/DeferredSpinner';
-import DocTooltip from '../../../components/docs/DocTooltip';
-import NotFound from '../../../app/components/NotFound';
-import Suggestions from '../../../app/components/embed-docs-modal/Suggestions';
-import { withRouter, Location, Router } from '../../../components/hoc/withRouter';
-import { translate } from '../../../helpers/l10n';
-import { isLongLivingBranch } from '../../../helpers/branches';
-import { getSecurityHotspots } from '../../../api/security-reports';
-import { getType } from '../utils';
-import '../style.css';
-
-interface Props {
- branchLike?: T.BranchLike;
- component: T.Component;
- location: Pick<Location, 'pathname' | 'query'>;
- params: { type: string };
- router: Pick<Router, 'push'>;
-}
-
-interface State {
- loading: boolean;
- findings: T.SecurityHotspot[];
- hasVulnerabilities: boolean;
- type: T.StandardType;
- showCWE: boolean;
-}
-
-export class App extends React.PureComponent<Props, State> {
- mounted = false;
-
- constructor(props: Props) {
- super(props);
- this.state = {
- loading: false,
- findings: [],
- hasVulnerabilities: false,
- type: getType(props.params.type),
- showCWE: props.location.query.showCWE === 'true'
- };
- }
-
- componentDidMount() {
- this.mounted = true;
- this.fetchSecurityHotspots();
- }
-
- componentWillReceiveProps(newProps: Props) {
- if (newProps.location.pathname !== this.props.location.pathname) {
- const showCWE = newProps.location.query.showCWE === 'true';
- const type = getType(newProps.params.type);
- this.setState({ type, showCWE }, this.fetchSecurityHotspots);
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- fetchSecurityHotspots = () => {
- const { branchLike, component } = this.props;
- this.setState({ loading: true });
- getSecurityHotspots({
- project: component.key,
- standard: this.state.type,
- includeDistribution: this.state.showCWE,
- branch: isLongLivingBranch(branchLike) ? branchLike.name : undefined
- })
- .then(results => {
- if (this.mounted) {
- const hasVulnerabilities = results.categories.some(
- item =>
- item.vulnerabilities +
- item.openSecurityHotspots +
- item.toReviewSecurityHotspots +
- item.wontFixSecurityHotspots >
- 0
- );
- this.setState({ hasVulnerabilities, findings: results.categories, loading: false });
- }
- })
- .catch(() => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
- });
- };
-
- handleCheck = (checked: boolean) => {
- this.props.router.push({
- pathname: this.props.location.pathname,
- query: { id: this.props.component.key, showCWE: checked }
- });
- this.setState({ showCWE: checked }, this.fetchSecurityHotspots);
- };
-
- renderAdditionalRulesMessage = () => {
- const { findings } = this.state;
- if (findings.length === 0) {
- return null;
- }
-
- const total = findings.map(f => f.totalRules).reduce((sum, count) => sum + count);
- const active = findings.map(f => f.activeRules).reduce((sum, count) => sum + count);
- if (active >= total) {
- return null;
- }
-
- return (
- <Alert className="spacer-top" display="inline" variant="info">
- {translate('security_reports.more_rules')}
- </Alert>
- );
- };
-
- render() {
- const { branchLike, component, params } = this.props;
- const { loading, findings, showCWE, type } = this.state;
- if (!['owasp_top_10', 'sans_top_25', 'sonarsource_security'].includes(params.type)) {
- return <NotFound withContainer={false} />;
- }
- return (
- <div className="page page-limited" id="security-reports">
- <Suggestions suggestions="security_reports" />
- <Helmet title={translate('security_reports', type, 'page')} />
- <header className="page-header">
- <A11ySkipTarget anchor="security_main" />
- <h1 className="page-title">{translate('security_reports', type, 'page')}</h1>
- <div className="page-description">
- {translate('security_reports', type, 'description')}
- <Link
- className="spacer-left"
- target="_blank"
- to={{ pathname: '/documentation/user-guide/security-reports/' }}>
- {translate('learn_more')}
- </Link>
- {this.renderAdditionalRulesMessage()}
- </div>
- </header>
- <div className="display-inline-flex-center">
- <Checkbox
- checked={showCWE}
- className="spacer-left spacer-right vertical-middle"
- disabled={!this.state.hasVulnerabilities}
- id={'showCWE'}
- onCheck={this.handleCheck}>
- <label className="little-spacer-left" htmlFor={'showCWE'}>
- {translate('security_reports.cwe.show')}
- <DocTooltip
- className="spacer-left"
- doc={import(/* webpackMode: "eager" */ 'Docs/tooltips/security-reports/cwe.md')}
- />
- </label>
- </Checkbox>
- </div>
- <DeferredSpinner loading={loading}>
- <VulnerabilityList
- branchLike={branchLike}
- component={component}
- findings={findings}
- showCWE={showCWE}
- type={type}
- />
- </DeferredSpinner>
- </div>
- );
- }
-}
-
-export default withRouter(App);
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
deleted file mode 100755
index 2179b89f73e..00000000000
--- a/server/sonar-web/src/main/js/apps/securityReports/components/VulnerabilityList.tsx
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import * as classNames from 'classnames';
-import { sortBy } from 'lodash';
-import { Link } from 'react-router';
-import { translate } from '../../../helpers/l10n';
-import Rating from '../../../components/ui/Rating';
-import { getComponentIssuesUrl, getRulesUrl } from '../../../helpers/urls';
-import { getBranchLikeQuery } from '../../../helpers/branches';
-import HelpTooltip from '../../../components/controls/HelpTooltip';
-import VulnerabilityIcon from '../../../components/icons-components/VulnerabilityIcon';
-import SecurityHotspotIcon from '../../../components/icons-components/SecurityHotspotIcon';
-import {
- renderOwaspTop10Category,
- renderSansTop25Category,
- renderCWECategory,
- renderSonarSourceSecurityCategory
-} from '../utils';
-import DetachIcon from '../../../components/icons-components/DetachIcon';
-import Tooltip from '../../../components/controls/Tooltip';
-import { getRatingTooltip } from '../../../helpers/measures';
-import PlusCircleIcon from '../../../components/icons-components/PlusCircleIcon';
-import { isSonarCloud } from '../../../helpers/system';
-import * as theme from '../../../app/theme';
-import DeferredSpinner from '../../../components/common/DeferredSpinner';
-
-interface Props {
- branchLike?: T.BranchLike;
- component: T.Component;
- findings: T.SecurityHotspot[];
- showCWE: boolean;
- type: T.StandardType;
-}
-
-interface State {
- loading: boolean;
- standards: T.Standards;
- standardKeys: string[];
-}
-
-const STANDARDS_TAGS = {
- owaspTop10: 'owasp',
- sansTop25: 'sans-top25',
- cwe: 'cwe',
- sonarsourceSecurity: 'sonarsourceSecurity'
-};
-
-export default class VulnerabilityList extends React.PureComponent<Props, State> {
- mounted = false;
- state: State = {
- loading: false,
- standards: { owaspTop10: {}, sansTop25: {}, cwe: {}, sonarsourceSecurity: {} },
- standardKeys: []
- };
-
- componentDidMount() {
- this.mounted = true;
- this.loadStandards();
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- loadStandards = () => {
- this.setState({ loading: true });
- import('../../../helpers/standards.json')
- .then(x => x.default)
- .then(
- ({ owaspTop10, sansTop25, cwe, sonarsourceSecurity }: T.Standards) => {
- if (this.mounted) {
- const standards = { owaspTop10, sansTop25, cwe, sonarsourceSecurity };
- this.setState({
- loading: false,
- standards,
- standardKeys: Object.keys(standards[this.props.type])
- });
- }
- },
- () => {}
- );
- };
-
- getName(finding: T.SecurityHotspot, type: T.StandardType) {
- const category = finding.category || finding.cwe || 'unknown';
- const renderers = {
- owaspTop10: renderOwaspTop10Category,
- sansTop25: renderSansTop25Category,
- cwe: renderCWECategory,
- sonarsourceSecurity: renderSonarSourceSecurityCategory
- };
- return (
- <>
- {renderers[type](this.state.standards, category)}
- {this.state.standards[type][category] &&
- this.state.standards[type][category].description && (
- <HelpTooltip
- className="spacer-left"
- overlay={this.renderOverlay(this.state.standards[type][category].description)}
- />
- )}
- {finding.activeRules === 0 &&
- finding.totalRules > 0 &&
- category !== 'cwe' &&
- category !== 'unknown' && (
- <HelpTooltip
- className="spacer-left"
- overlay={this.renderMoreRulesOverlay(type, category)}>
- <PlusCircleIcon className="vertical-middle" fill={theme.blue} size={12} />
- </HelpTooltip>
- )}
- </>
- );
- }
-
- // We redirect the user to the rules page, using languages, types, keywords and tags filters
- // to display the correct list of rules
- renderMoreRulesOverlay = (type: T.StandardType, category: string) => {
- const languages = this.props.component.qualityProfiles
- ? this.props.component.qualityProfiles.map(qp => qp.language).join(',')
- : '';
- const sansTopCategoryTags: T.Dict<string> = {
- 'insecure-interaction': 'insecure',
- 'porous-defenses': 'porous',
- 'risky-resource': 'risky'
- };
- const tags = `${STANDARDS_TAGS[type]}-${
- type === 'sansTop25' ? sansTopCategoryTags[category.toLowerCase()] : category.toLowerCase()
- }`;
- return (
- <>
- <p>{translate('security_reports.activate_rules')}</p>
- <hr className="spacer-top spacer-bottom" />
- <Link
- className="spacer-left link-no-underline"
- to={getRulesUrl(
- { languages, tags, types: ['SECURITY_HOTSPOT', 'VULNERABILITY'].join() },
- isSonarCloud() ? this.props.component.organization : undefined
- )}>
- {translate('security_reports.activate_rules.link')}
- </Link>
- </>
- );
- };
-
- renderOverlay = (description: string | undefined) => {
- return (
- <>
- <p>{description}</p>
- <hr className="spacer-top spacer-bottom" />
- {translate('learn_more')}:
- <Link
- className="spacer-left"
- target="_blank"
- to={{ pathname: '/documentation/user-guide/security-reports/' }}>
- Security Reports
- </Link>
- <DetachIcon
- className="little-spacer-left little-spacer-right vertical-baseline"
- size={12}
- />
- </>
- );
- };
-
- renderComponentIssuesLink = (
- activeRules: number,
- query: T.Dict<string | undefined>,
- value: number,
- tooltip?: JSX.Element
- ) => {
- if (activeRules === 0) {
- return '-';
- }
- return value === 0 ? (
- <>
- {value}
- {tooltip}
- </>
- ) : (
- <>
- <Link to={getComponentIssuesUrl(this.props.component.key, query)}>{value}</Link>
- {tooltip}
- </>
- );
- };
-
- renderFinding(
- finding: T.SecurityHotspot,
- isCWE?: boolean,
- parent?: T.SecurityHotspot
- ): React.ReactFragment {
- const { branchLike, component, type } = this.props;
- const params: T.Dict<string | undefined> = {
- ...getBranchLikeQuery(branchLike),
- types: 'SECURITY_HOTSPOT'
- };
- if (isCWE && parent) {
- params['cwe'] = finding.cwe;
- params[type] = parent.category;
- } else {
- params[type] = finding.category;
- }
-
- const subFindings =
- this.props.showCWE && finding.distribution
- ? finding.distribution.map(f => this.renderFinding(f, true, finding))
- : null;
-
- const title = getRatingTooltip('security_rating', finding.vulnerabilityRating || 1);
- return (
- <React.Fragment key={finding.category || finding.cwe}>
- <tr>
- <td className={classNames({ 'cwe-title-cell': isCWE })}>
- {this.getName(finding, isCWE ? 'cwe' : type)}
- </td>
- <td className="text-right">
- <div className="display-inline-flex-center">
- {this.renderComponentIssuesLink(
- finding.activeRules,
- {
- ...params,
- types: 'VULNERABILITY',
- resolved: 'false'
- },
- finding.vulnerabilities,
- <Tooltip overlay={title}>
- <Link
- className="link-no-underline spacer-left"
- to={getComponentIssuesUrl(component.key, {
- ...params,
- types: 'VULNERABILITY',
- resolved: 'false'
- })}>
- <Rating value={finding.vulnerabilityRating || 1} />
- </Link>
- </Tooltip>
- )}
- </div>
- </td>
- <td className="text-right security-column-separator">
- {this.renderComponentIssuesLink(
- finding.activeRules,
- {
- ...params,
- types: 'SECURITY_HOTSPOT',
- resolved: 'false',
- statuses: 'OPEN,REOPENED'
- },
- finding.openSecurityHotspots
- )}
- </td>
- <td className="text-right">
- {this.renderComponentIssuesLink(
- finding.activeRules,
- {
- ...params,
- types: 'SECURITY_HOTSPOT',
- resolutions: 'FIXED',
- statuses: 'RESOLVED'
- },
- finding.toReviewSecurityHotspots
- )}
- </td>
- <td className="text-right">
- {this.renderComponentIssuesLink(
- finding.activeRules,
- {
- ...params,
- types: 'SECURITY_HOTSPOT',
- resolutions: 'WONTFIX',
- statuses: 'RESOLVED'
- },
- finding.wontFixSecurityHotspots
- )}
- </td>
- </tr>
- {subFindings}
- </React.Fragment>
- );
- }
-
- render() {
- const { loading, standardKeys } = this.state;
- const sortedFindings = sortBy(this.props.findings, ({ category }) => {
- const index = category ? standardKeys.indexOf(category) : standardKeys.length;
- return index < 0 ? standardKeys.length : index;
- });
-
- if (loading) {
- return <DeferredSpinner />;
- }
-
- return (
- <div className="boxed-group boxed-group-inner spacer-top">
- <table className="data zebra security-reports">
- <thead>
- <tr>
- <th className="security-category-column">
- {translate('security_reports.list.categories')}
- </th>
- <th className="security-result-column text-right">
- <div className="display-inline-flex-center">
- <VulnerabilityIcon className="spacer-right" />
- {translate('security_reports.list.vulnerabilities')}
- </div>
- </th>
- <th className="text-right security-column-separator" colSpan={3}>
- <div className="display-inline-flex-center">
- <SecurityHotspotIcon className="spacer-right" />
- {translate('security_reports.list.security_hotspots')}
- </div>
- </th>
- </tr>
- <tr className="subheader">
- <th colSpan={2} />
- <th className="text-right security-result-column security-column-separator">
- {translate('security_reports.line.open')}
- </th>
- <th className="text-right security-result-column">
- {translate('security_reports.line.in_review')}
- </th>
- <th className="text-right security-result-column">
- {translate('security_reports.line.wont_fix')}
- </th>
- </tr>
- </thead>
- <tbody>{sortedFindings.map(finding => this.renderFinding(finding))}</tbody>
- </table>
- </div>
- );
- }
-}
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
deleted file mode 100644
index 12bf3c5b428..00000000000
--- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/App-test.tsx
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-/* eslint-disable import/first, import/order */
-jest.mock('../../../../api/security-reports', () => ({
- getSecurityHotspots: jest.fn(() => {
- const distribution: any = [
- {
- cwe: '477',
- vulnerabilities: 1,
- vulnerabiliyRating: 1,
- toReviewSecurityHotspots: 2,
- openSecurityHotspots: 10,
- wontFixSecurityHotspots: 0
- },
- {
- cwe: '396',
- vulnerabilities: 2,
- vulnerabiliyRating: 2,
- toReviewSecurityHotspots: 2,
- openSecurityHotspots: 10,
- wontFixSecurityHotspots: 0
- }
- ];
- return Promise.resolve({
- categories: [
- {
- activeRules: 1,
- totalRules: 1,
- category: 'a1',
- vulnerabilities: 2,
- vulnerabiliyRating: 5,
- toReviewSecurityHotspots: 2,
- openSecurityHotspots: 10,
- wontFixSecurityHotspots: 0,
- distribution
- },
- {
- activeRules: 1,
- totalRules: 1,
- category: 'a2',
- vulnerabilities: 3,
- vulnerabiliyRating: 3,
- toReviewSecurityHotspots: 8,
- openSecurityHotspots: 100,
- wontFixSecurityHotspots: 10
- },
- {
- activeRules: 0,
- totalRules: 1,
- category: 'a3',
- vulnerabilities: 3,
- vulnerabiliyRating: 3,
- toReviewSecurityHotspots: 8,
- openSecurityHotspots: 100,
- wontFixSecurityHotspots: 10
- }
- ]
- });
- })
-}));
-
-import * as React from 'react';
-import { shallow } from 'enzyme';
-import { App } from '../App';
-import { waitAndUpdate } from '../../../../helpers/testUtils';
-
-const getSecurityHotspots = require('../../../../api/security-reports')
- .getSecurityHotspots as jest.Mock<any>;
-
-const component = { key: 'foo', name: 'Foo', qualifier: 'TRK' } as T.Component;
-const location = { pathname: 'foo', query: {} };
-const locationWithCWE = { pathname: 'foo', query: { showCWE: 'true' } };
-const owaspParams = { type: 'owasp_top_10' };
-const sansParams = { type: 'sans_top_25' };
-const sonarParams = { type: 'sonarsource_security' };
-const wrongParams = { type: 'foo' };
-
-beforeEach(() => {
- getSecurityHotspots.mockClear();
-});
-
-it('renders error on wrong type parameters', () => {
- const wrapper = shallow(
- <App
- component={component}
- location={location}
- params={wrongParams}
- router={{ push: jest.fn() }}
- />
- );
- expect(wrapper).toMatchSnapshot();
-});
-
-it('renders owaspTop10', async () => {
- const wrapper = shallow(
- <App
- component={component}
- location={location}
- params={owaspParams}
- router={{ push: jest.fn() }}
- />
- );
- await waitAndUpdate(wrapper);
- expect(getSecurityHotspots).toBeCalledWith({
- project: 'foo',
- standard: 'owaspTop10',
- includeDistribution: false,
- branch: undefined
- });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('renders with cwe', () => {
- const wrapper = shallow(
- <App
- component={component}
- location={locationWithCWE}
- params={owaspParams}
- router={{ push: jest.fn() }}
- />
- );
- expect(getSecurityHotspots).toBeCalledWith({
- project: 'foo',
- standard: 'owaspTop10',
- includeDistribution: true,
- branch: undefined
- });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('handle checkbox for cwe display', async () => {
- const wrapper = shallow(
- <App
- component={component}
- location={location}
- params={owaspParams}
- router={{ push: jest.fn() }}
- />
- );
- expect(getSecurityHotspots).toBeCalledWith({
- project: 'foo',
- standard: 'owaspTop10',
- includeDistribution: false,
- branch: undefined
- });
- expect(wrapper).toMatchSnapshot();
-
- wrapper.find('Checkbox').prop<Function>('onCheck')(true);
- await waitAndUpdate(wrapper);
-
- expect(getSecurityHotspots).toBeCalledWith({
- project: 'foo',
- standard: 'owaspTop10',
- includeDistribution: true,
- branch: undefined
- });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('renders sansTop25', () => {
- const wrapper = shallow(
- <App
- component={component}
- location={location}
- params={sansParams}
- router={{ push: jest.fn() }}
- />
- );
- expect(getSecurityHotspots).toBeCalledWith({
- project: 'foo',
- standard: 'sansTop25',
- includeDistribution: false,
- branch: undefined
- });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('renders sonarsourceSecurity', async () => {
- const wrapper = shallow(
- <App
- component={component}
- location={location}
- params={sonarParams}
- router={{ push: jest.fn() }}
- />
- );
- await waitAndUpdate(wrapper);
- expect(getSecurityHotspots).toBeCalledWith({
- project: 'foo',
- standard: 'sonarsourceSecurity',
- includeDistribution: false,
- branch: undefined
- });
- expect(wrapper).toMatchSnapshot();
-});
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
deleted file mode 100644
index c5ab079ad23..00000000000
--- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/VulnerabilityList-test.tsx
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import { shallow } from 'enzyme';
-import VulnerabilityList from '../VulnerabilityList';
-import { waitAndUpdate } from '../../../../helpers/testUtils';
-
-jest.mock('../../../../helpers/standards.json', () => ({
- default: {
- owaspTop10: { a1: { title: 'a1 title' }, unknown: { title: 'Not OWAPS' } },
- sansTop25: { 'risky-resource': { title: 'Risky Resource Management' } },
- cwe: { 42: { title: 'cwe-42 title' }, unknown: { title: 'Unknown CWE' } }
- }
-}));
-
-const component = { key: 'foo', name: 'Foo', qualifier: 'TRK' } as T.Component;
-const findings = [
- {
- activeRules: 1,
- totalRules: 1,
- category: 'a1',
- 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: 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,
- toReviewSecurityHotspots: 8,
- openSecurityHotspots: 100,
- wontFixSecurityHotspots: 10
- }
-];
-
-it('renders', async () => {
- const wrapper = shallow(
- <VulnerabilityList
- component={component}
- findings={findings}
- showCWE={false}
- type="owaspTop10"
- />
- );
- await waitAndUpdate(wrapper);
- expect(wrapper.find('tr').length).toBe(6);
- expect(wrapper).toMatchSnapshot();
-});
-
-it('renders with cwe', async () => {
- const wrapper = shallow(
- <VulnerabilityList component={component} findings={findings} showCWE={true} type="owaspTop10" />
- );
- await waitAndUpdate(wrapper);
- 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
deleted file mode 100644
index b89aa9c57c4..00000000000
--- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap
+++ /dev/null
@@ -1,697 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`handle checkbox for cwe display 1`] = `
-<div
- className="page page-limited"
- id="security-reports"
->
- <Suggestions
- suggestions="security_reports"
- />
- <HelmetWrapper
- defer={true}
- encodeSpecialCharacters={true}
- title="security_reports.owaspTop10.page"
- />
- <header
- className="page-header"
- >
- <A11ySkipTarget
- anchor="security_main"
- />
- <h1
- className="page-title"
- >
- security_reports.owaspTop10.page
- </h1>
- <div
- className="page-description"
- >
- security_reports.owaspTop10.description
- <Link
- className="spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to={
- Object {
- "pathname": "/documentation/user-guide/security-reports/",
- }
- }
- >
- learn_more
- </Link>
- </div>
- </header>
- <div
- className="display-inline-flex-center"
- >
- <Checkbox
- checked={false}
- className="spacer-left spacer-right vertical-middle"
- disabled={true}
- id="showCWE"
- onCheck={[Function]}
- thirdState={false}
- >
- <label
- className="little-spacer-left"
- htmlFor="showCWE"
- >
- security_reports.cwe.show
- <DocTooltip
- className="spacer-left"
- doc={Promise {}}
- />
- </label>
- </Checkbox>
- </div>
- <DeferredSpinner
- loading={true}
- timeout={100}
- >
- <VulnerabilityList
- component={
- Object {
- "key": "foo",
- "name": "Foo",
- "qualifier": "TRK",
- }
- }
- findings={Array []}
- showCWE={false}
- type="owaspTop10"
- />
- </DeferredSpinner>
-</div>
-`;
-
-exports[`handle checkbox for cwe display 2`] = `
-<div
- className="page page-limited"
- id="security-reports"
->
- <Suggestions
- suggestions="security_reports"
- />
- <HelmetWrapper
- defer={true}
- encodeSpecialCharacters={true}
- title="security_reports.owaspTop10.page"
- />
- <header
- className="page-header"
- >
- <A11ySkipTarget
- anchor="security_main"
- />
- <h1
- className="page-title"
- >
- security_reports.owaspTop10.page
- </h1>
- <div
- className="page-description"
- >
- security_reports.owaspTop10.description
- <Link
- className="spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to={
- Object {
- "pathname": "/documentation/user-guide/security-reports/",
- }
- }
- >
- learn_more
- </Link>
- <Alert
- className="spacer-top"
- display="inline"
- variant="info"
- >
- security_reports.more_rules
- </Alert>
- </div>
- </header>
- <div
- className="display-inline-flex-center"
- >
- <Checkbox
- checked={true}
- className="spacer-left spacer-right vertical-middle"
- disabled={false}
- id="showCWE"
- onCheck={[Function]}
- thirdState={false}
- >
- <label
- className="little-spacer-left"
- htmlFor="showCWE"
- >
- security_reports.cwe.show
- <DocTooltip
- className="spacer-left"
- doc={Promise {}}
- />
- </label>
- </Checkbox>
- </div>
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <VulnerabilityList
- component={
- Object {
- "key": "foo",
- "name": "Foo",
- "qualifier": "TRK",
- }
- }
- findings={
- Array [
- Object {
- "activeRules": 1,
- "category": "a1",
- "distribution": Array [
- Object {
- "cwe": "477",
- "openSecurityHotspots": 10,
- "toReviewSecurityHotspots": 2,
- "vulnerabilities": 1,
- "vulnerabiliyRating": 1,
- "wontFixSecurityHotspots": 0,
- },
- Object {
- "cwe": "396",
- "openSecurityHotspots": 10,
- "toReviewSecurityHotspots": 2,
- "vulnerabilities": 2,
- "vulnerabiliyRating": 2,
- "wontFixSecurityHotspots": 0,
- },
- ],
- "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,
- },
- Object {
- "activeRules": 0,
- "category": "a3",
- "openSecurityHotspots": 100,
- "toReviewSecurityHotspots": 8,
- "totalRules": 1,
- "vulnerabilities": 3,
- "vulnerabiliyRating": 3,
- "wontFixSecurityHotspots": 10,
- },
- ]
- }
- showCWE={true}
- type="owaspTop10"
- />
- </DeferredSpinner>
-</div>
-`;
-
-exports[`renders error on wrong type parameters 1`] = `
-<NotFound
- withContainer={false}
-/>
-`;
-
-exports[`renders owaspTop10 1`] = `
-<div
- className="page page-limited"
- id="security-reports"
->
- <Suggestions
- suggestions="security_reports"
- />
- <HelmetWrapper
- defer={true}
- encodeSpecialCharacters={true}
- title="security_reports.owaspTop10.page"
- />
- <header
- className="page-header"
- >
- <A11ySkipTarget
- anchor="security_main"
- />
- <h1
- className="page-title"
- >
- security_reports.owaspTop10.page
- </h1>
- <div
- className="page-description"
- >
- security_reports.owaspTop10.description
- <Link
- className="spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to={
- Object {
- "pathname": "/documentation/user-guide/security-reports/",
- }
- }
- >
- learn_more
- </Link>
- <Alert
- className="spacer-top"
- display="inline"
- variant="info"
- >
- security_reports.more_rules
- </Alert>
- </div>
- </header>
- <div
- className="display-inline-flex-center"
- >
- <Checkbox
- checked={false}
- className="spacer-left spacer-right vertical-middle"
- disabled={false}
- id="showCWE"
- onCheck={[Function]}
- thirdState={false}
- >
- <label
- className="little-spacer-left"
- htmlFor="showCWE"
- >
- security_reports.cwe.show
- <DocTooltip
- className="spacer-left"
- doc={Promise {}}
- />
- </label>
- </Checkbox>
- </div>
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <VulnerabilityList
- component={
- Object {
- "key": "foo",
- "name": "Foo",
- "qualifier": "TRK",
- }
- }
- findings={
- Array [
- Object {
- "activeRules": 1,
- "category": "a1",
- "distribution": Array [
- Object {
- "cwe": "477",
- "openSecurityHotspots": 10,
- "toReviewSecurityHotspots": 2,
- "vulnerabilities": 1,
- "vulnerabiliyRating": 1,
- "wontFixSecurityHotspots": 0,
- },
- Object {
- "cwe": "396",
- "openSecurityHotspots": 10,
- "toReviewSecurityHotspots": 2,
- "vulnerabilities": 2,
- "vulnerabiliyRating": 2,
- "wontFixSecurityHotspots": 0,
- },
- ],
- "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,
- },
- Object {
- "activeRules": 0,
- "category": "a3",
- "openSecurityHotspots": 100,
- "toReviewSecurityHotspots": 8,
- "totalRules": 1,
- "vulnerabilities": 3,
- "vulnerabiliyRating": 3,
- "wontFixSecurityHotspots": 10,
- },
- ]
- }
- showCWE={false}
- type="owaspTop10"
- />
- </DeferredSpinner>
-</div>
-`;
-
-exports[`renders sansTop25 1`] = `
-<div
- className="page page-limited"
- id="security-reports"
->
- <Suggestions
- suggestions="security_reports"
- />
- <HelmetWrapper
- defer={true}
- encodeSpecialCharacters={true}
- title="security_reports.sansTop25.page"
- />
- <header
- className="page-header"
- >
- <A11ySkipTarget
- anchor="security_main"
- />
- <h1
- className="page-title"
- >
- security_reports.sansTop25.page
- </h1>
- <div
- className="page-description"
- >
- security_reports.sansTop25.description
- <Link
- className="spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to={
- Object {
- "pathname": "/documentation/user-guide/security-reports/",
- }
- }
- >
- learn_more
- </Link>
- </div>
- </header>
- <div
- className="display-inline-flex-center"
- >
- <Checkbox
- checked={false}
- className="spacer-left spacer-right vertical-middle"
- disabled={true}
- id="showCWE"
- onCheck={[Function]}
- thirdState={false}
- >
- <label
- className="little-spacer-left"
- htmlFor="showCWE"
- >
- security_reports.cwe.show
- <DocTooltip
- className="spacer-left"
- doc={Promise {}}
- />
- </label>
- </Checkbox>
- </div>
- <DeferredSpinner
- loading={true}
- timeout={100}
- >
- <VulnerabilityList
- component={
- Object {
- "key": "foo",
- "name": "Foo",
- "qualifier": "TRK",
- }
- }
- findings={Array []}
- showCWE={false}
- type="sansTop25"
- />
- </DeferredSpinner>
-</div>
-`;
-
-exports[`renders sonarsourceSecurity 1`] = `
-<div
- className="page page-limited"
- id="security-reports"
->
- <Suggestions
- suggestions="security_reports"
- />
- <HelmetWrapper
- defer={true}
- encodeSpecialCharacters={true}
- title="security_reports.sonarsourceSecurity.page"
- />
- <header
- className="page-header"
- >
- <A11ySkipTarget
- anchor="security_main"
- />
- <h1
- className="page-title"
- >
- security_reports.sonarsourceSecurity.page
- </h1>
- <div
- className="page-description"
- >
- security_reports.sonarsourceSecurity.description
- <Link
- className="spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to={
- Object {
- "pathname": "/documentation/user-guide/security-reports/",
- }
- }
- >
- learn_more
- </Link>
- <Alert
- className="spacer-top"
- display="inline"
- variant="info"
- >
- security_reports.more_rules
- </Alert>
- </div>
- </header>
- <div
- className="display-inline-flex-center"
- >
- <Checkbox
- checked={false}
- className="spacer-left spacer-right vertical-middle"
- disabled={false}
- id="showCWE"
- onCheck={[Function]}
- thirdState={false}
- >
- <label
- className="little-spacer-left"
- htmlFor="showCWE"
- >
- security_reports.cwe.show
- <DocTooltip
- className="spacer-left"
- doc={Promise {}}
- />
- </label>
- </Checkbox>
- </div>
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <VulnerabilityList
- component={
- Object {
- "key": "foo",
- "name": "Foo",
- "qualifier": "TRK",
- }
- }
- findings={
- Array [
- Object {
- "activeRules": 1,
- "category": "a1",
- "distribution": Array [
- Object {
- "cwe": "477",
- "openSecurityHotspots": 10,
- "toReviewSecurityHotspots": 2,
- "vulnerabilities": 1,
- "vulnerabiliyRating": 1,
- "wontFixSecurityHotspots": 0,
- },
- Object {
- "cwe": "396",
- "openSecurityHotspots": 10,
- "toReviewSecurityHotspots": 2,
- "vulnerabilities": 2,
- "vulnerabiliyRating": 2,
- "wontFixSecurityHotspots": 0,
- },
- ],
- "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,
- },
- Object {
- "activeRules": 0,
- "category": "a3",
- "openSecurityHotspots": 100,
- "toReviewSecurityHotspots": 8,
- "totalRules": 1,
- "vulnerabilities": 3,
- "vulnerabiliyRating": 3,
- "wontFixSecurityHotspots": 10,
- },
- ]
- }
- showCWE={false}
- type="sonarsourceSecurity"
- />
- </DeferredSpinner>
-</div>
-`;
-
-exports[`renders with cwe 1`] = `
-<div
- className="page page-limited"
- id="security-reports"
->
- <Suggestions
- suggestions="security_reports"
- />
- <HelmetWrapper
- defer={true}
- encodeSpecialCharacters={true}
- title="security_reports.owaspTop10.page"
- />
- <header
- className="page-header"
- >
- <A11ySkipTarget
- anchor="security_main"
- />
- <h1
- className="page-title"
- >
- security_reports.owaspTop10.page
- </h1>
- <div
- className="page-description"
- >
- security_reports.owaspTop10.description
- <Link
- className="spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to={
- Object {
- "pathname": "/documentation/user-guide/security-reports/",
- }
- }
- >
- learn_more
- </Link>
- </div>
- </header>
- <div
- className="display-inline-flex-center"
- >
- <Checkbox
- checked={true}
- className="spacer-left spacer-right vertical-middle"
- disabled={true}
- id="showCWE"
- onCheck={[Function]}
- thirdState={false}
- >
- <label
- className="little-spacer-left"
- htmlFor="showCWE"
- >
- security_reports.cwe.show
- <DocTooltip
- className="spacer-left"
- doc={Promise {}}
- />
- </label>
- </Checkbox>
- </div>
- <DeferredSpinner
- loading={true}
- timeout={100}
- >
- <VulnerabilityList
- component={
- Object {
- "key": "foo",
- "name": "Foo",
- "qualifier": "TRK",
- }
- }
- findings={Array []}
- showCWE={true}
- type="owaspTop10"
- />
- </DeferredSpinner>
-</div>
-`;
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
deleted file mode 100644
index 2f6c25221bb..00000000000
--- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/VulnerabilityList-test.tsx.snap
+++ /dev/null
@@ -1,1264 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`renders 1`] = `
-<div
- className="boxed-group boxed-group-inner spacer-top"
->
- <table
- className="data zebra security-reports"
- >
- <thead>
- <tr>
- <th
- className="security-category-column"
- >
- security_reports.list.categories
- </th>
- <th
- className="security-result-column text-right"
- >
- <div
- className="display-inline-flex-center"
- >
- <VulnerabilityIcon
- className="spacer-right"
- />
- security_reports.list.vulnerabilities
- </div>
- </th>
- <th
- className="text-right security-column-separator"
- colSpan={3}
- >
- <div
- className="display-inline-flex-center"
- >
- <SecurityHotspotIcon
- className="spacer-right"
- />
- security_reports.list.security_hotspots
- </div>
- </th>
- </tr>
- <tr
- className="subheader"
- >
- <th
- colSpan={2}
- />
- <th
- className="text-right security-result-column security-column-separator"
- >
- security_reports.line.open
- </th>
- <th
- className="text-right security-result-column"
- >
- security_reports.line.in_review
- </th>
- <th
- className="text-right security-result-column"
- >
- security_reports.line.wont_fix
- </th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td
- className=""
- >
- A1 - a1 title
- </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": "a1",
- "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": "a1",
- "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": "a1",
- "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": "a1",
- "resolutions": "FIXED",
- "statuses": "RESOLVED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 2
- </Link>
- </td>
- <td
- className="text-right"
- >
- 0
- </td>
- </tr>
- <tr>
- <td
- className=""
- >
- Not OWAPS
- </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": "unknown",
- "resolved": "false",
- "types": "VULNERABILITY",
- },
- }
- }
- >
- 3
- </Link>
- <Tooltip
- overlay="metric.security_rating.tooltip.C"
- >
- <Link
- className="link-no-underline spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/project/issues",
- "query": Object {
- "id": "foo",
- "owaspTop10": "unknown",
- "resolved": "false",
- "types": "VULNERABILITY",
- },
- }
- }
- >
- <Rating
- value={3}
- />
- </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": "unknown",
- "resolved": "false",
- "statuses": "OPEN,REOPENED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 100
- </Link>
- </td>
- <td
- className="text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/project/issues",
- "query": Object {
- "id": "foo",
- "owaspTop10": "unknown",
- "resolutions": "FIXED",
- "statuses": "RESOLVED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 8
- </Link>
- </td>
- <td
- className="text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/project/issues",
- "query": Object {
- "id": "foo",
- "owaspTop10": "unknown",
- "resolutions": "WONTFIX",
- "statuses": "RESOLVED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 10
- </Link>
- </td>
- </tr>
- <tr>
- <td
- className=""
- >
- A2
- </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"
- >
- 0
- </td>
- </tr>
- <tr>
- <td
- className=""
- >
- A3
- <HelpTooltip
- className="spacer-left"
- overlay={
- <React.Fragment>
- <p>
- security_reports.activate_rules
- </p>
- <hr
- className="spacer-top spacer-bottom"
- />
- <Link
- className="spacer-left link-no-underline"
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/coding_rules",
- "query": Object {
- "languages": "",
- "tags": "owasp-a3",
- "types": "SECURITY_HOTSPOT,VULNERABILITY",
- },
- }
- }
- >
- security_reports.activate_rules.link
- </Link>
- </React.Fragment>
- }
- >
- <PlusCircleIcon
- className="vertical-middle"
- fill="#4b9fd5"
- size={12}
- />
- </HelpTooltip>
- </td>
- <td
- className="text-right"
- >
- <div
- className="display-inline-flex-center"
- >
- -
- </div>
- </td>
- <td
- className="text-right security-column-separator"
- >
- -
- </td>
- <td
- className="text-right"
- >
- -
- </td>
- <td
- className="text-right"
- >
- -
- </td>
- </tr>
- </tbody>
- </table>
-</div>
-`;
-
-exports[`renders with cwe 1`] = `
-<div
- className="boxed-group boxed-group-inner spacer-top"
->
- <table
- className="data zebra security-reports"
- >
- <thead>
- <tr>
- <th
- className="security-category-column"
- >
- security_reports.list.categories
- </th>
- <th
- className="security-result-column text-right"
- >
- <div
- className="display-inline-flex-center"
- >
- <VulnerabilityIcon
- className="spacer-right"
- />
- security_reports.list.vulnerabilities
- </div>
- </th>
- <th
- className="text-right security-column-separator"
- colSpan={3}
- >
- <div
- className="display-inline-flex-center"
- >
- <SecurityHotspotIcon
- className="spacer-right"
- />
- security_reports.list.security_hotspots
- </div>
- </th>
- </tr>
- <tr
- className="subheader"
- >
- <th
- colSpan={2}
- />
- <th
- className="text-right security-result-column security-column-separator"
- >
- security_reports.line.open
- </th>
- <th
- className="text-right security-result-column"
- >
- security_reports.line.in_review
- </th>
- <th
- className="text-right security-result-column"
- >
- security_reports.line.wont_fix
- </th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td
- className=""
- >
- A1 - a1 title
- </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": "a1",
- "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": "a1",
- "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": "a1",
- "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": "a1",
- "resolutions": "FIXED",
- "statuses": "RESOLVED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 2
- </Link>
- </td>
- <td
- className="text-right"
- >
- 0
- </td>
- </tr>
- <tr>
- <td
- className="cwe-title-cell"
- >
- CWE-42 - cwe-42 title
- </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": "a1",
- "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": "a1",
- "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": "a1",
- "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": "a1",
- "resolutions": "FIXED",
- "statuses": "RESOLVED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 2
- </Link>
- </td>
- <td
- className="text-right"
- >
- 0
- </td>
- </tr>
- <tr>
- <td
- className=""
- >
- Not OWAPS
- </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": "unknown",
- "resolved": "false",
- "types": "VULNERABILITY",
- },
- }
- }
- >
- 3
- </Link>
- <Tooltip
- overlay="metric.security_rating.tooltip.C"
- >
- <Link
- className="link-no-underline spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/project/issues",
- "query": Object {
- "id": "foo",
- "owaspTop10": "unknown",
- "resolved": "false",
- "types": "VULNERABILITY",
- },
- }
- }
- >
- <Rating
- value={3}
- />
- </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": "unknown",
- "resolved": "false",
- "statuses": "OPEN,REOPENED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 100
- </Link>
- </td>
- <td
- className="text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/project/issues",
- "query": Object {
- "id": "foo",
- "owaspTop10": "unknown",
- "resolutions": "FIXED",
- "statuses": "RESOLVED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 8
- </Link>
- </td>
- <td
- className="text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/project/issues",
- "query": Object {
- "id": "foo",
- "owaspTop10": "unknown",
- "resolutions": "WONTFIX",
- "statuses": "RESOLVED",
- "types": "SECURITY_HOTSPOT",
- },
- }
- }
- >
- 10
- </Link>
- </td>
- </tr>
- <tr>
- <td
- className=""
- >
- A2
- </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"
- >
- 0
- </td>
- </tr>
- <tr>
- <td
- className="cwe-title-cell"
- >
- CWE-42 - cwe-42 title
- </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"
- >
- 0
- </td>
- </tr>
- <tr>
- <td
- className=""
- >
- A3
- <HelpTooltip
- className="spacer-left"
- overlay={
- <React.Fragment>
- <p>
- security_reports.activate_rules
- </p>
- <hr
- className="spacer-top spacer-bottom"
- />
- <Link
- className="spacer-left link-no-underline"
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/coding_rules",
- "query": Object {
- "languages": "",
- "tags": "owasp-a3",
- "types": "SECURITY_HOTSPOT,VULNERABILITY",
- },
- }
- }
- >
- security_reports.activate_rules.link
- </Link>
- </React.Fragment>
- }
- >
- <PlusCircleIcon
- className="vertical-middle"
- fill="#4b9fd5"
- size={12}
- />
- </HelpTooltip>
- </td>
- <td
- className="text-right"
- >
- <div
- className="display-inline-flex-center"
- >
- -
- </div>
- </td>
- <td
- className="text-right security-column-separator"
- >
- -
- </td>
- <td
- className="text-right"
- >
- -
- </td>
- <td
- className="text-right"
- >
- -
- </td>
- </tr>
- <tr>
- <td
- className="cwe-title-cell"
- >
- CWE-42 - cwe-42 title
- </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"
- >
- 0
- </td>
- </tr>
- </tbody>
- </table>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/securityReports/style.css b/server/sonar-web/src/main/js/apps/securityReports/style.css
deleted file mode 100644
index 254f6047285..00000000000
--- a/server/sonar-web/src/main/js/apps/securityReports/style.css
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-.security-column-separator {
- border-left: 1px solid var(--barBorderColor);
-}
-
-.security-category-column {
- width: 52%;
-}
-
-.security-result-column {
- width: 12%;
-}
-
-table.data.security-reports > thead:after {
- content: none;
-}
-
-.cwe-title-cell {
- padding-left: 80px !important;
-}
diff --git a/server/sonar-web/src/main/js/apps/securityReports/utils.ts b/server/sonar-web/src/main/js/apps/securityReports/utils.ts
deleted file mode 100755
index 8d378b80b90..00000000000
--- a/server/sonar-web/src/main/js/apps/securityReports/utils.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-export function renderOwaspTop10Category(
- standards: T.Standards,
- category: string,
- withPrefix = false
-): string {
- const record = standards.owaspTop10[category];
- if (!record) {
- return addPrefix(category.toUpperCase(), 'OWASP', withPrefix);
- } else if (category === 'unknown') {
- return record.title;
- } else {
- return addPrefix(`${category.toUpperCase()} - ${record.title}`, 'OWASP', withPrefix);
- }
-}
-
-export function renderCWECategory(standards: T.Standards, category: string): string {
- const record = standards.cwe[category];
- if (!record) {
- return `CWE-${category}`;
- } else if (category === 'unknown') {
- return record.title;
- } else {
- return `CWE-${category} - ${record.title}`;
- }
-}
-
-export function renderSansTop25Category(
- standards: T.Standards,
- category: string,
- withPrefix = false
-): string {
- const record = standards.sansTop25[category];
- return addPrefix(record ? record.title : category, 'SANS', withPrefix);
-}
-
-export function renderSonarSourceSecurityCategory(
- standards: T.Standards,
- category: string,
- withPrefix = false
-): string {
- const record = standards.sonarsourceSecurity[category];
- return addPrefix(record ? record.title : category, 'SONAR', withPrefix);
-}
-
-function addPrefix(title: string, prefix: string, withPrefix: boolean) {
- return withPrefix ? `${prefix} ${title}` : title;
-}
-
-const TYPES_MAP: T.Dict<T.StandardType> = {
- owasp_top_10: 'owaspTop10',
- sans_top_25: 'sansTop25',
- sonarsource_security: 'sonarsourceSecurity'
-};
-
-export function getType(type: string): T.StandardType {
- return TYPES_MAP[type] || 'sonarsourceSecurity';
-}
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/security-standard-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/security-standard-test.ts
new file mode 100644
index 00000000000..18d5e62ba4f
--- /dev/null
+++ b/server/sonar-web/src/main/js/helpers/__tests__/security-standard-test.ts
@@ -0,0 +1,123 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import {
+ renderCWECategory,
+ renderOwaspTop10Category,
+ renderSansTop25Category,
+ renderSonarSourceSecurityCategory
+} from '../security-standard';
+
+describe('renderCWECategory', () => {
+ const standards: T.Standards = {
+ cwe: {
+ '1004': {
+ title: "Sensitive Cookie Without 'HttpOnly' Flag"
+ },
+ unknown: {
+ title: 'No CWE associated'
+ }
+ },
+ owaspTop10: {},
+ sansTop25: {},
+ sonarsourceSecurity: {}
+ };
+ it('should render categories correctly', () => {
+ expect(renderCWECategory(standards, '1004')).toEqual(
+ "CWE-1004 - Sensitive Cookie Without 'HttpOnly' Flag"
+ );
+ expect(renderCWECategory(standards, '124')).toEqual('CWE-124');
+ expect(renderCWECategory(standards, 'unknown')).toEqual('No CWE associated');
+ });
+});
+
+describe('renderOwaspTop10Category', () => {
+ const standards: T.Standards = {
+ cwe: {},
+ owaspTop10: {
+ a1: {
+ title: 'Injection'
+ },
+ unknown: {
+ title: 'Not OWASP'
+ }
+ },
+ sansTop25: {},
+ sonarsourceSecurity: {}
+ };
+ it('should render categories correctly', () => {
+ expect(renderOwaspTop10Category(standards, 'a1')).toEqual('A1 - Injection');
+ expect(renderOwaspTop10Category(standards, 'a1', true)).toEqual('OWASP A1 - Injection');
+ expect(renderOwaspTop10Category(standards, 'a2')).toEqual('A2');
+ expect(renderOwaspTop10Category(standards, 'a2', true)).toEqual('OWASP A2');
+ expect(renderOwaspTop10Category(standards, 'unknown')).toEqual('Not OWASP');
+ expect(renderOwaspTop10Category(standards, 'unknown', true)).toEqual('Not OWASP');
+ });
+});
+
+describe('renderSansTop25Category', () => {
+ const standards: T.Standards = {
+ cwe: {},
+ owaspTop10: {},
+ sansTop25: {
+ 'insecure-interaction': {
+ title: 'Insecure Interaction Between Components'
+ }
+ },
+ sonarsourceSecurity: {}
+ };
+ it('should render categories correctly', () => {
+ expect(renderSansTop25Category(standards, 'insecure-interaction')).toEqual(
+ 'Insecure Interaction Between Components'
+ );
+ expect(renderSansTop25Category(standards, 'insecure-interaction', true)).toEqual(
+ 'SANS Insecure Interaction Between Components'
+ );
+ expect(renderSansTop25Category(standards, 'unknown')).toEqual('unknown');
+ expect(renderSansTop25Category(standards, 'unknown', true)).toEqual('SANS unknown');
+ });
+});
+
+describe('renderSonarSourceSecurityCategory', () => {
+ const standards: T.Standards = {
+ cwe: {},
+ owaspTop10: {},
+ sansTop25: {},
+ sonarsourceSecurity: {
+ xss: {
+ title: 'Cross-Site Scripting (XSS)'
+ },
+ others: {
+ title: 'Others'
+ }
+ }
+ };
+ it('should render categories correctly', () => {
+ expect(renderSonarSourceSecurityCategory(standards, 'xss')).toEqual(
+ 'Cross-Site Scripting (XSS)'
+ );
+ expect(renderSonarSourceSecurityCategory(standards, 'xss', true)).toEqual(
+ 'SONAR Cross-Site Scripting (XSS)'
+ );
+ expect(renderSonarSourceSecurityCategory(standards, 'unknown')).toEqual('unknown');
+ expect(renderSonarSourceSecurityCategory(standards, 'unknown', true)).toEqual('SONAR unknown');
+ expect(renderSonarSourceSecurityCategory(standards, 'others')).toEqual('Others');
+ expect(renderSonarSourceSecurityCategory(standards, 'others', true)).toEqual('Others');
+ });
+});
diff --git a/server/sonar-web/src/main/js/helpers/security-standard.ts b/server/sonar-web/src/main/js/helpers/security-standard.ts
index 685c6ef4033..cc44d1b2226 100644
--- a/server/sonar-web/src/main/js/helpers/security-standard.ts
+++ b/server/sonar-web/src/main/js/helpers/security-standard.ts
@@ -20,3 +20,55 @@
export function getStandards(): Promise<T.Standards> {
return import('./standards.json').then(x => x.default);
}
+
+export function renderCWECategory(standards: T.Standards, category: string): string {
+ const record = standards.cwe[category];
+ if (!record) {
+ return `CWE-${category}`;
+ } else if (category === 'unknown') {
+ return record.title;
+ } else {
+ return `CWE-${category} - ${record.title}`;
+ }
+}
+
+export function renderOwaspTop10Category(
+ standards: T.Standards,
+ category: string,
+ withPrefix = false
+): string {
+ const record = standards.owaspTop10[category];
+ if (!record) {
+ return addPrefix(category.toUpperCase(), 'OWASP', withPrefix);
+ } else if (category === 'unknown') {
+ return record.title;
+ } else {
+ return addPrefix(`${category.toUpperCase()} - ${record.title}`, 'OWASP', withPrefix);
+ }
+}
+
+export function renderSansTop25Category(
+ standards: T.Standards,
+ category: string,
+ withPrefix = false
+): string {
+ const record = standards.sansTop25[category];
+ return addPrefix(record ? record.title : category, 'SANS', withPrefix);
+}
+
+export function renderSonarSourceSecurityCategory(
+ standards: T.Standards,
+ category: string,
+ withPrefix = false
+): string {
+ const record = standards.sonarsourceSecurity[category];
+ if (category === 'others') {
+ return record.title;
+ } else {
+ return addPrefix(record ? record.title : category, 'SONAR', withPrefix);
+ }
+}
+
+function addPrefix(title: string, prefix: string, withPrefix: boolean) {
+ return withPrefix ? `${prefix} ${title}` : title;
+}