量角器:单击按钮后如何等待页面完成?

Posted

技术标签:

【中文标题】量角器:单击按钮后如何等待页面完成?【英文标题】:Protractor : How to wait for page complete after click a button? 【发布时间】:2014-03-11 23:44:22 【问题描述】:

在测试规范中,我需要单击网页上的按钮,然后等待新页面完全加载。

emailEl.sendKeys('jack');
passwordEl.sendKeys('123pwd');

btnLoginEl.click();

// ...Here need to wait for page complete... How?

ptor.waitForAngular();
expect(ptor.getCurrentUrl()).toEqual(url + 'abc#/efg');

【问题讨论】:

您能否在您等待的页面上更具体一些?您只是在等待页面更改或一些异步加载吗? 【参考方案1】:

根据你想做什么,你可以尝试:

browser.waitForAngular();

btnLoginEl.click().then(function() 
  // do some stuff 
); 

解决承诺。如果你能在beforeEach中做到这一点会更好。

注意:我注意到,expect() 会等待内部的 promise(即 getCurrentUrl)在比较之前得到解决。

【讨论】:

感谢分享,帮助发现了一些奇怪的间歇性问题。 我仍然有问题:等待异步脚本结果超时 这并没有解决我在点击按钮后等待javascript完成修改页面的问题。按照建议的below 添加browser.driver.sleep(1000) 就可以了。 waitForAngular()should not be used。关于click().then(),它对我不起作用。我只能依靠browser.wait(//use of protractor.ExpectedConditions)【参考方案2】:

我刚刚查看了源代码 - Protractor 仅在少数情况下等待 Angular(例如在调用 element.all 或设置/获取位置时)。

所以 Protractor 不会在每次命令后等待 Angular 稳定下来。

另外,在我的测试中,有时我会在 Angular 摘要循环和点击事件之间进行竞争,所以有时我必须这样做:

elm.click();
browser.driver.sleep(1000);
browser.waitForAngular();

使用睡眠等待执行进入AngularJS上下文(由click事件触发)。

【讨论】:

量角器不同步.click(),它同步了下一个涉及ElementFinder/ElementArrayFinder的操作。 我从经验中知道,在使用 expect 评估期望值时,量角器会等待角度。在其他情况下,我明确使用waitForAngular 虽然你的帖子已经快两年了,但我发现你还是对的。我目前需要在量角器 element(by.css('my-css')).click() 之后添加一个 '.sleep(1000)' 。 .click 似乎没有等待,尽管返回了一个承诺。 我总是使用承诺。例如:return elm.click().then(function () return nextAction(); 我不建议使用显式睡眠,因为即使您的应用程序加载速度比配置的睡眠快,您也会进入睡眠状态。【参考方案3】:

您无需等待。 Protractor 会自动等待 angular 准备好,然后执行控制流中的下一步。

【讨论】:

理论上是的,因为 waitForAngular() 是在内部调用的,但我也必须为某些规格调用它。 它会自动等待吗?看着像browser.get 这样的东西,它明确表示它的存在是为了覆盖它包装的东西。如果ElementFinder 没有click 方法,那么它似乎只是委托给webDriver.WebElement。 angular.github.io/protractor/#/api?view=ElementFinder @Snekse Protractor 同步了 ElementFinder 和 ElementArrayFinder 上的所有操作。因此,每当您的测试尝试查找任何元素时,查找本身都会等待 angular 完成消化周期,然后将调用委托给 webdriver。在 expect() 调用中也会发生同样的情况。 如果我们不需要等待,那么这个帖子不会被浏览 100,000 次。【参考方案4】:

使用 Protractor,您可以使用以下方法

var EC = protractor.ExpectedConditions;
// Wait for new page url to contain newPageName
browser.wait(EC.urlContains('newPageName'), 10000);

所以你的代码看起来像,

emailEl.sendKeys('jack');
passwordEl.sendKeys('123pwd');

btnLoginEl.click();

var EC = protractor.ExpectedConditions;
// Wait for new page url to contain efg
ptor.wait(EC.urlContains('efg'), 10000);

expect(ptor.getCurrentUrl()).toEqual(url + 'abc#/efg');

注意:这可能并不意味着新页面已完成加载并且 DOM 已准备就绪。随后的“expect()”语句将确保 Protractor 等待 DOM 可用于测试。

参考:Protractor ExpectedConditions

【讨论】:

【参考方案5】:

在这种情况下,您可以使用:

页面对象:

    waitForURLContain(urlExpected: string, timeout: number) 
        try 
            const condition = browser.ExpectedConditions;
            browser.wait(condition.urlContains(urlExpected), timeout);
         catch (e) 
            console.error('URL not contain text.', e);
        ;
    

页面测试:

page.waitForURLContain('abc#/efg', 30000);

【讨论】:

【参考方案6】:

我通常只是在控制流中添加一些东西,即:

it('should navigate to the logfile page when attempting ' +
   'to access the user login page, after logging in', function() 
  userLoginPage.login(true);
  userLoginPage.get();
  logfilePage.expectLogfilePage();
);

日志文件页面:

function login() 
  element(by.buttonText('Login')).click();

  // Adding this to the control flow will ensure the resulting page is loaded before moving on
  browser.getLocationAbsUrl();

【讨论】:

【参考方案7】:

用这个我觉得更好

   *isAngularSite(false);*
    browser.get(crmUrl);


    login.username.sendKeys(username);
    login.password.sendKeys(password);
    login.submit.click();

    *isAngularSite(true);*

要使用 isAngularSite 的这个设置,应该把它放在你的 protractor.conf.js 中:

        global.isAngularSite = function(flag) 
        browser.ignoreSynchronization = !flag;
        ;

【讨论】:

【参考方案8】:

要等到点击本身完成(即解决 Promise),请使用 await 关键字

it('test case 1', async () => 
  await login.submit.click();
)

这将停止命令队列,直到点击(sendKeys、sleep 或任何其他命令)完成

如果您很幸运,并且您在构建良好且没有待处理的微观和宏观任务的角度页面上,那么 Protractor 应该自行等待,直到页面准备好。但有时您需要自己处理等待,例如通过非 Angular 页面登录时(阅读how to find out if page has pending tasks and how to work with non angular pages)

如果您手动处理等待,browser.wait 是您的最佳选择。只需将一个函数传递给它,该函数将具有等待的条件。例如等到页面上没有加载动画

let $animation = $$('.loading');

await browser.wait(
  async () => (await animation.count()) === 0, // function; if returns true it stops waiting; can wait for anything in the world if you get creative with it
  5000, // timeout
  `message on timeout`
);

请务必使用await

【讨论】:

【参考方案9】:

你可以这样做

emailEl.sendKeys('jack');
passwordEl.sendKeys('123pwd');

btnLoginEl.click().then(function()
browser.wait(5000);
);

【讨论】:

browser.wait(5000) 将返回“不可分配给类型函数”,因为 browser.wait 接受 >1 个参数,第一个是条件,第二个是时间...跨度> 【参考方案10】:
browser.waitForAngular();

btnLoginEl.click().then(function()  Do Something );

兑现承诺。

【讨论】:

以上是关于量角器:单击按钮后如何等待页面完成?的主要内容,如果未能解决你的问题,请参考以下文章

单击按钮后等待加载页面

单击模态窗口中的按钮 - 量角器

如何避免在asp.net中的按钮单击事件后页面刷新

如何python应用flask

在量角器中单击if元素是否可单击

Sikuli如何用于等待按钮,直到它显示它然后单击它?