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

如何用Jest正确测试集成最新Material Web Components的Next.js/React应用?

解决Jest测试Next.js/React + Material Web Components的问题

1. 修复TypeError: this.attachInternals is not a function

方案A:升级jsdom(推荐)

如果你的Jest环境使用的jsdom版本低于20.x,直接升级到最新版——jsdom从20版本开始原生支持attachInternals API,无需手动Mock。

修改package.json中的依赖:

{
  "devDependencies": {
    "jsdom": "^22.0.0",
    "jest-environment-jsdom": "^29.0.0"
  }
}

执行npm install或yarn install更新依赖。

方案B:安全Mock attachInternals

若无法升级jsdom,避免直接覆盖HTMLElement.prototype引发副作用,改用条件定义或Jest Spy实现:

在Jest配置的setupFilesAfterEnv指定文件(如jest.setup.js)中添加:

// 仅在API不存在时添加,避免覆盖原生实现
if (!HTMLElement.prototype.attachInternals) {
  Object.defineProperty(HTMLElement.prototype, 'attachInternals', {
    value: function() {
      return {
        setFormValue: () => {},
        setValidity: () => {},
        checkValidity: () => true,
        reportValidity: () => true
      };
    },
    configurable: true,
    writable: true
  });
}

或者在单个测试文件中局部Mock,测试后恢复:

beforeAll(() => {
  jest.spyOn(HTMLElement.prototype, 'attachInternals')
    .mockReturnValue({
      setFormValue: jest.fn(),
      setValidity: jest.fn()
    });
});

afterAll(() => {
  jest.restoreAllMocks();
});

2. 解决按钮属性(name/role)丢失问题

确保Material Web Components正确注册

在Jest setup文件中导入你使用的MWC组件,保证自定义元素被正确定义:

// jest.setup.js
import '@material/web/button/filled-button.js';
import '@material/web/button/outlined-button.js';
// 其他用到的MWC组件

验证React属性传递逻辑

确保在React组件中正确给MWC按钮传递属性:

// 示例组件
import { FilledButton } from '@material/web/button/filled-button.js';

export default function SignInButton() {
  return (
    <FilledButton 
      name="Redirect to Sign in" 
      role="link"
      onClick={() => {/* 业务逻辑 */}}
    >
      Sign In
    </FilledButton>
  );
}

测试时灵活选择查询方式

若getByRole查询仍有问题,可先用getByTestId作为临时方案,同时排查属性丢失原因:

// 组件中添加测试标识
<FilledButton 
  data-testid="sign-in-link"
  name="Redirect to Sign in" 
  role="link"
>
  Sign In
</FilledButton>

// 测试用例
test('renders sign in link with correct attributes', () => {
  render(<SignInButton />);
  const button = screen.getByTestId('sign-in-link');
  expect(button).toHaveAttribute('name', 'Redirect to Sign in');
  expect(button).toHaveAttribute('role', 'link');
});

额外注意事项

  • 优先选择升级依赖而非全局修改原生DOM原型,减少测试环境副作用
  • 确保Jest配置中testEnvironment设置为jsdom
  • 若使用TypeScript,可添加@types/web补全自定义元素的类型定义

内容的提问来源于stack exchange,提问作者Gerson Yesid Lazaro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:15:03