14

I've written a test to check if a element is visible on screen, in my case an angular-ui-bootstrap collapsible panel, aka, the "warning". The code works, but the tests used to fail ~75% of the time.

There is a collapse animation on the display of the "warning", and I can't shutwod the animation for the tests, since it's a jquery animation. The warning is always 'present' in the DOM, just collapsed when there is no reason to show it.

At first, I've tested with this code, which is pretty easy:

expect(element('.warning').isDisplayed()).toEqual(true);

The problem came when I needed to test that the element is not displayed, e.g. : once the warning is displayed, some action cause it to collapse.

That test:

expect(element('.warning').isDisplayed()).toEqual(false);

will pass only if the animation started. It will fail when the condition is checked while the element is still displayed.

I've came up with two solutions.

The easy one using a ptor.driver.sleep(2000). Is slows my tests and is not acceptable.

The hard, ugly one, but that gives me good results:

exports.isWarningDisplayed = function (expectedVisibility) {
  return ptor.driver.wait(function () {
     if (expectedVisibility) {
       return element(by.css('.warning')).isDisplayed().then(function(visibility) {
         return visibility === expectedVisibility;
       });
      } else {
        return element.all(by.css('.warning .collapse.in')).then(function(items) {
          return items.length === 0;
       });
      }
    }, 2000).then(function() {
      return element.all(by.css('.warning .collapse.in'));
    }).then(function (items) {
      return items.length > 0;
    });
};

My problem is that it just feels awfully wrong. Have you found a better way to handle that situation? My expectation would be to have something like:

expect(element('.warning').not.isDisplayed()).toEqual(true);

...but there is no .not in protractor or webDriver AFAIK.

Julien Bérubé
  • 1,256
  • 1
  • 13
  • 22

4 Answers4

18

I had a similar issue - wanting to test for when an element is no longer disabled. I struggled trying to work around things without the .not test and then realized that I could just move the 'not' test into the css selector:

// we're looking for when the element doesn't have a .disabled class
var availableElement = by.css('.some-class:not(.disabled)');
browser.wait(function() {
  return ptor.isElementPresent(availableElement);
}, 30000);

expect(ptor.isElementPresent(availableElement)).toBeTruthy();

Not sure if it helps but I had a moment of clarity so thought I would share.

mattgi
  • 712
  • 1
  • 7
  • 11
  • It does help! Thanks, that is so much cleaner that what I've got! – Julien Bérubé Jul 02 '14 at 21:40
  • I get a Error which says `TypeError: Unimplemented function: "isPending"` from selenium-webdriver's promise.js when using isElementPresent :-(?! – Sebastian Jul 31 '14 at 09:57
  • 5
    I need to use `browser.isElementPresent( ...` – mvndaai Jan 16 '15 at 23:11
  • I was experiencing a very similar issue causing many of our tests to be shaky, with seemingly random fails depending on what machine was running them. I found that disabling css transitions helped significantly, as these were used in some ui bootstrap components we're relying on: http://stackoverflow.com/a/32264842/446030 – JcT Aug 28 '15 at 07:25
8

Using the elementexplorer (https://github.com/angular/protractor/blob/master/docs/debugging.md) I looked at the protractor object and found an answer that is working wonderfully for me:

var el = element(by.id('visibleElementId'));
browser.driver.wait(protractor.until.elementIsNotVisible(el));
Al Joslin
  • 765
  • 10
  • 14
2
expect(ptor.isElementPresent(by.css('.warning'))).toBe(false);

This is another way of checking if something is displayed on the page or not

Julien Bérubé
  • 1,256
  • 1
  • 13
  • 22
Liam's musings
  • 167
  • 4
  • 9
0

From my experience, this is a common "sad" issue. You know your code is written properly, but test is failed due to waits. For instance, in Chrome I get the next error in console :

< unknown error: Element is not clickable at point (952, 275). >

So, I created separate function in my WebDriver class and seems it works:

this.waitElementToBeShown = function (elmLocator) {
        browser.sleep(500);
        browser.wait(function () {
            return (elmLocator).isPresent();
        }, 3000);
        browser.wait(function () {
            return (elmLocator).isDisplayed();
        }, 3000);
    }
  • 2
    I would strongly advocate against using a `browser.sleep` if any other option is still available. From my experience, slow tests are run less often, which make them less usefull, so they are run less often. – Julien Bérubé Aug 18 '15 at 17:05