如何使用react测试库测试更改的url搜索



我有一个组件可以对url搜索的更改做出反应,还有一个按钮可以更改url搜索。我想测试一下,当我点击按钮时,组件会做出相应的反应。这是一个代码沙盒:https://codesandbox.io/s/react-testing-library-url-change-test-b5zq1.

App.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>
);
}

App.spec.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!"));
});
});

问题是我得到了:

Error: Not implemented: navigation (except hash changes)

注意:只有当我没有加载沙箱,并运行npm安装和npm测试时,我才能看到这个错误。

我必须用setter和getter来模拟window.location对象吗?最好的方法是什么?

组件代码实现存在一些问题。

如果第二个参数是空数组,则useEffect将只执行一次,因此在事件处理程序handleURLSearchChange中更改window.location.search的值将不会再次触发useEffect。您需要在事件处理程序中检查location.search,以决定是否设置urlChanged的值。

正如@jonrsharpe的评论所说,JSDOM不支持导航。我们需要使用Object.defineProperty()来模拟它。

此外,URLSearchParams类的实例不能分配给window.location.search。使用.toString()将其转换为字符串。

例如

App.tsx:

import React from 'react';
import { useEffect, useState } from 'react';
export default function App() {
const [urlChanged, setUrlChanged] = useState(false);
const handleURLSearchChange = () => {
window.location.search = '?' + new URLSearchParams({ foo: 'bar' }).toString();
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>
);
}

App.test.tsx:

import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import React from 'react';
import App from './App';
describe('App', () => {
it('Reacts to url changes when touching the button', async () => {
Object.defineProperty(window, 'location', {
value: {
search: '',
},
});
render(<App />);
const button = await screen.findByLabelText('change');
let label = await screen.findByLabelText('URL Status');
await waitFor(() => expect(label).toHaveTextContent('Not yet'));
userEvent.click(button);
label = await screen.findByLabelText('URL Status');
await waitFor(() => expect(label).toHaveTextContent('Changed!'));
});
});

测试结果:

PASS  examples/67572637/App.test.tsx (8.34 s)
App
✓ Reacts to url changes when touching the button (48 ms)
----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |       75 |     100 |     100 |                   
App.tsx  |     100 |       75 |     100 |     100 | 8                 
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.906 s

最新更新