Skip to content

Migrate out of Enzyme testing library to facilitate react 18 upgrade #2524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@
"devDependencies": {
"@craco/craco": "^7.1.0",
"@svgr/webpack": "^6.3.1",
"@testing-library/react": "^12.1.2",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "12.1.2",
"@testing-library/user-event": "^14.3.0",
"@types/acorn": "^6.0.0",
"@types/enzyme": "3.10.13",
"@types/gapi": "^0.0.44",
"@types/gapi.auth2": "^0.0.57",
"@types/gapi.client": "^1.0.5",
Expand All @@ -108,21 +108,19 @@
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"@types/react-syntax-highlighter": "^15.5.7",
"@types/react-test-renderer": "^18.0.0",
"@types/react-test-renderer": "^17.0.2",
"@types/react-textarea-autosize": "^8.0.0",
"@types/redux-mock-store": "^1.0.3",
"@types/showdown": "^2.0.1",
"@types/uuid": "^8.3.4",
"@types/xml2js": "^0.4.11",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.7",
"babel-core": "6",
"babel-runtime": "^6.26.0",
"buffer": "^6.0.3",
"canvas": "^2.9.3",
"constants-browserify": "^1.0.0",
"coveralls": "^3.1.1",
"cross-env": "^7.0.3",
"enzyme": "^3.11.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"https-browserify": "^1.0.0",
"husky": "^8.0.2",
Expand All @@ -132,7 +130,7 @@
"process": "^0.11.10",
"react-error-overlay": "^6.0.11",
"react-scripts": "^5.0.1",
"react-test-renderer": "^18.2.0",
"react-test-renderer": "^17.0.2",
"redux-saga-test-plan": "^4.0.6",
"resize-observer-polyfill": "^1.5.1",
"sass": "^1.62.1",
Expand Down
7 changes: 3 additions & 4 deletions src/commons/__tests__/ContentDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { mount } from 'enzyme';

import ContentDisplay, { ContentDisplayProps } from '../ContentDisplay';
import { renderTreeJson } from '../utils/TestUtils';

const mockProps: ContentDisplayProps = {
display: <div> Test Content </div>,
Expand All @@ -9,6 +8,6 @@ const mockProps: ContentDisplayProps = {

test('ContentDisplay page renders correctly', () => {
const app = <ContentDisplay {...mockProps} />;
const tree = mount(app);
expect(tree.debug()).toMatchSnapshot();
const tree = renderTreeJson(app);
expect(tree).toMatchSnapshot();
});
6 changes: 3 additions & 3 deletions src/commons/__tests__/Markdown.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { mount } from 'enzyme';
import { Chapter, Variant } from 'js-slang/dist/types';

import { getLanguageConfig } from '../application/ApplicationTypes';
import Markdown from '../Markdown';
import { generateLanguageIntroduction } from '../utils/IntroductionHelper';
import { renderTreeJson } from '../utils/TestUtils';

const mockProps = (sourceChapter: Chapter, sourceVariant: Variant) => {
return {
Expand All @@ -14,8 +14,8 @@ const mockProps = (sourceChapter: Chapter, sourceVariant: Variant) => {

test('Markdown page renders correctly', () => {
const app = <Markdown {...mockProps(Chapter.SOURCE_1, Variant.DEFAULT)} />;
const tree = mount(app);
expect(tree.debug()).toMatchSnapshot();
const tree = renderTreeJson(app);
expect(tree).toMatchSnapshot();
});

test('Markdown page renders correct Source information', () => {
Expand Down
24 changes: 13 additions & 11 deletions src/commons/__tests__/__snapshots__/ContentDisplay.tsx.snap
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ContentDisplay page renders correctly 1`] = `
"<ContentDisplay display={{...}} loadContentDispatch={[Function: loadContentDispatch]}>
<div className=\\"ContentDisplay row center-xs\\">
<div className=\\"col-md-10 col-xs-11 contentdisplay-content-parent\\">
<Blueprint4.Card className=\\"contentdisplay-content\\" elevation={3} interactive={false}>
<div className=\\"bp4-card bp4-elevation-3 contentdisplay-content\\">
<div>
Test Content
</div>
</div>
</Blueprint4.Card>
<div
className="ContentDisplay row center-xs"
>
<div
className="col-md-10 col-xs-11 contentdisplay-content-parent"
>
<div
className="bp4-card bp4-elevation-3 contentdisplay-content"
>
<div>
Test Content
</div>
</div>
</div>
</ContentDisplay>"
</div>
`;
15 changes: 12 additions & 3 deletions src/commons/__tests__/__snapshots__/Markdown.tsx.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Markdown page renders correctly 1`] = `
"<Memo(Markdown) content=\\"\\\\nWelcome to the Source Academy playground!\\\\n\\\\nThe book [_Structure and Interpretation of Computer Programs, JavaScript Edition_](https://sourceacademy.org/sicpjs/)\\\\nuses JavaScript sublanguages that we call [_Source_](https://docs.sourceacademy.org/). You have chosen the sublanguage [_Source §1_](https://docs.sourceacademy.org/source_1/).\\\\n\\\\nIn the editor on the left, you can use the [_Ace keyboard shortcuts_](https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts) \\\\nand also the [_Source Academy keyboard shortcuts_](https://github.com/source-academy/frontend/wiki/Source-Academy-Keyboard-Shortcuts).\\\\n\\\\n\\" openLinksInNewWindow={true}>
<div className=\\"md bp4-running-text\\" dangerouslySetInnerHTML={{...}} />
</Memo(Markdown)>"
<div
className="md bp4-running-text"
dangerouslySetInnerHTML={
Object {
"__html": "<p>Welcome to the Source Academy playground!</p>
<p>The book <a href=\\"https://sourceacademy.org/sicpjs/\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Structure and Interpretation of Computer Programs, JavaScript Edition</em></a>
uses JavaScript sublanguages that we call <a href=\\"https://docs.sourceacademy.org/\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Source</em></a>. You have chosen the sublanguage <a href=\\"https://docs.sourceacademy.org/source_1/\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Source §1</em></a>.</p>
<p>In the editor on the left, you can use the <a href=\\"https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Ace keyboard shortcuts</em></a>
and also the <a href=\\"https://github.com/source-academy/frontend/wiki/Source-Academy-Keyboard-Shortcuts\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Source Academy keyboard shortcuts</em></a>.</p>",
}
}
/>
`;
6 changes: 3 additions & 3 deletions src/commons/application/__tests__/Application.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { shallow } from 'enzyme';
import { useSelector } from 'react-redux';
import { shallowRender } from 'src/commons/utils/TestUtils';

import Application from '../Application';

Expand All @@ -25,6 +25,6 @@ test('Application renders correctly', () => {
useSelectorMock.mockReturnValue({ name: 'Bob' });

const app = <Application />;
const tree = shallow(app);
expect(tree.debug()).toMatchSnapshot();
const tree = shallowRender(app);
expect(tree).toMatchSnapshot();
});
51 changes: 21 additions & 30 deletions src/commons/application/__tests__/ApplicationWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { act, waitFor } from '@testing-library/react';
import { mount } from 'enzyme';
import { render, screen, waitFor } from '@testing-library/react';
import moment from 'moment';
import { Provider } from 'react-redux';
import { createMemoryRouter, RouterProvider } from 'react-router';
Expand Down Expand Up @@ -31,7 +30,7 @@ describe('ApplicationWrapper', () => {
store = createStore();
});

test('ApplicationWrapper renders NotFound on unknown routes (Full Academy)', () => {
test('ApplicationWrapper renders NotFound on unknown routes (Full Academy)', async () => {
const routerConfig = getFullAcademyRouterConfig({
name: 'Bob',
role: Role.Student,
Expand All @@ -46,12 +45,12 @@ describe('ApplicationWrapper', () => {
/>
</Provider>
);
const tree = mount(app);
waitFor(() => expect(tree.find('.NoPage').length).toBe(1));
expect(tree.find('.NavigationBar__link.pt-active').length).toBe(0);
render(app);
const element = await waitFor(() => screen.getByTestId('NotFound-Component'));
expect(element).toBeTruthy();
});

test('ApplicationWrapper renders NotFound on unknown routes (Playground Only)', () => {
test('ApplicationWrapper renders NotFound on unknown routes (Playground Only)', async () => {
const routerConfig = playgroundOnlyRouterConfig;

const app = (
Expand All @@ -61,12 +60,12 @@ describe('ApplicationWrapper', () => {
/>
</Provider>
);
const tree = mount(app);
waitFor(() => expect(tree.find('.NoPage').length).toBe(1));
expect(tree.find('.NavigationBar__link.pt-active').length).toBe(0);
render(app);
const element = await waitFor(() => screen.getByTestId('NotFound-Component'));
expect(element).toBeTruthy();
});

test('ApplicationWrapper renders Disabled on unknown routes (Disabled)', () => {
test('ApplicationWrapper renders Disabled on unknown routes (Disabled)', async () => {
const store = createStore();
const routerConfig = getDisabledRouterConfig('testing');

Expand All @@ -77,14 +76,12 @@ describe('ApplicationWrapper', () => {
/>
</Provider>
);
const tree = mount(app);
waitFor(() => expect(tree.find('.NoPage').length).toBe(1));
waitFor(() =>
expect(
tree.text().includes('The Source Academy has been disabled for this reason: testing.')
).toBe(true)
render(app);
const element = await waitFor(() => screen.getByTestId('Disabled-Component'));
expect(element).toBeTruthy();
expect(element).toHaveTextContent(
'The Source Academy has been disabled for this reason: testing.'
);
expect(tree.find('.NavigationBar__link.pt-active').length).toBe(0);
});

test('Application shows disabled when in disabled period', async () => {
Expand All @@ -105,21 +102,15 @@ describe('ApplicationWrapper', () => {
<ApplicationWrapper />
</Provider>
);
const tree = mount(app);

// Let react-router loader functions finish running
await waitForComponentToPaint(tree);

expect(tree.debug()).toMatchSnapshot();
render(app);
const element = await waitFor(() => screen.getByTestId('Disabled-Component'));
expect(element).toBeTruthy();
expect(element).toHaveTextContent(
'The Source Academy has been disabled for this reason: Testing.'
);

Constants.disablePeriods = origPeriods;
Constants.playgroundOnly = origPlaygroundOnly;
});
});

const waitForComponentToPaint = async (wrapper: any) => {
await act(async () => {
await new Promise(resolve => setTimeout(resolve));
wrapper.update();
});
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Application renders correctly 1`] = `
"<ContextProvider value={{...}}>
<div className=\\"Application\\">
<Context.Provider
value={
Array [
Object {
"editorBinding": "",
},
[Function],
]
}
>
<div
className="Application"
>
<NavigationBar />
<div className=\\"Application__main\\">
<div
className="Application__main"
>
<Outlet />
</div>
</div>
</ContextProvider>"
</Context.Provider>
`;
Loading