Skip to content Skip to sidebar Skip to footer

How Can I Dynamically Inject Functions To Evaluate Using Puppeteer?

I am using Puppeteer for headless Chrome. I wish to evaluate a function inside the page that uses parts of other functions, defined dynamically elsewhere. The code below is a mini

Solution 1:

You can add function to page context with addScriptTag:

const browser = await puppeteer.launch();
const page = await browser.newPage();

functionfunctionToInject (){
    return1+1;
}

functionotherFunctionToInject(input){
    return6
}

await page.addScriptTag({ content: `${functionToInject}${otherFunctionToInject}`});

var data = await page.evaluate(function(){
    console.log('woo I run inside a browser')
    returnfunctionToInject() + otherFunctionToInject();
});

console.log(data);

await browser.close();

This example is a dirty way of solving this problem with string concatenation. More clean would be using a url or path in the addScriptTag method.


Or use exposeFunction (but now functions are wrapped in Promise):

const browser = await puppeteer.launch();
const page = await browser.newPage();

var functionToInject = function(){
    return1+1;
}

var otherFunctionToInject = function(input){
    return6
}

await page.exposeFunction('functionToInject', functionToInject);
await page.exposeFunction('otherFunctionToInject', otherFunctionToInject);

var data = await page.evaluate(asyncfunction(){
    console.log('woo I run inside a browser')
    returnawaitfunctionToInject() + awaitotherFunctionToInject();
});

console.log(data);

await browser.close();

Solution 2:

working example accessible by link, in the same repo you can see the tested component.

it("click should return option value", async () => {
    const optionToReturn = "ClickedOption";

    const page = awaitnewE2EPage();
    const mockCallBack = jest.fn();

    await page.setContent(
      `<list-option option='${optionToReturn}'></list-option>`
    );

    await page.exposeFunction("functionToInject", mockCallBack); // Inject functionawait page.$eval("list-option", (elm: any) => {
      elm.onOptionSelected = this.functionToInject;  // Assign function
    });
    await page.waitForChanges();

    const element = await page.find("list-option");
    await element.click();
    expect(mockCallBack.mock.calls.length).toEqual(1); // Check callsexpect(mockCallBack.mock.calls[0][0]).toBe(optionToReturn); // Check argument
  });

Solution 3:

You can also use page.exposeFunction() which will make your function return a Promise (requiring the use of async and await). This happens because your function will not be running inside your browser, but inside your nodejs application and its results are being send back and forth into/to the browser code.

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(someURL);       

var functionToInject = function(){
    return1+1;
}

var otherFunctionToInject = function(input){
    return6
}

await page.exposeFunction("functionToInject", functionToInject)
await page.exposeFunction("otherFunctionToInject", otherFunctionToInject)

var data = await page.evaluate(asyncfunction(){
    console.log('woo I run inside a browser')
    returnawaitfunctionToInject() + awaitotherFunctionToInject();
});

return data

Related questions:

  1. exposeFunction() does not work after goto()
  2. exposed function queryseldtcor not working in puppeteer
  3. How to use evaluateOnNewDocument and exposeFunction?
  4. exposeFunction remains in memory?
  5. Puppeteer: pass variable in .evaluate()
  6. Puppeteer evaluate function
  7. allow to pass a parameterized funciton as a string to page.evaluate
  8. Functions bound with page.exposeFunction() produce unhandled promise rejections
  9. How to pass a function in Puppeteers .evaluate() method?
  10. Why can't I access 'window' in an exposeFunction() function with Puppeteer?

Post a Comment for "How Can I Dynamically Inject Functions To Evaluate Using Puppeteer?"