What is wrong with this code? It displays the says: hello bar from the out.js console.log but does not run the rest of the script doesn't add the link inside <div id="link"></div>
If I put the script directly in the code it works, but not in a .js file
teste2.js
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="link"></div>
<p>Hello world</p>
<script src="http://localhost/2022/jsdom/out.js"></script>
</body>
</html>`, { resources: "usable", runScripts: "dangerously"});
const document = dom.window.document;
console.log(document.getElementsByTagName('html')[0].innerHTML);
out.js
let T = document.getElementById('link');
T.innerHTML = '<a href="htt://">LINK</a>';
console.log('bar says: hello');
CodePudding user response:
JSDOM loads sub-resources asynchronously, so your Node.js code is accessing the DOM before the <script>
code has executed.
This is also why the log of document.getElementsByTagName('html')[0].innerHTML
appears before the log of 'bar says: hello'
.
You can handle this by explicitly waiting for the load
event:
const document = dom.window.document;
document.addEventListener('load', () => {
console.log(document.getElementsByTagName('html')[0].innerHTML);
});
You'll need more complex logic if the script itself does anything asynchronously. Firing a custom event that you can listen for is a good approach.