@testing-library 等待在延迟加载的组件中找不到元素
@testing-library waitfor not finding element in lazy loaded component
我正在尝试使用 @testing-library/react
waitfor
在比较快照之前等待延迟加载的组件。
App.tsx就是这样:
const MyComponent = lazy(() => import('my/component'));
function App() {
return (
<Suspense
fallback={
<div>
<h1>Loading…</h1>
</div>
}
>
<MyComponent />
</Suspense>
);
MyComponent
是:
export const MyComponent = memo(() => {
return <div data-testid='test' />;
});
测试是:
describe('<App />', () => {
it('should render the App', async () => {
const { container, findByTestId } = render(<App />);
await waitFor(() => findByTestId('test'));
expect(container.firstChild).toMatchSnapshot();
});
});
waitFor
超时,因为 findByTestId('test')
没有找到组件。如果我将 <MyComponent />
替换为 <div data-testid='test' />
,那么测试会按预期工作。
如果延迟加载,为什么无法正确呈现?
亚当
来自 React.lazy 文档:
React.lazy
takes a function that must call a dynamic import()
. This must return a Promise
which resolves to a module with a default
export containing a React component.
这是React.lazy
方法的签名:
function lazy<T extends ComponentType<any>>(
factory: () => Promise<{ default: T }>
): LazyExoticComponent<T>;
所以factory
函数应该是:
const MyComponent = lazy(() => import('./component').then(({ MyComponent }) => ({ default: MyComponent })));
此外,您不需要将 waitFor
与 findBy*
查询一起使用,因为:
findBy*
methods are a combination of getBy*
queries and waitFor
完整的工作示例:
component.tsx
:
import React from 'react';
import { memo } from 'react';
export const MyComponent = memo(() => {
return <div data-testid="test" />;
});
index.tsx
:
import React, { lazy, Suspense } from 'react';
const MyComponent = lazy(() => import('./component').then(({ MyComponent }) => ({ default: MyComponent })));
export function App() {
return (
<Suspense
fallback={
<div>
<h1>Loading…</h1>
</div>
}
>
<MyComponent />
</Suspense>
);
}
index.test.tsx
:
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
import { App } from '.';
describe('<App />', () => {
it('should render the App', async () => {
const { container, findByTestId } = render(<App />);
expect(container.firstChild).toMatchInlineSnapshot(`
<div>
<h1>
Loading…
</h1>
</div>
`);
const mycomp = await findByTestId('test');
expect(mycomp).toBeInTheDocument();
expect(container.firstChild).toMatchInlineSnapshot(`
<div
data-testid="test"
/>
`);
});
});
测试结果:
PASS Whosebug/71926928/index.test.tsx (11.382 s)
<App />
✓ should render the App (78 ms)
---------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
component.tsx | 100 | 100 | 100 | 100 |
index.tsx | 100 | 100 | 100 | 100 |
---------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 2 passed, 2 total
Time: 12.685 s
包版本:
"react": "^16.14.0",
"jest": "^26.6.3",
"@testing-library/react": "^11.2.7"
我正在尝试使用 @testing-library/react
waitfor
在比较快照之前等待延迟加载的组件。
App.tsx就是这样:
const MyComponent = lazy(() => import('my/component'));
function App() {
return (
<Suspense
fallback={
<div>
<h1>Loading…</h1>
</div>
}
>
<MyComponent />
</Suspense>
);
MyComponent
是:
export const MyComponent = memo(() => {
return <div data-testid='test' />;
});
测试是:
describe('<App />', () => {
it('should render the App', async () => {
const { container, findByTestId } = render(<App />);
await waitFor(() => findByTestId('test'));
expect(container.firstChild).toMatchSnapshot();
});
});
waitFor
超时,因为 findByTestId('test')
没有找到组件。如果我将 <MyComponent />
替换为 <div data-testid='test' />
,那么测试会按预期工作。
如果延迟加载,为什么无法正确呈现?
亚当
来自 React.lazy 文档:
React.lazy
takes a function that must call a dynamicimport()
. This must return aPromise
which resolves to a module with adefault
export containing a React component.
这是React.lazy
方法的签名:
function lazy<T extends ComponentType<any>>(
factory: () => Promise<{ default: T }>
): LazyExoticComponent<T>;
所以factory
函数应该是:
const MyComponent = lazy(() => import('./component').then(({ MyComponent }) => ({ default: MyComponent })));
此外,您不需要将 waitFor
与 findBy*
查询一起使用,因为:
findBy*
methods are a combination ofgetBy*
queries andwaitFor
完整的工作示例:
component.tsx
:
import React from 'react';
import { memo } from 'react';
export const MyComponent = memo(() => {
return <div data-testid="test" />;
});
index.tsx
:
import React, { lazy, Suspense } from 'react';
const MyComponent = lazy(() => import('./component').then(({ MyComponent }) => ({ default: MyComponent })));
export function App() {
return (
<Suspense
fallback={
<div>
<h1>Loading…</h1>
</div>
}
>
<MyComponent />
</Suspense>
);
}
index.test.tsx
:
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
import { App } from '.';
describe('<App />', () => {
it('should render the App', async () => {
const { container, findByTestId } = render(<App />);
expect(container.firstChild).toMatchInlineSnapshot(`
<div>
<h1>
Loading…
</h1>
</div>
`);
const mycomp = await findByTestId('test');
expect(mycomp).toBeInTheDocument();
expect(container.firstChild).toMatchInlineSnapshot(`
<div
data-testid="test"
/>
`);
});
});
测试结果:
PASS Whosebug/71926928/index.test.tsx (11.382 s)
<App />
✓ should render the App (78 ms)
---------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
component.tsx | 100 | 100 | 100 | 100 |
index.tsx | 100 | 100 | 100 | 100 |
---------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 2 passed, 2 total
Time: 12.685 s
包版本:
"react": "^16.14.0",
"jest": "^26.6.3",
"@testing-library/react": "^11.2.7"