Jest, part 2: 什么是jsdom以及jest-dom

December 30, 2019 ... ☕️ 2 min read

什么是JSDom

jsdom是一套纯js实现的web标准,特别是DOM和HTML标准,运行在node.js上。用来测试和模拟真实的web app。简而言之,在server端使用浏览器环境。

jsdom和jest(facebook)没啥关系。可以单独使用,new即可新建一个DOM文档。文档包含了html、head、body标签,并且有一系列的属性,比如window,在此之上,可以使用querySelector等选择器。

// 注意:这并不是一个测试用例
const jsdom = require("jsdom");
const { JSDOM } = jsdom;

const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
console.log(dom.window.document.querySelector("p").textContent); // "Hello world"

jsdom除了实现cookie注入、资源载入(script、css、images、iframe等)、脚本(script)执行等常规功能之外,还有从URL、文件载入DOM,以及在创建之前注入一些代码的功能。

所以,理论上需要DOM支持的测试套件,都可以在jsdom上跑,比如…jQuery

const html = `<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <input type="text" id="address">
</body>
</html>`;

const {JSDOM} = jsdom;
const dom = new JSDOM(html);
const $ = (require('jquery'))(dom.window);

console.log($('#address'));

JSDom优点

对于跑在服务器端的测试用例来说,一套同样运行于服务器端的浏览器环境很有必要,JSDom有以下几个优点:

  • 与浏览器完整交互,根据需要发送测试命令,并获取测试结果,排除真实环境浏览器其他条件影响;
  • 速度快。与PhantomJS不同,JSDom不回执行layout和渲染过程,也实际不实现navigation跳转。它只是操纵DOM树,或者触发一些事件。所以“打开”页面速度很快;
  • 轻量。JSDom只有几M的大小。而puppeter大概有200多M,PhantomJS体积也比较大;
  • 平台无关。由于完全在服务器端跑,所以不必下载对应平台的浏览器。尤其对于平台不同的团队比较友好。

所以很多测试库(如Jest)都推荐JSDom,方便创建DOM片段,也方便收集测试结果,生成完整的测试报告。

什么是jest-dom

和jsdom名字很像。却在测试框架中处于不同“层”:它是一套jest的matcher扩展,方便写基于DOM状态的测试用例,比如检查attr、class名、text内容等。

它提供的API和jest的类似,也是toBeXXX的结构,但是丰富很多:

toBeDisabled
toBeEnabled
toBeEmpty
toBeInTheDocument
toBeInvalid
toBeRequired
toBeValid
toBeVisible
toContainElement
toContainHTML
toHaveAttribute
toHaveClass
toHaveFocus
toHaveFormValues
toHaveStyle
toHaveTextContent
toHaveValue
toBeChecked

写法也是可以无缝过渡

import '@testing-library/jest-dom/extend-expect';

// ...
const detachedElement = document.createElement('div');
expect(detachedElement).toBeInTheDocument();
// ...

extend-expect调用了jest提供的matcher扩展函数expect.extend

#jest

SideEffect is a blog for front-end web development.
Code by Axiu / rss