php-webdriver / php-webdriver

PHP client for Selenium/WebDriver protocol. Previously facebook/php-webdriver
MIT License
5.12k stars 844 forks source link

isDisplayed does not work with Safari on OS X Catalina #843

Closed jogi-check closed 2 years ago

jogi-check commented 3 years ago

What are you trying to achieve? (Expected behavior)

We want to test my website on variuos OS and browsers with Browserstack through local tunnel, including Safari on OS X Catalina. Previously, we used facebook/webdriver 1.7.1, and everything worked. Now we want to upgrade to newer versions of php-webdriver.

What do you get instead? (Actual behavior)

The connection is OK, but the webdriver does not find any element in Safari on OS X Catalina, so it jus does nothing after loading the page. Other browsers like Chrome on Windows 10, iPhones or Samsung Galaxy devices work as expected.

How could the issue be reproduced? (Steps to reproduce)

Described behaviour is reproducible, just upgrade php-webdriver from 1.7.1 to 1.8.0 or above. We initialize the webdriver as follows:

$driver = RemoteWebDriver::create(
    'https://local.example.com',
    [
        'acceptSslCerts'                => true,
        'browserstack-tunnel'           => true,
        'browserstack.local'            => true,
        'browserstack.autoWait'         => 60,
        'browserstack.debug'            => true,
        'browserstack.idleTimeout'      => 300,
        'os'                            => 'OS X',
        'os_version'                    => 'Catalina',
        'browser'                       => 'Safari',
        'resolution'                    => '1920x1080',
        'browser_version'               => 'latest',
        'browserstack.selenium_version' => '3.14.0',
        'build'                         => 'myBuild',
        'name'                          => 'Project Name',
        'browserstack.localIdentifier'  => 'abcdefg'
    ],
    null,
    120000
);

Details

OndraM commented 3 years ago

Hi, try using the latest version of Selenium 3.x. (which is I guess 3.141.59).

If it didn't help, please provide logs you have from BrowserStack. And also what is the exact error you are getting, and the code snippet you use to find the element.

andrewnicols commented 3 years ago

Just to note that I regularly run php-webdriver 1.8.1 with Selenium 3.141.59 on Catalina, however the official safaridriver is rubbish and does not even support clicking on buttons.

jogi-check commented 3 years ago

Hi, I've tried php-webdriver 1.8.1 with Selenium 3.141.59 just now, but again without luck.

Here is a selenium log from working php-webdriver 1.7.1 and Selenium 3.141.59, provided by browserstack

10:05:19.505 DEBUG [ReverseProxyHandler.execute] - To upstream: {"using":"css selector","value":".my-page-title"}
10:05:19.505 DEBUG [HttpURLConnection.writeRequests] - sun.net.www.MessageHeader@307e751417 pairs: {POST /session/3324B637-7BED-4F87-A02F-4DDE3936CC3E/elements HTTP/1.1: null}{Accept: application/json}{X-Forwarded-Proto: http}{X-Forwarded-Host: hub-cloud.browserstack.com}{x-conn: keep-alive}{Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{X-Forwarded-For: 123.123.123.123, 45.148.168.22}{x-connid: 4014751284}{BStack-Host: 10.144.144.81}{X-Real-IP: 45.148.168.22}{Content-Type: application/json; charset=utf-8}{Cache-Control: no-cache}{Pragma: no-cache}{User-Agent: Java/1.8.0_51}{Host: localhost:40540}{Connection: keep-alive}{Content-Length: 49}
10:05:19.509 DEBUG [HttpURLConnection.getInputStream0] - sun.net.www.MessageHeader@748004238 pairs: {null: HTTP/1.1 200 OK}{Server: SafariDriver/1.0}{Content-Type: application/json; charset=utf-8}{Date: Mon, 14 Dec 2020 09:05:19 GMT}{Accept-Ranges: bytes}{Content-Length: 95}{Cache-Control: no-cache}{Connection: keep-alive}
10:05:19.509 DEBUG [ReverseProxyHandler.execute] - To downstream: {"value":[{"element-6066-11e4-a52e-4f735466cecf":"node-C9F7AE07-3E69-4F13-948A-6CC2C829D740"}]}
10:05:19.555 DEBUG [WebDriverServlet.handle] - Found handler: 3324B637-7BED-4F87-A02F-4DDE3936CC3E (org.openqa.selenium.safari.SafariDriverService)
10:05:19.556 DEBUG [WebDriverServlet.lambda$handle$0] - Handler thread for session 3324B637-7BED-4F87-A02F-4DDE3936CC3E (Safari): Executing POST on /session/3324B637-7BED-4F87-A02F-4DDE3936CC3E/execute/sync (handler: ServicedSession)
10:05:19.556 DEBUG [ReverseProxyHandler.execute] - To upstream: {"script":"return (function(){return function(){var k=this;function l(a){....VERY LONG JAVASCRIPT CROPPED....);","args":[{"ELEMENT":"node-C9F7AE07-3E69-4F13-948A-6CC2C829D740","element-6066-11e4-a52e-4f735466cecf":"node-C9F7AE07-3E69-4F13-948A-6CC2C829D740"}]}
10:05:19.556 DEBUG [HttpURLConnection.writeRequests] - sun.net.www.MessageHeader@7e5b663617 pairs: {POST /session/3324B637-7BED-4F87-A02F-4DDE3936CC3E/execute/sync HTTP/1.1: null}{Accept: application/json}{X-Forwarded-Proto: http}{X-Forwarded-Host: hub-cloud.browserstack.com}{x-conn: keep-alive}{Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{X-Forwarded-For: 123.123.123.123, 45.148.168.23}{x-connid: 4014751284}{BStack-Host: 10.144.144.81}{X-Real-IP: 45.148.168.23}{Content-Type: application/json; charset=utf-8}{Cache-Control: no-cache}{Pragma: no-cache}{User-Agent: Java/1.8.0_51}{Host: localhost:40540}{Connection: keep-alive}{Content-Length: 45641}
10:05:19.562 DEBUG [HttpURLConnection.getInputStream0] - sun.net.www.MessageHeader@1175e0088 pairs: {null: HTTP/1.1 200 OK}{Server: SafariDriver/1.0}{Content-Type: application/json; charset=utf-8}{Date: Mon, 14 Dec 2020 09:05:19 GMT}{Accept-Ranges: bytes}{Content-Length: 14}{Cache-Control: no-cache}{Connection: keep-alive}
10:05:19.562 DEBUG [ReverseProxyHandler.execute] - To downstream: {"value":true}
10:05:19.650 DEBUG [WebDriverServlet.handle] - Found handler: 3324B637-7BED-4F87-A02F-4DDE3936CC3E (org.openqa.selenium.safari.SafariDriverService)
10:05:19.650 DEBUG [WebDriverServlet.lambda$handle$0] - Handler thread for session 3324B637-7BED-4F87-A02F-4DDE3936CC3E (Safari): Executing POST on /session/3324B637-7BED-4F87-A02F-4DDE3936CC3E/execute/sync (handler: ServicedSession)
10:05:19.650 DEBUG [ReverseProxyHandler.execute] - To upstream: {"script":"return document.readyState","args":[]}
10:05:19.650 DEBUG [HttpURLConnection.writeRequests] - sun.net.www.MessageHeader@52e0e1e714 pairs: {POST /session/3324B637-7BED-4F87-A02F-4DDE3936CC3E/execute/sync HTTP/1.1: null}{Accept: application/json}{X-Forwarded-Proto: http}{X-Forwarded-For: 45.148.168.20}{BStack-Host: 10.144.144.81}{Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3}{X-Real-IP: 45.148.168.20}{Content-Type: application/json; charset=utf-8}{Cache-Control: no-cache}{Pragma: no-cache}{User-Agent: Java/1.8.0_51}{Host: localhost:40540}{Connection: keep-alive}{Content-Length: 49}
10:05:19.653 DEBUG [HttpURLConnection.getInputStream0] - sun.net.www.MessageHeader@263556848 pairs: {null: HTTP/1.1 200 OK}{Server: SafariDriver/1.0}{Content-Type: application/json; charset=utf-8}{Date: Mon, 14 Dec 2020 09:05:19 GMT}{Accept-Ranges: bytes}{Content-Length: 20}{Cache-Control: no-cache}{Connection: keep-alive}
10:05:19.653 DEBUG [ReverseProxyHandler.execute] - To downstream: {"value":"complete"}
10:05:19.698 DEBUG [WebDriverServlet.handle] - Found handler: 3324B637-7BED-4F87-A02F-4DDE3936CC3E (org.openqa.selenium.safari.SafariDriverService)

And here we have a selenium log for php-webdriver 1.8.1 and Selenium 3.141.59, provided by browserstack:

10:48:04.202 DEBUG [WebDriverServlet.handle] - Found handler: E774DDAC-9240-497B-B921-89B169D37DFB (org.openqa.selenium.safari.SafariDriverService)
10:48:04.203 DEBUG [WebDriverServlet.lambda$handle$0] - Handler thread for session E774DDAC-9240-497B-B921-89B169D37DFB (Safari): Executing POST on /session/E774DDAC-9240-497B-B921-89B169D37DFB/elements (handler: ServicedSession)
10:48:04.203 DEBUG [ReverseProxyHandler.execute] - To upstream: {"using":"css selector","value":".my-page-title"}
10:48:04.203 DEBUG [HttpURLConnection.writeRequests] - sun.net.www.MessageHeader@723103be15 pairs: {POST /session/E774DDAC-9240-497B-B921-89B169D37DFB/elements HTTP/1.1: null}{Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{Accept: application/json}{X-Forwarded-Host: hub-cloud.browserstack.com}{X-Forwarded-For: 123.123.123.123}{x-connid: 4042371392}{BStack-Host: 185.200.103.51}{x-conn: keep-alive}{Content-Type: application/json; charset=utf-8}{Cache-Control: no-cache}{Pragma: no-cache}{User-Agent: Java/1.8.0_51}{Host: localhost:29906}{Connection: keep-alive}{Content-Length: 49}
10:48:04.207 DEBUG [HttpURLConnection.getInputStream0] - sun.net.www.MessageHeader@302775748 pairs: {null: HTTP/1.1 200 OK}{Server: SafariDriver/1.0}{Content-Type: application/json; charset=utf-8}{Date: Mon, 14 Dec 2020 09:48:04 GMT}{Accept-Ranges: bytes}{Content-Length: 95}{Cache-Control: no-cache}{Connection: keep-alive}
10:48:04.207 DEBUG [ReverseProxyHandler.execute] - To downstream: {"value":[{"element-6066-11e4-a52e-4f735466cecf":"node-81E2D5D6-A581-4FC0-9E35-BDC2CDBAFB68"}]}
10:48:04.234 DEBUG [WebDriverServlet.handle] - Found handler: E774DDAC-9240-497B-B921-89B169D37DFB (org.openqa.selenium.safari.SafariDriverService)
10:48:04.235 DEBUG [WebDriverServlet.lambda$handle$0] - Handler thread for session E774DDAC-9240-497B-B921-89B169D37DFB (Safari): Executing GET on /session/E774DDAC-9240-497B-B921-89B169D37DFB/element/node-81E2D5D6-A581-4FC0-9E35-BDC2CDBAFB68/displayed (handler: ServicedSession)
10:48:04.235 DEBUG [HttpURLConnection.writeRequests] - sun.net.www.MessageHeader@3aec5a9014 pairs: {GET /session/E774DDAC-9240-497B-B921-89B169D37DFB/element/node-81E2D5D6-A581-4FC0-9E35-BDC2CDBAFB68/displayed HTTP/1.1: null}{Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{Accept: application/json}{X-Forwarded-Host: hub-cloud.browserstack.com}{X-Forwarded-For: 123.123.123.123}{x-connid: 4042371392}{BStack-Host: 185.200.103.51}{x-conn: keep-alive}{Content-Type: application/json;charset=UTF-8}{Cache-Control: no-cache}{Pragma: no-cache}{User-Agent: Java/1.8.0_51}{Host: localhost:29906}{Connection: keep-alive}
10:48:04.237 DEBUG [HttpURLConnection.getInputStream0] - sun.net.www.MessageHeader@554fe2868 pairs: {null: HTTP/1.1 404 Not Found}{Server: SafariDriver/1.0}{Content-Type: application/json; charset=utf-8}{Date: Mon, 14 Dec 2020 09:48:04 GMT}{Accept-Ranges: bytes}{Content-Length: 209}{Cache-Control: no-cache}{Connection: keep-alive}
10:48:04.238 DEBUG [ReverseProxyHandler.execute] - To downstream: {"value":{"error":"unknown command","message":"The command 'GET \/session\/E774DDAC-9240-497B-B921-89B169D37DFB\/element\/node-81E2D5D6-A581-4FC0-9E35-BDC2CDBAFB68\/displayed' was not found.","stacktrace":""}}
10:48:04.833 DEBUG [WebDriverServlet.handle] - Found handler: E774DDAC-9240-497B-B921-89B169D37DFB (org.openqa.selenium.safari.SafariDriverService)

The only call I do here is:

$elements = $driver->findElements(WebDriverBy::cssSelector('.my-page-title'));
foreach ($elements as $element) {
    if($element->isDisplayed()) {
        return $element;
    }
}

Same code, same browser, same browser version, same Selenium version, just another php-webdriver version.

andrewnicols commented 3 years ago

I've tested this with WebDriver 1.7.1, and against the main branch with Browserstack and can replicate the issue.

This issue is not with the element selection, but with the use of the isDisplayed() function, which is not a part of the W3C specification.

The difference between 1.7.1, and main is the fact that main supports the W3C specification.

There is no easy way to have Safari not return a W3C session, unlike in some other browsers (i.e. Chrome supports the w3c:bool experimental option). As a result whenever the firstMatch capability is included, then safaridriver returns a W3C-compatible session and actively disabled commands which are not a part of the W3C specification.

From a personal perspective I'd encourage you to start updating your tests to stop using features which are not part of the W3C specification, which will allow you to move forward and to test with other browsers, however I understand that's not an ideal solution for the here and now.

We could look to have a flag to not request a w3c session during the session creation - perhaps via some kind of flag in the list of capabilities (though that seems wrong), or via a new argument to create(). Such a flag could essentially change the W3C protocol selection to:

        if ($attemptW3c) {
            // W3C
            $parameters['capabilities'] = [
                'firstMatch' => [(object) $desired_capabilities->toW3cCompatibleArray()],
            ];

            if ($required_capabilities !== null && !empty($required_capabilities->toArray())) {
                $parameters['capabilities']['alwaysMatch'] = (object) $required_capabilities->toW3cCompatibleArray();
            }
        }

Really though the JsonWire specification is likely to disappear at some point and it may be better to spend the effort removing use of fragile functions like isDisplayed().

@OndraM any thoughts?

no-response[bot] commented 3 years ago

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. If the original issue author adds comment with more information, this issue will be automatically reopened and we can investigate further.

OndraM commented 3 years ago

This was actually waiting on my reaction I guess, not on the reaction of the original author :-D . I will have a look.

OndraM commented 3 years ago

Well, @andrewnicols is right - "displayed" method is not officially supported in W3C protocol (however - both Chromedriver and Geckodriver does support it). The reason why its not part of the protocol is explained in its specification.

Also see for example: https://stackoverflow.com/questions/51542203/webdriverexception-message-the-command-get-session-7-displayed-was-not-f - there are some workarounds.

You can also omit use of isDisplayed() and use some other way how to determine if the element is on the page...

But if we want to preserve "displayed" method for the users in all browser, we would need to use isShown javascript atom from Selenium project, and execute it instead of the displayed command. This is the way how its done in webdriver libraries for other browsers... For example ruby, https://github.com/SeleniumHQ/selenium/blob/a2d9b94833f5e265d9416476093b78aae44722e7/java/client/src/org/openqa/selenium/remote/codec/w3c/W3CHttpCommandCodec.java#L298 etc. Also Geckodriver does it internally using this atoms.

Having atom support would be nice, because they support many other features, which could be included in php-webdriver. But I'm not sure if someone will volunteer to implement it - but it would be definitely appreciated!

jogi-check commented 3 years ago

Thank you very much for the explanations @OndraM and @andrewnicols . We will try to create a workaround for this.

OndraM commented 2 years ago

This issue will be solved by https://github.com/php-webdriver/php-webdriver/pull/1013 :tada: