This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Magium; |
||
4 | |||
5 | use Facebook\WebDriver\Exception\NoSuchElementException; |
||
6 | use Facebook\WebDriver\Exception\WebDriverException; |
||
7 | use Facebook\WebDriver\WebDriverElement; |
||
8 | use Magium\Assertions\Element\Clickable; |
||
9 | use Magium\Assertions\Element\Displayed; |
||
10 | use Magium\Assertions\Element\Exists; |
||
11 | use Magium\Assertions\Element\NotClickable; |
||
12 | use Magium\Assertions\Element\NotDisplayed; |
||
13 | use Magium\Assertions\Element\NotExists; |
||
14 | use Magium\Assertions\LoggingAssertionExecutor; |
||
15 | use Magium\Commands\Open; |
||
16 | use Magium\TestCase\Initializer; |
||
17 | use Magium\TestCase\InitializerContainer; |
||
18 | use Magium\Themes\BaseThemeInterface; |
||
19 | use Magium\Util\Log\LoggerInterface; |
||
20 | use Magium\Util\Phpunit\MasterListener; |
||
21 | use Magium\Util\Phpunit\MasterListenerInterface; |
||
22 | use Magium\WebDriver\WebDriver; |
||
23 | use PHPUnit\Framework\TestCase; |
||
24 | use Zend\Di\Di; |
||
25 | |||
26 | abstract class AbstractTestCase extends TestCase |
||
27 | { |
||
28 | |||
29 | protected static $baseNamespaces = []; |
||
30 | |||
31 | protected $baseThemeClass = 'Magium\Themes\ThemeConfigurationInterface'; |
||
32 | |||
33 | protected $postCallbacks = []; |
||
34 | |||
35 | /** |
||
36 | * @var MasterListener |
||
37 | */ |
||
38 | |||
39 | protected static $masterListener; |
||
40 | |||
41 | /** |
||
42 | * @var \Magium\WebDriver\WebDriver |
||
43 | */ |
||
44 | protected $webdriver; |
||
45 | |||
46 | /** |
||
47 | * @var Di |
||
48 | */ |
||
49 | |||
50 | protected $di; |
||
51 | |||
52 | protected $textElementNodeSearch = [ |
||
53 | 'button', 'span', 'a', 'li', 'label', 'option', 'h1', 'h2', 'h3', 'td' |
||
54 | ]; |
||
55 | |||
56 | protected $initializer; |
||
57 | |||
58 | const BY_XPATH = 'byXpath'; |
||
59 | const BY_ID = 'byId'; |
||
60 | const BY_CSS_SELECTOR = 'byCssSelector'; |
||
61 | const BY_TEXT = 'byText'; |
||
62 | |||
63 | private $sectionTimerStart; |
||
64 | |||
65 | public function startTimer() |
||
66 | { |
||
67 | $this->sectionTimerStart = microtime(true); |
||
68 | } |
||
69 | |||
70 | public function endTimer($name, $minimumElapsedTime = null) |
||
71 | { |
||
72 | $endTime = microtime(true); |
||
73 | if (!$this->sectionTimerStart) { |
||
74 | throw new \Exception('sendTimer(name) requires startTimer() to be called previously'); |
||
75 | } |
||
76 | |||
77 | $elapsedMs = (int)(($endTime - $this->sectionTimerStart) * 1000); |
||
78 | $elapsedExact = $endTime - $this->sectionTimerStart; |
||
79 | |||
80 | $pass = $elapsedExact > $minimumElapsedTime; |
||
81 | |||
82 | $message = sprintf('%s - elapsed %sms', $name, $elapsedMs); |
||
83 | $this->getLogger()->notice($message, [ |
||
84 | 'type' => 'timer', |
||
85 | 'name' => $name, |
||
86 | 'elapsed_ms' => $elapsedMs, |
||
87 | 'elapsed' => $elapsedExact, |
||
88 | 'start_time' => $this->sectionTimerStart, |
||
89 | 'end_time' => $endTime, |
||
90 | 'unix_timestamp' => time(), |
||
91 | 'pass' => $pass |
||
92 | ]); |
||
93 | $this->sectionTimerStart = false; |
||
94 | if ($minimumElapsedTime !== null) { |
||
95 | self::assertGreaterThan($minimumElapsedTime, $elapsedExact); |
||
96 | } else { |
||
97 | self::assertNotEquals(0, $elapsedExact); // Immediate return is an indication of something bad |
||
98 | } |
||
99 | } |
||
100 | |||
101 | protected static $registrationCallbacks; |
||
102 | |||
103 | protected function setUp() |
||
104 | { |
||
105 | /** |
||
106 | * Putting this in the setup and not in the property means that an extending class can inject itself easily |
||
107 | * before the Magium namespace, thus, taking preference over the base namespace |
||
108 | */ |
||
109 | |||
110 | self::addBaseNamespace('Magium'); |
||
111 | |||
112 | /** |
||
113 | * This weird little bit of code (the InitializerContainer) is done like this so we can provide a type |
||
114 | * preference for the Initializer. This is because Magium is a DI-based setup rigged inside a non-DI-based |
||
115 | * setup |
||
116 | */ |
||
117 | if (!$this->initializer instanceof InitializerContainer) { |
||
118 | $this->initializer = Initializer::getInitializationDependencyInjectionContainer()->get(InitializerContainer::class); |
||
119 | } |
||
120 | $this->initializer->initialize($this); |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * @return Di |
||
125 | */ |
||
126 | public function getDi() |
||
127 | { |
||
128 | return $this->di; |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * @param Di $di |
||
133 | */ |
||
134 | public function setDi($di) |
||
135 | { |
||
136 | $this->di = $di; |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * @return WebDriver |
||
141 | */ |
||
142 | public function getWebdriver() |
||
143 | { |
||
144 | if (!$this->webdriver instanceof WebDriver) { |
||
145 | $this->webdriver = $this->get(WebDriver::class); |
||
146 | } |
||
147 | return $this->webdriver; |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * @param WebDriver $webdriver |
||
152 | */ |
||
153 | public function setWebdriver(WebDriver $webdriver) |
||
154 | { |
||
155 | $this->webdriver = $webdriver; |
||
156 | } |
||
157 | |||
158 | public function getInitializer() |
||
159 | { |
||
160 | return $this->initializer; |
||
161 | } |
||
162 | |||
163 | |||
164 | public function __construct($name = null, array $data = [], $dataName = null, Initializer $initializer = null) |
||
0 ignored issues
–
show
|
|||
165 | { |
||
166 | // Init at the earliest possible convenience. |
||
167 | self::getMasterListener(); |
||
168 | parent::__construct($name, $data, $dataName); |
||
169 | } |
||
170 | |||
171 | public function setUseErrorHandlerFromAnnotation() { |
||
172 | /* |
||
173 | * This odd little function is here because the first place where you can reliably add a listener without |
||
174 | * having to make a phpunit.xml or program argument change AND the result object is available AND there is |
||
175 | * no incompatibility with PHPUnit 5. |
||
176 | */ |
||
177 | $result = $this->getTestResultObject(); |
||
178 | self::getMasterListener()->bindToResult($result); |
||
179 | return parent::setUseErrorHandlerFromAnnotation(); |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * @return MasterListener |
||
184 | */ |
||
185 | |||
186 | public static function getMasterListener() |
||
187 | { |
||
188 | if (!self::$masterListener instanceof MasterListenerInterface) { |
||
189 | if (interface_exists('PHPUnit_Framework_Test')) { |
||
190 | self::$masterListener = new \Magium\Util\Phpunit5\MasterListener(); |
||
0 ignored issues
–
show
It seems like
new \Magium\Util\Phpunit5\MasterListener() of type object<Magium\Util\Phpunit5\MasterListener> is incompatible with the declared type object<Magium\Util\Phpunit\MasterListener> of property $masterListener .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
191 | } else { |
||
192 | self::$masterListener = new MasterListener(); |
||
193 | } |
||
194 | } |
||
195 | return self::$masterListener; |
||
0 ignored issues
–
show
The expression
self::$masterListener; of type Magium\Util\Phpunit5\Mas...\Phpunit\MasterListener adds the type Magium\Util\Phpunit5\MasterListener to the return on line 195 which is incompatible with the return type documented by Magium\AbstractTestCase::getMasterListener of type Magium\Util\Phpunit\MasterListener .
![]() |
|||
196 | } |
||
197 | |||
198 | protected function tearDown() |
||
199 | { |
||
200 | foreach ($this->postCallbacks as $callback) { |
||
201 | if (is_callable($callback)) { |
||
202 | call_user_func($callback); |
||
203 | } |
||
204 | } |
||
205 | parent::tearDown(); |
||
206 | if ($this->webdriver instanceof WebDriver) { |
||
207 | try { |
||
208 | $this->webdriver->close(); |
||
209 | } catch (\Exception $e) { |
||
210 | // All closed |
||
211 | } |
||
212 | |||
213 | $this->webdriver->quit(); |
||
214 | $this->webdriver = null; |
||
215 | } |
||
216 | } |
||
217 | |||
218 | |||
219 | public function filterWebDriverAction($by) |
||
220 | { |
||
221 | switch ($by) { |
||
222 | case WebDriver::BY_XPATH: |
||
223 | return 'xpath'; |
||
224 | case WebDriver::BY_CSS_SELECTOR: |
||
225 | return 'css_selector'; |
||
226 | case WebDriver::BY_ID: |
||
227 | return 'id'; |
||
228 | default: |
||
229 | return $by; |
||
230 | } |
||
231 | } |
||
232 | |||
233 | public function assertElementClickable($selector, $by = WebDriver::BY_ID) |
||
234 | { |
||
235 | $this->elementAssertion($selector, $by, Clickable::ASSERTION); |
||
236 | } |
||
237 | |||
238 | |||
239 | public function assertElementNotClickable($selector, $by = WebDriver::BY_ID) |
||
240 | { |
||
241 | $this->elementAssertion($selector, $by, NotClickable::ASSERTION); |
||
242 | |||
243 | } |
||
244 | |||
245 | public static function addBaseNamespace($namespace) |
||
246 | { |
||
247 | if (!in_array($namespace, self::$baseNamespaces)) { |
||
248 | self::$baseNamespaces[] = trim($namespace, '\\'); |
||
249 | } |
||
250 | } |
||
251 | |||
252 | public static function resolveClass( $class, $prefix = null) |
||
253 | { |
||
254 | $origClass = $class; |
||
255 | if ($prefix !== null) { |
||
256 | $class = "{$prefix}\\{$class}"; |
||
257 | } |
||
258 | foreach (self::$baseNamespaces as $namespace) { |
||
259 | if (strpos($class, $namespace) === 0) { |
||
260 | // We have a fully qualified class name |
||
261 | return $class; |
||
262 | } |
||
263 | } |
||
264 | |||
265 | foreach (self::$baseNamespaces as $namespace) { |
||
266 | $fqClass = $namespace . '\\' . $class; |
||
267 | try { |
||
268 | if (class_exists($fqClass)) { |
||
269 | return $fqClass; |
||
270 | } |
||
271 | } catch (\Exception $e) { |
||
272 | /* |
||
273 | * Nothing to see here |
||
274 | * http://www.reactiongifs.us/wp-content/uploads/2015/04/nothing_to_see_here_naked_gun.gif |
||
275 | * |
||
276 | * This is necessary because, in Magento, when developer mode is turned on, Magento will throw an |
||
277 | * exception if the autoloader can't find a file. |
||
278 | */ |
||
279 | } |
||
280 | } |
||
281 | return $origClass; |
||
282 | } |
||
283 | |||
284 | public function setTypePreference($type, $preference) |
||
285 | { |
||
286 | $type = self::resolveClass($type); |
||
287 | $preference = self::resolveClass($preference); |
||
288 | $this->di->instanceManager()->unsetTypePreferences($type); |
||
289 | $this->di->instanceManager()->setTypePreference($type, [$preference]); |
||
290 | |||
291 | } |
||
292 | |||
293 | protected function normalizeClassRequest($class) |
||
294 | { |
||
295 | return str_replace('/', '\\', $class); |
||
296 | } |
||
297 | |||
298 | public function addPostTestCallback($callback) |
||
299 | { |
||
300 | if (!is_callable($callback)) { |
||
301 | throw new InvalidConfigurationException('Callback is not callable'); |
||
302 | } |
||
303 | $this->postCallbacks[] = $callback; |
||
304 | } |
||
305 | |||
306 | /** |
||
307 | |||
308 | * @param string $theme |
||
309 | * @return \Magium\Themes\ThemeConfigurationInterface |
||
310 | */ |
||
311 | |||
312 | public function getTheme($theme = null) |
||
313 | { |
||
314 | if ($theme === null) { |
||
315 | return $this->get($this->baseThemeClass); |
||
316 | } |
||
317 | $theme = self::resolveClass($theme, 'Themes'); |
||
318 | return $this->get($theme); |
||
319 | } |
||
320 | |||
321 | /** |
||
322 | * |
||
323 | * @param string $action |
||
324 | * @return mixed |
||
325 | */ |
||
326 | |||
327 | public function getAction($action) |
||
328 | { |
||
329 | $action = self::resolveClass($action, 'Actions'); |
||
330 | |||
331 | return $this->get($action); |
||
332 | } |
||
333 | |||
334 | |||
335 | /** |
||
336 | * @param string $name |
||
337 | * @return \Magium\Identities\NameInterface |
||
338 | */ |
||
339 | |||
340 | public function getIdentity($name = 'Customer') |
||
341 | { |
||
342 | $name = self::resolveClass($name, 'Identities'); |
||
343 | |||
344 | return $this->get($name); |
||
345 | } |
||
346 | |||
347 | /** |
||
348 | * |
||
349 | * @param string $navigator |
||
350 | * @return \Magium\Navigators\NavigatorInterface |
||
351 | */ |
||
352 | |||
353 | public function getNavigator($navigator = 'BaseMenu') |
||
354 | { |
||
355 | $navigator = self::resolveClass($navigator, 'Navigators'); |
||
356 | |||
357 | return $this->get($navigator); |
||
358 | } |
||
359 | |||
360 | public function getAssertion($assertion) |
||
361 | { |
||
362 | $assertion = self::resolveClass($assertion, 'Assertions'); |
||
363 | |||
364 | return $this->get($assertion); |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * |
||
369 | * @param string $extractor |
||
370 | * @return \Magium\Extractors\AbstractExtractor |
||
371 | */ |
||
372 | |||
373 | public function getExtractor($extractor) |
||
374 | { |
||
375 | $extractor = self::resolveClass($extractor, 'Extractors'); |
||
376 | |||
377 | return $this->get($extractor); |
||
378 | } |
||
379 | |||
380 | /** |
||
381 | * Sleep the specified amount of time. |
||
382 | * |
||
383 | * Options: 1s (1 second), 1ms (1 millisecond), 1us (1 microsecond), 1ns (1 nanosecond) |
||
384 | * |
||
385 | * @param $time |
||
386 | */ |
||
387 | |||
388 | public function sleep($time) |
||
389 | { |
||
390 | $length = (int)$time; |
||
391 | |||
392 | if (strpos($time, 'ms') !== false) { |
||
393 | usleep($length * 1000); |
||
394 | } else if (strpos($time, 'us') !== false) { |
||
395 | usleep($length); |
||
396 | } else if (strpos($time, 'ns') !== false) { |
||
397 | time_nanosleep(0, $length); |
||
398 | } else { |
||
399 | sleep($length); |
||
400 | } |
||
401 | } |
||
402 | |||
403 | |||
404 | public function commandOpen($url) |
||
405 | { |
||
406 | $this->get(Open::class)->open($url); |
||
407 | } |
||
408 | |||
409 | |||
410 | /** |
||
411 | * @return LoggerInterface |
||
412 | */ |
||
413 | |||
414 | public function getLogger() |
||
415 | { |
||
416 | return $this->get(LoggerInterface::class); |
||
417 | } |
||
418 | |||
419 | public function get($class) |
||
420 | { |
||
421 | $class = $this->normalizeClassRequest($class); |
||
422 | $preferredClass = $this->di->instanceManager()->getTypePreferences($class); |
||
423 | if (is_array($preferredClass) && count($preferredClass) > 0) { |
||
424 | $class = array_shift($preferredClass); |
||
425 | } |
||
426 | return $this->di->get($class); |
||
427 | } |
||
428 | |||
429 | public static function isPHPUnit5() |
||
430 | { |
||
431 | return class_exists('PHPUnit_Framework_TestSuite'); |
||
432 | } |
||
433 | |||
434 | public function assertElementExists($selector, $by = 'byId') |
||
435 | { |
||
436 | $this->elementAssertion($selector, $by, Exists::ASSERTION); |
||
437 | } |
||
438 | |||
439 | public function assertTitleEquals($title) |
||
440 | { |
||
441 | $webTitle = $this->webdriver->getTitle(); |
||
442 | self::assertEquals($title, $webTitle); |
||
443 | } |
||
444 | |||
445 | |||
446 | public function assertTitleContains($title) |
||
447 | { |
||
448 | $webTitle = $this->webdriver->getTitle(); |
||
449 | self::assertContains($title, $webTitle); |
||
450 | } |
||
451 | |||
452 | |||
453 | public function assertNotTitleEquals($title) |
||
454 | { |
||
455 | $webTitle = $this->webdriver->getTitle(); |
||
456 | self::assertNotEquals($title, $webTitle); |
||
457 | } |
||
458 | |||
459 | |||
460 | public function assertNotTitleContains($title) |
||
461 | { |
||
462 | $webTitle = $this->webdriver->getTitle(); |
||
463 | self::assertNotContains($title, $webTitle); |
||
464 | } |
||
465 | |||
466 | public function assertURLEquals($url) |
||
467 | { |
||
468 | $webUrl = $this->webdriver->getCurrentURL(); |
||
469 | self::assertEquals($url, $webUrl); |
||
470 | } |
||
471 | |||
472 | public function assertURLContains($url) |
||
473 | { |
||
474 | $webUrl = $this->webdriver->getCurrentURL(); |
||
475 | self::assertContains($url, $webUrl); |
||
476 | } |
||
477 | |||
478 | |||
479 | public function assertURLNotEquals($url) |
||
480 | { |
||
481 | $webUrl = $this->webdriver->getCurrentURL(); |
||
482 | self::assertNotEquals($url, $webUrl); |
||
483 | } |
||
484 | |||
485 | public function assertURLNotContains($url) |
||
486 | { |
||
487 | $webUrl = $this->webdriver->getCurrentURL(); |
||
488 | self::assertNotContains($url, $webUrl); |
||
489 | } |
||
490 | |||
491 | protected function elementAssertion($selector, $by, $name) |
||
492 | { |
||
493 | $executor = $this->getAssertion(LoggingAssertionExecutor::ASSERTION); |
||
494 | $assertion = $this->getAssertion($name); |
||
495 | $assertion->setSelector($selector)->setBy($by); |
||
496 | $executor->execute($assertion); |
||
497 | } |
||
498 | |||
499 | public function assertElementDisplayed($selector, $by = 'byId') |
||
500 | { |
||
501 | $this->elementAssertion($selector, $by, Displayed::ASSERTION); |
||
502 | } |
||
503 | |||
504 | public function assertElementNotDisplayed($selector, $by = 'byId') |
||
505 | { |
||
506 | $this->elementAssertion($selector, $by, NotDisplayed::ASSERTION); |
||
507 | } |
||
508 | |||
509 | public function assertElementNotExists($selector, $by = 'byId') |
||
510 | { |
||
511 | $this->elementAssertion($selector, $by, NotExists::ASSERTION); |
||
512 | } |
||
513 | |||
514 | /** |
||
515 | * @return LoggingAssertionExecutor |
||
516 | */ |
||
517 | |||
518 | public function getAssertionLogger() |
||
519 | { |
||
520 | return $this->getAssertion(LoggingAssertionExecutor::ASSERTION); |
||
521 | } |
||
522 | |||
523 | public function switchThemeConfiguration($fullyQualifiedClassName) |
||
524 | { |
||
525 | |||
526 | $reflection = new \ReflectionClass($fullyQualifiedClassName); |
||
527 | |||
528 | if ($reflection->implementsInterface('Magium\Themes\ThemeConfigurationInterface')) { |
||
529 | $this->baseThemeClass = $fullyQualifiedClassName; |
||
530 | $this->di->instanceManager()->unsetTypePreferences('Magium\Themes\ThemeConfigurationInterface'); |
||
531 | $this->di->instanceManager()->setTypePreference('Magium\Themes\ThemeConfigurationInterface', [$fullyQualifiedClassName]); |
||
532 | |||
533 | if ($reflection->implementsInterface('Magium\Themes\BaseThemeInterface')) { |
||
534 | $this->di->instanceManager()->unsetTypePreferences('Magium\Themes\BaseThemeInterface'); |
||
535 | $this->di->instanceManager()->setTypePreference('Magium\Themes\BaseThemeInterface', [$fullyQualifiedClassName]); |
||
536 | } |
||
537 | $theme = $this->getTheme(); |
||
538 | if ($theme instanceof BaseThemeInterface) { |
||
539 | $theme->configure($this); |
||
540 | } |
||
541 | } else { |
||
542 | throw new InvalidConfigurationException('The theme configuration implement Magium\Themes\ThemeConfigurationInterface'); |
||
543 | } |
||
544 | $this->getLogger()->addCharacteristic(LoggerInterface::CHARACTERISTIC_THEME, $fullyQualifiedClassName); |
||
545 | } |
||
546 | |||
547 | public static function assertWebDriverElement($element) |
||
548 | { |
||
549 | self::assertInstanceOf('Facebook\WebDriver\WebDriverElement', $element); |
||
550 | } |
||
551 | |||
552 | View Code Duplication | public function assertElementHasText($node, $text) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
553 | { |
||
554 | try { |
||
555 | $element = $this->byXpath(sprintf('//%s[contains(., "%s")]', $node, addslashes($text))); |
||
556 | self::assertWebDriverElement($element); |
||
557 | } catch (\Exception $e) { |
||
558 | $this->fail('The body did not contain the text: ' . $text); |
||
559 | } |
||
560 | } |
||
561 | |||
562 | View Code Duplication | public function assertPageHasText($text) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
563 | { |
||
564 | try { |
||
565 | $element = $this->webdriver->byXpath(sprintf('//body[contains(., "%s")]', $text)); |
||
566 | // If the element is not found then an exception will be thrown |
||
567 | self::assertWebDriverElement($element); |
||
568 | } catch (\Exception $e) { |
||
569 | $this->fail('The body did not contain the text: ' . $text); |
||
570 | } |
||
571 | } |
||
572 | |||
573 | public function assertPageNotHasText($text) |
||
574 | { |
||
575 | try { |
||
576 | $this->webdriver->byXpath(sprintf('//body[contains(., "%s")]', $text)); |
||
577 | $this->fail('The page contains the words: ' . $text); |
||
578 | } catch (NoSuchElementException $e) { |
||
579 | // Exception thrown is a success |
||
580 | self::assertInstanceOf(NoSuchElementException::class, $e); |
||
581 | } |
||
582 | } |
||
583 | |||
584 | /** |
||
585 | * @param $xpath |
||
586 | * @return \Facebook\WebDriver\Remote\RemoteWebElement |
||
587 | */ |
||
588 | |||
589 | public function byXpath($xpath) |
||
590 | { |
||
591 | return $this->webdriver->byXpath($xpath); |
||
592 | } |
||
593 | |||
594 | /** |
||
595 | * @param $id |
||
596 | * @return \Facebook\WebDriver\Remote\RemoteWebElement |
||
597 | */ |
||
598 | |||
599 | public function byId($id) |
||
600 | { |
||
601 | return $this->webdriver->byId($id); |
||
602 | } |
||
603 | |||
604 | /** |
||
605 | * @param $selector |
||
606 | * @return \Facebook\WebDriver\Remote\RemoteWebElement |
||
607 | */ |
||
608 | |||
609 | public function byCssSelector($selector) |
||
610 | { |
||
611 | return $this->webdriver->byCssSelector($selector); |
||
612 | } |
||
613 | |||
614 | protected function getElementByTextXpath($xpathTemplate, $text, $specificNodeType = null, $parentElementSelector = null) |
||
615 | { |
||
616 | |||
617 | if ($parentElementSelector !== null) { |
||
618 | $xpathTemplate = $parentElementSelector . $xpathTemplate; |
||
619 | } |
||
620 | if ($specificNodeType !== null) { |
||
621 | return $this->byXpath(sprintf($xpathTemplate, $specificNodeType, $this->getTranslator()->translatePlaceholders($text))); |
||
622 | } |
||
623 | |||
624 | foreach ($this->textElementNodeSearch as $nodeName) { |
||
625 | $xpath = sprintf($xpathTemplate, $nodeName, $this->getTranslator()->translatePlaceholders($text)); |
||
626 | if ($this->webdriver->elementExists($xpath, WebDriver::BY_XPATH)) { |
||
627 | return $this->webdriver->byXpath($xpath); |
||
628 | } |
||
629 | } |
||
630 | // This is here for consistency with the other by* methods |
||
631 | WebDriverException::throwException(7, 'Could not find element with text: ' . $this->getTranslator()->translatePlaceholders($text), []); |
||
632 | } |
||
633 | |||
634 | /** |
||
635 | * @param string $text |
||
636 | * @param string $specificNodeType |
||
637 | * @param string $parentElementSelector |
||
638 | * @return \Facebook\WebDriver\Remote\RemoteWebElement |
||
639 | */ |
||
640 | public function byText($text, $specificNodeType = null, $parentElementSelector = null) |
||
641 | { |
||
642 | $xpathTemplate = '//%s[concat(" ",normalize-space(.)," ") = " %s "]'; |
||
643 | return $this->getElementByTextXpath($xpathTemplate, $text, $specificNodeType, $parentElementSelector); |
||
644 | } |
||
645 | |||
646 | |||
647 | /** |
||
648 | * @param string $text |
||
649 | * @param string $specificNodeType |
||
650 | * @param string $parentElementSelector |
||
651 | * @return \Facebook\WebDriver\Remote\RemoteWebElement |
||
652 | */ |
||
653 | public function byContainsText($text, $specificNodeType = null, $parentElementSelector = null) |
||
654 | { |
||
655 | $xpathTemplate = '//%s[contains(., "%s")]'; |
||
656 | return $this->getElementByTextXpath($xpathTemplate, $text, $specificNodeType, $parentElementSelector); |
||
657 | } |
||
658 | |||
659 | /** |
||
660 | * @return \Magium\Util\Translator\Translator |
||
661 | */ |
||
662 | |||
663 | public function getTranslator() |
||
664 | { |
||
665 | return $this->get('Magium\Util\Translator\Translator'); |
||
666 | } |
||
667 | |||
668 | public function addTranslationCsvFile($file, $locale) |
||
669 | { |
||
670 | $this->getTranslator()->addTranslationCsvFile($file, $locale); |
||
671 | } |
||
672 | } |
||
673 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.