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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27947094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 00:59:51  来源:igfitidea点击:

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

javascriptjqueryangularjsselenium-webdriverprotractor

提问by adbarads

I'm using Protractor JS. And the site is written in Angular JS.

我正在使用量角器 JS。该网站是用 Angular JS 编写的。

So I have a toggle switch. And I noticed the value in the toggle switch goes from true to false and false to true when you switch it off or on.

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

I am trying create a condition when Protractor visits my page when it sees the toggle switch 'off' it will turn it 'on'. If the toggle switch is already 'on', it will first turn it 'off' then turn it 'on' again.

当 Protractor 访问我的页面时,当它看到切换开关“关闭”时,我正在尝试创建一个条件,它将“打开”它。如果切换开关已经“打开”,它会先将其“关闭”,然后再次“打开”。

I came up with this code, but for some reason it is not working:

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

 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')
       }

This code appears to work only for the if statement. For some reason it will never go to the else. Here is the error I'm receiving:

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

NoSuchElementError: No element found using locator: By.cssSelector("[value=\"false\"]")

NoSuchElementError: No element found using locator: By.cssSelector("[value=\"false\"]")

So then I tried

所以我尝试了

.isPresent()instead of .isDisplayed()I don't receive the above error anymore, but for some reason when using .isPresent() it always goes to the if statement and only runs that, and never the else statement. No errors displayed.

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

If there is a better way please let me know. This seems very limiting to not be able to create proper conditions in this framework.

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

回答by Lautaro Cozzani

Remember that isDisplayed()returns a promise, you can try with:

请记住,isDisplayed()返回一个承诺,您可以尝试:

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

回答by Ebru Yener

isDisplayed()did not work for me. The API may have been changed. isPresent()is my solution:

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

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

回答by alecxe

The problem is that isDisplayed(), as a lot of methods in WebDriverJS/Protractor, returns a promisewhich by definition is "truthy" which makes it difficult to debug problems like this.

问题是isDisplayed(),作为 WebDriverJS/Protractor 中的许多方法,返回一个根据定义是“真实”承诺,这使得调试这样的问题变得困难。

Let's work through an example to get a better understanding.

让我们通过一个例子来更好地理解。

Imagine, you have the following code, which may look okay at the first glance:

想象一下,您有以下代码,乍一看可能还不错:

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

Now, it has a serious problem. do smth elsepart will never be reached, since elm.isDisplayed()is not a boolean value - it is a promise. Even if the element is not displayed, you would still have // do smthpart executed.

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

Instead, if you need to check the value of isDisplayed()to use inside a conditional expression, you have to resolve the promise with then()explicitly:

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

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


There is also a way to catch these kind of errors without even running the code - statically with ESLintand eslint-plugin-protractorplugin. There is a relevant rulethat watches if certain Protractor methods are used inside ifconditions directly.

还有一种方法可以在不运行代码的情况下捕获此类错误 - 静态使用ESLinteslint-plugin-protractor插件。有一个相关规则可以观察某些 Protractor 方法是否if直接在条件内部使用。

Here is what it would output for the code above:

以下是上面代码的输出:

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

回答by Simple-Solution

Or try this solution implemented from the top of my head, Schedules a command to test if an element is present on the page. If any errors occur while evaluating the wait, they will be allowed to propagate.

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

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 usage is to keep trying again and again for 5 seconds till it's true. if the element cannot be found within 5 secthen it'll result in an error code; No such an element is found.Note, If the condition is fulfilled before wait (5s) it'll quickly move to then(...).

fn 的用法是一次又一次地尝试 5 秒钟,直到true. 如果在其中找不到该元素5 sec,则会导致错误代码;没有找到这样的元素。注意,如果条件在 wait ( 5s)之前满足,它将快速移动到then(...)