【发布时间】:2019-12-18 23:05:45
【问题描述】:
这可能更像是一个 JavaScript/TypeScript 问题,然后是关于 React/Testing。
但我会给出完整的故事。所以我有一个具有基本路由功能的测试应用程序和测试来验证路由是否有效。
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
一切正常。然后我添加了一个 useEffect 挂钩来初始化我的国际化库:
useEffect(() => {
async function initMessages() {
await intl.init({
currentLocale: "en-US",
locales
});
}
initMessages().then(() => setLoading(false));
}, [loading]);
这会加载我所有的英文文本资源。这工作正常,但通过以下错误消息破坏了我的所有测试:
Warning: An update to App inside a test was not wrapped in act(...).
在阅读了on the internet 之后,我设法通过添加这个“行为”功能来修复我的测试,这里是一个例子:
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.");
}
});
现在我正在使用@ts-ignore 抑制TS2454: Variable 'app' is used before being assigned. 警告。这很丑陋。如果我将断言移到 act 函数中,我会再次收到相同的 Warning: An update to App inside a test was not wrapped in act(...). 错误。
有没有办法从渲染函数中获取解构的容器对象,而不必使用@ts-ignore 和 if 子句进行空检查?
我为与这个问题相关的当前代码创建了一个标签: https://github.com/Leejjon/pwa-seo/releases/tag/uglylines 链接到最后一次提交:https://github.com/Leejjon/pwa-seo/commit/2434f78c0619be2d55f9de965149f6bd6d1a0b90
【问题讨论】:
-
它可以是未定义的,但你声明它只是HTMLElement?
-
TypeScript 无法判断
act是否会调用回调,也不能保证app会被定义。您可以尝试将act包装在另一个承诺中,该承诺将在回调内部使用app解决。在继续之前,您可能还需要等待act解决。 -
@alexey 说了什么。您可以在回调中移动测试代码。这会让 TS 闭嘴,因为它会保证 app 被定义。
-
@colefner 他试过了,但这违背了
act的目的,即允许 React 在使用expect进行断言之前完成所有生命周期钩子。 -
啊,是的,我错过了那部分。很好的收获,@AlexeyLebedev
标签: reactjs typescript jestjs react-testing-library