1: <?php
2: namespace Azalea\Selenium\Core;
3:
4: abstract class WebDriver
5: {
6:
7: protected $driver = null;
8:
9:
10: protected $timeout = 30;
11:
12: 13: 14: 15:
16: public function __construct($driver)
17: {
18: if (!$driver) {
19: throw new \InvalidArgumentException(get_class($this).": driver not defined");
20: }
21:
22: if ($driver instanceof WebDriver) {
23: $this->setDriver($driver->getDriver());
24: } else {
25: $this->setDriver($driver);
26: }
27:
28: $this->spinWait(array($this, "verify"), $this->timeout);
29: }
30:
31: 32: 33: 34:
35: public function getDriver()
36: {
37: return $this->driver;
38: }
39:
40: 41: 42: 43: 44:
45: public function setDriver($driver)
46: {
47:
48:
49:
50:
51: $this->driver = $driver;
52: }
53:
54: 55: 56: 57: 58:
59: public function getElementsByCss($css)
60: {
61: return $elements = $this->elements(
62: $this->using('css selector')->value($css)
63: );
64: }
65:
66: 67: 68: 69: 70: 71:
72: public function exists()
73: {
74: try {
75: $args = func_get_args();
76: foreach($args as $css) {
77: $this->driver->byCss($css);
78: }
79: } catch (\Exception $e) {
80: return false;
81: }
82: return true;
83: }
84:
85: 86: 87: 88: 89: 90:
91: public function existsById()
92: {
93: try {
94: $args = func_get_args();
95: foreach($args as $id) {
96: $this->driver->byId($id);
97: }
98: } catch (\Exception $e) {
99: return false;
100: }
101: return true;
102: }
103:
104: 105: 106: 107: 108: 109:
110: public function displayed()
111: {
112: $args = func_get_args();
113: foreach($args as $css) {
114: if (!$this->exists($css) || !$this->byCss($css)->displayed()) {
115: return false;
116: }
117: }
118: return true;
119: }
120:
121: 122: 123: 124: 125: 126:
127: public function displayedById()
128: {
129: $args = func_get_args();
130: foreach($args as $id) {
131: if (!$this->existsById($id) || !$this->byId($id)->displayed()) {
132: return false;
133: }
134: }
135: return true;
136: }
137:
138: 139: 140: 141:
142: public function wait($timeout = 2)
143: {
144: sleep($timeout);
145: }
146:
147: 148: 149: 150: 151:
152: public function clickAndWait($element, $timeout = 2)
153: {
154: $element->click();
155: $this->wait($timeout);
156: }
157:
158: 159: 160: 161:
162: public function getCurrentHash()
163: {
164: return $this->execute(array(
165: 'script' => "return window.location.hash",
166: 'args' => array()
167: ));
168: }
169:
170: 171: 172: 173:
174: public function updateHash($hash)
175: {
176: $this->execute(array(
177: 'script' => "window.location.hash = '".$hash."'",
178: 'args' => array(),
179: ));
180: return true;
181: }
182:
183: 184: 185: 186:
187: protected function verify()
188: {
189: return true;
190: }
191:
192: 193: 194: 195: 196:
197: protected function spinWait($test, $timeout = 30)
198: {
199: $num_tries = 0;
200: $result = false;
201: while ($num_tries < $timeout && !$result) {
202: try {
203: $result = call_user_func($test);
204: } catch (\Exception $e) {
205: $result = false;
206: }
207:
208: if (!$result) {
209: sleep(1);
210: }
211:
212: $num_tries++;
213: }
214:
215: if ($result) {
216: return true;
217: }
218:
219: throw new \RuntimeException(get_class($this).": Timeout verifying ".get_called_class()." after ".$num_tries." seconds.");
220: }
221:
222: 223: 224: 225: 226: 227:
228: public function __call($method, $args)
229: {
230: if (!$this->driver) {
231: throw new \InvalidArgumentException(get_class($this).": driver not defined");
232: }
233:
234: if (is_callable(array($this->driver, $method))) {
235: try {
236: return call_user_func_array(array($this->driver, $method), $args);
237: } catch (\Exception $e) {
238: throw new \RuntimeException(get_class($this)." -> " . $method . " with args ".implode(",", $args)." Exception: " . $e->getMessage());
239: }
240: } else {
241: throw new \RuntimeException("Method " . $method . " is not callable on the web driver.");
242: }
243: }
244: }