import { flatMap, range } from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
-import { addSideBarClass, removeSideBarClass } from 'sonar-ui-common/helpers/pages';
import { getMeasures } from '../../api/measures';
import { getSecurityHotspotList, getSecurityHotspots } from '../../api/security-hotspots';
import { withCurrentUser } from '../../components/hoc/withCurrentUser';
componentDidMount() {
this.mounted = true;
- addSideBarClass();
this.fetchInitialData();
this.registerKeyboardEvents();
}
}
componentWillUnmount() {
- removeSideBarClass();
this.unregisterKeyboardEvents();
this.mounted = false;
}
onShowAllHotspots={props.onShowAllHotspots}
/>
- {loading && <DeferredSpinner className="huge-spacer-left big-spacer-top" />}
+ {loading && (
+ <div className="layout-page">
+ <div className="layout-page-side-inner">
+ <DeferredSpinner className="big-spacer-top" />
+ </div>
+ </div>
+ )}
{!loading &&
(hotspots.length === 0 || !selectedHotspot ? (
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { addSideBarClass } from 'sonar-ui-common/helpers/pages';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { getMeasures } from '../../../api/measures';
import { getSecurityHotspotList, getSecurityHotspots } from '../../../api/security-hotspots';
beforeEach(() => jest.clearAllMocks());
-jest.mock('sonar-ui-common/helpers/pages', () => ({
- addSideBarClass: jest.fn(),
- removeSideBarClass: jest.fn()
-}));
-
jest.mock('../../../api/measures', () => ({
getMeasures: jest.fn().mockResolvedValue([])
}));
expect(wrapper.state().loading).toBe(true);
expect(wrapper.state().loadingMeasure).toBe(true);
- expect(addSideBarClass).toBeCalled();
expect(getStandards).toBeCalled();
expect(getSecurityHotspots).toBeCalledWith(
expect.objectContaining({
onChangeFilters={[MockFunction]}
onShowAllHotspots={[MockFunction]}
/>
- <DeferredSpinner
- className="huge-spacer-left big-spacer-top"
- />
+ <div
+ className="layout-page"
+ >
+ <div
+ className="layout-page-side-inner"
+ >
+ <DeferredSpinner
+ className="big-spacer-top"
+ />
+ </div>
+ </div>
</div>
`;
import ListFooter from 'sonar-ui-common/components/controls/ListFooter';
import SecurityHotspotIcon from 'sonar-ui-common/components/icons/SecurityHotspotIcon';
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import { addSideBarClass, removeSideBarClass } from 'sonar-ui-common/helpers/pages';
import { HotspotStatusFilter, RawHotspot, RiskExposure } from '../../../types/security-hotspots';
import { groupByCategory, RISK_EXPOSURE_LEVELS } from '../utils';
import HotspotCategory from './HotspotCategory';
};
}
+ componentDidMount() {
+ addSideBarClass();
+ }
+
componentDidUpdate(prevProps: Props) {
// Force open the category of selected hotspot
if (
}
}
+ componentWillUnmount() {
+ removeSideBarClass();
+ }
+
groupHotspots = (hotspots: RawHotspot[], securityCategories: T.StandardSecurityCategories) => {
const risks = groupBy(hotspots, h => h.vulnerabilityProbability);
import ListFooter from 'sonar-ui-common/components/controls/ListFooter';
import SecurityHotspotIcon from 'sonar-ui-common/components/icons/SecurityHotspotIcon';
import { translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import { addSideBarClass, removeSideBarClass } from 'sonar-ui-common/helpers/pages';
import { SecurityStandard, Standards } from '../../../types/security';
import { RawHotspot } from '../../../types/security-hotspots';
import { SECURITY_STANDARD_RENDERER } from '../utils';
standards: Standards;
}
-export default function HotspotSimpleList(props: HotspotSimpleListProps) {
- const {
- filterByCategory,
- filterByCWE,
- hotspots,
- hotspotsTotal,
- loadingMore,
- selectedHotspot,
- standards
- } = props;
+export default class HotspotSimpleList extends React.Component<HotspotSimpleListProps> {
+ componentDidMount() {
+ addSideBarClass();
+ }
- const categoryLabel =
- filterByCategory &&
- SECURITY_STANDARD_RENDERER[filterByCategory.standard](standards, filterByCategory.category);
+ componentWillUnmount() {
+ removeSideBarClass();
+ }
- const cweLabel =
- filterByCWE && SECURITY_STANDARD_RENDERER[SecurityStandard.CWE](standards, filterByCWE);
+ render() {
+ const {
+ filterByCategory,
+ filterByCWE,
+ hotspots,
+ hotspotsTotal,
+ loadingMore,
+ selectedHotspot,
+ standards
+ } = this.props;
- return (
- <div className="hotspots-list-single-category huge-spacer-bottom">
- <h1 className="hotspot-list-header bordered-bottom">
- <SecurityHotspotIcon className="spacer-right" />
- {translateWithParameters('hotspots.list_title', hotspotsTotal)}
- </h1>
- <div className="big-spacer-bottom">
- <div className="hotspot-category">
- <div className="hotspot-category-header">
- <strong className="flex-1 spacer-right break-word">
- {categoryLabel}
- {categoryLabel && cweLabel && <hr />}
- {cweLabel}
- </strong>
+ const categoryLabel =
+ filterByCategory &&
+ SECURITY_STANDARD_RENDERER[filterByCategory.standard](standards, filterByCategory.category);
+
+ const cweLabel =
+ filterByCWE && SECURITY_STANDARD_RENDERER[SecurityStandard.CWE](standards, filterByCWE);
+
+ return (
+ <div className="hotspots-list-single-category huge-spacer-bottom">
+ <h1 className="hotspot-list-header bordered-bottom">
+ <SecurityHotspotIcon className="spacer-right" />
+ {translateWithParameters('hotspots.list_title', hotspotsTotal)}
+ </h1>
+ <div className="big-spacer-bottom">
+ <div className="hotspot-category">
+ <div className="hotspot-category-header">
+ <strong className="flex-1 spacer-right break-word">
+ {categoryLabel}
+ {categoryLabel && cweLabel && <hr />}
+ {cweLabel}
+ </strong>
+ </div>
+ <ul>
+ {hotspots.map(h => (
+ <li data-hotspot-key={h.key} key={h.key}>
+ <HotspotListItem
+ hotspot={h}
+ onClick={this.props.onHotspotClick}
+ selected={h.key === selectedHotspot.key}
+ />
+ </li>
+ ))}
+ </ul>
</div>
- <ul>
- {hotspots.map(h => (
- <li data-hotspot-key={h.key} key={h.key}>
- <HotspotListItem
- hotspot={h}
- onClick={props.onHotspotClick}
- selected={h.key === selectedHotspot.key}
- />
- </li>
- ))}
- </ul>
</div>
+ <ListFooter
+ count={hotspots.length}
+ loadMore={!loadingMore ? this.props.onLoadMore : undefined}
+ loading={loadingMore}
+ total={hotspotsTotal}
+ />
</div>
- <ListFooter
- count={hotspots.length}
- loadMore={!loadingMore ? props.onLoadMore : undefined}
- loading={loadingMore}
- total={hotspotsTotal}
- />
- </div>
- );
+ );
+ }
}
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { addSideBarClass, removeSideBarClass } from 'sonar-ui-common/helpers/pages';
+import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { mockRawHotspot } from '../../../../helpers/mocks/security-hotspots';
import { HotspotStatusFilter, RiskExposure } from '../../../../types/security-hotspots';
import HotspotList from '../HotspotList';
+jest.mock('sonar-ui-common/helpers/pages', () => ({
+ addSideBarClass: jest.fn(),
+ removeSideBarClass: jest.fn()
+}));
+
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ loadingMore: true })).toMatchSnapshot();
});
+it('should add/remove sidebar classes', async () => {
+ const wrapper = shallowRender();
+
+ await waitAndUpdate(wrapper);
+
+ expect(addSideBarClass).toHaveBeenCalled();
+
+ wrapper.unmount();
+
+ expect(removeSideBarClass).toHaveBeenCalled();
+});
+
it('should render correctly when the list of hotspot is static', () => {
expect(shallowRender({ isStaticListOfHotspots: true })).toMatchSnapshot();
});
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { addSideBarClass, removeSideBarClass } from 'sonar-ui-common/helpers/pages';
+import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { mockRawHotspot } from '../../../../helpers/mocks/security-hotspots';
import { SecurityStandard } from '../../../../types/security';
import HotspotSimpleList, { HotspotSimpleListProps } from '../HotspotSimpleList';
+jest.mock('sonar-ui-common/helpers/pages', () => ({
+ addSideBarClass: jest.fn(),
+ removeSideBarClass: jest.fn()
+}));
+
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('filter by category');
expect(shallowRender({ filterByCategory: undefined, filterByCWE: '327' })).toMatchSnapshot(
expect(shallowRender({ filterByCWE: '327' })).toMatchSnapshot('filter by both');
});
+it('should add/remove sidebar classes', async () => {
+ const wrapper = shallowRender();
+
+ await waitAndUpdate(wrapper);
+
+ expect(addSideBarClass).toHaveBeenCalled();
+
+ wrapper.unmount();
+
+ expect(removeSideBarClass).toHaveBeenCalled();
+});
+
function shallowRender(props: Partial<HotspotSimpleListProps> = {}) {
const hotspots = [mockRawHotspot({ key: 'h1' }), mockRawHotspot({ key: 'h2' })];