如何在量角器中为元素是否存在创建条件

How to create a condition in protractor for when an element exists or not

我正在使用 Protractor JS。网站是用 Angular JS 编写的。

所以我有一个拨动开关。我注意到切换开关中的值从 true 变为 false 并且 关闭或打开时从 false 变为 true。

我正在尝试创建一个条件,当 Protractor 访问我的页面时,当它看到切换开关 'off' 时,它将转动它 ​​'on'。如果拨动开关已经是 'on',它会先将它转动 'off' 然后再转动它 'on'。

我想出了这段代码,但由于某种原因它不起作用:

 if( expect(element(By.id('toggle-switch')).element(By.css('[value="false"]')).isDisplayed()) ) {
            element(By.id('toggle-switch')).click();
            console.log('in the if')
       }

       else{
           element(By.id('toggle-switch')).click();
           browser.sleep(3000);
           element(By.id('toggle-switch')).click();
           console.log('in the else')
       }

此代码似乎仅适用于 if 语句。由于某种原因,它永远不会去其他地方。这是我收到的错误:

NoSuchElementError: 使用定位器找不到元素: By.cssSelector("[value=\"false\"]")

然后我试了

.isPresent() 而不是 .isDisplayed() 我不再收到上述错误,但由于某种原因,在使用 .isPresent() 时,它总是转到 if 语句并且只运行它,而从不运行 else 语句。没有显示错误。

如果有更好的方法请告诉我。这似乎非常有限,无法在此框架中创造适当的条件。

记住isDisplayed() returns一个承诺,你可以试试:

element(anyFinder).isDisplayed().then(function(result) {
    if ( result ) {
        //Whatever if it is true (displayed)
    } else {
        //Whatever if it is false (not displayed)
    }
});

isDisplayed() 对我不起作用。 API 可能已更改。 isPresent() 是我的解决方案:

    var logoutButton =  element(by.css('[ng-click="log_out()"]'));
    logoutButton.isPresent().then(function(result) {
    if ( result ) {
        logoutButton.click();
    } else {
        //do nothing
    }
    });

或者尝试从我的脑海中实现这个解决方案,安排一个命令来测试页面上是否存在元素。如果在评估等待时发生任何错误,它们将被允许传播。

function alwaysSwitchOn(element) {
   browser.driver.isElementPresent(element).then(function(isPresent) {
      if (isPresent) {
        isPresent = true;
      } 
      else {
        browser.driver.wait(function () {
          return browser.driver.isElementPresent(element);
        }, 5000);
      }
      // to fail the test, then uncomment this line
      //expect(isPresent).toBeTruthy();
   }).then(function () {
      if (element.getAttribute('value') === 'OFF') {
         element.click();
      }
      else {
         // turn it OFF
         element.click();
         // turn it back ON
         element.click();
      }
   });
}

fn的用法是反复尝试5秒,直到true。如果在 5 sec 中找不到该元素,则会产生错误代码;没有这样的元素是found.Note,如果在等待(5s)之前条件满足,它会迅速移动到then(...)

问题是 isDisplayed(), as a lot of methods in WebDriverJS/Protractor, returns a promise 根据定义是 "truthy" 这使得调试此类问题变得困难。

让我们通过一个例子来加深理解。

想象一下,您有以下代码,乍一看可能没问题:

var elm = $("#myid");
if (elm.isDisplayed()) {
    // do smth
} else {
    // do smth else
}

现在,它有一个严重的问题。 do smth else 部分将永远不会达到 ,因为 elm.isDisplayed() 不是布尔值 - 它是一个承诺。即使不显示该元素,您仍然会执行 // do smth 部分。

相反,如果您需要检查 isDisplayed() 的值以在条件表达式中使用,则必须 显式 then() 解决承诺 :

var elm = $("#myid");
elm.isDisplayed().then(function (isDisplayed) {
  if (isDisplayed) {
      // do smth
  } else {
      // do smth else
  }
});

还有一种方法可以在没有 运行 代码的情况下捕获此类错误 - 静态地使用 ESLint and eslint-plugin-protractor plugin. There is a relevant rule 监视是否在 if 条件中直接使用了某些 Protractor 方法。

以上代码的输出结果如下:

$ eslint test.js
test.js
  2:1  warning  Unexpected "isDisplayed()" inside if condition  protractor/no-promise-in-if

如果您在 2021 年或之后的年份

忘记 .then()。改为这样做:

it('test case', async () => {
  if (await element(anyFinder).isDisplayed()) {
    // Whatever if it is true (displayed)
  } else {
    // Whatever if it is false (not displayed)
  }
});