Chris@0: Chris@0: * @author Anthon Pang Chris@0: * @author Fabrizio Branca Chris@0: */ Chris@0: Chris@0: namespace WebDriver; Chris@0: Chris@0: use WebDriver\Exception as WebDriverException; Chris@0: Chris@0: /** Chris@0: * Abstract WebDriver\Container class Chris@0: * Chris@0: * @package WebDriver Chris@0: */ Chris@0: abstract class Container extends AbstractWebDriver Chris@0: { Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function __construct($url = 'http://localhost:4444/wd/hub') Chris@0: { Chris@0: parent::__construct($url); Chris@0: Chris@0: $locatorStrategy = new \ReflectionClass('WebDriver\LocatorStrategy'); Chris@0: $this->strategies = $locatorStrategy->getConstants(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Find element: /session/:sessionId/element (POST) Chris@0: * Find child element: /session/:sessionId/element/:id/element (POST) Chris@0: * Search for element on page, starting from the document root. Chris@0: * Chris@0: * @param string $using the locator strategy to use Chris@0: * @param string $value the search target Chris@0: * Chris@0: * @return \WebDriver\Element Chris@0: * Chris@0: * @throws \WebDriver\Exception if element not found, or invalid XPath Chris@0: */ Chris@0: public function element($using = null, $value = null) Chris@0: { Chris@0: $locatorJson = $this->parseArgs('element', func_get_args()); Chris@0: Chris@0: try { Chris@0: $result = $this->curl( Chris@0: 'POST', Chris@0: '/element', Chris@0: $locatorJson Chris@0: ); Chris@0: } catch (WebDriverException\NoSuchElement $e) { Chris@0: throw WebDriverException::factory( Chris@0: WebDriverException::NO_SUCH_ELEMENT, Chris@0: sprintf( Chris@0: "Element not found with %s, %s\n\n%s", Chris@0: $locatorJson['using'], Chris@0: $locatorJson['value'], Chris@0: $e->getMessage() Chris@0: ), Chris@0: $e Chris@0: ); Chris@0: } Chris@0: Chris@0: $element = $this->webDriverElement($result['value']); Chris@0: Chris@0: if ($element === null) { Chris@0: throw WebDriverException::factory( Chris@0: WebDriverException::NO_SUCH_ELEMENT, Chris@0: sprintf( Chris@0: "Element not found with %s, %s\n", Chris@0: $locatorJson['using'], Chris@0: $locatorJson['value'] Chris@0: ) Chris@0: ); Chris@0: } Chris@0: Chris@0: return $element; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Find elements: /session/:sessionId/elements (POST) Chris@0: * Find child elements: /session/:sessionId/element/:id/elements (POST) Chris@0: * Search for multiple elements on page, starting from the document root. Chris@0: * Chris@0: * @param string $using the locator strategy to use Chris@0: * @param string $value the search target Chris@0: * Chris@0: * @return array Chris@0: * Chris@0: * @throws \WebDriver\Exception if invalid XPath Chris@0: */ Chris@0: public function elements($using = null, $value = null) Chris@0: { Chris@0: $locatorJson = $this->parseArgs('elements', func_get_args()); Chris@0: Chris@0: $result = $this->curl( Chris@0: 'POST', Chris@0: '/elements', Chris@0: $locatorJson Chris@0: ); Chris@0: Chris@0: if (!is_array($result['value'])) { Chris@0: return array(); Chris@0: } Chris@0: Chris@0: return array_filter( Chris@0: array_map( Chris@0: array($this, 'webDriverElement'), Chris@0: $result['value'] Chris@0: ) Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Parse arguments allowing either separate $using and $value parameters, or Chris@0: * as an array containing the JSON parameters Chris@0: * Chris@0: * @param string $method method name Chris@0: * @param array $argv arguments Chris@0: * Chris@0: * @return array Chris@0: * Chris@0: * @throws \WebDriver\Exception if invalid number of arguments to the called method Chris@0: */ Chris@0: private function parseArgs($method, $argv) Chris@0: { Chris@0: $argc = count($argv); Chris@0: Chris@0: switch ($argc) { Chris@0: case 2: Chris@0: $using = $argv[0]; Chris@0: $value = $argv[1]; Chris@0: break; Chris@0: Chris@0: case 1: Chris@0: $arg = $argv[0]; Chris@0: Chris@0: if (is_array($arg)) { Chris@0: $using = $arg['using']; Chris@0: $value = $arg['value']; Chris@0: break; Chris@0: } Chris@0: Chris@0: // fall through Chris@0: default: Chris@0: throw WebDriverException::factory( Chris@0: WebDriverException::JSON_PARAMETERS_EXPECTED, Chris@0: sprintf('Invalid arguments to %s method: %s', $method, print_r($argv, true)) Chris@0: ); Chris@0: } Chris@0: Chris@0: return $this->locate($using, $value); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Return JSON parameter for element / elements command Chris@0: * Chris@0: * @param string $using locator strategy Chris@0: * @param string $value search target Chris@0: * Chris@0: * @return array Chris@0: * Chris@0: * @throws \WebDriver\Exception if invalid locator strategy Chris@0: */ Chris@0: public function locate($using, $value) Chris@0: { Chris@0: if (!in_array($using, $this->strategies)) { Chris@0: throw WebDriverException::factory( Chris@0: WebDriverException::UNKNOWN_LOCATOR_STRATEGY, Chris@0: sprintf('Invalid locator strategy %s', $using) Chris@0: ); Chris@0: } Chris@0: Chris@0: return array( Chris@0: 'using' => $using, Chris@0: 'value' => $value, Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Return WebDriver\Element wrapper for $value Chris@0: * Chris@0: * @param mixed $value Chris@0: * Chris@0: * @return \WebDriver\Element|null Chris@0: */ Chris@0: protected function webDriverElement($value) Chris@0: { Chris@0: return array_key_exists('ELEMENT', (array) $value) Chris@0: ? new Element( Chris@0: $this->getElementPath($value['ELEMENT']), // url Chris@0: $value['ELEMENT'] // id Chris@0: ) Chris@0: : null; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function __call($name, $arguments) Chris@0: { Chris@0: if (count($arguments) === 1 && in_array(str_replace('_', ' ', $name), $this->strategies)) { Chris@0: return $this->locate($name, $arguments[0]); Chris@0: } Chris@0: Chris@0: // fallback to executing WebDriver commands Chris@0: return parent::__call($name, $arguments); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get wire protocol URL for an element Chris@0: * Chris@0: * @param string $elementId Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: abstract protected function getElementPath($elementId); Chris@0: }