jsdomは、ドキュメントの<head>
タグ内でインラインのスクリプトを実行できますが、 <script src="">
を介してドキュメントヘッドにリンクされているスクリプトを実行するにはどうすればよいですか?
私が使用しているオプションの場合:
{
url: url,
resources: 'usable',
runScripts: 'dangerously',
}
// index.js
const request = require('request')
const jsdom = require('jsdom')
const {JSDOM} = jsdom
const url = 'http://localhost:8000'
request(url, (error, response, body) => {
const options = {
url: url,
resources: 'usable',
runScripts: 'dangerously',
}
const dom = new JSDOM(body, options)
console.log(dom.window.document.body.children.length) // Expecting to see `1`
console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
})
// external.js
document.addEventListener('DOMContentLoaded', () => {
document.write('<h1>Hello world!</h1>')
})
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSDOM test</title>
<script src="external.js"></script>
</head>
<body>
</body>
</html>
最小限の作業例を完了する: https ://github.com/cg433n/jsdom-test
ここでの問題は、 DOMContentLoaded
が非同期イベントであるということです。 発生する前にログに記録しています。 あなたはそれが発火するのを待つ必要があります。 そうして初めて、あなたのdocument.write()
が起こります。
このようなものはおそらく機能するはずです:
const dom = new JSDOM(body, options)
dom.window.document.addEventListener('DOMContentLoaded', () => {
// We need to delay one extra turn because we are the first DOMContentLoaded listener,
// but we want to execute this code only after the second DOMContentLoaded listener
// (added by external.js) fires.
setImmediate(() => {
console.log(dom.window.document.body.children.length) // Expecting to see `1`
console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
});
});
そうか! あなたたちは素晴らしいです-良い仕事を続けてください!
注意:上記のデモの2つの機能にはリスクが伴います。
request
は減価償却されます。 npm install request
の結果:setImmediate
は長期的には危険です。または、 fs
を使用してファイルからjsコードを読み取り、読み込むことをお勧めします。#3023の@EricRickettsのFS.read()
アプローチと@DomenicのaddEventListener()
に基づくStackoverflowを参照してください。 #1914。 私が提案する作業デモには次のものが含まれます。
fs.readFileSync
を使用して、外部jsを文字列としてhtmlにロードしますこれにより、xhr / API呼び出しを実行できなくなる可能性があり、したがって問題は部分的にしか解決されません。
URLを機能させる方法がわかりませんでした。
理想的には、 URL作業デモを介してexternal.jsファイルをロードする更新された最小限のJSDOMが歓迎されます。 :心臓:
最も参考になるコメント
ここでの問題は、
DOMContentLoaded
が非同期イベントであるということです。 発生する前にログに記録しています。 あなたはそれが発火するのを待つ必要があります。 そうして初めて、あなたのdocument.write()
が起こります。このようなものはおそらく機能するはずです: