Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JSDOM-未定义文档_Javascript_Html_Json_Dom_Jsdom - Fatal编程技术网

Javascript 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

我创建了一个非常简单的页面,只显示一条消息,因为我正在尝试测试JSDOM以使用
文档
。然而,我得到了下面的错误

首先,除了在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(“更改消息”)
,我的测试显然运行良好。

在该示例中,您有几个问题:

  • 您混合了jsdom窗口和全局节点上下文。避免分配给
    global
    (因为这样更容易出错),不要
    require()
    要在虚拟窗口中运行的脚本

  • 默认情况下,jsdom阻止在页面脚本上运行,因此您的module.js既不会加载也不会执行。您必须提供
    {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
    在浏览器中不存在。

    在该示例中,您有几个问题:

  • 您混合了jsdom窗口和全局节点上下文。避免分配给
    global
    (因为这样更容易出错),不要
    require()
    要在虚拟窗口中运行的脚本

  • 默认情况下,jsdom阻止在页面脚本上运行,因此您的module.js既不会加载也不会执行。您必须提供
    {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标记会触发正确的加载并使函数可用。这也意味着其他节点内部(需求、模块等)不可用!它确实给了你一个“完美”的浏览器来测试——这也意味着,如果你想要模块分辨率,你必须求助于网页包装,并再次加载带有适当标签的脚本。