使用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环境导入时直接报错
- 增加环境判断逻辑,自动注册仅在浏览器环境触发
- 暴露手动注册方法,测试时可灵活调用
测试失败修复方案
你之前测试失败的核心原因有两个:
- 执行顺序错误:先导入组件包、后初始化jsdom,导入组件时全局还不存在
window对象,自动注册逻辑自然不会执行 - 手动注册的方式错误:把类转成字符串插入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源码的配置
- 安装依赖:
npm i c8 @babel/core @babel/preset-env @babel/register ignore-styles -D - 项目根目录新增babel配置文件
.babelrc:
{ "presets": ["@babel/preset-env"] }
- 测试时修改导入路径为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
相关产品推荐
相关产品推荐

