UPDATE #4: Eureka!!
I made a breakthrough by recursively navigating through the parent nodes and returning the same values as shown below. Surprisingly, one of the parent nodes - the inner mat-drawer-container
- also returned false for isDisplayed, while all others returned true which seemed peculiar.
Upon inspecting that particular node, I discovered that it was the only tag on the site with the CSS property display: contents
. Removing this attribute resulted in the button in question - along with everything else below it - being identified as visible. In fact, Protractor was even able to click the button and display the expected result in the browser.
Now the lingering question is: is this behavior expected or is it a bug? It's not simply a case of an ancestor having display: contents applied; when I directly applied it to rb-container
, Protractor was still able to locate the button.
I'm currently delving into end-to-end testing using Protractor for the first time, and I've hit a snag when attempting to check for the visibility of a button. Despite the button element being present in the DOM and visible, the isDisplayed method returns false causing my assertion to fail.
Here is the initial failing assertion:
expect(element(by.css("mat-drawer-content rb-container rb-fab-button[data-qaid='create-button'] > button")).isDisplayed()).toBe(true);
(Yes, I agree, the selector is quite convoluted, but unfortunately, I have no control over the HTML structure.)
To investigate further, I introduced a lengthy browser.sleep() interval to effectively pause the browser so I could use the developer tools to examine the visibly-displayed element. According to the CSS properties, it should indeed be recognized as visible.
After exhausting all avenues without success, I resorted to logging some data to the console which reinforced my belief that isDisplayed should yield a positive result:
[ UPDATES #2, #3: Logged additional information about all the direct children of rb-container; only one node appears "visible" based on Protractor's assessment. ]
let selector = element.all(by.tagName("mat-drawer-content")).get(0).all(by.css("rb-container > *"));
selector.count().then(function(selCount) {
for (let match = 0; match < selCount; match ++) {
browser.sleep(1000).then(() => {
let elm = selector.get(match);
console.log("\n >> " + match + "]");
elm.getTagName().then(tag => { console.log("tag name:", tag); });
elm.getCssValue("visibility").then(vis => { console.log("visibility:", vis); });
elm.getCssValue("display").then(disp => { console.log("display:", disp); });
elm.getCssValue("opacity").then(opa => { console.log("opacity:", opa); });
elm.getCssValue("overflow").then(ov => { console.log("overflow:", ov); });
elm.getAttribute("hidden").then(hid => { console.log("hidden:", hid); });
elm.getAttribute("class").then(c => { console.log("class:", c)});
elm.getSize().then(size => { console.log("size:", size); });
elm.getCssValue("position").then(ov => { console.log("position:", ov); });
elm.getLocation().then(loc => { console.log("location:", loc); });
elm.isPresent().then(pres => { console.log("isPresent:", pres); });
elm.isDisplayed().then(disp => { console.log("isDisplayed:", disp); });
});
}
});
The logged information reveals the following details:
>> 0]
tag name: div
visibility: visible
display: block
opacity: 1
...
isPresent: true
isDisplayed: false
>> 1]
tag name: div
visibility: visible
display: block
opacity: 1
...
isPresent: true
isDisplayed: false
>> 2]
tag name: rb-fab-button
visibility: visible
display: block
opacity: 1
...
isPresent: true
isDisplayed: false
...
<p>Node 4, the only child element where isDisplayed returns true, appears to be a key example to compare against node 2, the rb-fab-button element I am trying to access. The noticeable difference seems to be that rb-fab-button is absolutely positioned; however, other statically-positioned elements also return false for isDisplayed.</p>
<p>Could I be overlooking something here? I would settle for checking the CSS visibility instead, but my next task involves clicking that button, which will throw an error if the element is not deemed visible.</p>
<p>[ <em><strong>UPDATE #1:</strong> Included some HTML snippets:</em> ]</p>
<p><div>
<div>
<pre><code><mat-drawer-container _ngcontent-c0="" class="root-container w-100 mat-drawer-container mat-drawer-container-explicit-backdrop" hasbackdrop="true" ng-reflect-has-backdrop="true">
<div class="mat-drawer-backdrop ng-star-inserted"></div>
...
</mat-drawer-container>