我正在尝试使用Selenium Web驱动程序和node js自动执行几个页面。我能够登录,但是登录后我想使用由Web驱动程序启动的同一会话,以便可以在受会话保护的页面上进行自动测试。这是我的尝试
async function login(){
Let d = await new Builder()
.forBrowser('chrome')
.build();
await d.get('https://demo.textdomain.com/')
await d.findElement(By.id('username')).sendKeys('admin ')
await d.findElement(By.id('password')).sendKeys('admin');
await d.findElement(By.css('button[type="submit"]')).click();
await d.getPageSource().then(function(content) {
if(content.indexOf('Welcome text') !==-1 ) {
console.log('Test passed');
console.log('landing page');
d.get('https://demo.textdomain.com/landingpage') //this is still going to login page as i cannot use the previous session
} else {
console.log('Test failed');
return false;
}
//driver.quit();
});
}
login();
我是否在登录后不小心丢弃了浏览器。
答案 0 :(得分:4)
通过类似SQA StackExchange的问题,您可以存储和恢复当前会话的cookie:
使用Javascript:
// Storing cookies:
driver.manage().getCookies().then(function (cookies) {
allCookies = cookies;
});
// Restoring cookies:
for (var key in allCookies) {
driver.manage().addCookie(key, allCookies[key]);
}
答案 1 :(得分:3)
您可能只在处理计时问题。硒很快移动。比您作为用户进行交互的方式要快得多。因此,它通常以似乎无法预测的方式起作用。但这仅仅是因为Selenium的运行速度比您作为用户的速度快得多。为了解决此问题,您应该充分利用Selenium的内置driver.wait
。例如:
const button = driver.wait(
until.elementLocated(By.id('my-button')),
20000
);
button.click();
以上内容一直等到ID为my-button
的按钮出现在DOM中,然后单击它。最多等待20000毫秒,但是只要按钮可用,操作就会结束。
因此,在您的情况下,如果在用户成功登录后仍有可用的东西,则可以等待该元素,然后再进入代码中的新页面。
顺便说一句,我也不确定为什么要使用getPageSource()
?这似乎是获得所需内容的一种非常笨拙的方法。那不是您可以获取其中内容的元素中的内容吗?
我写了一篇有关How to write reliable browser tests using Selenium and Node.js的文章,它可以帮助您更详细地理解文章中的上述代码示例,以及可以用来可靠地等待浏览器中各种条件的其他技术。
答案 2 :(得分:2)
我相信您的问题没有正确地等待登录完成。
Selenium不会等待异步操作完成,而是移至下一行,因此当您请求页面源时,很有可能登录服务器上的登录操作未完成,结果是不是您的期望。
您必须明确告知Selenium等待,因此您需要在登录名和检查用户是否登录的代码之间添加一些代码,出于这种假设,请增加10秒钟的超时时间。
如果这对您有用,您就不想浪费时间,因此您需要等待页面上的某些元素由于登录而发生更改,例如,您需要等待状态(或可见性)标头中的用户照片(如果已在DOM中)。
另外,我不确定“ getPageSource”函数的行为方式,它可以使用现有页面,还是可以要求新的副本。
我建议您使用其他方法通过检查DOM来测试用户是否已登录。
答案 3 :(得分:0)
我建议在其他Web驱动程序实例中首次登录后重新使用会话cookie。
首先存储cookie:
var cookieValue = firstWebDriver.Manage().Cookies.GetCookieNamed(name:"cookie_name");
然后,您可以将其传递给任何WebDriver实例,对其进行设置并驱动该Web应用程序,因为它是同一用户使用不同的浏览器实例:
anotherWebDriver.Manage().Cookies.AddCookie(new Cookie(name:"cookie_name", value:cookieValue));
如果要使用相同的浏览器实例,则必须对其进行同步,因为WebDriver调用通常不是线程安全的,并且probalby经常会导致异常(例如, stale ,因为元素更改或找不到,因为一个Web驱动程序导航到了另一个页面。
然后,我建议仅对下一个实例使用窗口句柄,而不关心会话。第一个打开,最后一个关闭会话(计算引用的句柄),并确保一次只有一个驱动程序使用此句柄。您还可以创建新的浏览器窗口,这将保留会话并为您提供新的句柄:
var handle = firstWebDriver.CurrentWindowHandle;
otherWebDriver.SwitchTo().Window(handle);
我用C#编写了代码,但是应该很容易适应JavaScript。