3 * Copyright (C) 2009-2020 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 import { shallow } from 'enzyme';
21 import { range } from 'lodash';
22 import * as React from 'react';
23 import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
24 import { getSources } from '../../../../api/components';
25 import { mockBranch } from '../../../../helpers/mocks/branch-like';
26 import { mockHotspot } from '../../../../helpers/mocks/security-hotspots';
27 import { mockComponent, mockSourceLine } from '../../../../helpers/testMocks';
28 import HotspotSnippetContainer from '../HotspotSnippetContainer';
29 import HotspotSnippetContainerRenderer from '../HotspotSnippetContainerRenderer';
31 jest.mock('../../../../api/components', () => ({
32 getSources: jest.fn().mockResolvedValue([])
35 const branch = mockBranch();
37 it('should render correctly', () => {
38 expect(shallowRender()).toMatchSnapshot();
41 it('should load sources on mount', async () => {
42 (getSources as jest.Mock).mockResolvedValueOnce(
43 range(5, 18).map(line => mockSourceLine({ line }))
46 const hotspot = mockHotspot({
47 textRange: { startLine: 10, endLine: 11, startOffset: 0, endOffset: 12 }
50 const wrapper = shallowRender({ hotspot });
52 await waitAndUpdate(wrapper);
54 expect(getSources).toBeCalledWith(
55 expect.objectContaining({
59 expect(wrapper.state().lastLine).toBeUndefined();
60 expect(wrapper.state().sourceLines).toHaveLength(12);
63 it('should handle end-of-file on mount', async () => {
64 (getSources as jest.Mock).mockResolvedValueOnce(
65 range(5, 15).map(line => mockSourceLine({ line }))
68 const hotspot = mockHotspot({
69 textRange: { startLine: 10, endLine: 11, startOffset: 0, endOffset: 12 }
72 const wrapper = shallowRender({ hotspot });
74 await waitAndUpdate(wrapper);
76 expect(getSources).toBeCalled();
77 expect(wrapper.state().lastLine).toBe(14);
78 expect(wrapper.state().sourceLines).toHaveLength(10);
81 describe('Expansion', () => {
83 (getSources as jest.Mock).mockResolvedValueOnce(
84 range(5, 18).map(line => mockSourceLine({ line }))
88 const hotspot = mockHotspot({
89 textRange: { startLine: 10, endLine: 11, startOffset: 0, endOffset: 12 }
92 it('up should work', async () => {
93 (getSources as jest.Mock).mockResolvedValueOnce(
94 range(1, 5).map(line => mockSourceLine({ line }))
97 const wrapper = shallowRender({ hotspot });
98 await waitAndUpdate(wrapper);
101 .find(HotspotSnippetContainerRenderer)
103 .onExpandBlock('up');
105 await waitAndUpdate(wrapper);
107 expect(getSources).toBeCalledWith(
108 expect.objectContaining({
112 expect(wrapper.state().sourceLines).toHaveLength(16);
115 it('down should work', async () => {
116 (getSources as jest.Mock).mockResolvedValueOnce(
117 // lastLine + expand + extra for EOF check + range end is excluded
119 range(17, 68).map(line => mockSourceLine({ line }))
122 const wrapper = shallowRender({ hotspot });
123 await waitAndUpdate(wrapper);
126 .find(HotspotSnippetContainerRenderer)
128 .onExpandBlock('down');
130 await waitAndUpdate(wrapper);
132 expect(wrapper.state().lastLine).toBeUndefined();
133 expect(wrapper.state().sourceLines).toHaveLength(62);
136 it('down should work and handle EOF', async () => {
137 (getSources as jest.Mock).mockResolvedValueOnce(
138 // lastLine + expand + extra for EOF check + range end is excluded - 1 to trigger end-of-file
139 // 16 + 50 + 1 + 1 - 1
140 range(17, 67).map(line => mockSourceLine({ line }))
143 const wrapper = shallowRender({ hotspot });
144 await waitAndUpdate(wrapper);
147 .find(HotspotSnippetContainerRenderer)
149 .onExpandBlock('down');
151 await waitAndUpdate(wrapper);
153 expect(wrapper.state().lastLine).toBe(66);
154 expect(wrapper.state().sourceLines).toHaveLength(62);
158 it('should handle line popups', async () => {
159 (getSources as jest.Mock).mockResolvedValueOnce(
160 range(5, 18).map(line => mockSourceLine({ line }))
163 const wrapper = shallowRender();
164 await waitAndUpdate(wrapper);
166 const params = wrapper.state().sourceLines[0];
169 .find(HotspotSnippetContainerRenderer)
171 .onLinePopupToggle(params);
173 expect(wrapper.state().linePopup).toEqual(params);
177 .find(HotspotSnippetContainerRenderer)
179 .onLinePopupToggle(params);
181 expect(wrapper.state().linePopup).toBeUndefined();
184 it('should handle symbol click', () => {
185 const wrapper = shallowRender();
186 const symbols = ['symbol'];
188 .find(HotspotSnippetContainerRenderer)
190 .onSymbolClick(symbols);
191 expect(wrapper.state().highlightedSymbols).toBe(symbols);
194 function shallowRender(props?: Partial<HotspotSnippetContainer['props']>) {
195 return shallow<HotspotSnippetContainer>(
196 <HotspotSnippetContainer
198 component={mockComponent()}
199 hotspot={mockHotspot()}