Summer Sale! All accounts are 50% off this week.

zachleigh's avatar

Dusk suddenly can't find elements that need scrolling to access

I updated composer dependencies yesterday and since then am getting this error on several tests:

Facebook\WebDriver\Exception\UnknownServerException: unknown error: Element is not clickable at point (1450, 2309)

Test code:

$browser->visit(new EditPage()
    ->click('#add');

The element it is trying to access (#add) is simply down the page a bit. It is fully visible and if I pause the test before the click and manually scroll down, the test continues as normal. I'm not 100% sure if the update yesterday is related to the issue, but I can't think of anything else that may have caused this to happen so suddenly. Any body else experiencing this? Any ideas on how to fix it?

0 likes
11 replies
bashy's avatar

Why not rollback to the previous version that you knew it worked and check?

danielbaylis's avatar

I am experiencing the same. I've rolled everything back to a state that worked previously, but the issue persists - Certain elements (buttons, radio, checkbox) are no longer clickable if they require scrolling to be in the viewport.

The issue seems to have started in the last 10 days or so. I noticed Chrome 61 came out on September 5. Is dusk ultimately just controlling the Chrome version we have installed, and something has changed there perhaps?

I remember this being an issue last year, and I was needing to put something like this in all my tests with big forms so the save button at the end would be accessible:

$browser->script('window.scrollTo(0,document.body.scrollHeight)');

At some point that became unnecessary, but now it seems to have reverted...

This Dusk Issue seems to describe the same thing and mentions Vue as a possible cause but doesn't seem to come to any real conclusion other than manually calling scripts to trigger scrolling.

Did you have any luck?

zachleigh's avatar

@bashy Yes, I tried that and had no luck.

@danielbaylis Could be a Chrome issue. Don't know if I feel like managing outdated Chrome versions just to make tests pass though.

I found that same GitHub issue and one comment in there suggested first using type near the element to draw focus. All my failing tests are on forms so I type something near the button before doing the click. Its dirty and I don't like it, but it works.

danielbaylis's avatar
Level 8

@zachleigh I came up with a few macros to make it a little cleaner. One to scroll to the bottom of the form and press the save button - This makes sure it is always visible and cleans up the test code. Because type won't work on checkboxes or radios, the other macro scrolls the browser to their position, so can be called in the test method chain to scroll them in to view before attempting to interact with them.

It works but I don't like needing to do this when we didn't before. I wonder if there is another factor at play as surely this must be effecting more people.

    /**
     * Scrolls page to the bottom and presses Save.
     */
    Browser::macro('saveForm', function () {
        $this->script('window.scrollTo(0,document.body.scrollHeight)');
        $this->press('Save');

        return $this;
    });

    /**
     * Scrolls page to a specific element.
     *
     * Leaves a buffer at the top to account for a fixed header.
     */
    Browser::macro('scrollTo', function ($id) {
        $this->script("document.getElementById('$id').scrollIntoView()");
        $this->script('window.scroll(0, window.scrollY - 50)');

        return $this;
    });
1 like
zachleigh's avatar

@danielbaylis Excellent. Had no idea Browser was macroable. The scrollTo one works perfectly for my situation. Thanks a lot!

1 like
zoispag's avatar

What if the element is not a button? I don't want to add the macro to every action browser object does. And because of the nature of the tests, it's not always certain which fields can get off view-port.

Is there any way to at least call ScrollTo for every type/select/check/press/etc. action?

MikeHopley's avatar

This issue is caused by the Chrome update. There is a newer version of Chromedriver that apparently fixes the problem.

I found the problem was resolved by using the latest version of Dusk. I had to use an unreleased (dev-master) version, but it may now have made it into a release.

This sort of thing frequently happens when new browser versions come out: browser tests break, and an upgrade to the browser testing driver fixes it.

MikeHopley's avatar

@bobbyborisov My comment is pretty old now, so I don't know!

As I mentioned, these things tend to go in cycles: a browser update breaks Webdriver behaviour, then Webdriver releases a fix.

Dusk is built on top of Webdriver / Chromedriver, so you may have to wait a bit longer for Dusk to update.

Automated browser-testing software like Webdriver is complicated and rather fragile. I think it's a miracle it works at all...

rawfan's avatar

If you allow me, I'll warm this up because I still have this problem in 2021. I'm using a scrollTo macro that scrolls the element into the center of the view instead of scrolling it to the top (default). I'll probably also PR this to dusk because it makes more sense, IMO.

Browser::macro('scrollToElement', function ($selector) {
    $selector = addslashes($this->resolver->format($selector));
            $this->driver->executeScript("document.querySelector(\"$selector\").scrollIntoView({block: \"center\", inline: \"center\"});");
    return $this;
});
1 like
Hashim's avatar

@rawfan Did you ever make this PR? Be happy to add my voice to it because this is clearly still an issue and really needs to be fixed.

EDIT: It doesn't seem to work as is in Laravel 8, $resolver and $driver show as undefined properties. Is there some code missing?

1 like

Please or to participate in this conversation.