Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global function declared in background page does not get called via evaluateHandle

I have a global function in background page like so:

window.myfn = function(){
    return new Promise((resolve, reject) => { stuff; });
};

I am using Jest and Puppeteer. Consider this in my test.js file:

async function getBackgroundPage() {
    const targets = await browser.targets(),
        backgroundPageTarget = targets.find(
            target => target.type() === "background_page",
        ),
        backgroundPage = await backgroundPageTarget.page();

    return backgroundPage;
}

async function sendUpdate() {
    const bgPage = await getBackgroundPage(),
        argString = `() => window.myfn()`;
    await bgPage.evaluateHandle(argString);
    await sleep(30000);
}

getBackgroundPage is literally copied from the docs, so I hope it's correct. However, sendUpdate() does not work as expected. Ideally, window.myfn should be called but actually it is never called. I know this because:

  1. I put several console.logs in it, so if it was called there should have been some log output.
  2. The 30second sleep gives me enough time to goto chrome://extensions, and open the background page console via Inspect Views, and I could not find any log outputs there.

There are no errors in both the background page, and the Jest console. What is the problem then? Why is that global function not being called?

like image 540
Gaurang Tandon Avatar asked Oct 22 '25 10:10

Gaurang Tandon


1 Answers

There is a minor difference between giving a function and giving a string to the evaluateHandle (and evaluate) function.

If you pass a function, the function will be called inside the page. If you pass a string, the string will be executed in the page context. This means, that these two lines do different things:

await bgPage.evaluate(() => console.log("test"););
await bgPage.evaluate('() => console.log("test");');

The first line will execute the function (and run console.log) inside the page. However, the second line will only declare the function and not call it. Therefore, if we pass a string we have to do one of these things:

await bgPage.evaluate('console.log("test")'); // directly run console.log
await bgPage.evaluate('(() => console.log("test"))()'); // execute the function

Fixing your code

Coming back to your code, this means you either have directly call window.myfn() or you pass the argument as a function:

await bgPage.evaluateHandle('window.myfn()'); // directly call the function
await bgPage.evaluateHandle(() => window.myfn()); // or pass as a function and not as string
like image 72
Thomas Dondorf Avatar answered Oct 24 '25 00:10

Thomas Dondorf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!