Browse Source

[NO JIRA] Make frontend test execute faster using SWC

tags/9.4.0.54424
Mathieu Suen 2 years ago
parent
commit
0abfd42644

+ 8
- 1
server/sonar-web/jest.config.js View File

@@ -27,7 +27,14 @@ module.exports = {
testRegex: '(/__tests__/.*|\\-test)\\.(ts|tsx|js)$',
transform: {
'\\.js$': 'babel-jest',
'\\.(ts|tsx)$': 'ts-jest'
'^.+\\.tsx?$': [
'@swc/jest',
{
jsc: {
target: 'es2018'
}
}
]
},
reporters: [
'default',

+ 3
- 1
server/sonar-web/package.json View File

@@ -60,6 +60,8 @@
"@babel/preset-env": "7.16.11",
"@babel/preset-react": "7.16.7",
"@emotion/jest": "11.7.1",
"@swc/core": "1.2.157",
"@swc/jest": "0.2.20",
"@testing-library/dom": "8.11.3",
"@testing-library/jest-dom": "5.16.2",
"@testing-library/react": "12.1.2",
@@ -117,7 +119,7 @@
"glob": "7.2.0",
"glob-promise": "3.4.0",
"http-proxy": "1.18.1",
"jest": "27.4.7",
"jest": "27.5.1",
"jest-emotion": "10.0.32",
"jest-junit": "13.0.0",
"jsdom": "16.7.0",

+ 13
- 7
server/sonar-web/src/main/js/app/components/__tests__/KeyboardShortcutsModal-test.tsx View File

@@ -23,16 +23,22 @@ import Modal from '../../../components/controls/Modal';
import { mockEvent } from '../../../helpers/testMocks';
import KeyboardShortcutsModal from '../KeyboardShortcutsModal';

let handle: void | (() => void);
beforeEach(() => {
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => {
handle = f();
});
jest.mock('react', () => {
let close: () => void;
return {
...jest.requireActual('react'),
useEffect: jest.fn().mockImplementation(f => {
close = f();
}),
clean: () => {
close();
}
};
});

afterEach(() => {
if (handle) {
handle();
if ((React as any).clean as () => void) {
(React as any).clean();
}
});


+ 17
- 3
server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx View File

@@ -29,9 +29,24 @@ import ComponentNav, { ComponentNavProps } from '../ComponentNav';
import Menu from '../Menu';
import InfoDrawer from '../projectInformation/InfoDrawer';

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useEffect: jest.fn().mockImplementation(f => f())
};
});

jest.mock('../../../RecentHistory', () => {
return {
__esModule: true,
default: class RecentHistory {
static add = jest.fn();
}
};
});

beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
});

it('renders correctly', () => {
@@ -53,7 +68,6 @@ it('correctly adds data to the history if there are breadcrumbs', () => {
const key = 'foo';
const name = 'Foo';
const qualifier = ComponentQualifier.Portfolio;
const spy = jest.spyOn(RecentHistory, 'add');

shallowRender({
component: mockComponent({
@@ -69,7 +83,7 @@ it('correctly adds data to the history if there are breadcrumbs', () => {
})
});

expect(spy).toBeCalledWith(key, name, qualifier.toLowerCase());
expect(RecentHistory.add).toBeCalledWith(key, name, qualifier.toLowerCase());
});

it('correctly toggles the project info display', () => {

+ 8
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/AzurePersonalAccessTokenForm-test.tsx View File

@@ -27,6 +27,13 @@ import AzurePersonalAccessTokenForm, {
AzurePersonalAccessTokenFormProps
} from '../AzurePersonalAccessTokenForm';

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useEffect: jest.fn()
};
});

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ submitting: true })).toMatchSnapshot('submitting');
@@ -51,7 +58,7 @@ it('should correctly handle form interactions', () => {
// If validation fails, we toggle the submitting flag and call useEffect()
// to set the `touched` flag to false again. Trigger a re-render, and mock
// useEffect(). This should de-activate the submit button again.
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
(React.useEffect as jest.Mock).mockImplementationOnce(f => f());
wrapper.setProps({ submitting: false });
expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true);
});

+ 6
- 3
server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx View File

@@ -33,9 +33,12 @@ import CreateProjectModeSelection from '../CreateProjectModeSelection';
import { CreateProjectPage } from '../CreateProjectPage';
import { CreateProjectModes } from '../types';

jest.mock('../../../../api/alm-settings', () => ({
getAlmSettings: jest.fn().mockResolvedValue([{ alm: AlmKeys.BitbucketServer, key: 'foo' }])
}));
jest.mock('../../../../api/alm-settings', () => {
const { AlmKeys } = jest.requireActual('../../../../types/alm-settings');
return {
getAlmSettings: jest.fn().mockResolvedValue([{ alm: AlmKeys.BitbucketServer, key: 'foo' }])
};
});

beforeEach(jest.clearAllMocks);


+ 0
- 6
server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-test.tsx View File

@@ -31,12 +31,6 @@ jest.mock('../../../../api/issues', () => ({
searchIssueTags: jest.fn().mockResolvedValue([undefined, []])
}));

jest.mock('../BulkChangeModal', () => {
const mock = jest.requireActual('../BulkChangeModal');
mock.MAX_PAGE_SIZE = 1;
return mock;
});

jest.mock('../../utils', () => ({
searchAssignees: jest.fn().mockResolvedValue({
results: [

+ 2
- 2
server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap View File

@@ -109,7 +109,7 @@ exports[`should display form when issues are present 1`] = `

exports[`should display warning when too many issues are passed 1`] = `
<h2>
issue_bulk_change.form.title.1
issue_bulk_change.form.title.500
</h2>
`;

@@ -123,7 +123,7 @@ exports[`should display warning when too many issues are passed 2`] = `
values={
Object {
"max": <strong>
1
500
</strong>,
}
}

+ 11
- 3
server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx View File

@@ -40,6 +40,14 @@ beforeEach(() => {
jest.clearAllMocks();
});

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useRef: jest.fn(),
useEffect: jest.fn()
};
});

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(
@@ -97,9 +105,9 @@ describe('side effect', () => {
const fakeParent = document.createElement('div');

beforeEach(() => {
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
(React.useEffect as jest.Mock).mockImplementationOnce(f => f());
jest.spyOn(document, 'querySelector').mockImplementationOnce(() => fakeElement);
jest.spyOn(React, 'useRef').mockImplementationOnce(() => ({ current: fakeParent }));
(React.useRef as jest.Mock).mockImplementationOnce(() => ({ current: fakeParent }));
});

it('should trigger scrolling', () => {
@@ -117,7 +125,7 @@ describe('side effect', () => {
});

it('should not trigger scrolling if no parent', () => {
const mockUseRef = jest.spyOn(React, 'useRef');
const mockUseRef = React.useRef as jest.Mock;
mockUseRef.mockReset();
mockUseRef.mockImplementationOnce(() => ({ current: null }));
shallowRender({ selectedHotspot: mockRawHotspot() });

+ 14
- 6
server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotPrimaryLocationBox-test.tsx View File

@@ -28,6 +28,14 @@ import {
HotspotPrimaryLocationBoxProps
} from '../HotspotPrimaryLocationBox';

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useRef: jest.fn(),
useEffect: jest.fn()
};
});

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('User logged in');
expect(shallowRender({ currentUser: mockCurrentUser() })).toMatchSnapshot('User not logged in ');
@@ -55,8 +63,8 @@ it('should handle click', () => {

it('should scroll on load if no secondary locations selected', () => {
const node = document.createElement('div');
jest.spyOn(React, 'useRef').mockImplementationOnce(() => ({ current: node }));
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
(React.useRef as jest.Mock).mockImplementationOnce(() => ({ current: node }));
(React.useEffect as jest.Mock).mockImplementationOnce(f => f());

const scroll = jest.fn();
shallowRender({ scroll });
@@ -66,8 +74,8 @@ it('should scroll on load if no secondary locations selected', () => {

it('should not scroll on load if a secondary location is selected', () => {
const node = document.createElement('div');
jest.spyOn(React, 'useRef').mockImplementationOnce(() => ({ current: node }));
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
(React.useRef as jest.Mock).mockImplementationOnce(() => ({ current: node }));
(React.useEffect as jest.Mock).mockImplementationOnce(f => f());

const scroll = jest.fn();
shallowRender({ scroll, secondaryLocationSelected: true });
@@ -76,8 +84,8 @@ it('should not scroll on load if a secondary location is selected', () => {
});

it('should not scroll on load if node is not defined', () => {
jest.spyOn(React, 'useRef').mockImplementationOnce(() => ({ current: undefined }));
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
(React.useRef as jest.Mock).mockImplementationOnce(() => ({ current: undefined }));
(React.useEffect as jest.Mock).mockImplementationOnce(f => f());

const scroll = jest.fn();
shallowRender({ scroll });

+ 9
- 2
server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotReviewHistory-test.tsx View File

@@ -28,6 +28,13 @@ import { mockUser } from '../../../../helpers/testMocks';
import HotspotCommentPopup from '../HotspotCommentPopup';
import HotspotReviewHistory, { HotspotReviewHistoryProps } from '../HotspotReviewHistory';

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useState: jest.fn().mockImplementation(() => ['', jest.fn()])
};
});

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ showFullHistory: true })).toMatchSnapshot('show full list');
@@ -46,7 +53,7 @@ it('should render correctly', () => {
it('should correctly handle comment updating', () => {
return new Promise<void>((resolve, reject) => {
const setEditedCommentKey = jest.fn();
jest.spyOn(React, 'useState').mockImplementationOnce(() => ['', setEditedCommentKey]);
(React.useState as jest.Mock).mockImplementationOnce(() => ['', setEditedCommentKey]);

const onEditComment = jest.fn();
const wrapper = shallowRender({ onEditComment, showFullHistory: true });
@@ -102,7 +109,7 @@ it('should correctly handle comment updating', () => {
it('should correctly handle comment deleting', () => {
return new Promise<void>((resolve, reject) => {
const setEditedCommentKey = jest.fn();
jest.spyOn(React, 'useState').mockImplementationOnce(() => ['', setEditedCommentKey]);
(React.useState as jest.Mock).mockImplementationOnce(() => ['', setEditedCommentKey]);

const onDeleteComment = jest.fn();
const wrapper = shallowRender({ onDeleteComment, showFullHistory: true });

+ 11
- 4
server/sonar-web/src/main/js/apps/settings/components/__tests__/SettingsSearchRenderer-test.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import React from 'react';
import * as React from 'react';
import { mockDefinition } from '../../../../helpers/mocks/settings';
import { scrollToElement } from '../../../../helpers/scrolling';
import SettingsSearchRenderer, { SettingsSearchRendererProps } from '../SettingsSearchRenderer';
@@ -27,6 +27,14 @@ jest.mock('../../../../helpers/scrolling', () => ({
scrollToElement: jest.fn()
}));

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useRef: jest.fn(),
useEffect: jest.fn()
};
});

afterAll(() => {
jest.clearAllMocks();
});
@@ -52,11 +60,10 @@ it('should scroll to selected element', () => {
const selected = {};
const selectedRef = { current: selected };

jest
.spyOn(React, 'useRef')
(React.useRef as jest.Mock)
.mockImplementationOnce(() => scrollableRef)
.mockImplementationOnce(() => selectedRef);
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
(React.useEffect as jest.Mock).mockImplementationOnce(f => f());

shallowRender();


+ 11
- 3
server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineCoverage-test.tsx View File

@@ -18,9 +18,17 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import React from 'react';
import * as React from 'react';
import { LineCoverage, LineCoverageProps } from '../LineCoverage';

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useRef: jest.fn(),
useEffect: jest.fn()
};
});

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('covered');
expect(shallowRender({ line: { line: 3, coverageStatus: 'uncovered' } })).toMatchSnapshot(
@@ -39,8 +47,8 @@ it('should render correctly', () => {

it('should correctly trigger a scroll', () => {
const element = { current: {} };
jest.spyOn(React, 'useEffect').mockImplementation(f => f());
jest.spyOn(React, 'useRef').mockImplementation(() => element);
(React.useEffect as jest.Mock).mockImplementation(f => f());
(React.useRef as jest.Mock).mockImplementation(() => element);

const scroll = jest.fn();
shallowRender({ scroll, scrollToUncoveredLine: true });

+ 8
- 1
server/sonar-web/src/main/js/components/ui/__tests__/DismissableAlert-test.tsx View File

@@ -32,9 +32,16 @@ jest.mock('../../../helpers/storage', () => ({
save: jest.fn()
}));

jest.mock('react', () => {
return {
...jest.requireActual('react'),
useEffect: jest.fn()
};
});

beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
(React.useEffect as jest.Mock).mockImplementationOnce(f => f());
});

it('should render correctly', () => {

+ 651
- 310
server/sonar-web/yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save