selenium-webdriver 将函数数组作为参数传递给 executeScript
selenium-webdriver pass an array of functions as argument to executeScript
import webdriver from 'selenium-webdriver';
const driver = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.build();
driver.get('https://www.google.com');
let foo = function(rules) {
rules.forEach(rule => {
rule();
});
}
let bar = function() { return 'bar' };
let baz = function() { return 'baz' };
driver.executeScript(foo, [bar, baz]).then(function(result) {
console.log(result);
});
driver.quit();
它出错了
WebDriverError: unknown error: rule is not a function
let foo = function(rules) {
return rules;
// rules.forEach(rule => {
// rule();
// });
}
let bar = function() { return 'bar' };
let baz = function() { return 'baz' };
driver.executeScript(foo, [bar, baz]).then(function(result) {
console.log(result); // refer the log pasted below
});
看起来函数正在序列化 string
[ 'function bar() {\n return \'bar\';\n}',
'function baz() {\n return \'baz\';\n}' ]
任何关于如何通过 array of functions as arguments
的指示都会有所帮助。
问题:
所有作为参数传递给函数的重要数据都将转换为字符串,因为这是从 selenium 驱动程序向浏览器注入内容的唯一方法。
Arguments must be a number, a boolean, a String, WebElement, or a List of any combination of the above.
解决方案
您可以将字符串转换为函数并使用 eval
或函数构造函数 new Function('...function body here...')
执行它。是的,这是非常糟糕的,但实际上,没有其他方法可以将重要数据从驱动程序传递到浏览器。实际上,当您调用此 driver.executeScript(foo, [], ...)
时,foo
函数也被转换为字符串并在浏览器中使用 eval
执行。
如果我是你,我会尝试寻找另一种无需将函数作为参数传递即可获得结果的方法。
您可以在以下位置阅读更多信息:https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/JavascriptExecutor.html
我想你可以使用 eval。请参阅下面的代码:
driver.get('https://www.google.com');
let foo = function(rules) {
var results = [];
rules.forEach(rule => {
results.push(eval(rule));
});
return results;
}
let bar = "(function() { return ' message returned from bar' })()";
let baz = "(function() { return 'message returned from baz' })()";
driver.executeScript(foo, [bar, baz]).then(function(result) {
console.log(result);
});
我找到了一个不同的解决方法,w/o 使用 eval
显式 ,但方式相似。
- 要注入的函数必须命名
函数
注入function.toString()
作为<script>
的内容
function foo(rules) {
var result = [];
rules.forEach(rule => {
result.push(rule());
});
return result;
}
function bar() { return 'bar' };
function baz() { return 'baz' };
function inject(content) {
var script = document.createElement('script');
script.innerHTML = content;
document.head.appendChild(script);
}
let script = `${bar.toString()} ${baz.toString()} ${foo.toString()}`;
driver.executeScript(inject, script);
然后执行想要的函数为
driver.executeScript('return foo([bar, baz])').then(function(result) {
// use the result
});
完整示例
// example.js
import webdriver from 'selenium-webdriver';
const driver = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.build();
driver.get('https://www.google.com');
function foo(rules) {
var result = [];
rules.forEach(rule => {
result.push(rule());
});
return result;
}
function bar() { return 'bar' };
function baz() { return 'baz' };
function inject(content) {
var script = document.createElement('script');
script.innerHTML = content;
document.head.appendChild(script);
}
let script = `${bar.toString()} ${baz.toString()} ${foo.toString()}`;
driver.executeScript(inject, script);
driver.executeScript('return foo([bar, baz])').then(function(result) {
console.log(result);
});
driver.quit();
> babel-node example.js
[ 'bar', 'baz' ]
import webdriver from 'selenium-webdriver';
const driver = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.build();
driver.get('https://www.google.com');
let foo = function(rules) {
rules.forEach(rule => {
rule();
});
}
let bar = function() { return 'bar' };
let baz = function() { return 'baz' };
driver.executeScript(foo, [bar, baz]).then(function(result) {
console.log(result);
});
driver.quit();
它出错了
WebDriverError: unknown error: rule is not a function
let foo = function(rules) {
return rules;
// rules.forEach(rule => {
// rule();
// });
}
let bar = function() { return 'bar' };
let baz = function() { return 'baz' };
driver.executeScript(foo, [bar, baz]).then(function(result) {
console.log(result); // refer the log pasted below
});
看起来函数正在序列化 string
[ 'function bar() {\n return \'bar\';\n}',
'function baz() {\n return \'baz\';\n}' ]
任何关于如何通过 array of functions as arguments
的指示都会有所帮助。
问题: 所有作为参数传递给函数的重要数据都将转换为字符串,因为这是从 selenium 驱动程序向浏览器注入内容的唯一方法。
Arguments must be a number, a boolean, a String, WebElement, or a List of any combination of the above.
解决方案
您可以将字符串转换为函数并使用 eval
或函数构造函数 new Function('...function body here...')
执行它。是的,这是非常糟糕的,但实际上,没有其他方法可以将重要数据从驱动程序传递到浏览器。实际上,当您调用此 driver.executeScript(foo, [], ...)
时,foo
函数也被转换为字符串并在浏览器中使用 eval
执行。
如果我是你,我会尝试寻找另一种无需将函数作为参数传递即可获得结果的方法。
您可以在以下位置阅读更多信息:https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/JavascriptExecutor.html
我想你可以使用 eval。请参阅下面的代码:
driver.get('https://www.google.com');
let foo = function(rules) {
var results = [];
rules.forEach(rule => {
results.push(eval(rule));
});
return results;
}
let bar = "(function() { return ' message returned from bar' })()";
let baz = "(function() { return 'message returned from baz' })()";
driver.executeScript(foo, [bar, baz]).then(function(result) {
console.log(result);
});
我找到了一个不同的解决方法,w/o 使用 eval
显式 ,但方式相似。
- 要注入的函数必须命名 函数
注入
的内容function.toString()
作为<script>
function foo(rules) { var result = []; rules.forEach(rule => { result.push(rule()); }); return result; } function bar() { return 'bar' }; function baz() { return 'baz' }; function inject(content) { var script = document.createElement('script'); script.innerHTML = content; document.head.appendChild(script); } let script = `${bar.toString()} ${baz.toString()} ${foo.toString()}`; driver.executeScript(inject, script);
然后执行想要的函数为
driver.executeScript('return foo([bar, baz])').then(function(result) { // use the result });
完整示例
// example.js
import webdriver from 'selenium-webdriver';
const driver = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.build();
driver.get('https://www.google.com');
function foo(rules) {
var result = [];
rules.forEach(rule => {
result.push(rule());
});
return result;
}
function bar() { return 'bar' };
function baz() { return 'baz' };
function inject(content) {
var script = document.createElement('script');
script.innerHTML = content;
document.head.appendChild(script);
}
let script = `${bar.toString()} ${baz.toString()} ${foo.toString()}`;
driver.executeScript(inject, script);
driver.executeScript('return foo([bar, baz])').then(function(result) {
console.log(result);
});
driver.quit();
> babel-node example.js
[ 'bar', 'baz' ]