9

I run into this issue whenever I try to wait until an DOM element is removed from the current DOM tree on the web page that my protractor test is testing. I already got a hang of it when I try to wait until a DOM element becomes hidden with this nice technique offered by user2912739 in another thread.

var el = element(by.css('.your-css-class'));
return browser.wait(protractor.until.elementIsNotVisible(el));

This works pretty decent. However, when it comes to waiting for an element got removed from the DOM tree both .isDisplayed() and .isPresent() or the above lines do NOT seem to work. The test would continue run but it appears like it is trying to get that element but never succeeds so it eventually timed out based on the timeout setting the configuration file. For example. this is the log.

timeout: timed out after 30000 msec waiting for spec to complete

The use case of this can be quite frequent whenever you are dealing with testing if an element is removed from the DOM tree, for instance, a modal that is closed and removed from the page when user click actions that dismisses that modal element, or an element that you just want to "delete" so that it no longer exists on the page. So, in the test, you just want to continue the test run as soon as it is removed from DOM tree.

I've searched through protractor and web driver api, and it seems there is no api that does this job.

Andrew Eisenberg
  • 28,387
  • 9
  • 92
  • 148
vichsu
  • 1,880
  • 5
  • 17
  • 20
  • I'm new to protractor and that's first time I seen how to use that `until`. no docs says it's defined inside `protractor`... – llamerr Jan 25 '16 at 16:27

1 Answers1

19

not sure where you got protractor.until from as that's not part of the core library. This is how you would do it with protractor:

var el = element(by.css('.your-css-class'));
return browser.wait(function() {
  return el.isPresent().then(function(present) {
    return !present;
  })
});

Once feat(expectedConditions) is in (probably protractor 1.7), you can do:

var EC = protractor.ExpectedConditions;

var el = element(by.css('.your-css-class'));
return browser.wait(EC.not(EC.presenceOf(el)));
hankduan
  • 5,994
  • 1
  • 29
  • 43
  • Thanks, Hankduan, That was similar approach to what I had in my previous post http://stackoverflow.com/questions/26411574/protractor-wait-for-element-to-become-invisible-hidden – vichsu Feb 11 '15 at 22:40
  • But when it comes to wait for if element is "removed" from DOM, both el.isPresent() or el.isDisplayed() can not return a promise as soon as it happens or it is already not part of DOM, because it is never fulfilled. The result is protractor would just time out for this block of code in the Jasmine it function block. I guess we are dealing with a condition that can never be satisfied. – vichsu Feb 11 '15 at 22:57
  • Can you clarify that? I'm not sure what you mean. – hankduan Feb 12 '15 at 20:13
  • Hankduan, What I am guessing is if an element is already removed from DOM and then the protractor code starts to execute ---> element(by.css(".my-class")).isDisplayed or ---> element(by.css(".my-class")).isPresent, these two methods can not return a promise because such element is not part of the DOM tree. So, as a result, it simply times out (based on the max time out value we set in protractor.conf.js) and move on to the next "it" block. – vichsu Feb 25 '15 at 18:37
  • 3
    These kind of use case is quite often when you deal with modal interaction, e.g. user clicks the save/ok button then wait until the modal is disappeared. In this case, there are modal plug-ins that remove its modal html elements as soon as the modal is closed/disappeared. This is when our protractor test code needs to know as soon as the modal is closed so we can assert the result. – vichsu Feb 25 '15 at 18:39
  • 2
    Yes, but your question never mentioned isDisplayed. isDisplayed will throw an error; isPresent will not. If you are checking for isDisplayed, you want to do this: `return browser.wait(EC.not(EC. visibilityOf(el))` – hankduan Feb 25 '15 at 21:28
  • Thanks for the insight. Hankduan. So, if we use isPresent(), it is not going to thrown an error but instead it will not fulfill the promise because it just can't (such element is not going to be present). So, I will check if return browser.wait(EC.not(EC. visibilityOf(el)) in protractor 1.7 would work. – vichsu Feb 26 '15 at 17:07
  • There is a difference between isPresent and isDisplayed (see http://stackoverflow.com/questions/28119084/what-is-the-difference-between-ispresent-vs-isdisplayed-in-protractor). But in terms of protractor/webdriver, isPresent returns a promies of true/false, while isDisplayed throws an error if element is not found, true if element is displayed, and false if element is found but not displayed. – hankduan Feb 26 '15 at 19:16