You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Ts+Vite项目Jest无法获取CSS类的问题及解决

React + TypeScript + Vite测试CSS模块类返回undefined及元素查询失败的解决方案

问题场景

在React + TypeScript + Vite项目中测试HighlightedBox组件时,遇到两个问题:

  1. 组件渲染的DOM元素class属性显示为undefined undefined
  2. 测试用例中使用screen.getByRole('div')报错,提示找不到可访问元素

组件代码

import styles from './HighlightedBox.module.scss'

type HighlightedBoxProps = {
    state: String
}

export const HighlightedBox = ({state}: HighlightedBoxProps) => {
    function capitalize(str: String){
       return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
    }

    return <div className={styles.container + " " + 
    (state.toLowerCase() === "rechazado" ? styles.failed : styles.passed)}>
        <span className={styles.highlightText}>{capitalize(state)}</span>
    </div>
}

样式文件(HighlightedBox.module.scss)

.container{
    display: inline-block;
    padding: .25em .5em;
    font-size: 1rem;
    font-weight: 600;
}
.highlightText{
    line-height: 1;
}
.passed{
    background-color: var(--green-color-2);
    color: var(--green-color-8);
}
.failed{
    background-color: var(--red-color-1);
    color: var(--red-color-7);
}

测试代码

import { render, screen, prettyDOM } from '@testing-library/react';
import { HighlightedBox } from './HighlightedBox';
import { EstadoDictamen } from '../../enums/EstadoDictamen';

describe('HighlightedBox', () => {
  beforeEach(() => {
    const component = render(<HighlightedBox state={'rechazado'} />);
  })

  it('should render a box with the correct class based on the state', () => {
    const boxElement = screen.getByRole('div');
    expect(boxElement).toHaveClass('failed');
  });

  it('should capitalize the state text', () => {
    render(<HighlightedBox state={EstadoDictamen.Aprobado} />);
    const textElement = screen.getByText('Aprobado');
    expect(textElement).toBeInTheDocument();
  });
});

报错信息

● HighlightedBox › should render a box with the correct class based on the state

    TestingLibraryElementError: Unable to find an accessible element with the role "div"

    There are no accessible roles. But there might be some inaccessible roles. If you wish to access them, 
then set the `hidden` option to `true`. Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole

      10 |
      11 |   it('should render a box with the correct class based on the state', () => {
    > 12 |     const boxElement = screen.getByRole('div');
         |                               ^
      13 |     expect(boxElement).toHaveClass('failed');
      14 |   });
      15 |

错误原因分析

  1. CSS模块类返回undefined:Vite在测试环境下默认不处理CSS模块,测试工具无法识别.module.scss文件导出的类名,导致styles.container、styles.failed等变量为undefined。
  2. getByRole查询失败:getByRole基于ARIA可访问角色查询元素,普通div标签默认无ARIA角色,因此无法通过该方法找到目标元素。

解决方案

1. 配置CSS模块Mock(解决类名undefined问题)

  • 安装identity-obj-proxy,用于在测试环境中mock CSS模块导出:
    npm install identity-obj-proxy --save-dev
    
  • 在Vite测试配置文件(如vitest.config.ts)中添加模块映射:
    import { defineConfig } from 'vitest/config';
    import react from '@vitejs/plugin-react';
    
    export default defineConfig({
      plugins: [react()],
      test: {
        environment: 'jsdom',
        moduleNameMapper: {
          '\\.(scss|sass|css)$': 'identity-obj-proxy',
        },
      },
    });
    
  • TypeScript环境下,在tsconfig.json补充测试相关类型:
    {
      "compilerOptions": {
        "types": ["vitest/globals", "@testing-library/jest-dom"]
      },
      "include": ["src/**/*", "vitest.config.ts"]
    }
    
    (若使用Jest框架,需在jest.config.js中配置moduleNameMapper,并确保TS路径解析正确)

2. 修正测试元素查询逻辑(解决getByRole报错)

  • 给组件的div添加data-testid属性,方便测试定位:
    import styles from './HighlightedBox.module.scss'
    
    type HighlightedBoxProps = {
        state: String
    }
    
    export const HighlightedBox = ({state}: HighlightedBoxProps) => {
        function capitalize(str: String){
           return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
        }
    
        return <div 
          data-testid="highlighted-box"
          className={`${styles.container} ${state.toLowerCase() === "rechazado" ? styles.failed : styles.passed}`}
        >
            <span className={styles.highlightText}>{capitalize(state)}</span>
        </div>
    }
    
  • 修改测试用例中的查询方法:
    it('should render a box with the correct class based on the state', () => {
      render(<HighlightedBox state={'rechazado'} />);
      const boxElement = screen.getByTestId('highlighted-box');
      expect(boxElement).toHaveClass('failed');
    });
    

验证效果

配置完成后重新运行测试,即可解决类名undefined问题,同时测试用例能正确找到目标元素并验证类名。

内容的提问来源于stack exchange,提问作者Nico Godoy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 18:14:56