I am trying to write unit tests for JS code using Node.js, but the JS code will ultimately run in the browser and in some cases depends on browser-only objects (like document
). I’m trying to get Puppeteer to work in this context, but can’t seem to get past the basics.
The code I am testing is bundled into a single JS file, so I’m using the addScriptTag
of the page
object in Puppeteer to add this JS file, then using page.evaluate
to execute my test code.
My JS bundle (the code under test) exports a single object, and when I try to access this object from within the evaluate
execution, it is undefined
. In trying to track down why, I discovered that addScriptTag
doesn’t seem to add anything, and the document.scripts
array is empty.
Here’s an example:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.addScriptTag({
path: '/foo/bar/somescript.js', // This path is fake, but in my actual environment is correct
}).catch(error => console.log(error));
const result = await page.evaluate(() => {
return document.scripts;
}).catch(error => console.log(error));
console.log(result.length); // This returns undefined!
await browser.close();
Does anyone know what is missing from the above to get the script to be added to the page?
2
Answers
OK.. looks like I am (somehow) holding it wrong. If I reduce the test case to a very simple JS file, it seems to work. The problem must be elsewhere. For example, the following will work.
Define a JS file for testing
test.js
Try to access the value of
foo
in Puppeteer:Not sure why
document.scripts
does not return anything (even in this "working" case)Indeed, there was an error loading the script. Adding a
pageerror
handler revealed it:test.js
Without the
pagerror
handler, the value offoo
us justundefined
. Adding the handler, we see:(in my real case, the error was:
Error [TypeError]: crypto.randomUUID is not a function
, which is a separate issue to diagnose)