3 * Copyright 2014-2017 Anthon Pang. All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 * @author Anthon Pang <apang@softwaredevelopment.ca>
20 * @author Damian Mooyman <damian@silverstripe.com>
23 namespace Test\WebDriver;
25 use WebDriver\ServiceFactory;
26 use WebDriver\WebDriver;
29 * Test WebDriver\WebDriver class
35 class WebDriverTest extends \PHPUnit_Framework_TestCase
39 private $testDocumentRootUrl = 'http://localhost';
40 private $testSeleniumRootUrl = 'http://localhost:4444/wd/hub';
45 protected function setUp()
47 ServiceFactory::getInstance()->setServiceClass('service.curl', '\\WebDriver\\Service\\CurlService');
49 if ($url = getenv('ROOT_URL')) {
50 $this->testDocumentRootUrl = $url;
53 if ($url = getenv('SELENIUM_URL')) {
54 $this->testSeleniumRootUrl = $url;
57 $this->driver = new WebDriver($this->getTestSeleniumRootUrl());
58 $this->session = null;
64 protected function tearDown()
67 $this->session->close();
72 * Returns the full url to the test site (corresponding to the root dir of the library).
73 * You can set this via env var ROOT_URL
77 protected function getTestDocumentRootUrl()
79 return $this->testDocumentRootUrl;
83 * Returns the full url to the Selenium server used for functional tests
87 * @todo make this configurable via env var
89 protected function getTestSeleniumRootUrl()
91 return $this->testSeleniumRootUrl;
97 * @param \Exception $exception
101 protected function isSeleniumDown($exception)
103 return preg_match('/Failed to connect to .* Connection refused/', $exception->getMessage()) != false
104 || strpos($exception->getMessage(), 'couldn\'t connect to host') !== false
105 || strpos($exception->getMessage(), 'Unable to connect to host') !== false;
109 * Test driver sessions
111 public function testSessions()
114 $this->assertCount(0, $this->driver->sessions());
116 $this->session = $this->driver->session();
117 } catch (\Exception $e) {
118 if ($this->isSeleniumDown($e)) {
119 $this->markTestSkipped('selenium server not running');
127 $this->assertCount(1, $this->driver->sessions());
128 $this->assertEquals($this->getTestSeleniumRootUrl(), $this->driver->getUrl());
134 public function testStatus()
137 $status = $this->driver->status();
138 } catch (\Exception $e) {
139 if ($this->isSeleniumDown($e)) {
140 $this->markTestSkipped('selenium server not running');
148 $this->assertCount(3, $status);
149 $this->assertTrue(isset($status['java']));
150 $this->assertTrue(isset($status['os']));
151 $this->assertTrue(isset($status['build']));
155 * Checks that an error connecting to Selenium gives back the expected exception
157 public function testSeleniumError()
160 $this->driver = new WebDriver($this->getTestSeleniumRootUrl() . '/../invalidurl');
162 $status = $this->driver->status();
164 $this->fail('Exception not thrown while connecting to invalid Selenium url');
165 } catch (\Exception $e) {
166 if ($this->isSeleniumDown($e)) {
167 $this->markTestSkipped('selenium server not running');
172 $this->assertEquals('WebDriver\Exception\CurlExec', get_class($e));
177 * Checks that a successful command to Selenium which returns an http error response gives back the expected exception
179 public function testSeleniumErrorResponse()
182 $status = $this->driver->status();
183 } catch (\Exception $e) {
184 if ($this->isSeleniumDown($e)) {
185 $this->markTestSkipped('selenium server not running');
194 $this->session = $this->driver->session();
195 $this->session->open($this->getTestDocumentRootUrl().'/test/Assets/index.html');
197 $element = $this->session->element('id', 'a-quite-unlikely-html-element-id');
199 $this->fail('Exception not thrown while looking for missing element in page');
200 } catch (\Exception $e) {
201 $this->assertEquals('WebDriver\Exception\NoSuchElement', get_class($e));
206 * Checks that a successful command to Selenium which returns 'nothing' according to spec does not raise an error
208 public function testSeleniumNoResponse()
211 $status = $this->driver->status();
212 } catch (\Exception $e) {
213 if ($this->isSeleniumDown($e)) {
214 $this->markTestSkipped('selenium server not running');
222 $this->session = $this->driver->session();
223 $timeouts = $this->session->timeouts();
224 $out = $timeouts->async_script(array('type' => 'implicit', 'ms' => 1000));
226 $this->assertEquals(null, $out);
230 * Assert that empty response does not trigger exception, but invalid JSON does
232 public function testNonJsonResponse()
234 $mockCurlService = $this->createMock('WebDriver\Service\CurlService');
235 $mockCurlService->expects($this->once())
237 ->will($this->returnCallback(function ($requestMethod, $url) {
240 'request_method' => $requestMethod,
244 $result = preg_match('#.*session$#', $url)
245 ? $result = 'some invalid json'
248 return array($result, $info);
251 ServiceFactory::getInstance()->setService('service.curl', $mockCurlService);
253 $result = $this->driver->status();
255 $this->assertNull($result);
257 // Test /session should error
258 $this->setExpectedException(
259 'WebDriver\Exception\CurlExec',
260 'Payload received from webdriver is not valid json: some invalid json'
263 $result = $this->driver->session();
265 $this->assertNull($result);