Dave P
Dave P

Reputation: 89

How to do 'isVisible' in Javascript/Protractor

I realize this question has been asked before, but I haven't found an answer that I understand yet. I am still new to asynchronous programming, and I'm having a difficult time trying to figure out how to do the simplest things in Protractor/Javascript.

For example, how do I construct the function "isVisible" following this algorithm:

    // Given an on-screen element:

    function isVisible(element) {
       if (element does NOT exist) {
          return false; // If the element doesn't exist, it isn't visible
       } else {
          if (element is currently visible) {
             // For simplicity, I don't care at this point if it's visible on screen 
             return true;
          } else {
             return false;
          }
       }
    }

This function should NEVER, EVER, UNDER ANY CIRCUMSTANCES return an error, exception, or fail in any way.

Further restrictions, do not incorporate an "expect" clause, because that is the province of whatever function is calling "isVisible". The function should return a Promise.

jQuery is also not an option.

Please help, because I'm just not getting it. Also, if you could please explain why you construct your solution as you do, that would be immensely helpful.

Thanks in advance, Dave

Upvotes: 0

Views: 338

Answers (3)

Dave P
Dave P

Reputation: 89

Thank you Gunderson, your solution is essentially the same as the one I figured out:

exports.isVisible = (element) => {
     return new Promise((resolve) => {
            element.isPresent().then((elmPresent) => {
                if (!elmPresent) {
                    resolve(false);
                } else {
                    element.isDisplayed().then((elmDisplayed) => {
                        resolve(elmDisplayed);
                    });
                }
            });
        });
    }

Like I said, I'm still fairly new to Protractor, Promises, etc. I didn't realize that I could return the result of isPresent as my promise (although it makes perfect sense now that you've shown me), and I didn't know that I could return a scalar value without using resolve.

In response to your follow up question, isDisplayed() throws an error if the element does not exist (at least that's what it is doing in our framework). In our application, sometimes the target element is hidden, and other times it just hasn't been added to the DOM (yet). I don't want it to fail just because it isn't defined in the DOM.

I would have bumped the score on your answer, but SO won't let me. I don't have any reputation

Upvotes: 0

Gunderson
Gunderson

Reputation: 3268

I'm still not following how this will be used reliably, but here's the protractor equivalent of your pseudo code:

isVisible(el) {
    return el.isPresent().then((present) => {
        if (!present) {
            console.log('block 1: el does not exist');
            return false; // If the element doesn't exist, it isn't visible
        } else {
            return el.isDisplayed().then((displayed) => {
                if (displayed) {
                    console.log('block 2: el exists AND visible');
                    // For simplicity, I don't care at this point if it's visible on screen 
                    return true;
                } else {
                    console.log('block 3: el exists but NOT visible');
                    return false;
                }
            })
        }
    });
};

I tried it with an element that (1) did not exist at all, (2) existed AND visible, (3) existed but NOT visible. This function hits all 3 blocks. And since isPresent and isDisplayed both return promises, this function also returns a promise by returning those.

The reason I dont really understand what you want this for is because, as you can see, my solution is based purely on protractor functions. That is essentially the equivalent of this:

// this exists but is not visible
expect(el.isPresent()).toBe(true);
expect(el.isDisplayed()).toBe(false);

// this exists AND visible
expect(el.isDisplayed()).toBe(true);

// this does not exist at all
expect(el.isPresent()).toBe(false);

Upvotes: 0

MadPapo
MadPapo

Reputation: 495

If you have jQuery in your project the solution is easy:

function isVisible(element){
   var $el = $(element);
   if (!$el.length)
      return false;
   else
       if (!$el.is(":visible"))
             return false;       
   return true;
}

Upvotes: 1

Related Questions