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