From c7338818154ecaf188f16c83c3e1f5274fbc526f Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 17 May 2023 16:14:53 -0500 Subject: [PATCH] fix some test console errors The react testing library prints errors to the console about not using act(). This adds fixes/workarounds for most cases. --- package.json | 1 + src/app/App.test.tsx | 14 +++++++++++++- src/components/toolbar/Toolbar.test.tsx | 18 +++++++++--------- src/settings/Settings.test.tsx | 13 +++++++++++++ src/setupTests.ts | 6 +++++- yarn.lock | 10 ++++++++++ 6 files changed, 51 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index ddf36d5c..79179093 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@types/react": "^18.2.6", "@types/react-dom": "^18.2.4", "@types/react-splitter-layout": "^3.0.2", + "@types/react-transition-group": "^4.4.6", "@types/redux-logger": "^3.0.9", "@types/semver": "^7.5.0", "@types/w3c-web-usb": "^1.0.6", diff --git a/src/app/App.test.tsx b/src/app/App.test.tsx index f8891854..a4123493 100644 --- a/src/app/App.test.tsx +++ b/src/app/App.test.tsx @@ -1,11 +1,18 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2021-2022 The Pybricks Authors +// Copyright (c) 2021-2023 The Pybricks Authors import { cleanup } from '@testing-library/react'; import React from 'react'; import { testRender } from '../../test'; import App from './App'; +jest.mock('react', () => { + const React = jest.requireActual('react'); + // don't lazy-load, just use fallback for React.Suspense + React.Suspense = ({ fallback }: Record) => fallback; + return React; +}); + beforeAll(() => { // this lets us use jest.spyOn with window.innerWidth const defaultInnerWidth = window.innerWidth; @@ -14,6 +21,11 @@ beforeAll(() => { }); }); +beforeEach(() => { + // prevent tour popup + localStorage.setItem('tour.showOnStartup', 'false'); +}); + afterEach(() => { cleanup(); jest.resetAllMocks(); diff --git a/src/components/toolbar/Toolbar.test.tsx b/src/components/toolbar/Toolbar.test.tsx index d636341d..d4dabb85 100644 --- a/src/components/toolbar/Toolbar.test.tsx +++ b/src/components/toolbar/Toolbar.test.tsx @@ -68,7 +68,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button1.focus(); + act(() => button1.focus()); await act(() => user.keyboard('{ArrowRight}')); expect(button2).toHaveFocus(); @@ -82,7 +82,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button3.focus(); + act(() => button3.focus()); await act(() => user.keyboard('{ArrowLeft}')); expect(button2).toHaveFocus(); @@ -96,7 +96,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button3.focus(); + act(() => button3.focus()); await act(() => user.keyboard('{ArrowRight}')); expect(button1).toHaveFocus(); @@ -110,7 +110,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button1.focus(); + act(() => button1.focus()); await act(() => user.keyboard('{ArrowLeft}')); expect(button3).toHaveFocus(); @@ -124,7 +124,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button3.focus(); + act(() => button3.focus()); await act(() => user.keyboard('{Home}')); expect(button1).toHaveFocus(); @@ -138,7 +138,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button1.focus(); + act(() => button1.focus()); await act(() => user.keyboard('{End}')); expect(button3).toHaveFocus(); @@ -152,7 +152,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button2.focus(); + act(() => button2.focus()); await act(() => user.keyboard('{ArrowUp}')); expect(button2).toHaveFocus(); @@ -166,7 +166,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button2.focus(); + act(() => button2.focus()); await act(() => user.keyboard('{ArrowDown}')); expect(button2).toHaveFocus(); @@ -180,7 +180,7 @@ describe('Toolbar', () => { const { button1, button2, button3 } = getButtons(toolbar); - button2.focus(); + act(() => button2.focus()); await act(() => user.tab()); expect(document.body).toHaveFocus(); diff --git a/src/settings/Settings.test.tsx b/src/settings/Settings.test.tsx index a50a27aa..dd201d8c 100644 --- a/src/settings/Settings.test.tsx +++ b/src/settings/Settings.test.tsx @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2022-2023 The Pybricks Authors +import { AbstractPureComponent2 } from '@blueprintjs/core'; import { act, cleanup, getByLabelText, waitFor } from '@testing-library/react'; import React from 'react'; import { testRender } from '../../test'; @@ -8,6 +9,18 @@ import { firmwareInstallPybricks } from '../firmware/actions'; import { firmwareRestoreOfficialDialogShow } from '../firmware/restoreOfficialDialog/actions'; import Settings from './Settings'; +beforeEach(() => { + // this avoids react testing lib errors about not using act() by running + // callbacks immediately instead of deferring + jest.spyOn( + AbstractPureComponent2.prototype, + 'requestAnimationFrame', + ).mockImplementation((callback) => { + callback(); + return () => undefined; + }); +}); + afterEach(() => { cleanup(); jest.resetAllMocks(); diff --git a/src/setupTests.ts b/src/setupTests.ts index 59d1cf08..f2d17eef 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2020-2022 The Pybricks Authors +// Copyright (c) 2020-2023 The Pybricks Authors // jest-dom adds custom jest matchers for asserting on DOM nodes. // allows you to do things like: @@ -15,6 +15,10 @@ import { } from '@blueprintjs/core/lib/cjs/components/hotkeys/hotkeyParser'; // @ts-expect-error no typings import matchMediaPolyfill from 'mq-polyfill'; +import { config } from 'react-transition-group'; + +// avoid react testing library errors about not using act() +config.disabled = true; jest.mock('./fileStorage/hooks'); diff --git a/yarn.lock b/yarn.lock index 6d2494ec..00b6b573 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2652,6 +2652,7 @@ __metadata: "@types/react": ^18.2.6 "@types/react-dom": ^18.2.4 "@types/react-splitter-layout": ^3.0.2 + "@types/react-transition-group": ^4.4.6 "@types/redux-logger": ^3.0.9 "@types/semver": ^7.5.0 "@types/w3c-web-usb": ^1.0.6 @@ -4943,6 +4944,15 @@ __metadata: languageName: node linkType: hard +"@types/react-transition-group@npm:^4.4.6": + version: 4.4.6 + resolution: "@types/react-transition-group@npm:4.4.6" + dependencies: + "@types/react": "*" + checksum: 0872143821d7ee20a1d81e965f8b1e837837f11cd2206973f1f98655751992d9390304d58bac192c9cd923eca95bff107d8c9e3364a180240d5c2a6fd70fd7c3 + languageName: node + linkType: hard + "@types/react@npm:*, @types/react@npm:^18.2.6": version: 18.2.6 resolution: "@types/react@npm:18.2.6"