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

Reactjs 如何使用react测试库测试更改的url搜索?,reactjs,jestjs,mocking,react-testing-library,jsdom,Reactjs,Jestjs,Mocking,React Testing Library,Jsdom,我有一个对url搜索更改做出反应的组件和一个更改url搜索的按钮。我想测试一下,当我点击按钮时,组件会做出相应的反应。这里有一个代码沙盒: App.js 导出默认函数App(){ const[urlChanged,setUrlChanged]=useState(false); 常量handleURLSearchChange=()=>{ window.location.search=新的URLSearchParams({foo:bar}); }; useffect(()=>{ if(window.

我有一个对url搜索更改做出反应的组件和一个更改url搜索的按钮。我想测试一下,当我点击按钮时,组件会做出相应的反应。这里有一个代码沙盒:

App.js

导出默认函数App(){
const[urlChanged,setUrlChanged]=useState(false);
常量handleURLSearchChange=()=>{
window.location.search=新的URLSearchParams({foo:bar});
};
useffect(()=>{
if(window.location.search.length!==0){
setUrlChanged(true);
}
}, []);
返回(
更改URL搜索

{urlChanged?”Changed!”:“尚未”}

); }
App.spec.js

description(“应用程序”),()=>{
它(“触摸按钮时对url更改作出反应”,异步()=>{
render();
const button=wait screen.findByLabelText(“更改”);
userEvent.click(按钮);
const label=wait screen.findByLabelText(“URL状态”);
等待waitFor(()=>expect(label).toHaveTextContent(“Changed!”);
});
});
问题是我得到了:

    Error: Not implemented: navigation (except hash changes)

注意:只有在我不加载沙箱并运行npm安装和npm测试的情况下,我才能看到这个错误


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

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

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


正如@jornsharpe的评论所说,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>
  );
}
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

JSDOM不支持导航:。您要么需要用测试双精度替换
window.location
,要么使用React Router之类的工具(请参阅以了解如何测试)。