我正在使用Puppeteer用于无头Chrome。我希望评估页面内部使用其他函数部分的函数,这些函数在其他地方动态定义。
以下代码是最小的示例/证明。实际上functionToInject()
和otherFunctionToInject()
更复杂,需要页面DOM。
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(someURL);
var functionToInject = function(){
return 1+1;
}
var otherFunctionToInject = function(input){
return 6
}
var data = await page.evaluate(function(functionToInject, otherFunctionToInject){
console.log('woo I run inside a browser')
return functionToInject() + otherFunctionToInject();
});
return data
当我运行代码时,我得到:
错误:评估失败:TypeError:functionToInject不是函数
我理解:functionToInject
没有被传递到页面的JS上下文中。但是如何将它传递到页面的JS上下文中?
答案 0 :(得分:11)
您可以使用addScriptTag
const browser = await puppeteer.launch();
const page = await browser.newPage();
function functionToInject (){
return 1+1;
}
function otherFunctionToInject(input){
return 6
}
await page.addScriptTag({ content: `${functionToInject} ${otherFunctionToInject}`});
var data = await page.evaluate(function(){
console.log('woo I run inside a browser')
return functionToInject() + otherFunctionToInject();
});
console.log(data);
await browser.close();
此示例是使用字符串连接解决此问题的一种肮脏方式。更干净的方法是在url
方法中使用path
或addScriptTag
。
或者使用exposeFunction
(但现在函数包含在Promise中):
const browser = await puppeteer.launch();
const page = await browser.newPage();
var functionToInject = function(){
return 1+1;
}
var otherFunctionToInject = function(input){
return 6
}
await page.exposeFunction('functionToInject', functionToInject);
await page.exposeFunction('otherFunctionToInject', otherFunctionToInject);
var data = await page.evaluate(async function(){
console.log('woo I run inside a browser')
return await functionToInject() + await otherFunctionToInject();
});
console.log(data);
await browser.close();
答案 1 :(得分:0)
工作示例accessible by link,在同一仓库中,您可以看到经过测试的组件。
it("click should return option value", async () => {
const optionToReturn = "ClickedOption";
const page = await newE2EPage();
const mockCallBack = jest.fn();
await page.setContent(
`<list-option option='${optionToReturn}'></list-option>`
);
await page.exposeFunction("functionToInject", mockCallBack); // Inject function
await 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 calls
expect(mockCallBack.mock.calls[0][0]).toBe(optionToReturn); // Check argument
});
答案 2 :(得分:0)
您还可以使用page.exposeFunction()
,这会使您的函数返回Promise
(要求使用async
和await
)。发生这种情况是因为您的功能不是running inside your browser,而是在您的nodejs
应用程序内部,并且其结果在浏览器代码之间来回发送。
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(someURL);
var functionToInject = function(){
return 1+1;
}
var otherFunctionToInject = function(input){
return 6
}
await page.exposeFunction("functionToInject", functionToInject)
await page.exposeFunction("otherFunctionToInject", otherFunctionToInject)
var data = await page.evaluate(async function(){
console.log('woo I run inside a browser')
return await functionToInject() + await otherFunctionToInject();
});
return data
相关问题: