aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2019-04-30 15:59:32 +0200
committersonartech <sonartech@sonarsource.com>2019-05-06 11:01:15 +0200
commitd5b454babf688705a9cd4c8fd862b0fc0a9898d2 (patch)
treea3a080a46589066c8b7fd4efd4c944f92cf252a0 /server/sonar-web
parent6c37e7a9c7ef1b048c2067250235e24b386f4fc9 (diff)
downloadsonarqube-d5b454babf688705a9cd4c8fd862b0fc0a9898d2.tar.gz
sonarqube-d5b454babf688705a9cd4c8fd862b0fc0a9898d2.zip
SONAR-11898 Fix quality issues and improve coverage
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureContent-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesSourceViewer-test.tsx51
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap294
-rw-r--r--server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueBox-test.tsx10
-rw-r--r--server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetViewer.tsx42
-rw-r--r--server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewerWrapper.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/ComponentSourceSnippetViewer-test.tsx70
-rw-r--r--server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/CrossComponentSourceViewerWrapper-test.tsx11
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.tsx5
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeaderSlim.tsx6
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewerHeaderSlim-test.tsx55
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerHeaderSlim-test.tsx.snap120
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx9
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineCode-test.tsx60
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineCode-test.tsx.snap99
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/indexing-test.ts27
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/issueLocations-test.ts46
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.ts (renamed from server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.tsx)0
-rw-r--r--server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceComponentViewer-test.tsx.snap2
20 files changed, 795 insertions, 121 deletions
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureContent-test.tsx.snap b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureContent-test.tsx.snap
index d25d9196349..762028e42a4 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureContent-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureContent-test.tsx.snap
@@ -95,7 +95,7 @@ exports[`should render correctly for a file 1`] = `
<div
className="measure-details-viewer"
>
- <LazyLoader
+ <SourceViewer
component="foo:src/index.tsx"
/>
</div>
diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesSourceViewer-test.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesSourceViewer-test.tsx
new file mode 100644
index 00000000000..47580bcf048
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesSourceViewer-test.tsx
@@ -0,0 +1,51 @@
+/*
+ * 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 IssuesSourceViewer from '../IssuesSourceViewer';
+import { mockMainBranch, mockIssue } from '../../../../helpers/testMocks';
+
+it('should render SourceViewer correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+it('should render CrossComponentSourceViewer correctly', () => {
+ expect(
+ shallowRender({ issues: [mockIssue(true)], openIssue: mockIssue(true) })
+ ).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<IssuesSourceViewer['props']> = {}) {
+ return shallow(
+ <IssuesSourceViewer
+ branchLike={mockMainBranch()}
+ issues={[mockIssue()]}
+ loadIssues={jest.fn()}
+ locationsNavigator={true}
+ onIssueChange={jest.fn()}
+ onIssueSelect={jest.fn()}
+ onLocationSelect={jest.fn()}
+ openIssue={mockIssue()}
+ selectedFlowIndex={undefined}
+ selectedLocationIndex={undefined}
+ {...props}
+ />
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap
new file mode 100644
index 00000000000..416ec4a47fd
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap
@@ -0,0 +1,294 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render CrossComponentSourceViewer correctly 1`] = `
+<div>
+ <CrossComponentSourceViewer
+ branchLike={
+ Object {
+ "analysisDate": "2018-01-01",
+ "isMain": true,
+ "name": "master",
+ }
+ }
+ components={
+ Array [
+ "main.js",
+ ]
+ }
+ issue={
+ Object {
+ "actions": Array [],
+ "component": "main.js",
+ "componentLongName": "main.js",
+ "componentQualifier": "FIL",
+ "componentUuid": "foo1234",
+ "creationDate": "2017-03-01T09:36:01+0100",
+ "flows": Array [
+ Array [
+ Object {
+ "component": "main.js",
+ "index": 0,
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "index": 1,
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "index": 2,
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ ],
+ Array [
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ ],
+ ],
+ "fromHotspot": false,
+ "key": "AVsae-CQS-9G3txfbFN2",
+ "line": 25,
+ "message": "Reduce the number of conditional operators (4) used in the expression",
+ "organization": "myorg",
+ "project": "myproject",
+ "projectKey": "foo",
+ "projectName": "Foo",
+ "projectOrganization": "org",
+ "rule": "javascript:S1067",
+ "ruleName": "foo",
+ "secondaryLocations": Array [
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ ],
+ "severity": "MAJOR",
+ "status": "OPEN",
+ "textRange": Object {
+ "endLine": 26,
+ "endOffset": 15,
+ "startLine": 25,
+ "startOffset": 0,
+ },
+ "transitions": Array [],
+ "type": "BUG",
+ }
+ }
+ issues={
+ Array [
+ Object {
+ "actions": Array [],
+ "component": "main.js",
+ "componentLongName": "main.js",
+ "componentQualifier": "FIL",
+ "componentUuid": "foo1234",
+ "creationDate": "2017-03-01T09:36:01+0100",
+ "flows": Array [
+ Array [
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ ],
+ Array [
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ ],
+ ],
+ "fromHotspot": false,
+ "key": "AVsae-CQS-9G3txfbFN2",
+ "line": 25,
+ "message": "Reduce the number of conditional operators (4) used in the expression",
+ "organization": "myorg",
+ "project": "myproject",
+ "projectKey": "foo",
+ "projectName": "Foo",
+ "projectOrganization": "org",
+ "rule": "javascript:S1067",
+ "ruleName": "foo",
+ "secondaryLocations": Array [
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ ],
+ "severity": "MAJOR",
+ "status": "OPEN",
+ "textRange": Object {
+ "endLine": 26,
+ "endOffset": 15,
+ "startLine": 25,
+ "startOffset": 0,
+ },
+ "transitions": Array [],
+ "type": "BUG",
+ },
+ ]
+ }
+ locations={
+ Array [
+ Object {
+ "component": "main.js",
+ "index": 0,
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "index": 1,
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ Object {
+ "component": "main.js",
+ "index": 2,
+ "textRange": Object {
+ "endLine": 2,
+ "endOffset": 2,
+ "startLine": 1,
+ "startOffset": 1,
+ },
+ },
+ ]
+ }
+ onIssueChange={[MockFunction]}
+ onLoaded={[Function]}
+ onLocationSelect={[MockFunction]}
+ scroll={[Function]}
+ />
+</div>
+`;
+
+exports[`should render SourceViewer correctly 1`] = `
+<div>
+ <SourceViewer
+ aroundLine={26}
+ branchLike={
+ Object {
+ "analysisDate": "2018-01-01",
+ "isMain": true,
+ "name": "master",
+ }
+ }
+ component="main.js"
+ displayAllIssues={true}
+ displayLocationMarkers={false}
+ highlightedLocations={Array []}
+ loadIssues={[MockFunction]}
+ onIssueChange={[MockFunction]}
+ onIssueSelect={[MockFunction]}
+ onLoaded={[Function]}
+ onLocationSelect={[MockFunction]}
+ scroll={[Function]}
+ selectedIssue="AVsae-CQS-9G3txfbFN2"
+ slimHeader={true}
+ />
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueBox-test.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueBox-test.tsx
index b7f18bfdfc5..654bbf8fa6d 100644
--- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueBox-test.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueBox-test.tsx
@@ -21,14 +21,18 @@ import * as React from 'react';
import { shallow } from 'enzyme';
import ConciseIssueBox from '../ConciseIssueBox';
import { mockIssue } from '../../../../helpers/testMocks';
-import { waitAndUpdate } from '../../../../helpers/testUtils';
+import { waitAndUpdate, click } from '../../../../helpers/testUtils';
it('should render correctly', async () => {
- const wrapper = shallowRender();
+ const onClick = jest.fn();
+ const wrapper = shallowRender({ onClick });
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
- expect(shallowRender({ issue: mockIssue(true) })).toMatchSnapshot();
+ const issue = mockIssue(true);
+ expect(shallowRender({ issue })).toMatchSnapshot();
+ click(wrapper.find('.concise-issue-box-message'));
+ expect(onClick).toBeCalledWith(issue.key);
});
const shallowRender = (props: Partial<ConciseIssueBox['props']> = {}) => {
diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetViewer.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetViewer.tsx
index 9e5c90afc8c..3e362317db0 100644
--- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetViewer.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetViewer.tsx
@@ -59,6 +59,7 @@ interface Props {
interface State {
additionalLines: { [line: number]: T.SourceLine };
highlightedSymbols: string[];
+ linePopup?: { index?: number; line: number; name: string };
loading: boolean;
openIssuesByLine: T.Dict<boolean>;
snippets: T.SourceLine[][];
@@ -139,6 +140,7 @@ export default class ComponentSourceSnippetViewer extends React.PureComponent<Pr
return {
additionalLines: combinedLines,
+ linePopup: undefined,
snippets: expandSnippet({
direction,
lines: { ...combinedLines, ...this.props.snippetGroup.sources },
@@ -149,7 +151,7 @@ export default class ComponentSourceSnippetViewer extends React.PureComponent<Pr
});
}
},
- () => null
+ () => {}
);
};
@@ -161,7 +163,7 @@ export default class ComponentSourceSnippetViewer extends React.PureComponent<Pr
getSources({ key }).then(
lines => {
if (this.mounted) {
- this.setState({ loading: false, snippets: [lines] });
+ this.setState({ linePopup: undefined, loading: false, snippets: [lines] });
}
},
() => {
@@ -172,6 +174,32 @@ export default class ComponentSourceSnippetViewer extends React.PureComponent<Pr
);
};
+ handleLinePopupToggle = ({
+ index,
+ line,
+ name,
+ open
+ }: {
+ index?: number;
+ line: number;
+ name: string;
+ open?: boolean;
+ }) => {
+ this.setState((state: State) => {
+ const samePopup =
+ state.linePopup !== undefined &&
+ state.linePopup.name === name &&
+ state.linePopup.line === line &&
+ state.linePopup.index === index;
+ if (open !== false && !samePopup) {
+ return { linePopup: { index, line, name } };
+ } else if (open !== true && samePopup) {
+ return { linePopup: undefined };
+ }
+ return null;
+ });
+ };
+
handleOpenIssues = (line: T.SourceLine) => {
this.setState(state => ({
openIssuesByLine: { ...state.openIssuesByLine, [line.line]: true }
@@ -184,6 +212,10 @@ export default class ComponentSourceSnippetViewer extends React.PureComponent<Pr
}));
};
+ handleSymbolClick = (highlightedSymbols: string[]) => {
+ this.setState({ highlightedSymbols });
+ };
+
renderLine({
index,
issuesForLine,
@@ -231,7 +263,7 @@ export default class ComponentSourceSnippetViewer extends React.PureComponent<Pr
key={line.line}
last={false}
line={line}
- linePopup={undefined}
+ linePopup={this.state.linePopup}
loadDuplications={noop}
onIssueChange={this.props.onIssueChange}
onIssuePopupToggle={this.props.onIssuePopupToggle}
@@ -239,9 +271,9 @@ export default class ComponentSourceSnippetViewer extends React.PureComponent<Pr
onIssueUnselect={noop}
onIssuesClose={this.handleCloseIssues}
onIssuesOpen={this.handleOpenIssues}
- onLinePopupToggle={noop}
+ onLinePopupToggle={this.handleLinePopupToggle}
onLocationSelect={this.props.onLocationSelect}
- onSymbolClick={highlightedSymbols => this.setState({ highlightedSymbols })}
+ onSymbolClick={this.handleSymbolClick}
openIssues={openIssuesByLine[line.line]}
previousLine={index > 0 ? snippet[index - 1] : undefined}
renderDuplicationPopup={this.props.renderDuplicationPopup}
diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx
index ff48d1ea91a..6c81a5744ec 100644
--- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx
@@ -19,8 +19,9 @@
*/
import { lazyLoad } from '../../../components/lazyLoad';
-const CrossComponentSourceViewer = lazyLoad(() =>
- import(/* webpackPrefetch: true */ './CrossComponentSourceViewerWrapper')
+const CrossComponentSourceViewer = lazyLoad(
+ () => import(/* webpackPrefetch: true */ './CrossComponentSourceViewerWrapper'),
+ 'CrossComponentSourceViewer'
);
export default CrossComponentSourceViewer;
diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewerWrapper.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewerWrapper.tsx
index 6f27127d2e1..92760bb3b22 100644
--- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewerWrapper.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewerWrapper.tsx
@@ -121,7 +121,7 @@ export default class CrossComponentSourceViewerWrapper extends React.PureCompone
issue={this.props.issue}
issuePopup={this.state.issuePopup}
issuesByLine={issuesByComponent[g.component.key] || {}}
- key={this.props.issue.key + '-' + this.props.selectedFlowIndex + '-' + i}
+ key={`${this.props.issue.key}-${this.props.selectedFlowIndex}-${i}`}
last={i === locationsByComponent.length - 1}
locations={g.locations || []}
onIssueChange={this.props.onIssueChange}
diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/ComponentSourceSnippetViewer-test.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/ComponentSourceSnippetViewer-test.tsx
index 6076ef40b02..980df641334 100644
--- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/ComponentSourceSnippetViewer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/ComponentSourceSnippetViewer-test.tsx
@@ -19,28 +19,25 @@
*/
import * as React from 'react';
import { shallow } from 'enzyme';
+import { times } from 'lodash';
import ComponentSourceSnippetViewer from '../ComponentSourceSnippetViewer';
import {
mockMainBranch,
mockIssue,
mockSourceViewerFile,
mockFlowLocation,
- mockSnippetsByComponent
+ mockSnippetsByComponent,
+ mockSourceLine
} from '../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../helpers/testUtils';
+import { getSources } from '../../../../api/components';
-jest.mock('../../../../api/components', () => {
- const { mockSnippetsByComponent } = require.requireActual('../../../../helpers/testMocks');
+jest.mock('../../../../api/components', () => ({
+ getSources: jest.fn().mockResolvedValue([])
+}));
- return {
- getSources: jest
- .fn()
- .mockResolvedValue(
- Object.values(
- mockSnippetsByComponent('a', [22, 23, 24, 25, 26, 27, 28, 29, 30, 31]).sources
- )
- )
- };
+beforeEach(() => {
+ jest.clearAllMocks();
});
it('should render correctly', () => {
@@ -48,6 +45,9 @@ it('should render correctly', () => {
});
it('should expand block', async () => {
+ (getSources as jest.Mock).mockResolvedValueOnce(
+ Object.values(mockSnippetsByComponent('a', [22, 23, 24, 25, 26, 27, 28, 29, 30, 31]).sources)
+ );
const snippetGroup: T.SnippetGroup = {
locations: [
mockFlowLocation({
@@ -67,11 +67,57 @@ it('should expand block', async () => {
wrapper.instance().expandBlock(0, 'up');
await waitAndUpdate(wrapper);
+ expect(getSources).toHaveBeenCalledWith({ from: 19, key: 'a', to: 31 });
expect(wrapper.state('snippets')).toHaveLength(2);
expect(wrapper.state('snippets')[0]).toHaveLength(15);
expect(Object.keys(wrapper.state('additionalLines'))).toHaveLength(10);
});
+it('should expand full component', async () => {
+ (getSources as jest.Mock).mockResolvedValueOnce(
+ Object.values(mockSnippetsByComponent('a', times(14)).sources)
+ );
+ const snippetGroup: T.SnippetGroup = {
+ locations: [
+ mockFlowLocation({
+ component: 'a',
+ textRange: { startLine: 3, endLine: 3, startOffset: 0, endOffset: 0 }
+ }),
+ mockFlowLocation({
+ component: 'a',
+ textRange: { startLine: 12, endLine: 12, startOffset: 0, endOffset: 0 }
+ })
+ ],
+ ...mockSnippetsByComponent('a', [1, 2, 3, 4, 5, 10, 11, 12, 13, 14])
+ };
+
+ const wrapper = shallowRender({ snippetGroup });
+
+ wrapper.instance().expandComponent();
+ await waitAndUpdate(wrapper);
+
+ expect(getSources).toHaveBeenCalledWith({ key: 'a' });
+ expect(wrapper.state('snippets')).toHaveLength(1);
+ expect(wrapper.state('snippets')[0]).toHaveLength(14);
+});
+
+it('should handle correctly open/close issue', () => {
+ const wrapper = shallowRender();
+ const sourceLine = mockSourceLine();
+ expect(wrapper.state('openIssuesByLine')).toEqual({});
+ wrapper.instance().handleOpenIssues(sourceLine);
+ expect(wrapper.state('openIssuesByLine')).toEqual({ [sourceLine.line]: true });
+ wrapper.instance().handleCloseIssues(sourceLine);
+ expect(wrapper.state('openIssuesByLine')).toEqual({ [sourceLine.line]: false });
+});
+
+it('should handle symbol highlighting', () => {
+ const wrapper = shallowRender();
+ expect(wrapper.state('highlightedSymbols')).toEqual([]);
+ wrapper.instance().handleSymbolClick(['foo']);
+ expect(wrapper.state('highlightedSymbols')).toEqual(['foo']);
+});
+
function shallowRender(props: Partial<ComponentSourceSnippetViewer['props']> = {}) {
const snippetGroup: T.SnippetGroup = {
component: mockSourceViewerFile(),
diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/CrossComponentSourceViewerWrapper-test.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/CrossComponentSourceViewerWrapper-test.tsx
index 63051e1575e..634537fd178 100644
--- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/CrossComponentSourceViewerWrapper-test.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/CrossComponentSourceViewerWrapper-test.tsx
@@ -22,6 +22,7 @@ import { shallow } from 'enzyme';
import CrossComponentSourceViewerWrapper from '../CrossComponentSourceViewerWrapper';
import { mockIssue, mockSourceViewerFile } from '../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../helpers/testUtils';
+import { getIssueFlowSnippets } from '../../../../api/issues';
jest.mock('../../../../api/issues', () => {
const { mockSourceViewerFile } = require.requireActual('../../../../helpers/testMocks');
@@ -30,6 +31,10 @@ jest.mock('../../../../api/issues', () => {
};
});
+beforeEach(() => {
+ jest.clearAllMocks();
+});
+
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});
@@ -38,8 +43,12 @@ it('Should fetch data', async () => {
const wrapper = shallowRender();
wrapper.instance().fetchIssueFlowSnippets('124');
await waitAndUpdate(wrapper);
-
+ expect(getIssueFlowSnippets).toBeCalled();
expect(wrapper.state('components')).toEqual([mockSourceViewerFile()]);
+
+ (getIssueFlowSnippets as jest.Mock).mockClear();
+ wrapper.setProps({ issue: mockIssue(true, { key: 'foo' }) });
+ expect(getIssueFlowSnippets).toBeCalledWith('foo');
});
it('should handle issue popup', () => {
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.tsx
index 46d568bb1b8..6311df20195 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.tsx
@@ -19,5 +19,8 @@
*/
import { lazyLoad } from '../lazyLoad';
-const SourceViewer = lazyLoad(() => import(/* webpackPrefetch: true */ './SourceViewerBase'));
+const SourceViewer = lazyLoad(
+ () => import(/* webpackPrefetch: true */ './SourceViewerBase'),
+ 'SourceViewer'
+);
export default SourceViewer;
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeaderSlim.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeaderSlim.tsx
index 167472a692a..cfc2c65ba7f 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeaderSlim.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeaderSlim.tsx
@@ -28,7 +28,7 @@ import { collapsedDirFromPath, fileFromPath } from '../../helpers/path';
import { isMainBranch } from '../../helpers/branches';
import './SourceViewerHeaderSlim.css';
-interface Props {
+export interface Props {
branchLike: T.BranchLike | undefined;
expandable?: boolean;
loading?: boolean;
@@ -57,9 +57,9 @@ export default function SourceViewerHeaderSlim({
</div>
{subProject !== undefined && (
- <div className="">
+ <>
<QualifierIcon qualifier="BRC" /> <span>{subProjectName}</span>
- </div>
+ </>
)}
<div className="spacer-left">
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewerHeaderSlim-test.tsx b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewerHeaderSlim-test.tsx
new file mode 100644
index 00000000000..2bc8557ec28
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewerHeaderSlim-test.tsx
@@ -0,0 +1,55 @@
+/*
+ * 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 SourceViewerHeaderSlim, { Props } from '../SourceViewerHeaderSlim';
+import { mockMainBranch, mockSourceViewerFile } from '../../../helpers/testMocks';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+it('should allow to mark as favorite', () => {
+ expect(
+ shallowRender({ sourceViewerFile: mockSourceViewerFile({ canMarkAsFavorite: true }) })
+ .find('Favorite')
+ .exists()
+ ).toBe(true);
+});
+
+it('should render correctly for subproject', () => {
+ expect(
+ shallowRender({
+ sourceViewerFile: mockSourceViewerFile({ subProject: 'foo', subProjectName: 'Foo' })
+ })
+ ).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<Props> = {}) {
+ return shallow(
+ <SourceViewerHeaderSlim
+ branchLike={mockMainBranch()}
+ expandable={true}
+ onExpand={jest.fn()}
+ sourceViewerFile={mockSourceViewerFile()}
+ {...props}
+ />
+ );
+}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerHeaderSlim-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerHeaderSlim-test.tsx.snap
new file mode 100644
index 00000000000..20f543700bf
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerHeaderSlim-test.tsx.snap
@@ -0,0 +1,120 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+ className="source-viewer-header-slim display-flex-row display-flex-space-between"
+>
+ <div
+ className="display-flex-row flex-1"
+ >
+ <div>
+ <a
+ className="link-with-icon"
+ href="/dashboard?id=my-project"
+ >
+ <QualifierIcon
+ qualifier="TRK"
+ />
+
+ <span>
+ MyProject
+ </span>
+ </a>
+ </div>
+ <div
+ className="spacer-left"
+ >
+ <QualifierIcon
+ qualifier="FIL"
+ />
+
+ <span>
+ foo/
+ </span>
+ <span
+ className="component-name-file"
+ >
+ bar.ts
+ </span>
+ </div>
+ </div>
+ <DeferredSpinner
+ className="little-spacer-right"
+ timeout={100}
+ >
+ <div
+ className="source-viewer-header-slim-actions flex-0"
+ >
+ <ButtonIcon
+ className="js-actions"
+ onClick={[MockFunction]}
+ >
+ <ExpandSnippetIcon />
+ </ButtonIcon>
+ </div>
+ </DeferredSpinner>
+</div>
+`;
+
+exports[`should render correctly for subproject 1`] = `
+<div
+ className="source-viewer-header-slim display-flex-row display-flex-space-between"
+>
+ <div
+ className="display-flex-row flex-1"
+ >
+ <div>
+ <a
+ className="link-with-icon"
+ href="/dashboard?id=my-project"
+ >
+ <QualifierIcon
+ qualifier="TRK"
+ />
+
+ <span>
+ MyProject
+ </span>
+ </a>
+ </div>
+ <QualifierIcon
+ qualifier="BRC"
+ />
+
+ <span>
+ Foo
+ </span>
+ <div
+ className="spacer-left"
+ >
+ <QualifierIcon
+ qualifier="FIL"
+ />
+
+ <span>
+ foo/
+ </span>
+ <span
+ className="component-name-file"
+ >
+ bar.ts
+ </span>
+ </div>
+ </div>
+ <DeferredSpinner
+ className="little-spacer-right"
+ timeout={100}
+ >
+ <div
+ className="source-viewer-header-slim-actions flex-0"
+ >
+ <ButtonIcon
+ className="js-actions"
+ onClick={[MockFunction]}
+ >
+ <ExpandSnippetIcon />
+ </ButtonIcon>
+ </div>
+ </DeferredSpinner>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
index 485353c9626..ca5118377b9 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
@@ -217,11 +217,8 @@ export default class LineCode extends React.PureComponent<Props, State> {
leadingMarker = (index === 0 ? true : leadingMarker) && !token.text.trim().length;
});
- const style = padding
- ? {
- paddingBottom: padding + 'px'
- }
- : undefined;
+ const style = padding ? { paddingBottom: `${padding}px` } : undefined;
+ const filteredSelectedIssues = issues.filter(i => i.key === selectedIssue);
return (
<td className={className} data-line-number={line.line} style={style}>
@@ -243,7 +240,7 @@ export default class LineCode extends React.PureComponent<Props, State> {
<LineIssuesList
branchLike={this.props.branchLike}
issuePopup={this.props.issuePopup}
- issues={issues.filter(i => i.key === selectedIssue)}
+ issues={filteredSelectedIssues}
onIssueChange={this.props.onIssueChange}
onIssueClick={onIssueSelect}
onIssuePopupToggle={this.props.onIssuePopupToggle}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineCode-test.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineCode-test.tsx
index 8091d30aa14..50a447bf0c7 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineCode-test.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineCode-test.tsx
@@ -20,53 +20,23 @@
import * as React from 'react';
import { shallow } from 'enzyme';
import LineCode from '../LineCode';
-
-const issueBase: T.Issue = {
- actions: [],
- component: '',
- componentLongName: '',
- componentQualifier: '',
- componentUuid: '',
- creationDate: '',
- key: '',
- flows: [],
- fromHotspot: false,
- message: '',
- organization: '',
- project: '',
- projectName: '',
- projectOrganization: '',
- projectKey: '',
- rule: '',
- ruleName: '',
- secondaryLocations: [],
- severity: '',
- status: '',
- transitions: [],
- type: 'BUG'
-};
+import { mockShortLivingBranch, mockIssue, mockSourceLine } from '../../../../helpers/testMocks';
it('render code', () => {
- const line = {
- line: 3,
- code: '<span class="k">class</span> <span class="sym sym-1">Foo</span> {'
- };
- const issueLocations = [{ from: 0, to: 5, line: 3 }];
- const branch: T.ShortLivingBranch = {
- isMain: false,
- mergeBranch: 'master',
- name: 'feature',
- type: 'SHORT'
- };
- const wrapper = shallow(
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<LineCode['props']> = {}) {
+ return shallow(
<LineCode
- branchLike={branch}
- highlightedLocationMessage={undefined}
- highlightedSymbols={['sym1']}
- issueLocations={issueLocations}
+ branchLike={mockShortLivingBranch()}
+ displayLocationMarkers={true}
+ highlightedLocationMessage={{ index: 0, text: 'location description' }}
+ highlightedSymbols={['sym-9']}
+ issueLocations={[{ from: 0, to: 5, line: 16 }]}
issuePopup={undefined}
- issues={[{ ...issueBase, key: 'issue-1' }, { ...issueBase, key: 'issue-2' }]}
- line={line}
+ issues={[mockIssue(false, { key: 'issue-1' }), mockIssue(false, { key: 'issue-2' })]}
+ line={mockSourceLine()}
onIssueChange={jest.fn()}
onIssuePopupToggle={jest.fn()}
onIssueSelect={jest.fn()}
@@ -75,7 +45,7 @@ it('render code', () => {
secondaryIssueLocations={[]}
selectedIssue="issue-1"
showIssues={true}
+ {...props}
/>
);
- expect(wrapper).toMatchSnapshot();
-});
+}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineCode-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineCode-test.tsx.snap
index df5c914a676..cffede6b404 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineCode-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineCode-test.tsx.snap
@@ -3,7 +3,7 @@
exports[`render code 1`] = `
<td
className="source-line-code code has-issues"
- data-line-number={3}
+ data-line-number={16}
>
<div
className="source-line-code-inner"
@@ -13,34 +13,41 @@ exports[`render code 1`] = `
className="k source-line-code-issue"
key="0"
>
- class
+ impor
</span>
<span
- className=""
+ className="k"
key="1"
>
-
+ t
</span>
<span
- className="sym sym-1"
+ className=""
key="2"
>
- Foo
+ java.util.
</span>
<span
- className=""
+ className="sym-9 sym highlighted"
key="3"
>
- {
+ ArrayList
+ </span>
+ <span
+ className=""
+ key="4"
+ >
+ ;
</span>
</pre>
</div>
<LineIssuesList
branchLike={
Object {
+ "analysisDate": "2018-01-01",
"isMain": false,
"mergeBranch": "master",
- "name": "feature",
+ "name": "feature/foo",
"type": "SHORT",
}
}
@@ -48,49 +55,63 @@ exports[`render code 1`] = `
Array [
Object {
"actions": Array [],
- "component": "",
- "componentLongName": "",
- "componentQualifier": "",
- "componentUuid": "",
- "creationDate": "",
+ "component": "main.js",
+ "componentLongName": "main.js",
+ "componentQualifier": "FIL",
+ "componentUuid": "foo1234",
+ "creationDate": "2017-03-01T09:36:01+0100",
"flows": Array [],
"fromHotspot": false,
"key": "issue-1",
- "message": "",
- "organization": "",
- "project": "",
- "projectKey": "",
- "projectName": "",
- "projectOrganization": "",
- "rule": "",
- "ruleName": "",
+ "line": 25,
+ "message": "Reduce the number of conditional operators (4) used in the expression",
+ "organization": "myorg",
+ "project": "myproject",
+ "projectKey": "foo",
+ "projectName": "Foo",
+ "projectOrganization": "org",
+ "rule": "javascript:S1067",
+ "ruleName": "foo",
"secondaryLocations": Array [],
- "severity": "",
- "status": "",
+ "severity": "MAJOR",
+ "status": "OPEN",
+ "textRange": Object {
+ "endLine": 26,
+ "endOffset": 15,
+ "startLine": 25,
+ "startOffset": 0,
+ },
"transitions": Array [],
"type": "BUG",
},
Object {
"actions": Array [],
- "component": "",
- "componentLongName": "",
- "componentQualifier": "",
- "componentUuid": "",
- "creationDate": "",
+ "component": "main.js",
+ "componentLongName": "main.js",
+ "componentQualifier": "FIL",
+ "componentUuid": "foo1234",
+ "creationDate": "2017-03-01T09:36:01+0100",
"flows": Array [],
"fromHotspot": false,
"key": "issue-2",
- "message": "",
- "organization": "",
- "project": "",
- "projectKey": "",
- "projectName": "",
- "projectOrganization": "",
- "rule": "",
- "ruleName": "",
+ "line": 25,
+ "message": "Reduce the number of conditional operators (4) used in the expression",
+ "organization": "myorg",
+ "project": "myproject",
+ "projectKey": "foo",
+ "projectName": "Foo",
+ "projectOrganization": "org",
+ "rule": "javascript:S1067",
+ "ruleName": "foo",
"secondaryLocations": Array [],
- "severity": "",
- "status": "",
+ "severity": "MAJOR",
+ "status": "OPEN",
+ "textRange": Object {
+ "endLine": 26,
+ "endOffset": 15,
+ "startLine": 25,
+ "startOffset": 0,
+ },
"transitions": Array [],
"type": "BUG",
},
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/indexing-test.ts b/server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/indexing-test.ts
index 1dbd82fac36..19aef66e7b9 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/indexing-test.ts
+++ b/server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/indexing-test.ts
@@ -17,7 +17,32 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { symbolsByLine } from '../indexing';
+import { issuesByComponentAndLine, symbolsByLine } from '../indexing';
+import { mockIssue } from '../../../../helpers/testMocks';
+
+describe('issuesByComponentAndLine', () => {
+ it('should map issues by lines and components', () => {
+ const issues = [
+ mockIssue(true, { component: 'foo.js' }),
+ mockIssue(false, {
+ component: 'foo.js',
+ textRange: { startLine: 5, endLine: 5, startOffset: 0, endOffset: 0 }
+ }),
+ mockIssue(false, { component: 'bar.js' }),
+ mockIssue(),
+ mockIssue()
+ ];
+ const result = issuesByComponentAndLine(issues);
+ expect(Object.keys(result['foo.js'])).toHaveLength(2);
+ expect(Object.keys(result['foo.js'])).toEqual(['5', '26']);
+ expect(result['foo.js'][5]).toHaveLength(1);
+
+ expect(Object.keys(result['bar.js'])).toHaveLength(1);
+
+ expect(Object.keys(result['main.js'])).toHaveLength(1);
+ expect(result['main.js'][26]).toHaveLength(2);
+ });
+});
describe('symbolsByLine', () => {
it('should highlight symbols marked twice', () => {
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/issueLocations-test.ts b/server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/issueLocations-test.ts
new file mode 100644
index 00000000000..4096f9208d5
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/issueLocations-test.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 { getSecondaryIssueLocationsForLine, getLinearLocations } from '../issueLocations';
+import { mockSourceLine, mockFlowLocation } from '../../../../helpers/testMocks';
+
+describe('getSecondaryIssueLocationsForLine', () => {
+ it('should return secondary locations for a line', () => {
+ const sourceLine = mockSourceLine({ line: 2 });
+ expect(getSecondaryIssueLocationsForLine(sourceLine, undefined)).toEqual([]);
+ expect(getSecondaryIssueLocationsForLine(sourceLine, [mockFlowLocation()])).toEqual([
+ { from: 0, index: undefined, line: 2, startLine: 1, text: undefined, to: 2 }
+ ]);
+ });
+});
+
+describe('getLinearLocations', () => {
+ it('should return a linear location', () => {
+ expect(getLinearLocations({ startLine: 6, startOffset: 3, endLine: 8, endOffset: 56 })).toEqual(
+ [
+ { from: 3, line: 6, to: 999999 },
+ { from: 0, line: 7, to: 999999 },
+ { from: 0, line: 8, to: 56 }
+ ]
+ );
+ expect(getLinearLocations({ startLine: 6, startOffset: 0, endLine: 6, endOffset: 42 })).toEqual(
+ [{ from: 0, line: 6, to: 42 }]
+ );
+ });
+});
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.tsx b/server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.ts
index 9218ea9168e..9218ea9168e 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.ts
diff --git a/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceComponentViewer-test.tsx.snap b/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceComponentViewer-test.tsx.snap
index fb3201016c1..79e79272640 100644
--- a/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceComponentViewer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceComponentViewer-test.tsx.snap
@@ -28,7 +28,7 @@ exports[`should render 1`] = `
}
}
>
- <LazyLoader
+ <SourceViewer
component="foo"
onLoaded={[Function]}
/>