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

Vite React项目中Jest hasFocus()断言匹配失败问题求助

从Create React App迁移到Vite后,React Testing Library的hasFocus()断言失败问题

问题说明

从Create React App迁移到Vite后,使用React Testing Library(RTL)测试点击关联label时email、password输入框是否获得焦点,hasFocus()匹配器断言失败。HTML标签关联逻辑正常,但测试中hasFocus()匹配的是整个文档(body)而非目标输入框。

相关代码

Login组件

function Login() {
  return (
    <div>
      <p>Some text</p>
      <div>
        <label htmlFor="email">Email</label>
        <input type="email" name="email" id="email" />
        <label htmlFor="password">Password</label>
        <input type="text" name="password" id="password" />
        <button>OK</button>
      </div>
    </div>
  )
}

单元测试代码

test('it should check that the email input element will be focused whenever the associated label is clicked', () => {
  render(<Login />)

  const emailLabel = screen.getByLabelText('Email');
  const emailInput = screen.getByRole('textbox', {name: email});
  logRoles(emailInput, emailLabel)

  fireEvent.click(emailLabel);

  expect(emailInput).toHaveFocus();
})

依赖包配置

{
  "name": "my-app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview",
    "test": "jest"
  },
  "dependencies": {
    "@babel/preset-env": "^7.22.10",
    "@babel/preset-react": "^7.22.5",
    "identity-obj-proxy": "^3.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "styled-components": "^6.0.7"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^6.0.0",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/react": "^18.2.15",
    "@types/react-dom": "^18.2.7",
    "@vitejs/plugin-react": "^4.0.3",
    "eslint": "^8.45.0",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.3",
    "jest": "^29.6.2",
    "jest-environment-jsdom": "^29.6.2",
    "vite": "^4.4.5"
  },
  "jest": {
    "testEnvironment": "jsdom",
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js",
      "^.+\\.(css|less|scss)$": "identity-obj-proxy"
    },
    "setupFilesAfterEnv": [
      "<rootDir>/setupTests.js"
    ]
  }
}

错误信息

expect(element).toHaveFocus()

    Expected element with focus:
      <input id="password" name="Password" type="text" />
    Received element with focus:
      <body><div><div class="App-body"><p>Login to access the full dashboard</p><div class="form"><label for="email">Email</label><input id="email" name="Email" type="email" /><label for="password">Password</label><input id="password" name="Password" type="text" /><button>OK</button></div></div></div></body>

      38 |   fireEvent.click(passwordLabel);
      39 |
    > 40 |   expect(passwordInput).toHaveFocus();
         |                         ^
      41 | });
      42 |

      at Object.toHaveFocus (src/Login/Login.spec.js:40:25)

解决建议

  • 修正输入框选择器参数:测试代码中screen.getByRole('textbox', {name: email})的name参数未定义,应改为字符串'Email'或'email'(匹配输入框name属性或label文本)。
  • 使用userEvent替代fireEvent:RTL新版本推荐用userEvent模拟真实用户交互,fireEvent作为低级API可能无法触发label点击后的焦点行为,替换为userEvent.click(emailLabel)。
  • 检查依赖兼容性:确认jest-environment-jsdom、@testing-library/jest-dom与Jest、RTL的版本是否匹配,避免版本冲突导致的异常。
  • 验证测试初始化配置:确保setupTests.js中已正确导入@testing-library/jest-dom(如import '@testing-library/jest-dom';),否则toHaveFocus匹配器无法正常工作。

内容的提问来源于stack exchange,提问作者Moez Ben Rebah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 13:35:54