This is probably more of a JavaScript/TypeScript question then it is about React/Testing.
But I’ll give the complete story. So I have a test app with basic routing functionality and tests to verify that the routing works.
App.tsx
https://github.com/Leejjon/pwa-seo/blob/6f621968de1184b03744a262a68d291b4571c5c1/src/App.tsx
App.test.tsx
https://github.com/Leejjon/pwa-seo/blob/6f621968de1184b03744a262a68d291b4571c5c1/src/App.test.tsx
Everything worked fine. Then I added an useEffect hook to initialize my internationalization library:
useEffect(() => {
async function initMessages() {
await intl.init({
currentLocale: "en-US",
locales
});
}
initMessages().then(() => setLoading(false));
}, [loading]);
This loads all my text assets in English. This works fine, but broke all my tests with the following error message:
Warning: An update to App inside a test was not wrapped in act(...).
After some reading up on the internet I managed to fix my tests by adding this ‘act’ function, here is one example:
import React from 'react';
import {act, render, fireEvent, waitForElement} from '@testing-library/react';
import "@testing-library/jest-dom/extend-expect";
import App from './App';
test('Verify home page header', async() => {
let app: HTMLElement;
await act(async () => {
const {container} = render(<App/>);
app = container;
});
// @ts-ignore
if (app) {
const pageHeaderContent = app.querySelector("#pageHeader")?.firstChild?.textContent;
expect(pageHeaderContent).toMatch('Home page');
} else {
fail("The app should have been initialized.");
}
});
Right now I’m suppressing the TS2454: Variable 'app' is used before being assigned.
warning with the @ts-ignore. This is ugly. If I move my assertions into the act function, I get the same Warning: An update to App inside a test was not wrapped in act(...).
error again.
Is there a way to obtain the container object destructured from the render function without having to use the @ts-ignore and the if clause to do null checking?
I created a tag for the current code related to this question:
https://github.com/Leejjon/pwa-seo/releases/tag/uglylines
Link to last commit: https://github.com/Leejjon/pwa-seo/commit/2434f78c0619be2d55f9de965149f6bd6d1a0b90
2
Answers
After puzzling this is my result
Better suggestions (if there is some way of not having to use the 'act' function) are still welcome.
Typescript is complaining about the app variable to not have been initialised when you access it in the if-statement. You can simply fix that by assigning
null
to it.In case you use strict null checks you have to allow null on the type: