React 测试库 - 无法测试 Window Resize React Hook
React Testing Library - Failing to test Window Resize React Hook
我创建了一个自定义 React Hook,用于在 window 调整大小时获取视口宽度和高度(事件已去抖动)。钩子工作正常,但我一直无法找到使用 React 测试库进行测试的方法(我一直 运行 出错)。
我已经在 CodeSandbox 中重新创建了应用程序(连同测试)以尝试调试,但我在测试时 运行 遇到了不同的错误。
有时我得到:
Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'.`
但是一般的失败是hook出来的数据好像没有返回
expect(received).toBe(expected) // Object.is equality
Expected: 500
Received: undefined
这可能是我在 React 测试库中缺少的东西。
如果能帮助我们解决问题,我们将不胜感激!
演示 app/tests 此处:
https://codesandbox.io/s/useviewportsize-4l7gb?file=/src/use-viewport-size.test.tsx
===========
解决方案
感谢@tmhao2005,问题似乎出在从 document
而不是 window
:
获取调整值的问题上
setViewportSize({
width: window.innerWidth, //document.documentElement.clientWidth - doesn't work
height: window.innerHeight //document.documentElement.clientHeight - doesn't work
});
似乎在应用程序中获得 clientWidth/Height
没问题,但在 React 测试库测试中失败。
我选择了 client
大小调整,因为我认为这不包括滚动条宽度。
我认为您必须更改一些内容才能使您的测试再次运行:
- 你还没有等到你的去抖功能工作,这是主要问题。因此,您可以使用模拟计时器或等到您的去抖功能被调用。
// Make your test as `async` in case of wanting to wait
test("should return new values on window resize", async () => {
// If you go for mocking timer, uncomment this & below advance the timer
// jest.useFakeTimers();
const { result } = renderHook(() => useViewportSize());
act(() => {
window.resizeTo(500, 500);
//fireEvent(window, new Event("resize"));
});
// jest.advanceTimersByTime(251) // you can also use this way
await mockDelay(debounceDelay); // `await` 300ms to make sure the function callback run
expect(result.current.width).toBe(500);
expect(result.current.height).toBe(500);
});
- 您可以通过改为使用您的模拟值来改进您的实现代码:
const debouncedHandleResize = debounce(() => {
setViewportSize({
// using your mock values
width: window.innerWidth,
height: window.innerHeight
});
}, debounceTime);
PS: 我还根据异步方式编辑了你的codesandbox: https://codesandbox.io/s/useviewportsize-forked-pvnc1?file=/src/use-viewport-size.test.tsx
我创建了一个自定义 React Hook,用于在 window 调整大小时获取视口宽度和高度(事件已去抖动)。钩子工作正常,但我一直无法找到使用 React 测试库进行测试的方法(我一直 运行 出错)。
我已经在 CodeSandbox 中重新创建了应用程序(连同测试)以尝试调试,但我在测试时 运行 遇到了不同的错误。
有时我得到:
Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'.`
但是一般的失败是hook出来的数据好像没有返回
expect(received).toBe(expected) // Object.is equality
Expected: 500
Received: undefined
这可能是我在 React 测试库中缺少的东西。
如果能帮助我们解决问题,我们将不胜感激!
演示 app/tests 此处:
https://codesandbox.io/s/useviewportsize-4l7gb?file=/src/use-viewport-size.test.tsx
===========
解决方案
感谢@tmhao2005,问题似乎出在从 document
而不是 window
:
setViewportSize({
width: window.innerWidth, //document.documentElement.clientWidth - doesn't work
height: window.innerHeight //document.documentElement.clientHeight - doesn't work
});
似乎在应用程序中获得 clientWidth/Height
没问题,但在 React 测试库测试中失败。
我选择了 client
大小调整,因为我认为这不包括滚动条宽度。
我认为您必须更改一些内容才能使您的测试再次运行:
- 你还没有等到你的去抖功能工作,这是主要问题。因此,您可以使用模拟计时器或等到您的去抖功能被调用。
// Make your test as `async` in case of wanting to wait
test("should return new values on window resize", async () => {
// If you go for mocking timer, uncomment this & below advance the timer
// jest.useFakeTimers();
const { result } = renderHook(() => useViewportSize());
act(() => {
window.resizeTo(500, 500);
//fireEvent(window, new Event("resize"));
});
// jest.advanceTimersByTime(251) // you can also use this way
await mockDelay(debounceDelay); // `await` 300ms to make sure the function callback run
expect(result.current.width).toBe(500);
expect(result.current.height).toBe(500);
});
- 您可以通过改为使用您的模拟值来改进您的实现代码:
const debouncedHandleResize = debounce(() => {
setViewportSize({
// using your mock values
width: window.innerWidth,
height: window.innerHeight
});
}, debounceTime);
PS: 我还根据异步方式编辑了你的codesandbox: https://codesandbox.io/s/useviewportsize-forked-pvnc1?file=/src/use-viewport-size.test.tsx