标签: testing-library

如何使用 @testing-library/react 测试 React Router V6 Outlet

我在 React Router v6 中使用一个组件来管理私有路由,它对身份验证令牌进行一些检查,并且将呈现该Outlet组件或重定向到登录页面。

我有 -

import { Outlet } from 'react-router-dom';

export const CheckAuth = (props) => {
  const valid = ...;
  if (!valid) {
    window.location.replace(loginUrl);
    return null;
  }

  return <Outlet />;
};
Run Code Online (Sandbox Code Playgroud)

并像这样使用它 -

<Route element={<CheckAuth token={authToken} />}>
   // ... private routes ...
</Route>
Run Code Online (Sandbox Code Playgroud)

window.location.replace我可以用 Jest 来模拟

delete window.location;
window.location = { replace: jest.fn() };
...
render(<CheckAuth token={token} />)
expect(window.location.replace).toHaveBeenCalledWith(loginUrl);
Run Code Online (Sandbox Code Playgroud)

但如何Outlet使用测试库测试组件?

reactjs react-router react-router-dom testing-library

8
推荐指数
1
解决办法
5051
查看次数

如何等待测试库中不发生某些事情?

我想断言一个条件,我知道该条件不会立即为真,但在异步操作之后可能为真,此时测试应该失败。

假设我正在测试这个计数器组件:

function Counter() {
  const [value, setValue] = useState(1);
  function decrement() {
    if (value >= 0) { // <- off by one bug
      someAsyncAction().then(() => setValue(value - 1));
    }
  }
  return (
    <>
      Value is {value}
      <button onClick={decrement}>Decrement</button>
    </>
  );
}

Run Code Online (Sandbox Code Playgroud)

我可以编写此测试来检查该值不应低于零:

const button = screen.getByRole("button", { name: "Decrement" });
expect(screen.getByText("Value is 1")).toBeInTheDocument();

userEvent.click(button);
expect(await screen.findByText("Value is 0")).toBeInTheDocument();

userEvent.click(button);
// !!! wrong !!!
expect(screen.getByText("Value is 0")).toBeInTheDocument();
expect(screen.queryByText("Value is -1")).not.toBeInTheDocument();
// !!! wrong !!!
Run Code Online (Sandbox Code Playgroud)

但是最后两个断言总是会通过,即使组件有一个错误,这意味着它将异步更新以显示“值是-1”。

处理这种情况的推荐方法是什么?

jestjs react-testing-library testing-library

7
推荐指数
2
解决办法
2793
查看次数

如何测试反应组件道具(期望组件被调用)

opened={true}我需要测试在单击按钮后是否使用 prop 调用反应组件。我正在使用testing-librarytesting-library/react+ testing-library/jest-dom)。

我用类似的东西嘲笑了组件

import Component from "./path-to-file/component-name"
...
jest.mock("./path-to-file/component-name", () => {
  return jest.fn().mockImplementation(() => {
    return null
  })
})
Run Code Online (Sandbox Code Playgroud)

我首先尝试过:

expect(Component).toBeCalledWith(expect.objectContaining({"opened": true}))
expect(Component).toHaveBeenCalledWith(expect.objectContaining({"opened": true}))
expect(Component).toHaveBeenLastCalledWith(expect.objectContaining({"opened": true}))
Run Code Online (Sandbox Code Playgroud)

但我得到了Error: expect(jest.fn()).toBeCalledWith(...expected)

同样的事情expect.objectContaining({"opened": expect.anything()})

Expect.objectContaining({"opened":expect.anything()})

甚至对于expect(Component).toBeCalledWith(expect.anything())

期待.anything()

区别在于空数组: 空数组

我也尝试过expect(ChartMenu.mock).toBeCalledWith(expect.anything())。我遇到了不同的错误,但仍然无法工作(这次错误是Error: expect(received).toBeCalledWith(...expected)+ Matcher error: received value must be a mock or spy function嘲笑

谢谢您的建议!

编辑:这是我要测试的组件的简化版本:

const Component = () => {
  const [chartMenuOpened, setChartMenuOpened] = useState(false)
  return (
      <Flex> …
Run Code Online (Sandbox Code Playgroud)

reactjs jestjs react-testing-library testing-library

7
推荐指数
1
解决办法
1万
查看次数

对于存在的元素,什么可能导致“无法找到包含以下文本的标签”?

当元素确实存在时,什么可能导致getByLabelText测试库到\xc2\xa0报告找不到该元素?我得到的确切错误是

\n
\n

TestingLibraryElementError:无法找到带有以下文本的标签:删除项目:项目 C

\n
\n

它是在我运行测试后出现的,报告线路失败

\n
const removeItemButton = screen.getByLabelText(\'Remove Item: Item C\');\n
Run Code Online (Sandbox Code Playgroud)\n

测试输出包含\xc2\xa0included 的一大块页面源

\n
<span\n    class="my-company-span"\n    data-testid="custom-react-tag"\n>\n    Item: Item C\n    <button\n        aria-label="Remove Item: Item C"\n        class="myco-chp__button"\n        type="button"\n    >\n        ...\n
Run Code Online (Sandbox Code Playgroud)\n

为了进一步证明该元素确实存在,我最终使用不同的函数 ( getAllByRole) 来获取它,但我认为getByLabelText会更干净。

\n

该文档表示aria-label\xc2\xa0attributes 是getByLabelText. aria-label为了防止其中出现异常字符,我将错误输出中的名称直接复制粘贴到getByLabelText参数中,但没有任何变化。我getByLabelText()在同一文件中的其他元素上成功使用了该函数,因此这不是一个糟糕的导入。

\n

我在网上看到了很多类似但不一样的错误“无法找到带有文本的元素”的问题,但我发现针对我的情况的唯一问题是使用 iframe 的人,它不不适用于我。

\n

reactjs testing-library

7
推荐指数
1
解决办法
6425
查看次数

将 @testing-library/user-event 更新到 v.14 时出错

我正在遵循最新版本的所有说明@testing-library/user-event

前:

  test('request support action',() => {
    render(<SupportSection requestSupport={requestSupport} />);

    const button = screen.getByRole('button');

    userEvent.click(button);

    expect(requestSupport).toHaveBeenCalled();
  });
Run Code Online (Sandbox Code Playgroud)

后:

  test('request support action', async () => {
    const user = userEvent.setup();
    
    render(<SupportSection requestSupport={requestSupport} />);

    const button = screen.getByRole('button');

    await user.click(button);

    expect(requestSupport).toHaveBeenCalled();
  });
Run Code Online (Sandbox Code Playgroud)

requestSupport在更高的范围内被嘲笑const requestSupport = jest.fn();

我收到的错误是:

类型错误:range.cloneRange 不是函数

我的所有测试在库更新之前都通过了,现在全部失败了。

reactjs react-testing-library testing-library user-event

7
推荐指数
1
解决办法
5001
查看次数

如何使用测试库测试下一个/脚本?

我的 React 组件<script>使用 nextJS 渲染标签Head。当尝试使用测试库的方法查询元素时getByTestId,我收到以下消息:

TestingLibraryElementError: Unable to find an element by: [data-testid="keen-to-test"]
Ignored nodes: comments, <script />, <style />
Run Code Online (Sandbox Code Playgroud)

有没有办法包含script在输出中,或者我应该使用不同的策略来验证我的脚本是否已注入?提前致谢

成分

import Head from 'next/head';

const FancyScript = ({src}) => {
  if (src) {
   return (
     <Head>
      <script
        data-testid="keen-to-test"
        type="text/javascript"
        async
        src={src}
      </script>
     </Head>
   )
  }
  return null;
}
Run Code Online (Sandbox Code Playgroud)

测试

import { render } from '@testing-library/react';
import FancyScript from '/fancy-location';

it('return some fancy', () => {
    const { getByTestId } = …
Run Code Online (Sandbox Code Playgroud)

reactjs next.js react-testing-library testing-library

6
推荐指数
1
解决办法
4408
查看次数

vue3 测试库 - 如何在测试中使用 globalProperties

我是 Vue 新手,遵循使用 vue 测试库的建议。唯一的问题是我似乎找不到将代码注入渲染函数中的 globalProperties 的方法。

有谁知道我可以注入或模拟它的例子?

main.js

app.config.globalProperties.$globals = globalMethods

...
const app = createApp(App)
app.config.globalProperties.$globals = globalMethods
app.config.globalProperties.$globalVars = globalVars

app.component("font-awesome-icon", fontawesome)

app.use(applicationStore);
app.use (Hotjar, hotjarConfig)
app.use(i18n)
app.use(router)

app.mount('#app')
Run Code Online (Sandbox Code Playgroud)

从 create 中的 vue 组件我可以调用

组件.vue

让 formatedObj = this.$globals.maskValues(this.inputValue, this.inputType, this);

...  
  ,
  created() {
    let formatedObj = this.$globals.maskValues(this.inputValue, this.inputType, this);
    this.myInputValue = formatedObj.formatedString;
    this.formatedCharacterCount = formatedObj.formatedCharacterCount;
    this.prevValue = this.myInputValue;
  },
...
Run Code Online (Sandbox Code Playgroud)

测试规范.js

import { render } from '@testing-library/vue'
import FormatedNumericInput from '@/components/Component.vue'
import {globalMethods} from'@/config/global-methods'


const …
Run Code Online (Sandbox Code Playgroud)

vue.js vuejs3 testing-library vue-testing-library

6
推荐指数
1
解决办法
2571
查看次数

React 测试库:在这种情况下如何使用屏幕而不是容器

在React测试库中,按照惯例,最好使用屏幕而不是从渲染中解构方法。

我有一个组件,我需要在其中测试渲染的文本。该组件中的顶级容器是 div,因此没有可访问的查询来获取文本匹配。如何使用屏幕进行文本匹配?

我目前已经求助于使用解构道具中的容器,然后在容器上进行文本匹配。

// MyComponent - simplified
const MyComponent = () => <div> some text </div>

// test
const { container } = render(<MyComponent />);
expect(container).toHaveTextContent(...)

Run Code Online (Sandbox Code Playgroud)

参考: https: //kentcdodds.com/blog/common-mistakes-with-react-testing-library#not-using-screen

在博客文章中提到,解构主要是为了遗留目的而支持的,但没有任何用例不能使用屏幕来解决。这个用例可以使用屏幕来解决吗?

reactjs react-testing-library testing-library

6
推荐指数
1
解决办法
7659
查看次数

在 beforeEach() 中调用 userEvent.setup() - 这是好还是坏模式?

在需要在多个测试中调用 userEvent.setup() 的测试套件中,有时我会在 beforeEach 中执行 userEvent.setup() ,然后user在多个测试中引用相同的 var

let user: UserEvent
beforeEach(() => {
     user = userEvent.setup()
})

describe('SomeTests', () => {
    it('should test something', async () => {
        await user.click(someButton)
        ...
    })

    it('should test some other thing', async () => {
        await user.click(someButton)
        ...blahblahblah
    })
})
Run Code Online (Sandbox Code Playgroud)

但是,我担心这可能会导致并行运行测试出现问题,最好总是这样做:

describe('SomeTests', () => {
    it('should test something', async () => {
        const user = userEvent.setup()
        await user.click(someButton)
        ...blahblahblah
    })

    it('should test some other thing', async () => {
        const user …
Run Code Online (Sandbox Code Playgroud)

jestjs testing-library user-event

6
推荐指数
1
解决办法
1026
查看次数

类型错误:使用反应测试库测试组件时无法读取 null 的属性(读取“useState”)

我正在学习使用反应测试库和笑话来测试反应和反应组件。在尝试测试渲染组件时可以正常工作的组件时,它可以正常工作,但是在测试它时,我收到无效的挂钩错误。

\n

这是组件。

\n
import PropTypes from "prop-types";\nimport { useState } from "react";\n\nexport const CounterApp = ({ value }) => {\n    const [counter, setCounter] = useState(value);\n\n    function handleAdd() {\n        setCounter(counter + 1);\n    }\n    function handleSubtract() {\n        if (counter > 0) {\n            setCounter(counter - 1);\n        }\n    }\n\n    function handleReset() {\n        setCounter(0);\n    }\n    return (\n        <>\n            <h1>CounterApp</h1>\n            <h2> {counter} </h2>\n            <button onClick={handleAdd}>+1</button>\n            <button onClick={handleSubtract}>-1</button>\n            <button onClick={handleReset}>Reset</button>\n        </>\n    );\n};\n\nCounterApp.propTypes = {\n    value: PropTypes.number.isRequired,\n};\n\n
Run Code Online (Sandbox Code Playgroud)\n

这是我正在运行的测试

\n
import { render } from "@testing-library/react";\nimport { …
Run Code Online (Sandbox Code Playgroud)

components reactjs jestjs testing-library

6
推荐指数
1
解决办法
5685
查看次数