我在 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使用测试库测试组件?
我想断言一个条件,我知道该条件不会立即为真,但在异步操作之后可能为真,此时测试应该失败。
假设我正在测试这个计数器组件:
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”。
处理这种情况的推荐方法是什么?
opened={true}我需要测试在单击按钮后是否使用 prop 调用反应组件。我正在使用testing-library(testing-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(Component).toBeCalledWith(expect.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) 当元素确实存在时,什么可能导致getByLabelText从测试库到\xc2\xa0报告找不到该元素?我得到的确切错误是
\n\nTestingLibraryElementError:无法找到带有以下文本的标签:删除项目:项目 C
\n
它是在我运行测试后出现的,报告线路失败
\nconst removeItemButton = screen.getByLabelText(\'Remove Item: Item C\');\nRun 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 ...\nRun Code Online (Sandbox Code Playgroud)\n为了进一步证明该元素确实存在,我最终使用不同的函数 ( getAllByRole) 来获取它,但我认为getByLabelText会更干净。
该文档表示aria-label\xc2\xa0attributes 是getByLabelText. aria-label为了防止其中出现异常字符,我将错误输出中的名称直接复制粘贴到getByLabelText参数中,但没有任何变化。我getByLabelText()在同一文件中的其他元素上成功使用了该函数,因此这不是一个糟糕的导入。
我在网上看到了很多类似但不一样的错误“无法找到带有文本的元素”的问题,但我发现针对我的情况的唯一问题是使用 iframe 的人,它不不适用于我。
\n我正在遵循最新版本的所有说明@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 不是函数
我的所有测试在库更新之前都通过了,现在全部失败了。
我的 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) 我是 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) 在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
在博客文章中提到,解构主要是为了遗留目的而支持的,但没有任何用例不能使用屏幕来解决。这个用例可以使用屏幕来解决吗?
在需要在多个测试中调用 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) 我正在学习使用反应测试库和笑话来测试反应和反应组件。在尝试测试渲染组件时可以正常工作的组件时,它可以正常工作,但是在测试它时,我收到无效的挂钩错误。
\n这是组件。
\nimport 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\nRun Code Online (Sandbox Code Playgroud)\n这是我正在运行的测试
\nimport { render } from "@testing-library/react";\nimport { …Run Code Online (Sandbox Code Playgroud) testing-library ×10
reactjs ×7
jestjs ×4
user-event ×2
components ×1
next.js ×1
react-router ×1
vue.js ×1
vuejs3 ×1