我创建了一个非常简单的页面,仅显示一条消息,因为我正尝试测试JSDOM以使用document
。但是,出现以下错误。
首先,除了在Stack Overflow上发布的问题外,我还在网上看到了无数的示例,但是即使是最简单的示例,我也无法解决。附带说明,我是Java的新手。
到目前为止,我的代码如下:
根目录
---> index.html
---> module.js
---> package-lock.json
---> package.json
--->测试
---> ---> messageTest.js
不同的文件如下:
index.html
<!doctype html>
<head>
<meta charset="utf-8">
<title>jsdom Unit Test</title>
</head>
<body>
<p id='msg'>Hello, World!</p>
<script src="module.js"></script>
</body>
</html>
module.js
function updateMsg(newMsg) {
document.getElementById('msg').innerHTML = newMsg;
}
updateMsg("Changing message");
module.exports = updateMsg;
package.json
{
"name": "message-example",
"version": "1.0.0",
"description": "Testing how to use the JSDOM",
"main": "module.js",
"scripts": {
"test": "mocha"
},
"author": "",
"license": "ISC",
"devDependencies": {
"chai": "^4.2.0",
"jsdom": "^15.1.1",
"mocha": "^6.2.0",
"mocha-jsdom": "^2.0.0",
"rewire": "^4.0.1",
"sinon": "^7.3.2"
}
}
messageTest.js
var updateMsg = require('../module.js');
const expect = require('chai').expect
const { JSDOM } = require('jsdom');
describe('updateMsg', function () {
before(function() {
return JSDOM.fromFile('index.html')
.then((dom) => {
global.window = dom.window;
global.document = window.document;
});
})
it ('updates the innerHTML of element with id "msg"', function () {
expect(document.getElementById('msg').innerHTML).to.equal('Hello, World!');
updateMsg('The new msg!');
expect(document.getElementById('msg').innerHTML).to.equal('The new msg!');
});
});
如果我使用npm test
运行测试,则会在 module.js 文件的ReferenceError: document is not defined
步骤中收到document.getElementByID...
错误。
如果我删除了updateMsg("Changing message")
,我的测试显然可以正常运行。
答案 0 :(得分:1)
在该示例中,您有几个问题:
您正在混合jsdom窗口和全局节点上下文。避免分配给global
(因为这样更容易犯该错误),请不要require()
个要在虚拟窗口中运行的脚本。
jsdom默认情况下阻止运行页面脚本,因此不会加载也不执行module.js。您必须提供{ resources: "usable", runScripts: "outside-only" }
参数来解决此问题(请确保您已阅读jsdom README中的安全隐患)。
您不是在等待load
事件,因此在jsdom有机会加载脚本之前运行测试。
工作代码如下:
const expect = require("chai").expect;
const { JSDOM } = require("jsdom");
describe("updateMsg", function() {
let jsdom;
before(async function() {
jsdom = await JSDOM.fromFile("index.html", {
resources: "usable",
runScripts: "dangerously"
});
await new Promise(resolve =>
jsdom.window.addEventListener("load", resolve)
);
});
it('updates the innerHTML of element with id "msg"', function() {
expect(jsdom.window.document.getElementById("msg").innerHTML).to.equal(
"Hello, World!"
);
jsdom.window.updateMsg("The new msg!");
expect(jsdom.window.document.getElementById("msg").innerHTML).to.equal(
"The new msg!"
);
});
});
您还需要从module.js中删除模块行,module
在浏览器中不存在。