angular - 在 Protractor 中单击按钮后如何等待 URL 加载?

标签 angular typescript protractor end-to-end

我正在使用 Protractor 对 angular 2 项目进行端到端测试,我需要测试登录操作。这里的问题是,当单击登录按钮时,expect 语句仍然获取登录页面的 URL,就像主页一样。如果我等待,则测试成功。我在文档中的某处读到 Protractor 等待进程自动完成,所以,

  1. 是什么导致了这个错误?
  2. 如何在不显式使用 wait() 方法的情况下正确执行操作?
  3. Protractor 是否有类似 fakeAsyncasync 或至少 whenStable 的东西,比如 unit 测试?

这是我的测试用例

it("User successfully login",()=>{
    browser.get(browser.baseUrl + '/account/login').then(() => {
        return expect(browser.getCurrentUrl()).toBe(browser.baseUrl +  "/account/login")
    }).then(()=>{
        element(by.tagName('input[type=text]')).sendKeys('username');
        element(by.tagName('input[type=password]')).sendKeys('password');
        element(by.css('button[type=submit]')).click().then(()=>{
            return expect(browser.getCurrentUrl()).toBe(browser.baseUrl + "/home");
        });

    });
});

注意:

  1. 我有避免使用 browser.wait() 方法的说明。
  2. 登录按钮通过 API 向后端发送 http 请求。

解决方案[基于 Ernst 的解决方案]:

我解决了这个问题。我不知道它是否适用于其他场景,或者它是否是正确的方法。我加了

browser.wait(EC.urlContains(browser.baseUrl + "/account/login"), 10000);
browser.waitForAngularEnabled(false);
browser.wait(EC.urlContains(browser.baseUrl + "/home");

就在 click() 事件之后,它现在似乎可以正常工作。

最佳答案

错误原因:

click() 返回一个 promise , Protractor 等待解决。当登录请求被发送到服务器而不是主页加载时,它可能已经解决了。因此下一步的执行在页面加载之前开始。

为什么不wait():

我不确定,您是根据什么得到不使用 browser.wait() 的指令的。很可能你不应该使用 browser.sleep() (因为那个命令总是过时的),但是如果你不想使用 browser.wait() 你的开发人员可能不会离开最初打开的 Angular 页面。

fakeAsyncwhenStable 等:

Protractor 在 browser.waitForAngular() 中默认使用 whenStable,它总是在 promise 之后调用,只要您没有关闭 browser .waitForAngularEnabled(false)...您只需要为非 Angular 页面关闭它,或者如果您的开发人员使用即持久的 Macrotasks,这将导致超时。

此外,由于 Selenium 控制流可能会在 2018 年 11 月被弃用 (read about here),因此 async/await 可用。 Read this important guide here还有一些further infos from protractor about it here

现在你的情况:

您不需要在您的情况下使用 then(),因为您不需要立即解决 promise 。 expect() 将自动解决您的 promise ,因此那里不需要 then()

事实上 Protractor 逐行执行所有命令,就好像它们都包含在 then() 中一样,因此它会自动保持您的执行同步(只要您不启动异步任务通过在代码中使用 then()

所以这是我对您的代码的建议:

it("User successfully login",()=>{
    var EC = protractor.ExpectedConditions;  //or within onPrepare() of conf.js put global.EC = protractor.ExpectedConditions ... to make it everywhere available.
    browser.get(browser.baseUrl + '/account/login');
    //next line lets protractor wait max 5 seconds for your url to become, what you want.
    browser.wait(EC.urlContains(browser.baseUrl +  "/account/login"), 5000);
    //additionally after the URL appeared, use this command to wait until the page is fully loaded.
    browser.waitForAngular();
    expect(browser.getCurrentUrl()).toBe(browser.baseUrl +  "/account/login");
    element(by.tagName('input[type=text]')).sendKeys('username');
    element(by.tagName('input[type=password]')).sendKeys('password');
    element(by.css('button[type=submit]')).click();
    //next line lets protractor wait max 5 seconds for your url to become, what you want.
    //as here a new page is loaded and the click()-promise is resolved before, use this:
    browser.wait(EC.urlContains(browser.baseUrl +  "/account/login"), 5000);
    //additionally after the URL appeared, use this command to wait until the page is fully loaded.
    browser.waitForAngular();
    expect(browser.getCurrentUrl()).toBe(browser.baseUrl + "/home");
});

如果您现在超时,那么这是一个需要调试的单独问题。 检查this Protractor site for infos about timeouts并检查 this SO-Answer here了解如何调试超时。

关于angular - 在 Protractor 中单击按钮后如何等待 URL 加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47195796/

相关文章:

node.js - 组件之间的 Angular 4 ngModel

javascript - 只需稍加调整即可创建从一个对象到另一个对象的 JSON 对象

javascript - 使用 Protractor 测试 Chart.js Canvas

angularjs - Protractor 定位器链接无法找到元素文本

angularjs - 如何使用 Protractor 向流量控制队列添加 promise ?

javascript - Angular 2 @View with template vs @Component with template

javascript - 我们可以将 ngIf 显式更改为隐藏在 Angular 库中吗

Angular:每次运行 `ng test` 时,Karma 是否都必须编译我的所有代码?

javascript - 使用 typescript ENUM 动态传递 props

typescript :接口(interface)中的常量