wallaby icon indicating copy to clipboard operation
wallaby copied to clipboard

Wallaby does not click or throw an error for buttons that are not visible in the window

Open cysiegel opened this issue 6 years ago • 7 comments

I'm trying to click on a button that exists in the HTML however is no longer visible to a human user because the window scrolled down from an earlier part of the test

When calling the function click on the element no error is thrown - even though the DOM element never gets clicked on (assert_has also does not throw an error)

It seems strange that the click function does not throw an error because the element exists in the HTML - while at the same time fails to click on the element because its not in the visible window

While I solved my specific problem by scrolling up - (execute_script(session, "window.scrollTo(0, 0);")) - it would be nice to either be able to click elements that are visible in the HTML and if its not clickable then for an error to be thrown
(BTW it would be a nice feature to have wallaby scroll functions without having to use javascript)

    session
    |> assert_has(css(".automation-registration-loadin", count: 0))
    |> assert_has(css(".row", text: "Documents"))
    |> find(css(".row", text: "Documents"))
    |> assert_has(css(".app-expand-up-row-icon"))
    |> click(css(".app-expand-up-row-icon"))
    |> assert_has(css("#app-approved-documents-btn"))
    |> click(css("#app-approved-documents-btn"))

    IO.puts("test successfully reached here but no button was clicked")

.

cysiegel avatar Jan 12 '20 15:01 cysiegel

Hi @cysiegel Which driver are you using?

Visible doesn't mean visible in the viewport, it means visible on the page, so assert_has works correctly.

Most WebDriver implementations when told to interact with an element that is visible but off-the-screen are implicitly performing a scroll to that location before interacting. Sometimes that is implemented naively and can cause the interaction to fail. For example, I had a similar experience to yours with Chrome and pages that have a "sticky" floating menu visible on top of the window even after scrolling down. Chromedriver was sometimes scrolling to the element so that it was in the viewport but underneath the menu. Scrolling with JavaScript is a correct work-around IMO.

michallepicki avatar Jan 12 '20 15:01 michallepicki

@michallepicki thanks for your quick response I am using chromedriver

If I understand you correctly - we can't throw just an error when trying to interact with an element not in the viewport because the behavior varies between drivers and the DOM

cysiegel avatar Jan 13 '20 09:01 cysiegel

@cysiegel More or less, yes. We could add an additional check that could be used together with visible, something like in_viewport: true/false/nil but it would hurt performance so probably would't be enabled by defaut and AFAIK there's no reliable way to perform such check. I'm using this JavaScript heuristics, which is not perfect but in most cases works https://github.com/webdriverio/webdriverio/blob/9b83046725ea9ba68f7d2e5a4207b50a798f944f/packages/webdriverio/src/scripts/isDisplayedInViewport.js

michallepicki avatar Jan 13 '20 09:01 michallepicki

@michallepicki Thanks for your help!!!!

cysiegel avatar Jan 13 '20 09:01 cysiegel

They use a slightly different implementation now, I have not tested it: https://github.com/webdriverio/webdriverio/blob/5cceaa8e0b6b5fdc870a777e418fcd9f434f31f5/packages/webdriverio/src/scripts/isElementInViewport.js

There is some nuance here with elements fully vs only partially visible in the viewport, maybe that's why they changed it.

michallepicki avatar Jan 13 '20 10:01 michallepicki

FYI, I used a workaround in my case by scrolling 1 in y axis with Wallaby.Browser.touch_scroll/4:

use Wallaby.Feature
import Wallaby.Query

session
|> # omit some operations
|> touch_scroll(link("Paddings"), 0, 1)
|> click(link("Paddings"))

goofansu avatar Dec 12 '21 14:12 goofansu

FYI, I used a workaround in my case by scrolling 1 in y axis with Wallaby.Browser.touch_scroll/4:

use Wallaby.Feature
import Wallaby.Query

session
|> # omit some operations
|> touch_scroll(link("Paddings"), 0, 1)
|> click(link("Paddings"))

Notice that there is no touch_scroll/3 in Selenium driver.

goofansu avatar Apr 09 '22 05:04 goofansu