3

Hello dear people of Stackoverflow,

currently I am writing acceptance tests with Codeception using Selenium as WebDriver module. In my test to check if our sub-navigation exists, is complete and works I struggle with the following piece of code:

$I->see('Partners');
$I->click('Partners');

all the see calls are working perfectly, but the click call fails with an ElementNotVisibleException stating that the element to be clicked is not visible, which I don't understand since the see call worked.

To make sure we're not seeing any old "Partners" string on the page but it really is the link I want to click, I changed the call by adding the a selector.

$I->see('Partners', 'a');
$I->click('Partners');

Still, I'm getting the ElementNotVisibleException from before. In the next step, I added a context to the click call to this:

$I->click('Partners', 'a');

Which made the exception disappear. Still, the click never happens, the test simply fails with the message:

Link or Button or CSS or XPath element with 'Partner' was not found.

I even used XPath in the click call like this: //a[text()='Partners'] and get the same message.

What bothers me the most with this is that the see call seems to see the link I am trying to click and moreover, even the page source and screenshot provided by Codeception after a fail contain this very link, visible and in valid HTML.

I tried to click on some other elements within the sub-navigation with the same result, while - which is even more strange - clicks on links in the main navigation seem to work just fine.

I have no idea why this doesn't work but any help is greatly appreciated.

TheKvist
  • 583
  • 5
  • 16
  • Not familiar with codeception, but what is likely happening is the element you are finding has a `hidden` visibility style or its display style is `none`. Check these values. Selenium checks these values before trying to click on elements. That is why you receive the message that the element is not visible. You're finding the elements okay, otherwise Selenium would complain about *that*. – Ron Norris Nov 03 '17 at 12:30
  • 1
    Thanks, but unfortunately as far as I've understood, when using Codeception with WebDriver and Selenium the `see` call follows the same rule, failing for elements that have their `visibility` set to `hidden` or their `display` set to `none`.Since it does not fail, the element should be visible. Additionally, the screenshot proves that the link really is visible. Anyways, thank you very much for your idea – TheKvist Nov 03 '17 at 12:59
  • Another thought is that the element could be scrolled out of view. If Selenium tries to click on a visible and displayed element that is not in the viewport (scrolled out of view at the time of click), you will get `ElementNotVisibleException` as well. The trick here is to scroll the page so that the element is in the viewport. Don't know if that helps here. – Ron Norris Nov 03 '17 at 13:16
  • I've already checked that, the sub-navigation is right under the main navigation, both visible on top of the page, so scrolling should not be needed, as `see` sees elements way below the navigation. However, you I've had another thought about visibility. In the screenshot, I've noticed that the both the navigation and sub-navigation where kind of "crunched" together. Could an element from the navigation that "overlays" the sub-navigation element be the reason selenium can't see the element? – TheKvist Nov 03 '17 at 14:25
  • Yes, but modern browsers respond with a fairly clear error when there's an overlap situation. I tried Edge and Chrome and got these two errors, respectively: *Element is obscured*, and * is not clickable at point (103, 210). Other element would receive the click*. – Ron Norris Nov 03 '17 at 14:58
  • Is it possible for you to give the links a unique id? Maybe using strict locators would work: $I->click(['id' => 'partners']) – sunomad Nov 04 '17 at 21:55
  • @sunomad Using IDs is unfortunately not a long-term solution, but I will try it anyway, just to see if it _would_ work. Thanks a lot for the suggestion. – TheKvist Nov 06 '17 at 13:24
  • Dang still no answer, this is driving me nuts! Makes me consider going back to PHPBrowser, which has a lot of headaches of its own, but at least this aspect worked exactly as it should. If you can `->see()`, you should be able to `->click()`! – jerclarke Jul 29 '21 at 17:19
  • For me, it worked adding more specificity to the selector. `a.child` didn't work, but `.parent a.child` worked. – Rax Dec 20 '21 at 17:44

1 Answers1

0

I don't understand exactly why it happens in some cases and not others, but I've found a solution that works for me: Use CSS selectors only.

Basically in some cases (I think it has to do with clicking on div/span rather than a/button) ->see() will work with the fuzzy text string as first argument, but ->click() requires the explicit CSS selector.

So this will have the "I can see but not click" problems:

// BROKEN
$I->see("All topics", ".header-taxonomy .taxonomy-list-title");
$I->click("All topics", ".header-taxonomy .taxonomy-list-title");

But this will work:

// WORKS
$I->see("All topics", ".header-taxonomy .taxonomy-list-title");
$I->click(".header-taxonomy .taxonomy-list-title");

Obviously it's not ideal at all, partly because it requires a unique selector, but for me mostly just because it makes the tests and testing output less consistent and harder to read.

Either way, I just wanted to get this testing script finished, and now it's working, and because I'm still using ->see() with the fuzzy text locator, I'm still confident that the text is showing before I click.

Notably, this issue doesn't happen when using the PHPBrowser module, which is what tripped me up. I "upgraded" to WebDriver and found my scripts were broken in all these places due to the different behavior of ->click() (in addition to the expected need to open menus before using them, which wasn't needed in PHPBrowser)

jerclarke
  • 1,219
  • 1
  • 13
  • 23