Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load local JavaScript file with JSDOM?

I am unable to use JSDOM (version 13.0.0) to load scripts from the local filesystem with a relative path.

I have taken a look at the following questions but they do not answer my question:

  • jsdom can't load local html and javascript (I have already followed the runScripts and resources suggestion there).

File foo.js:

var jsdom = require('jsdom')

var html = `<!DOCTYPE html>
<html>
  <head>
    <title>Test</title>
    <script src="bar.js"></script>
  </head>
  <body>
    <div>Test</div>
  </body>
</html>`

global.window = new jsdom.JSDOM(html, { runScripts: "dangerously", resources: "usable" }).window
console.log('foo')

File bar.js:

console.log('bar')

Here is the error I get:

$ node foo.js
foo
Error: Could not load script: "bar.js"
    at onErrorWrapped (/Users/lone/so/node_modules/jsdom/lib/jsdom/browser/resources/per-document-resource-loader.js:41:19)
    at Object.check (/Users/lone/so/node_modules/jsdom/lib/jsdom/browser/resources/resource-queue.js:72:23)
    at request.then.catch.err (/Users/lone/so/node_modules/jsdom/lib/jsdom/browser/resources/resource-queue.js:124:14)
    at process._tickCallback (internal/process/next_tick.js:68:7)
    at Function.Module.runMain (internal/modules/cjs/loader.js:746:11)
    at startup (internal/bootstrap/node.js:240:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:564:3) Error: Tried to fetch invalid URL bar.js
    at ResourceLoader.fetch (/Users/lone/so/node_modules/jsdom/lib/jsdom/browser/resources/resource-loader.js:84:29)
    at PerDocumentResourceLoader.fetch (/Users/lone/so/node_modules/jsdom/lib/jsdom/browser/resources/per-document-resource-loader.js:16:42)
    at HTMLScriptElementImpl._fetchExternalScript (/Users/lone/so/node_modules/jsdom/lib/jsdom/living/nodes/HTMLScriptElement-impl.js:92:30)
    at HTMLScriptElementImpl._eval (/Users/lone/so/node_modules/jsdom/lib/jsdom/living/nodes/HTMLScriptElement-impl.js:161:12)
    at HTMLScriptElementImpl._poppedOffStackOfOpenElements (/Users/lone/so/node_modules/jsdom/lib/jsdom/living/nodes/HTMLScriptElement-impl.js:126:10)
    at OpenElementStack.pop (/Users/lone/so/node_modules/jsdom/lib/jsdom/browser/htmltodom.js:17:12)
    at Object.endTagInText [as END_TAG_TOKEN] (/Users/lone/so/node_modules/parse5/lib/parser/index.js:2153:20)
    at Parser._processToken (/Users/lone/so/node_modules/parse5/lib/parser/index.js:657:55)
    at Parser._processInputToken (/Users/lone/so/node_modules/parse5/lib/parser/index.js:684:18)
    at Parser._runParsingLoop (/Users/lone/so/node_modules/parse5/lib/parser/index.js:440:18)

How can I load a local JavaScript file while using JSDOM?

like image 548
Lone Learner Avatar asked Nov 10 '18 05:11

Lone Learner


People also ask

How upload local js file in HTML?

To include an external JavaScript file, we can use the script tag with the attribute src . You've already used the src attribute when using images. The value for the src attribute should be the path to your JavaScript file. This script tag should be included between the <head> tags in your HTML document.

How do I run a JavaScript file in node js?

The usual way to run a Node. js program is to run the globally available node command (once you install Node. js) and pass the name of the file you want to execute. While running the command, make sure you are in the same directory which contains the app.

How does Jsdom work?

JSDOM is a library which parses and interacts with assembled HTML just like a browser. The benefit is that it isn't actually a browser. Instead, it implements web standards like browsers do. You can feed it some HTML, and it will parse that HTML.


1 Answers

JSDOM doesn't know where to look for that file locally while executing. So running your example you can follow any of this two approaches.

1st Approach

You have to wait for the script file to load and execute.

Create a three files index.html,index.js and test.js into the same folder.

index.html

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    abc
    <script src='index.js'></script>
  </body>
</html>

index.js

document.body.textContent = 123;

test.js

'use strict';

const { JSDOM } = require('jsdom');

const options = {
  resources: 'usable',
  runScripts: 'dangerously',
};

JSDOM.fromFile('index.html', options).then((dom) => {
  console.log(dom.window.document.body.textContent.trim());

  setTimeout(() => {
    console.log(dom.window.document.body.textContent.trim());
  }, 5000);
});

 // console output
 // abc
 // 123

2nd Approach Set the external scripts base root folder in JSDOM env.

js/index.js

console.log('load from jsdom');
var loadFromJSDOM = 'load from jsdom';

test.js

'use strict';
const { JSDOM } = require('jsdom');
JSDOM.env({
        html: "<html><body></body></html>",
        documentRoot: __dirname + '/js',
        scripts: [
            'index.js'
        ]
    }, function (err, window) {
        console.log(window.loadFromJSDOM);
    }
);

Read more from these references

https://github.com/jsdom/jsdom/issues/1867

jsdom.env: local jquery script doesn't work

like image 58
front_end_dev Avatar answered Sep 17 '22 20:09

front_end_dev