gpt4 book ai didi

javascript - 再次使用同一实例webdriverJS

转载 作者:行者123 更新时间:2023-11-29 23:48:28 25 4
gpt4 key购买 nike

我真的是Selenium的新手。我设法使用下面的nodejs代码打开了一个网站

var webdriver = require('selenium-webdriver');

var driver = new webdriver.Builder()
.forBrowser('chrome')
.build();
console.log(driver);

driver.get('https://web.whatsapp.com');

//perform all other operations here.


https://web.whatsapp.com已打开,我手动扫描QR码并登录。现在,我有不同的javascript文件来执行操作,如删除,清除web.whatsapp.com中的聊天等。

现在,如果遇到一些错误,我将进行调试,然后当我再次使用 node test.js运行脚本时,又需要2分钟来加载页面并执行所需的步骤。我只想重新打开已经打开的标签并继续执行脚本,而是打开新窗口。

编辑第二天:仍在寻找解决方案。我尝试下面的代码保存对象并重用它。这是正确的方法吗?我收到JSON解析错误。

var o = new chrome.Options();
o.addArguments("user-data-dir=/Users/vishnu/Library/Application Support/Google/Chrome/Profile 2");
o.addArguments("disable-infobars");
o.addArguments("--no-first-run");

var driver = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).setChromeOptions(o).build();
var savefile = fs.writeFile('data.json', JSON.stringify(util.inspect(driver)) , 'utf-8');
var parsedJSON = require('./data.json');
console.log(parsedJSON);

最佳答案

我花了一些时间和几种不同的方法,但是我设法完成了一些我认为可以解决您的问题并允许以相当不错的方式进行测试的工作。

因为它不能直接回答如何在Selenium中重用浏览器会话(使用它们的JavaScript API)的问题,所以我将首先介绍我提出的解决方案,然后简要讨论我尝试过的其他方法。它可能会给其他人一个想法,并帮助他们以更好/更好的方式解决此问题。谁知道。至少我的尝试会被记录在案。

拟议的解决方案(经测试可行)

因为我实际上没有设法重用浏览器会话(请参见下文),所以我认为我可以尝试其他方法。方法如下。

理念


在一个文件(例如init.js)中有一个主循环,并在一个单独的文件(test.js)中进行测试。
主循环打开浏览器实例并使其保持打开状态。它还公开了某种CLI,该CLI可以运行(来自test.js的)测试,检查错误的发生并关闭浏览器实例并停止主循环。
test.js中的测试导出由主循环执行的测试功能。它通过了一个驱动程序实例来使用。主循环会捕获此处发生的任何错误。


由于浏览器实例仅打开一次,因此我们只需执行一次使用WhatsApp进行身份验证(扫描QR码)的手动过程。之后,运行测试将重新加载web.whatsapp.com,但它会记住我们已经过身份验证,因此可以立即运行在test.js中定义的任何测试。

为了使主循环保持活动状态,至关重要的是我们必须捕捉到测试中可能发生的每个错误。不幸的是,为此我不得不求助于uncaughtException

实作

这是我提出的上述想法的实现。如果您愿意的话,可以将其做得更加出色。我在这里为了简单起见(希望我设法做到了)。

init.js
这是上述想法的主要循环。

var webdriver = require('selenium-webdriver'),
by = webdriver.By,
until = webdriver.until,
driver = null,
prompt = '> ',
testPath = 'test.js',
lastError = null;

function initDriver() {
return new Promise((resolve, reject) => {
// already opened a browser? done
if (driver !== null) {
resolve();
return;
}
// open a new browser, let user scan QR code
driver = new webdriver.Builder().forBrowser('chrome').build();
driver.get('https://web.whatsapp.com');
process.stdout.write("Please scan the QR code within 30 seconds...\n");
driver.wait(until.elementLocated(by.className('chat')), 30000)
.then(() => resolve())
.catch((timeout) => {
process.stdout.write("\b\bTimed out waiting for code to" +
" be scanned.\n");
driver.quit();
reject();
});
});
}

function recordError(err) {
process.stderr.write(err.name + ': ' + err.message + "\n");
lastError = err;
// let user know that test failed
process.stdout.write("Test failed!\n");
// indicate we are ready to read the next command
process.stdout.write(prompt);
}

process.stdout.write(prompt);
process.stdin.setEncoding('utf8');
process.stdin.on('readable', () => {
var chunk = process.stdin.read();
if (chunk === null) {
// happens on initialization, ignore
return;
}
// do various different things for different commands
var line = chunk.trim(),
cmds = line.split(/\s+/);
switch (cmds[0]) {
case 'error':
// print last error, when applicable
if (lastError !== null) {
console.log(lastError);
}
// indicate we are ready to read the next command
process.stdout.write(prompt);
break;
case 'run':
// open a browser if we didn't yet, execute tests
initDriver().then(() => {
// carefully load test code, report SyntaxError when applicable
var file = (cmds.length === 1 ? testPath : cmds[1] + '.js');
try {
var test = require('./' + file);
} catch (err) {
recordError(err);
return;
} finally {
// force node to read the test code again when we
// require it in the future
delete require.cache[__dirname + '/' + file];
}
// carefully execute tests, report errors when applicable
test.execute(driver, by, until)
.then(() => {
// indicate we are ready to read the next command
process.stdout.write(prompt);
})
.catch(recordError);
}).catch(() => process.stdin.destroy());
break;
case 'quit':
// close browser if it was opened and stop this process
if (driver !== null) {
driver.quit();
}
process.stdin.destroy();
return;
}
});

// some errors somehow still escape all catches we have...
process.on('uncaughtException', recordError);


test.js
这是上述想法的考验。我写了一些东西只是为了测试主循环和一些WebDriver功能。这里几乎一切皆有可能。我已经使用 promises使测试执行在主循环中很好地工作了。

var driver, by, until,
timeout = 5000;

function waitAndClickElement(selector, index = 0) {
driver.wait(until.elementLocated(by.css(selector)), timeout)
.then(() => {
driver.findElements(by.css(selector)).then((els) => {
var element = els[index];
driver.wait(until.elementIsVisible(element), timeout);
element.click();
});
});
}

exports.execute = function(d, b, u) {
// make globally accessible for ease of use
driver = d;
by = b;
until = u;
// actual test as a promise
return new Promise((resolve, reject) => {
// open site
driver.get('https://web.whatsapp.com');
// make sure it loads fine
driver.wait(until.elementLocated(by.className('chat')), timeout);
driver.wait(until.elementIsVisible(
driver.findElement(by.className('chat'))), timeout);
// open menu
waitAndClickElement('.icon.icon-menu');
// click profile link
waitAndClickElement('.menu-shortcut', 1);
// give profile time to animate
// this prevents an error from occurring when we try to click the close
// button while it is still being animated (workaround/hack!)
driver.sleep(500);
// close profile
waitAndClickElement('.btn-close-drawer');
driver.sleep(500); // same for hiding profile
// click some chat
waitAndClickElement('.chat', 3);
// let main script know we are done successfully
// we do so after all other webdriver promise have resolved by creating
// another webdriver promise and hooking into its resolve
driver.wait(until.elementLocated(by.className('chat')), timeout)
.then(() => resolve());
});
};


输出示例

这是一些示例输出。第一次调用 run test将打开一个Chrome实例。其他调用将使用相同的实例。当发生错误时,可以如图所示对其进行检查。执行 quit将关闭浏览器实例并退出主循环。

$ node init.js
> run test
> run test
WebDriverError: unknown error: Element <div class="chat">...</div> is not clickable at point (163, 432). Other element would receive the click: <div dir="auto" contenteditable="false" class="input input-text">...</div>
(Session info: chrome=57.0.2987.133)
(Driver info: chromedriver=2.29.461571 (8a88bbe0775e2a23afda0ceaf2ef7ee74e822cc5),platform=Linux 4.9.0-2-amd64 x86_64)
Test failed!
> error
<prints complete stacktrace>
> run test
> quit


您可以通过简单地调用其他文件来运行测试。假设您有一个文件 test-foo.js,然后在上述提示中执行 run test-foo以运行它。所有测试将共享同一个Chrome实例。



失败的尝试1:保存和恢复存储

当使用我的开发工具检查页面时,我注意到它似乎使用了 localStorage。可以将 export作为JSON并 write生成文件。在下一次调用时,此文件可以是 readparsed,并在重新加载页面之前将其写入新的浏览器实例存储中。

不幸的是,WhatsApp仍然需要我扫描QR码。我试图找出我错过的内容(Cookie, sessionStorage,...),但没有解决。经过一段时间后,WhatsApp可能会将浏览器注册为已断开连接。还是它使用其他浏览器属性(会话ID?)来识别浏览器。从我的角度来看,这纯粹是猜测。



失败的尝试2:切换会话/窗口

通过WebDriver启动的每个浏览器实例都有一个会话ID。可以检索此ID,因此我认为可以启动会话,然后从测试用例连接到该会话,然后从一个单独的文件运行该会话(您可以看到这是最终解决方案的前身)。不幸的是,我无法找到一种设置会话ID的方法。我不确定这实际上可能是安全问题。在WebDriver的使用方面更精通的人也许可以在这里澄清。

我确实发现可以在 retrieve a list of window handlesthem之间切换。不幸的是,窗口仅在单个会话中共享,而没有跨会话共享。

关于javascript - 再次使用同一实例webdriverJS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43353279/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com