Javascript JSDOM-未定义文档
我创建了一个非常简单的页面,只显示一条消息,因为我正在尝试测试JSDOM以使用Javascript JSDOM-未定义文档,javascript,html,json,dom,jsdom,Javascript,Html,Json,Dom,Jsdom,我创建了一个非常简单的页面,只显示一条消息,因为我正在尝试测试JSDOM以使用文档。然而,我得到了下面的错误 首先,除了在Stack Overflow上发布的问题之外,我在网上看到了无数的例子,但我甚至无法解决最简单的例子。顺便说一句,我对Javascript还不熟悉 我的代码如下: 根目录 --->index.html --->module.js --->包锁。json --->package.json --->测试 --->--->messageTest.js 不同的文件如下所示: inde
文档
。然而,我得到了下面的错误
首先,除了在Stack Overflow上发布的问题之外,我在网上看到了无数的例子,但我甚至无法解决最简单的例子。顺便说一句,我对Javascript还不熟悉
我的代码如下:
根目录
--->index.html--->module.js
--->包锁。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>
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
function updateMsg(newMsg) {
document.getElementById('msg').innerHTML = newMsg;
}
updateMsg("Changing message");
module.exports = updateMsg;
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文件中的document.getElementByID…
步骤中得到ReferenceError:document未定义
错误
如果我删除
updateMsg(“更改消息”)
,我的测试显然运行良好。在该示例中,您有几个问题:
global
(因为这样更容易出错),不要require()
要在虚拟窗口中运行的脚本{resources:“可用”,runScripts:“仅限外部”}
参数来解决这个问题(请确保您阅读了中的安全含义)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
在浏览器中不存在。在该示例中,您有几个问题:
global
(因为这样更容易出错),不要require()
要在虚拟窗口中运行的脚本{resources:“可用”,runScripts:“仅限外部”}
参数来解决这个问题(请确保您阅读了中的安全含义)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
在浏览器中不存在。您的代码似乎运行良好,它在标记中显示文本“更改消息”,选中fiddle:并且它不是您描述的文档。getElementByID
,是document.getElementById
可能与感谢您的捕获重复。我的代码确实运行得很好(在物理浏览器上),但是当我在需要模拟浏览器的地方运行测试时,我发现没有找到文档元素。这应该用JSDOM来模拟(据我所知),但我不确定为什么它不起作用。您的代码似乎运行得很好,它在标记中显示文本“更改消息”,检查fiddle:并且,它不是您描述的文档。getElementByID
,是document.getElementById
可能与感谢您的捕获重复。我的代码确实运行得很好(在物理浏览器上),但是当我在需要模拟浏览器的地方运行测试时,我发现没有找到文档元素。这应该用JSDOM来模拟(据我所知),但我不确定为什么它不起作用。非常感谢您的回答!它解决了这个错误。尽管我已经从module.js中删除了模块行,您能告诉我updateMsg(“”)函数是如何从测试文件中访问的吗?@Adam jsdom实际上像一个真正的浏览器一样工作-它有自己的脚本加载机制,可以发出HTTP请求(或不使用节点模块解析机制的本地文件加载),因此,脚本src标记会触发正确的加载并使函数可用。这也意味着其他节点内部(需求、模块等)不可用!它确实给了你一个“完美”的浏览器来测试-这也意味着如果你想要模块分辨率,你将不得不求助于网页包装,并再次加载带有适当标签的脚本。非常感谢你的回答!它解决了这个错误。尽管我已经从module.js中删除了模块行,您能告诉我updateMsg(“”)函数是如何从测试文件中访问的吗?@Adam jsdom实际上像一个真正的浏览器一样工作-它有自己的脚本加载机制,可以发出HTTP请求(或不使用节点模块解析机制的本地文件加载),因此,脚本src标记会触发正确的加载并使函数可用。这也意味着其他节点内部(需求、模块等)不可用!它确实给了你一个“完美”的浏览器来测试——这也意味着,如果你想要模块分辨率,你必须求助于网页包装,并再次加载带有适当标签的脚本。