我有一个简单的React组件,它最初将有一个应用CSSdisplay: none
的Tailwind CSS类hidden
,并在单击按钮时将该类更改为visible
。当我使用expect().not.toBeVisible()
进行测试时,它"告诉"我元素已经可见,同时它有一个hidden
类。
如果我不使用Tailwind CSS并使用普通的style={{display: 'none'}}
,它将正确地识别出该元素不可见。这意味着问题显然与Tailwind CSS有关。
这是我的测试:
test("Notification bar should be initially hidden but visible on click", async () => {
render(<Notifications />);
expect(await screen.findByTestId("list")).not.toBeVisible();
// this test fails while the element already has a Tailwind CSS class of "hidden"
});
这是我的组件:
<ul className="hidden" data-testid="list">
<li>item 1</li>
</ul>
本堆栈溢出中解释的解决方案:对于语义ui react组件,无法检查预期不可见。基于该线程,我扩展了该解决方案,使其与TailwindCSS一起工作,如下所述的步骤,
项目结构
root/
src/
test/
index.css
test-utils.tsx
component.test.tsx
index.css
1.从TailwindCSS模板文件生成CSS
通过发出以下命令,名为index.css
的CSS文件将在src/test
目录中生成
npx tailwindcss -i ./src/index.css -o ./src/test/index.css
进一步阅读:TailwindCSS安装
2.创建自定义渲染功能
接下来,我们需要将生成的CSS文件注入到JSDOM中。自定义渲染功能将很有用,因此我们不需要为每个测试重复此任务
import { render, RenderOptions } from '@testing-library/react';
import React, { FC, ReactElement } from 'react';
import fs from 'fs';
const wrapper: FC<{ children: React.ReactNode }> = ({ children }) => {
return <>{children}<>;
};
const customRender = (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) => {
const view = render(ui, { wrapper, ...options });
const style = document.createElement('style');
style.innerHTML = fs.readFileSync('src/test/index.css', 'utf8');
document.head.appendChild(style);
return view;
};
export * from '@testing-library/react';
export { customRender as render };
进一步阅读:测试库设置
3.执行测试,单元测试现在假设成功
import React from 'react';
import { render, screen } from './test-utils';
test('Renders hidden hello world', () => {
render(<span className="hidden">Hello World</span>);
expect(screen.getByText('Hello World')).not.toBeVisible();
});
为什么我们不使用toHaveClass
匹配器呢
它不符合测试库的指导原则"强调关注与用户交互网页方式非常相似的测试">,因为这样做,你与组件的交互是不自然的
如果您使用Vite作为bundler,使用Vitest作为测试框架,则可以使用Vitest选项中的css: true
选项来启用对测试文件中CSS的处理。点击此处查看更多信息:https://vitest.dev/config/#css
此外,您必须在组件测试中导入index.css
(或任何路径名(,或者更好地导入VitestsetupTests
文件。