保持登录后的会话 - Selenium - JavaScript

3
我想使用Selenium Web Driver和Node.js自动化几个页面。我已经成功登录,但是在登录后,我希望可以使用由Web Driver启动的相同会话,以便在受会话保护的页面上进行自动化测试。这是我的尝试:
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();
    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();

我是否在登录后意外丢弃了浏览器。
4个回答

6

SQA StackExchange上一个类似的问题中,您可以存储并恢复当前会话的cookies:

使用JavaScript:

// Storing cookies:
driver.manage().getCookies().then(function (cookies) {
    allCookies = cookies;
}); 

// Restoring cookies:
for (var key in allCookies) {
    driver.manage().addCookie(key, allCookies[key]);
}

3

你可能只是处理时间问题。Selenium移动得非常快。比用户交互的速度快得多。因此,它经常以看似不可预测的方式行事。但这只是因为Selenium比您作为用户要快得多。为了解决这个问题,您应该充分利用Selenium内置的driver.wait。例如:

const button = driver.wait(
  until.elementLocated(By.id('my-button')), 
  20000
);

button.click();

上述代码会等到id为my-button的按钮出现在DOM中,然后点击它。最长等待时间为20000毫秒,但是只要按钮一出现就立即结束。
所以,在您的情况下,如果用户成功登录后有某些内容可用,您可以在代码中等待该元素,然后再前往新页面。
顺便说一句,我也不太确定为什么您要使用getPageSource()?这似乎是获得您要查找的内容的一种笨重方式。难道那个内容不是在某个元素中吗?
我写了一篇关于如何使用Selenium和Node.js编写可靠的浏览器测试的文章,其中介绍了更多关于文章中的示例代码以及其他可靠地等待浏览器中各种条件的技术。

1
我的问题还没有解决,但是当我按照你的解决方案时,我更接近解决了。 - sumit
@sumit请随时添加更多细节到你的问题中,我会尽力帮助你完全解决它。 - Todd Chaffee

2
我认为你的问题在于没有正确等待登录完成。Selenium不会等待异步操作完成,它会继续执行下一行代码。因此,在你请求页面源代码时,很有可能登录操作还没有在服务器上完成,结果并不符合你的期望。你需要明确告诉Selenium要等待,所以你需要在登录和检查用户是否已登录的代码之间添加一些代码,比如设置10秒的超时时间。如果这对你有效,你就不想浪费时间,所以你需要等待页面中某些元素因登录而发生变化,例如,你需要等待页眉中用户照片的存在(或可见性,如果它已经在DOM中)。此外,我不确定“getPageSource”函数的行为方式,它可以使用现有页面,也可以请求一个新的副本。我建议你使用其他方法来测试用户是否已登录,例如检查DOM。

1
我建议在其他 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调用通常不是线程安全的,并且可能经常导致异常(例如,元素已更改而导致“陈旧”,或者未找到,因为一个Web驱动程序导航到了另一个页面)。
然后我建议只使用窗口句柄来进行下一个实例,而不用关心会话。第一个打开并且最后一个关闭会话(计算引用的句柄数),并确保只有一个驱动程序在任何时候使用此句柄。您还可以创建新的浏览器窗口,这将保留会话并给您一个新的句柄:
var handle = firstWebDriver.CurrentWindowHandle;
otherWebDriver.SwitchTo().Window(handle);

我用C#编写了代码,但应该很容易适应JavaScript。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接