You need to enable JavaScript to run this app. 使用jsdom测试Web Component挂载失败及源码测试方案咨询
优惠活动
大模型
产品
解决方案
定价
更多

使用jsdom测试Web Component挂载失败及源码测试方案咨询

源码优化建议

首先调整现有代码的不规范问题,优化后可同时兼容生产环境和测试环境:

import html from 'template.html';
import css from 'styles.css';

// 兼容node测试环境不存在HTMLElement的场景
const _HTMLElement = typeof window !== 'undefined' ? window.HTMLElement : class {};

export class MyComponent extends _HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    // 可在这里把导入的html、css挂载到shadowRoot
    this.shadowRoot.innerHTML = `<style>${css}</style>${html}`;
  }
}

// 导出手动注册方法,方便测试调用
export function register() {
  if (typeof window !== 'undefined' && window.customElements && !window.customElements.get('my-component')) {
    window.customElements.define('my-component', MyComponent);
  }
}

// 生产环境自动注册,仅在存在浏览器全局对象时执行
if (typeof window !== 'undefined') {
  register();
}

优化点说明:

  • 取消直接导出IIFE执行结果的写法,避免node环境导入时直接报错
  • 增加环境判断逻辑,自动注册仅在浏览器环境触发
  • 暴露手动注册方法,测试时可灵活调用

测试失败修复方案

你之前测试失败的核心原因有两个:

  1. 执行顺序错误:先导入组件包、后初始化jsdom,导入组件时全局还不存在window对象,自动注册逻辑自然不会执行
  2. 手动注册的方式错误:把类转成字符串插入script标签的写法会丢失类的外部依赖(比如你导入的html、css变量),必然注册失败

修复后的测试代码如下:

import jsdomGlobal from 'jsdom-global';
import { expect } from 'chai';

describe('component test', function() {
  let jsdom;
  let MyComponent, register;

  before(async function(){
    // 先初始化jsdom,把window挂载到全局
    jsdom = jsdomGlobal('', { 
      runScripts: 'dangerously',
      customElements: true
    });
    // 初始化完成后再导入组件
    const componentModule = await import('../dist/my-component.esm');
    MyComponent = componentModule.MyComponent;
    register = componentModule.register;
    // 手动触发注册
    register();
  })

  after(function() {
    jsdom();
    // 清理模块缓存,避免用例间污染
    delete require.cache[require.resolve('../dist/my-component.esm')];
  });

  it('mounts correctly', async function() {
    await window.customElements.whenDefined('my-component');
    expect(window.customElements.get('my-component')).to.exist;
    // 追加挂载测试验证逻辑
    const el = document.createElement('my-component');
    document.body.appendChild(el);
    expect(el.shadowRoot).to.exist;
  })
})

源码测试与覆盖率统计优化

直接测试src源码的配置

  1. 安装依赖:npm i c8 @babel/core @babel/preset-env @babel/register ignore-styles -D
  2. 项目根目录新增babel配置文件.babelrc:
{
  "presets": ["@babel/preset-env"]
}
  1. 测试时修改导入路径为src目录,启动mocha时添加加载器参数:
mocha --require @babel/register --require ignore-styles test/**/*.test.js

ignore-styles会自动忽略css、html等非JS资源的导入,你也可以自定义钩子把html导入转为字符串返回,更贴近实际运行逻辑。

覆盖率统计优化

使用c8做覆盖率统计,它基于V8原生能力,支持源码映射,在package.json中添加配置:

{
  "c8": {
    "include": ["src/**/*.js"],
    "reporter": ["text", "lcov"],
    "sourceMap": true,
    "instrument": true
  }
}

运行测试时执行c8 mocha 你的测试启动参数,生成的覆盖率报告就会直接对应src目录下的源码行。


内容的提问来源于stack exchange,提问作者Donnie D'Amato

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 05:36:07