* @author Damian Mooyman */ namespace Test\WebDriver; use WebDriver\ServiceFactory; use WebDriver\WebDriver; /** * Test WebDriver\WebDriver class * * @package WebDriver * * @group Functional */ class WebDriverTest extends \PHPUnit_Framework_TestCase { private $driver; private $session; private $testDocumentRootUrl = 'http://localhost'; private $testSeleniumRootUrl = 'http://localhost:4444/wd/hub'; /** * {@inheritdoc} */ protected function setUp() { ServiceFactory::getInstance()->setServiceClass('service.curl', '\\WebDriver\\Service\\CurlService'); if ($url = getenv('ROOT_URL')) { $this->testDocumentRootUrl = $url; } if ($url = getenv('SELENIUM_URL')) { $this->testSeleniumRootUrl = $url; } $this->driver = new WebDriver($this->getTestSeleniumRootUrl()); $this->session = null; } /** * {@inheritdoc} */ protected function tearDown() { if ($this->session) { $this->session->close(); } } /** * Returns the full url to the test site (corresponding to the root dir of the library). * You can set this via env var ROOT_URL * * @return string */ protected function getTestDocumentRootUrl() { return $this->testDocumentRootUrl; } /** * Returns the full url to the Selenium server used for functional tests * * @return string * * @todo make this configurable via env var */ protected function getTestSeleniumRootUrl() { return $this->testSeleniumRootUrl; } /** * Is Selenium down? * * @param \Exception $exception * * @return boolean */ protected function isSeleniumDown($exception) { return preg_match('/Failed to connect to .* Connection refused/', $exception->getMessage()) != false || strpos($exception->getMessage(), 'couldn\'t connect to host') !== false || strpos($exception->getMessage(), 'Unable to connect to host') !== false; } /** * Test driver sessions */ public function testSessions() { try { $this->assertCount(0, $this->driver->sessions()); $this->session = $this->driver->session(); } catch (\Exception $e) { if ($this->isSeleniumDown($e)) { $this->markTestSkipped('selenium server not running'); return; } throw $e; } $this->assertCount(1, $this->driver->sessions()); $this->assertEquals($this->getTestSeleniumRootUrl(), $this->driver->getUrl()); } /** * Test driver status */ public function testStatus() { try { $status = $this->driver->status(); } catch (\Exception $e) { if ($this->isSeleniumDown($e)) { $this->markTestSkipped('selenium server not running'); return; } throw $e; } $this->assertCount(3, $status); $this->assertTrue(isset($status['java'])); $this->assertTrue(isset($status['os'])); $this->assertTrue(isset($status['build'])); } /** * Checks that an error connecting to Selenium gives back the expected exception */ public function testSeleniumError() { try { $this->driver = new WebDriver($this->getTestSeleniumRootUrl() . '/../invalidurl'); $status = $this->driver->status(); $this->fail('Exception not thrown while connecting to invalid Selenium url'); } catch (\Exception $e) { if ($this->isSeleniumDown($e)) { $this->markTestSkipped('selenium server not running'); return; } $this->assertEquals('WebDriver\Exception\CurlExec', get_class($e)); } } /** * Checks that a successful command to Selenium which returns an http error response gives back the expected exception */ public function testSeleniumErrorResponse() { try { $status = $this->driver->status(); } catch (\Exception $e) { if ($this->isSeleniumDown($e)) { $this->markTestSkipped('selenium server not running'); return; } throw $e; } try { $this->session = $this->driver->session(); $this->session->open($this->getTestDocumentRootUrl().'/test/Assets/index.html'); $element = $this->session->element('id', 'a-quite-unlikely-html-element-id'); $this->fail('Exception not thrown while looking for missing element in page'); } catch (\Exception $e) { $this->assertEquals('WebDriver\Exception\NoSuchElement', get_class($e)); } } /** * Checks that a successful command to Selenium which returns 'nothing' according to spec does not raise an error */ public function testSeleniumNoResponse() { try { $status = $this->driver->status(); } catch (\Exception $e) { if ($this->isSeleniumDown($e)) { $this->markTestSkipped('selenium server not running'); return; } throw $e; } $this->session = $this->driver->session(); $timeouts = $this->session->timeouts(); $out = $timeouts->async_script(array('type' => 'implicit', 'ms' => 1000)); $this->assertEquals(null, $out); } /** * Assert that empty response does not trigger exception, but invalid JSON does */ public function testNonJsonResponse() { $mockCurlService = $this->createMock('WebDriver\Service\CurlService'); $mockCurlService->expects($this->once()) ->method('execute') ->will($this->returnCallback(function ($requestMethod, $url) { $info = array( 'url' => $url, 'request_method' => $requestMethod, 'http_code' => 200, ); $result = preg_match('#.*session$#', $url) ? $result = 'some invalid json' : $result = ''; return array($result, $info); })); ServiceFactory::getInstance()->setService('service.curl', $mockCurlService); $result = $this->driver->status(); $this->assertNull($result); // Test /session should error $this->setExpectedException( 'WebDriver\Exception\CurlExec', 'Payload received from webdriver is not valid json: some invalid json' ); $result = $this->driver->session(); $this->assertNull($result); } }