How to verify visible text vs. hidden page elements in Protractor tests
01 December, 2019 - 3 min read
I started exploring Protractor for front-end / end-to-end testing on an existing project. Protractor is very easy to get started with and allows for rapid development of useful tests.
However, some behaviour details should be better highlighted in Protractor's documentation. Case in point: visible text.
Let's assume that we have a page menu implemented with unordered list (UL) + list items (LI) that expands on mouse hover to show child navigation items (which, again, are UL > LIs), which in markup looks like the following:
<!-- menu structure, bootstrap style -->
<ul>
<li><a href="...menu-item-1-url">menu 1</a></li>
<li><!-- menu item 2 --></li>
<!-- ... child menus -->
<ul>
<li><a href="...child-1" class="menu-item-2">child menu 1</a></li>
<!-- ... more child menus -->
</ul>
</ul>Normally, finding an element in Protractor is quite easy. Here is how we could go about getting the UL > LI.menu-item items that represent our main menu links based on earlier markup:
element(by.css('#main-menu').all(by.css('.menu-item');The child menu items are collapsed on page load and can't be seen. We have to mouse-over to get the main menu item to expand and show the child items. This is where the visible text "issue" kicks in: Protractor will return a blank string when we try to get the text of the child menu item - there's nothing for it as far as visible text goes - the user of the page doesn't see any text unless you hover the mouse and get the menu to expand and actually show (I imagine that getting the test to hover over and than test for text should yield the text of the link, but I have not gotten that far).
// initialize to a reference to the submenus of the above DOM menu structure
var submenus = cy.get('#main-menu ul li a');
// ...
// *** NOTE ***
// It turns out that due to CSS forcing these submenu items to be INVISIBLE we can't
// verify the visible text (as below two lines do not validate successfully)
//
// ** this FAILS please note **
expect(submenus.get(0).getText()).toEqual("child menu 1"); However, we can inspect HTML attributes for a given DOM element, regardless of whether they are visible or not:
expect(submenus.get(0).getAttribute('class')).toEqual("menu-item-2 ng-star-inserted");
// and since text is now invisible due to CSS, we can at least use the innerText attribute to get to it and validate
expect(submenus.get(0).getAttribute('innerText')).toEqual("child menu 1");
So remember to differentiate between whether the DOM element is visible or not in a given test scenario. If not, use the .innerText property to validate the contents of it instead of using .getText() method as the latter would return an empty string for DOM elements that are made hidden by CSS.