量角器间歇 "element is not found"

Intermittent "element is not found" in protractor

在 Protractor 中,我正在尝试编写一个函数来模拟单击响应式导航菜单项(即菜单是顶部的下拉菜单栏或汉堡包 link,如果是移动设备)。 bar 的结构由 MEANJS 定义,其中混入了一些 id="" 属性。

当我一次 运行 它一个规格时,它似乎完全按照我想要的方式工作,就像这样:

protractor app/tests/e2e/conf.js --suite mySuite

但是当我 运行 进行完整测试(其中只有 4 个测试)时,像这样:

protractor app/tests/e2e/conf.js

我开始间歇性地收到此错误(错误来源在以下 2 个地方):

Failed: element not visible

这是我的函数

commonPOs.clickNavBar = function(mainTab, linkUrl) {
  var deferred = protractor.promise.defer();

  var hamburger = element(by.id('nav-hamburger'));
  var linkCssExpression = 'a[href*="' + linkUrl + '"]';

  hamburger.isDisplayed().then(function(result) {
    if ( result ) {
      hamburger.click().then(function() {
        var navBar = hamburger
          .element(by.xpath('../..'))
          .element(by.id('myapp-navbar'));
          return clickItNow(mainTab, linkUrl, navBar);
      });
    } else {
      return clickItNow(mainTab, linkUrl, element(by.id('myapp-navbar')));
    }
  });

  return deferred.promise;

  function clickItNow(mainTab, linkUrl, navBar) {
    var link;
    if(mainTab) {
      // if mainTab was  passed, need to
      // click the parent first to expose the link
      var parentLink;

      if (mainTab == 'ACCTADMIN') {
        parentLink = navBar.element(by.id('account-admin-menu'));
      }
      else {
        parentLink = navBar.element(by.linkText(mainTab));
      }
      expect(parentLink.isPresent()).toBeTruthy();
      parentLink.click();   // FIRST PLACE ERROR HAPPENS
      link = parentLink.element(by.xpath('..')).element(by.css(linkCssExpression));
    } 
    else {
      link = navBar.element(by.css(linkCssExpression));
    }

    expect(link.isPresent()).toBeTruthy();
    link.click();     // SECOND PLACE ERROR HAPPENS
    return deferred.fulfill();
  }
};

我试过使用这两个,但都不起作用:

browser.sleep(500);
browser.driver.wait(protractor.until.elementIsVisible(parentLink));

我犯了什么 NOOB 异步错误?

自己回答...但更好的答案将赢得绿色复选标记!!!

已编辑 - 经过更多问题后,找到了一个不错的 'waitReady()' contribution from elgalu

我的原始代码存在一些明显的问题,但修复它们并没有解决问题。在尽我所能之后,解决方案似乎是我添加的 expect(navBar.waitReady()).toBeTruthy(); 行。我还必须将嵌套函数拆分出来。无论如何,这是现在似乎可以使用的新代码。更好(更全面)的答案将获得绿色复选标记!我很确定这里有一个或两个缺陷。

commonPOs.clickNavBar = function(mainTab, linkUrl) {
  var deferred = protractor.promise.defer();

  var hamburger = element(by.id('nav-hamburger'));

  hamburger.isDisplayed().then(function(result) {
    if ( result ) {
      hamburger.click().then(function() {
        var navBar = hamburger
          .element(by.xpath('../..'))
          .element(by.id('myapp-navbar'));
          return clickItNow(mainTab, linkUrl, navBar, deferred);
      });
    } else {
      return clickItNow(mainTab, linkUrl, element(by.id('myapp-navbar')), deferred);
    }
  });

  return deferred.promise;
};

function clickItNow(mainTab, linkUrl, navBar, deferred) {
  var targetLink;
  var linkCssExpression = 'a[href*="' + linkUrl + '"]';

  expect(navBar.waitReady()).toBeTruthy();

  if(mainTab) {
    // if mainTab was  passed, neet to
    // click the parent first to expose the link
    var parentTabLink;

    if (mainTab == 'ACCTADMIN') {
      parentTabLink = navBar.element(by.id('account-admin-menu'));
    }
    else {
      parentTabLink = navBar.element(by.id('main-menu-' + mainTab));
    }
    // expect(parentTabLink.isDisplayed()).toBeTruthy();
    expect(parentTabLink.waitReady()).toBeTruthy();
    parentTabLink.click();
    targetLink = parentTabLink.element(by.xpath('..')).element(by.css(linkCssExpression));
  }
  else {
    targetLink = navBar.element(by.css(linkCssExpression));
  }

  expect(targetLink.isDisplayed()).toBeTruthy();
  targetLink.click().then(function() {
    return deferred.fulfill();
  });
}