最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - JSDOM - Document is not defined - Stack Overflow

programmeradmin2浏览0评论

I've created a very simple page that just displays a single message, as I'm trying to test out the JSDOM to use document. However, I'm getting the below error.

First of all, I have seen the countless examples online, in addition to the questions posted on Stack Overflow, but I have not been able to resolve even the simplest example. As a side-note, I am new to Javascript.

My code so far is as follows:

Root Directory

--->index.html
--->module.js
--->package-lock.json
--->package.json
--->test
--->--->messageTest.js

The different files are as follows:

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!');
  });
});

If I run the test with npm test, I get the ReferenceError: document is not defined error at the document.getElementByID... step in the module.js file.

If I remove the updateMsg("Changing message"), my test obviously runs fine.

I've created a very simple page that just displays a single message, as I'm trying to test out the JSDOM to use document. However, I'm getting the below error.

First of all, I have seen the countless examples online, in addition to the questions posted on Stack Overflow, but I have not been able to resolve even the simplest example. As a side-note, I am new to Javascript.

My code so far is as follows:

Root Directory

--->index.html
--->module.js
--->package-lock.json
--->package.json
--->test
--->--->messageTest.js

The different files are as follows:

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!');
  });
});

If I run the test with npm test, I get the ReferenceError: document is not defined error at the document.getElementByID... step in the module.js file.

If I remove the updateMsg("Changing message"), my test obviously runs fine.

Share Improve this question edited Jul 19, 2019 at 13:53 user47589 asked Jul 19, 2019 at 13:48 AdamAdam 2,5627 gold badges40 silver badges75 bronze badges 3
  • Your code seems to run well, it display the text "Changing message" in the <p/> tag, check fiddle: jsfiddle/7k96oeuw And, its not document.getElementByID like you describe it, is document.getElementById – JC Hernández Commented Jul 19, 2019 at 13:57
  • Possible duplicate of stackoverflow./a/45961549/2444210 – IceMetalPunk Commented Jul 19, 2019 at 14:00
  • Thanks for the catch. My code runs fine indeed (on a physical browser) but when I run the test where the browser needs to be simulated, I get that the document element is not found. This should be simulated with JSDOM (as far as I understand), but I'm not sure why it doesn't work. – Adam Commented Jul 19, 2019 at 14:00
Add a ment  | 

1 Answer 1

Reset to default 2

You have a couple of issues in that example:

  1. You're mixing jsdom window and global node context. Avoid assigning to global (because that's making it easier to make that mistake), don't require() scripts that you want to run in your virtual window.

  2. jsdom prevents running on-page scripts by default, so your module.js is neither loaded nor executed. You'll have to provide { resources: "usable", runScripts: "outside-only" } parameters to fix that (make sure you read about the security implications in the jsdom README).

  3. You're not waiting for the load event, so your test is run before jsdom has a chance to load the script.

Working code would look something like this:

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!"
    );
  });
});

You'll also need to remove the module line from module.js, module doesn't exist in the browser.

发布评论

评论列表(0)

  1. 暂无评论