Checking if an element does not exist


I am trying to check if an element does not exist but it is failing with timeout issue. From my observation, I found out that the driver is first trying to find out that element first and then waiting for the element to go away instead of checking whether an element exists or does not exist immediately. I tried below methods.

1. browser.element.all(selector)
2. browser.driver.findElements(selector)
3. browser.isElementPresent(browser.element(selector))
4. element(selector).isPresent()

Background: When a button is clicked, a modal will appear. It has cancel and save buttons. On click of Cancel button the modal window disappears. Now I am trying to write an expect condition to check if the Modal has disappeared or not.

All above are failing. Please tell me a correct way where I can check if an element exists immediately.

Here is the error for all the above

Error: function timed out after 60000 milliseconds

I am Really not sure, why Protractor is unable to help to me just check if the element is not present in the DOM. I tried all the ways possible. Every method is trying to find whether existing element is being transitioned to not existing state or not. Then why these many APIs if all doing the same job.

I know this post is very very old. But i found a way that could be useful: i've created a function that, with 3 parameters

  • field: the ElementFinder which should not be present,
  • fieldName: the name of field just for log,
  • present: boolean to use this function to test if field-present too.

that could be used to test every element present (and not) in DOM

export async function checkField(field: any, fieldName: string, present?: any) {
  let text: string;
  if (present === false) {
    if (field.length > 0) {
      field.forEach(async el => {
        try {
          text = await el.getText();
          expect('should not be present (' + fieldName + ')').toEqual('but it is');
        } catch (e) {
          expect(el.isPresent()).toBe(present);
        }
      });
    } else {
      try {
        text = await field.getText();
        expect('should not be present (' + fieldName + ')').toEqual('but it is');
      } catch (e) {
        expect(field.isPresent()).toBe(present);
      }
    }
  } else {
    if (field.length > 0) {
      field.forEach(async el => {
        try {
          text = await el.getText();
          expect(el.isPresent()).toBe(true);
        } catch (e) {
          expect('element present (' + fieldName + ')').toEqual('but i can\'t find it');
          throw e;
        }
      });
    } else {
      try {
        text = await field.getText();
        expect(field.isPresent()).toBe(true);
      } catch (e) {
        expect('element present (' + fieldName + ')').toEqual('but i can\'t find it');
        throw e;
      }
    }
  }
}

this could obviously be written in better way, but certanily works!

For everyone who could search again this post.


Not sure why you're using browser. for your selectors, nor what your selector actually is, but I suspect you're hitting multiple issues.

First off, .isPresent() really asks is it in the dom; isDisplayed() asks is it visible. Thus, your strategy here will depend if your model his removed from the dom, or hidden (eg. display:none etc...).

Second, it doesn't appear you're handling the promise that either of these methods return. You also don't mention if you're running this in an expect (which automagically waits for the promise to resolve).

Thirdly, it's not clear if your modal selector returns a single element, or multiple (though you do indicate the later with your use of element.all.

Long story slightly longer, here's an example of how you might check if your modal is displayed, given the assumptions that your modal has a class of .myModal, is the only one, and it is removed from the dom when not displayed.

$('.myModal').isPresent().then(function(inDom) {
    return inDom; // returns bool
};

The above code grabs your element, checks if it is in the dom, handles the promise via .then and returns true/false if the element is in the dom.

That said, your code might have multiple modals, hidden via css. In this case, you'll need to find a strategy for that case. Maybe your code adds a .shown class to hidden elements? Great, check for the presence of $('.myModal.shown'). Maybe your code has multiple hidden modals in the dom... less great, but you could loop through each element, and test if any are displayed with isDisplayed().

Hope this helps a bit...


Below is an example taken from protractor api docs

expect(element(by.binding('notPresent')).isPresent()).toBe(false);

so your solution should be ,

expect(element(by.css('.elementClass')).isPresent()).toBe(false);


I had a similar issue, you might find better luck using expectedConditions to wait for the modal to go away, before you try the expect statement.

var WaitForElement = function(item, timeout = 15000) {
  var el = element(by.css(item));
  var EC = protractor.ExpectedConditions;
  browser.wait(EC.not(EC.presenceOf(el)), timeout).then(function(){
    return;
  });
};

WaitForElement('.example').then(function() {
    expect(element(by.css('.example')).isPresent()).toBe(false);
}

This will make protractor wait for the specified element, ('.example' in this case) to disappear before running the expect statement, or else it will timeout after fifteen seconds and the expect will fail.


expect($(".example").isPresent()).toBe(false)

Every method in protractor returns a promise. You have to use a helper to resolve it. Such as the built in expect function.