EDIT #4: Breakthrough!!
I started recursively going through the parent nodes and returning the same values as below. One of the parents--the inner
I started recursively going through the parent nodes and returning the same values as below. One of the parents--the inner mat-drawer-container
--also returned false for isDisplayed (all the others returned true, which seems odd).
Looking at that node, it turns out that it's the only tag on the site to have the CSS of display: contents
. Removing that causes the button in question--and everything else below it--to return true for isDisplayed. Heck, Protractor can even click the button and I can see the expected result in the browser.
Now I suppose the question remains: is this is expected behavior or a bug? It's not as straightforward as there being an ancestor with display: contents applied; I applied it directly to rb-container
and Protractor was still able to find the button.
I opened an issue on the protractor GitHub so they could look further into it.
[UPDATE: I've updated the issue on GitHub, but thought I'd share here as well:]
After some digging, I've found that it's a combination of two style declarations: display: contents
with overflow: hidden
.
On the surface, it sounds like common sense that you shouldn't really use those together, since you're trying to hide the overflow of a container element that isn't really there; however, I feel if a child of said element is being rendered visibly by the browser--and in this case, it is--it probably should be detected as visible by protractor.
The HTML/CSS:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>isDisplayed() issue</title>
<style>
.not-displayed .display-contents {
overflow: hidden;
display: contents;
}
</style>
</head>
<body>
<div class="not-displayed">
<div class="display-contents">
<div class="wrong">isDisplayed() returns false</div>
</div>
</div>
<div class="displayed">
<div class="display-contents">
<div class="right">isDisplayed() returns true</div>
</div>
</div>
</body>
</html>
Spec file:
import { browser, by, element } from 'protractor';
describe('Testing the Protractor Bug', () => {
it('should display debugging info', () => {
browser.waitForAngularEnabled(false);
browser.get('_[file location]_');
element(by.css('.wrong')).isDisplayed().then(disp => { console.log('"wrong" isDisplayed:', disp); });
element(by.css('.right')).isDisplayed().then(disp => { console.log('"right" isDisplayed:', disp); });
});
});
The output from that:
[17:04:50] I/launcher - Running 1 instances of WebDriver
[17:04:50] I/direct - Using ChromeDriver directly...
DevTools listening on ws://127.0.0.1:59412/devtools/browser/3f76f1a9-25f5-4497-8ae3-6933d01d0c7e
Jasmine started
"wrong" isDisplayed: false
"right" isDisplayed: true
Testing the Protractor Bug
√ should display debugging info
Executed 1 of 1 spec SUCCESS in 0.202 sec.
[17:04:53] I/launcher - 0 instance(s) of WebDriver still running
[17:04:53] I/launcher - chrome #01 passed