如何使用Jest测试无框架纯JS Web Components中的slotted插槽元素
问题原因
- 原组件中直接读取
<slot>元素的innerText属于依赖浏览器渲染特性的非标准写法:插槽元素本身的DOM结构是空的,浏览器渲染阶段会将宿主下分配给插槽的节点渲染到插槽对应位置,因此浏览器中可读取到innerText,但Jest默认使用的jsdom环境没有实现这类渲染层的文本计算逻辑,因此返回undefined。 - 测试中创建的自定义元素没有挂载到document上,jsdom不会触发插槽分配逻辑,导致插槽无法识别到传入的文本节点。
解决方案
第一步:修正组件的name getter,使用标准插槽API读取内容
替换原有的name getter为调用插槽标准assignedNodes()方法的实现,直接读取分配给插槽的节点内容,不依赖渲染层特性:
// placeholder.js 修正后的name getter get name() { const slot = this.shadowRoot.querySelector("slot"); // 读取所有分配给插槽的节点的文本内容并拼接 return slot.assignedNodes().map(node => node.textContent).join(''); }
第二步:修正测试用例,触发插槽分配
测试中需要将创建的自定义元素挂载到document上,触发jsdom的插槽分配逻辑,同时增加用例执行后的DOM清理逻辑避免测试污染:
// placeholder.test.js 修正后代码 import Placeholder from "../src/placeholder.js"; describe("name is 'Lorem Ipsum'", () => { let ph; beforeEach(() => { ph = new Placeholder(); const textNode = document.createTextNode("Lorem Ipsum"); ph.appendChild(textNode); // 将组件挂载到document,触发插槽分配 document.body.appendChild(ph); }); afterEach(() => { // 测试结束后清理DOM ph.remove(); }); test("if the name is 'Lorem Ipsum'", () => { expect(ph.name).toBe("Lorem Ipsum"); }); });
可选:补充Jest配置适配自定义元素
如果修改后仍报错,可在jest配置文件中增加jsdom的自定义元素支持配置:
// jest.config.js module.exports = { testEnvironment: "jsdom", testEnvironmentOptions: { customExportConditions: ["node", "custom"], runScripts: "dangerously" } }
内容的提问来源于stack exchange,提问作者Ich
相关产品推荐
相关产品推荐

