Dam*_*ira 5 mocking jsdom reactjs jestjs react-testing-library
我有一个对 url 搜索更改做出反应的组件,以及一个更改 url 搜索的按钮。我想测试当我单击按钮时,组件会做出相应的反应。这是一个codesandbox:https ://codesandbox.io/s/react-testing-library-url-change-test-b5zq1 。
应用程序.js
export default function App() {
const [urlChanged, setUrlChanged] = useState(false);
const handleURLSearchChange = () => {
window.location.search = new URLSearchParams({ foo: "bar" });
};
useEffect(() => {
if (window.location.search.length !== 0) {
setUrlChanged(true);
}
}, []);
return (
<div>
<button aria-label="change" onClick={handleURLSearchChange}>
Change URL search
</button>
<p aria-label="URL Status">{urlChanged ? "Changed!" : "Not yet"}</p>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
应用程序规范.js
describe("App", () => {
it("Reacts to url changes when touching the button", async () => {
render(<App />);
const button = await screen.findByLabelText("change");
userEvent.click(button);
const label = await screen.findByLabelText("URL Status");
await waitFor(() => expect(label).toHaveTextContent("Changed!"));
});
});
Run Code Online (Sandbox Code Playgroud)
问题是我得到:
Error: Not implemented: navigation (except hash changes)
Run Code Online (Sandbox Code Playgroud)
注意:只有当我下载沙箱并运行 npm install 和 npm test 时,我才能看到此错误。
我是否必须使用 setter 和 getter 来模拟 window.location 对象?更好的方法是什么?
您的组件代码实现存在一些问题。
\n如果第二个参数是空数组,则只会执行一次,因此更改事件处理程序中useEffect的值不会再次触发。您需要检查事件处理程序来决定是否设置 的值。window.location.searchhandleURLSearchChangeuseEffectlocation.searchurlChanged
正如 @jonrsharpe 的评论所说,JSDOM 不支持导航。我们需要使用 来模拟它Object.defineProperty()。
此外,类的实例URLSearchParams不能分配给window.location.search. 用于.toString()将其转换为字符串。
例如
\nApp.tsx:
import React from 'react';\nimport { useEffect, useState } from 'react';\n\nexport default function App() {\n const [urlChanged, setUrlChanged] = useState(false);\n const handleURLSearchChange = () => {\n window.location.search = '?' + new URLSearchParams({ foo: 'bar' }).toString();\n if (window.location.search.length !== 0) {\n setUrlChanged(true);\n }\n };\n\n return (\n <div>\n <button aria-label="change" onClick={handleURLSearchChange}>\n Change URL search\n </button>\n <p aria-label="URL Status">{urlChanged ? 'Changed!' : 'Not yet'}</p>\n </div>\n );\n}\nRun Code Online (Sandbox Code Playgroud)\nApp.test.tsx:
import { render, screen, waitFor } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\nimport '@testing-library/jest-dom';\nimport React from 'react';\nimport App from './App';\n\ndescribe('App', () => {\n it('Reacts to url changes when touching the button', async () => {\n Object.defineProperty(window, 'location', {\n value: {\n search: '',\n },\n });\n render(<App />);\n const button = await screen.findByLabelText('change');\n let label = await screen.findByLabelText('URL Status');\n await waitFor(() => expect(label).toHaveTextContent('Not yet'));\n userEvent.click(button);\n label = await screen.findByLabelText('URL Status');\n await waitFor(() => expect(label).toHaveTextContent('Changed!'));\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n测试结果:
\n PASS examples/67572637/App.test.tsx (8.34 s)\n App\n \xe2\x9c\x93 Reacts to url changes when touching the button (48 ms)\n\n----------|---------|----------|---------|---------|-------------------\nFile | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------|---------|----------|---------|---------|-------------------\nAll files | 100 | 75 | 100 | 100 | \n App.tsx | 100 | 75 | 100 | 100 | 8 \n----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests: 1 passed, 1 total\nSnapshots: 0 total\nTime: 8.906 s\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
21227 次 |
| 最近记录: |