comparison vendor/behat/mink/src/WebAssert.php @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children 5311817fb629
comparison
equal deleted inserted replaced
-1:000000000000 0:c75dbcec494b
1 <?php
2
3 /*
4 * This file is part of the Mink package.
5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11 namespace Behat\Mink;
12
13 use Behat\Mink\Element\Element;
14 use Behat\Mink\Element\ElementInterface;
15 use Behat\Mink\Element\NodeElement;
16 use Behat\Mink\Element\TraversableElement;
17 use Behat\Mink\Exception\ElementNotFoundException;
18 use Behat\Mink\Exception\ExpectationException;
19 use Behat\Mink\Exception\ResponseTextException;
20 use Behat\Mink\Exception\ElementHtmlException;
21 use Behat\Mink\Exception\ElementTextException;
22
23 /**
24 * Mink web assertions tool.
25 *
26 * @author Konstantin Kudryashov <ever.zet@gmail.com>
27 */
28 class WebAssert
29 {
30 protected $session;
31
32 /**
33 * Initializes assertion engine.
34 *
35 * @param Session $session
36 */
37 public function __construct(Session $session)
38 {
39 $this->session = $session;
40 }
41
42 /**
43 * Checks that current session address is equals to provided one.
44 *
45 * @param string $page
46 *
47 * @throws ExpectationException
48 */
49 public function addressEquals($page)
50 {
51 $expected = $this->cleanUrl($page);
52 $actual = $this->getCurrentUrlPath();
53
54 $this->assert($actual === $expected, sprintf('Current page is "%s", but "%s" expected.', $actual, $expected));
55 }
56
57 /**
58 * Checks that current session address is not equals to provided one.
59 *
60 * @param string $page
61 *
62 * @throws ExpectationException
63 */
64 public function addressNotEquals($page)
65 {
66 $expected = $this->cleanUrl($page);
67 $actual = $this->getCurrentUrlPath();
68
69 $this->assert($actual !== $expected, sprintf('Current page is "%s", but should not be.', $actual));
70 }
71
72 /**
73 * Checks that current session address matches regex.
74 *
75 * @param string $regex
76 *
77 * @throws ExpectationException
78 */
79 public function addressMatches($regex)
80 {
81 $actual = $this->getCurrentUrlPath();
82 $message = sprintf('Current page "%s" does not match the regex "%s".', $actual, $regex);
83
84 $this->assert((bool) preg_match($regex, $actual), $message);
85 }
86
87 /**
88 * Checks that specified cookie exists and its value equals to a given one.
89 *
90 * @param string $name cookie name
91 * @param string $value cookie value
92 *
93 * @throws ExpectationException
94 */
95 public function cookieEquals($name, $value)
96 {
97 $this->cookieExists($name);
98
99 $actualValue = $this->session->getCookie($name);
100 $message = sprintf('Cookie "%s" value is "%s", but should be "%s".', $name, $actualValue, $value);
101
102 $this->assert($actualValue == $value, $message);
103 }
104
105 /**
106 * Checks that specified cookie exists.
107 *
108 * @param string $name cookie name
109 *
110 * @throws ExpectationException
111 */
112 public function cookieExists($name)
113 {
114 $message = sprintf('Cookie "%s" is not set, but should be.', $name);
115 $this->assert($this->session->getCookie($name) !== null, $message);
116 }
117
118 /**
119 * Checks that current response code equals to provided one.
120 *
121 * @param int $code
122 *
123 * @throws ExpectationException
124 */
125 public function statusCodeEquals($code)
126 {
127 $actual = $this->session->getStatusCode();
128 $message = sprintf('Current response status code is %d, but %d expected.', $actual, $code);
129
130 $this->assert(intval($code) === intval($actual), $message);
131 }
132
133 /**
134 * Checks that current response code not equals to provided one.
135 *
136 * @param int $code
137 *
138 * @throws ExpectationException
139 */
140 public function statusCodeNotEquals($code)
141 {
142 $actual = $this->session->getStatusCode();
143 $message = sprintf('Current response status code is %d, but should not be.', $actual);
144
145 $this->assert(intval($code) !== intval($actual), $message);
146 }
147
148 /**
149 * Checks that current response header equals value.
150 *
151 * @param string $name
152 * @param string $value
153 *
154 * @throws ExpectationException
155 */
156 public function responseHeaderEquals($name, $value)
157 {
158 $actual = $this->session->getResponseHeader($name);
159 $message = sprintf('Current response header "%s" is "%s", but "%s" expected.', $name, $actual, $value);
160
161 $this->assert($value === $actual, $message);
162 }
163
164 /**
165 * Checks that current response header does not equal value.
166 *
167 * @param string $name
168 * @param string $value
169 *
170 * @throws ExpectationException
171 */
172 public function responseHeaderNotEquals($name, $value)
173 {
174 $actual = $this->session->getResponseHeader($name);
175 $message = sprintf('Current response header "%s" is "%s", but should not be.', $name, $actual, $value);
176
177 $this->assert($value !== $actual, $message);
178 }
179
180 /**
181 * Checks that current response header contains value.
182 *
183 * @param string $name
184 * @param string $value
185 *
186 * @throws ExpectationException
187 */
188 public function responseHeaderContains($name, $value)
189 {
190 $actual = $this->session->getResponseHeader($name);
191 $message = sprintf('The text "%s" was not found anywhere in the "%s" response header.', $value, $name);
192
193 $this->assert(false !== stripos($actual, $value), $message);
194 }
195
196 /**
197 * Checks that current response header does not contain value.
198 *
199 * @param string $name
200 * @param string $value
201 *
202 * @throws ExpectationException
203 */
204 public function responseHeaderNotContains($name, $value)
205 {
206 $actual = $this->session->getResponseHeader($name);
207 $message = sprintf('The text "%s" was found in the "%s" response header, but it should not.', $value, $name);
208
209 $this->assert(false === stripos($actual, $value), $message);
210 }
211
212 /**
213 * Checks that current response header matches regex.
214 *
215 * @param string $name
216 * @param string $regex
217 *
218 * @throws ExpectationException
219 */
220 public function responseHeaderMatches($name, $regex)
221 {
222 $actual = $this->session->getResponseHeader($name);
223 $message = sprintf('The pattern "%s" was not found anywhere in the "%s" response header.', $regex, $name);
224
225 $this->assert((bool) preg_match($regex, $actual), $message);
226 }
227
228 /**
229 * Checks that current response header does not match regex.
230 *
231 * @param string $name
232 * @param string $regex
233 *
234 * @throws ExpectationException
235 */
236 public function responseHeaderNotMatches($name, $regex)
237 {
238 $actual = $this->session->getResponseHeader($name);
239 $message = sprintf(
240 'The pattern "%s" was found in the text of the "%s" response header, but it should not.',
241 $regex,
242 $name
243 );
244
245 $this->assert(!preg_match($regex, $actual), $message);
246 }
247
248 /**
249 * Checks that current page contains text.
250 *
251 * @param string $text
252 *
253 * @throws ResponseTextException
254 */
255 public function pageTextContains($text)
256 {
257 $actual = $this->session->getPage()->getText();
258 $actual = preg_replace('/\s+/u', ' ', $actual);
259 $regex = '/'.preg_quote($text, '/').'/ui';
260 $message = sprintf('The text "%s" was not found anywhere in the text of the current page.', $text);
261
262 $this->assertResponseText((bool) preg_match($regex, $actual), $message);
263 }
264
265 /**
266 * Checks that current page does not contains text.
267 *
268 * @param string $text
269 *
270 * @throws ResponseTextException
271 */
272 public function pageTextNotContains($text)
273 {
274 $actual = $this->session->getPage()->getText();
275 $actual = preg_replace('/\s+/u', ' ', $actual);
276 $regex = '/'.preg_quote($text, '/').'/ui';
277 $message = sprintf('The text "%s" appears in the text of this page, but it should not.', $text);
278
279 $this->assertResponseText(!preg_match($regex, $actual), $message);
280 }
281
282 /**
283 * Checks that current page text matches regex.
284 *
285 * @param string $regex
286 *
287 * @throws ResponseTextException
288 */
289 public function pageTextMatches($regex)
290 {
291 $actual = $this->session->getPage()->getText();
292 $message = sprintf('The pattern %s was not found anywhere in the text of the current page.', $regex);
293
294 $this->assertResponseText((bool) preg_match($regex, $actual), $message);
295 }
296
297 /**
298 * Checks that current page text does not matches regex.
299 *
300 * @param string $regex
301 *
302 * @throws ResponseTextException
303 */
304 public function pageTextNotMatches($regex)
305 {
306 $actual = $this->session->getPage()->getText();
307 $message = sprintf('The pattern %s was found in the text of the current page, but it should not.', $regex);
308
309 $this->assertResponseText(!preg_match($regex, $actual), $message);
310 }
311
312 /**
313 * Checks that page HTML (response content) contains text.
314 *
315 * @param string $text
316 *
317 * @throws ExpectationException
318 */
319 public function responseContains($text)
320 {
321 $actual = $this->session->getPage()->getContent();
322 $regex = '/'.preg_quote($text, '/').'/ui';
323 $message = sprintf('The string "%s" was not found anywhere in the HTML response of the current page.', $text);
324
325 $this->assert((bool) preg_match($regex, $actual), $message);
326 }
327
328 /**
329 * Checks that page HTML (response content) does not contains text.
330 *
331 * @param string $text
332 *
333 * @throws ExpectationException
334 */
335 public function responseNotContains($text)
336 {
337 $actual = $this->session->getPage()->getContent();
338 $regex = '/'.preg_quote($text, '/').'/ui';
339 $message = sprintf('The string "%s" appears in the HTML response of this page, but it should not.', $text);
340
341 $this->assert(!preg_match($regex, $actual), $message);
342 }
343
344 /**
345 * Checks that page HTML (response content) matches regex.
346 *
347 * @param string $regex
348 *
349 * @throws ExpectationException
350 */
351 public function responseMatches($regex)
352 {
353 $actual = $this->session->getPage()->getContent();
354 $message = sprintf('The pattern %s was not found anywhere in the HTML response of the page.', $regex);
355
356 $this->assert((bool) preg_match($regex, $actual), $message);
357 }
358
359 /**
360 * Checks that page HTML (response content) does not matches regex.
361 *
362 * @param $regex
363 *
364 * @throws ExpectationException
365 */
366 public function responseNotMatches($regex)
367 {
368 $actual = $this->session->getPage()->getContent();
369 $message = sprintf('The pattern %s was found in the HTML response of the page, but it should not.', $regex);
370
371 $this->assert(!preg_match($regex, $actual), $message);
372 }
373
374 /**
375 * Checks that there is specified number of specific elements on the page.
376 *
377 * @param string $selectorType element selector type (css, xpath)
378 * @param string|array $selector element selector
379 * @param int $count expected count
380 * @param ElementInterface $container document to check against
381 *
382 * @throws ExpectationException
383 */
384 public function elementsCount($selectorType, $selector, $count, ElementInterface $container = null)
385 {
386 $container = $container ?: $this->session->getPage();
387 $nodes = $container->findAll($selectorType, $selector);
388
389 $message = sprintf(
390 '%d %s found on the page, but should be %d.',
391 count($nodes),
392 $this->getMatchingElementRepresentation($selectorType, $selector, count($nodes) !== 1),
393 $count
394 );
395
396 $this->assert(intval($count) === count($nodes), $message);
397 }
398
399 /**
400 * Checks that specific element exists on the current page.
401 *
402 * @param string $selectorType element selector type (css, xpath)
403 * @param string|array $selector element selector
404 * @param ElementInterface $container document to check against
405 *
406 * @return NodeElement
407 *
408 * @throws ElementNotFoundException
409 */
410 public function elementExists($selectorType, $selector, ElementInterface $container = null)
411 {
412 $container = $container ?: $this->session->getPage();
413 $node = $container->find($selectorType, $selector);
414
415 if (null === $node) {
416 if (is_array($selector)) {
417 $selector = implode(' ', $selector);
418 }
419
420 throw new ElementNotFoundException($this->session->getDriver(), 'element', $selectorType, $selector);
421 }
422
423 return $node;
424 }
425
426 /**
427 * Checks that specific element does not exists on the current page.
428 *
429 * @param string $selectorType element selector type (css, xpath)
430 * @param string|array $selector element selector
431 * @param ElementInterface $container document to check against
432 *
433 * @throws ExpectationException
434 */
435 public function elementNotExists($selectorType, $selector, ElementInterface $container = null)
436 {
437 $container = $container ?: $this->session->getPage();
438 $node = $container->find($selectorType, $selector);
439
440 $message = sprintf(
441 'An %s appears on this page, but it should not.',
442 $this->getMatchingElementRepresentation($selectorType, $selector)
443 );
444
445 $this->assert(null === $node, $message);
446 }
447
448 /**
449 * Checks that specific element contains text.
450 *
451 * @param string $selectorType element selector type (css, xpath)
452 * @param string|array $selector element selector
453 * @param string $text expected text
454 *
455 * @throws ElementTextException
456 */
457 public function elementTextContains($selectorType, $selector, $text)
458 {
459 $element = $this->elementExists($selectorType, $selector);
460 $actual = $element->getText();
461 $regex = '/'.preg_quote($text, '/').'/ui';
462
463 $message = sprintf(
464 'The text "%s" was not found in the text of the %s.',
465 $text,
466 $this->getMatchingElementRepresentation($selectorType, $selector)
467 );
468
469 $this->assertElementText((bool) preg_match($regex, $actual), $message, $element);
470 }
471
472 /**
473 * Checks that specific element does not contains text.
474 *
475 * @param string $selectorType element selector type (css, xpath)
476 * @param string|array $selector element selector
477 * @param string $text expected text
478 *
479 * @throws ElementTextException
480 */
481 public function elementTextNotContains($selectorType, $selector, $text)
482 {
483 $element = $this->elementExists($selectorType, $selector);
484 $actual = $element->getText();
485 $regex = '/'.preg_quote($text, '/').'/ui';
486
487 $message = sprintf(
488 'The text "%s" appears in the text of the %s, but it should not.',
489 $text,
490 $this->getMatchingElementRepresentation($selectorType, $selector)
491 );
492
493 $this->assertElementText(!preg_match($regex, $actual), $message, $element);
494 }
495
496 /**
497 * Checks that specific element contains HTML.
498 *
499 * @param string $selectorType element selector type (css, xpath)
500 * @param string|array $selector element selector
501 * @param string $html expected text
502 *
503 * @throws ElementHtmlException
504 */
505 public function elementContains($selectorType, $selector, $html)
506 {
507 $element = $this->elementExists($selectorType, $selector);
508 $actual = $element->getHtml();
509 $regex = '/'.preg_quote($html, '/').'/ui';
510
511 $message = sprintf(
512 'The string "%s" was not found in the HTML of the %s.',
513 $html,
514 $this->getMatchingElementRepresentation($selectorType, $selector)
515 );
516
517 $this->assertElement((bool) preg_match($regex, $actual), $message, $element);
518 }
519
520 /**
521 * Checks that specific element does not contains HTML.
522 *
523 * @param string $selectorType element selector type (css, xpath)
524 * @param string|array $selector element selector
525 * @param string $html expected text
526 *
527 * @throws ElementHtmlException
528 */
529 public function elementNotContains($selectorType, $selector, $html)
530 {
531 $element = $this->elementExists($selectorType, $selector);
532 $actual = $element->getHtml();
533 $regex = '/'.preg_quote($html, '/').'/ui';
534
535 $message = sprintf(
536 'The string "%s" appears in the HTML of the %s, but it should not.',
537 $html,
538 $this->getMatchingElementRepresentation($selectorType, $selector)
539 );
540
541 $this->assertElement(!preg_match($regex, $actual), $message, $element);
542 }
543
544 /**
545 * Checks that an attribute exists in an element.
546 *
547 * @param string $selectorType
548 * @param string|array $selector
549 * @param string $attribute
550 *
551 * @return NodeElement
552 *
553 * @throws ElementHtmlException
554 */
555 public function elementAttributeExists($selectorType, $selector, $attribute)
556 {
557 $element = $this->elementExists($selectorType, $selector);
558
559 $message = sprintf(
560 'The attribute "%s" was not found in the %s.',
561 $attribute,
562 $this->getMatchingElementRepresentation($selectorType, $selector)
563 );
564
565 $this->assertElement($element->hasAttribute($attribute), $message, $element);
566
567 return $element;
568 }
569
570 /**
571 * Checks that an attribute of a specific elements contains text.
572 *
573 * @param string $selectorType
574 * @param string|array $selector
575 * @param string $attribute
576 * @param string $text
577 *
578 * @throws ElementHtmlException
579 */
580 public function elementAttributeContains($selectorType, $selector, $attribute, $text)
581 {
582 $element = $this->elementAttributeExists($selectorType, $selector, $attribute);
583 $actual = $element->getAttribute($attribute);
584 $regex = '/'.preg_quote($text, '/').'/ui';
585
586 $message = sprintf(
587 'The text "%s" was not found in the attribute "%s" of the %s.',
588 $text,
589 $attribute,
590 $this->getMatchingElementRepresentation($selectorType, $selector)
591 );
592
593 $this->assertElement((bool) preg_match($regex, $actual), $message, $element);
594 }
595
596 /**
597 * Checks that an attribute of a specific elements does not contain text.
598 *
599 * @param string $selectorType
600 * @param string|array $selector
601 * @param string $attribute
602 * @param string $text
603 *
604 * @throws ElementHtmlException
605 */
606 public function elementAttributeNotContains($selectorType, $selector, $attribute, $text)
607 {
608 $element = $this->elementAttributeExists($selectorType, $selector, $attribute);
609 $actual = $element->getAttribute($attribute);
610 $regex = '/'.preg_quote($text, '/').'/ui';
611
612 $message = sprintf(
613 'The text "%s" was found in the attribute "%s" of the %s.',
614 $text,
615 $attribute,
616 $this->getMatchingElementRepresentation($selectorType, $selector)
617 );
618
619 $this->assertElement(!preg_match($regex, $actual), $message, $element);
620 }
621
622 /**
623 * Checks that specific field exists on the current page.
624 *
625 * @param string $field field id|name|label|value
626 * @param TraversableElement $container document to check against
627 *
628 * @return NodeElement
629 *
630 * @throws ElementNotFoundException
631 */
632 public function fieldExists($field, TraversableElement $container = null)
633 {
634 $container = $container ?: $this->session->getPage();
635 $node = $container->findField($field);
636
637 if (null === $node) {
638 throw new ElementNotFoundException($this->session->getDriver(), 'form field', 'id|name|label|value', $field);
639 }
640
641 return $node;
642 }
643
644 /**
645 * Checks that specific field does not exists on the current page.
646 *
647 * @param string $field field id|name|label|value
648 * @param TraversableElement $container document to check against
649 *
650 * @throws ExpectationException
651 */
652 public function fieldNotExists($field, TraversableElement $container = null)
653 {
654 $container = $container ?: $this->session->getPage();
655 $node = $container->findField($field);
656
657 $this->assert(null === $node, sprintf('A field "%s" appears on this page, but it should not.', $field));
658 }
659
660 /**
661 * Checks that specific field have provided value.
662 *
663 * @param string $field field id|name|label|value
664 * @param string $value field value
665 * @param TraversableElement $container document to check against
666 *
667 * @throws ExpectationException
668 */
669 public function fieldValueEquals($field, $value, TraversableElement $container = null)
670 {
671 $node = $this->fieldExists($field, $container);
672 $actual = $node->getValue();
673 $regex = '/^'.preg_quote($value, '/').'$/ui';
674
675 $message = sprintf('The field "%s" value is "%s", but "%s" expected.', $field, $actual, $value);
676
677 $this->assert((bool) preg_match($regex, $actual), $message);
678 }
679
680 /**
681 * Checks that specific field have provided value.
682 *
683 * @param string $field field id|name|label|value
684 * @param string $value field value
685 * @param TraversableElement $container document to check against
686 *
687 * @throws ExpectationException
688 */
689 public function fieldValueNotEquals($field, $value, TraversableElement $container = null)
690 {
691 $node = $this->fieldExists($field, $container);
692 $actual = $node->getValue();
693 $regex = '/^'.preg_quote($value, '/').'$/ui';
694
695 $message = sprintf('The field "%s" value is "%s", but it should not be.', $field, $actual);
696
697 $this->assert(!preg_match($regex, $actual), $message);
698 }
699
700 /**
701 * Checks that specific checkbox is checked.
702 *
703 * @param string $field field id|name|label|value
704 * @param TraversableElement $container document to check against
705 *
706 * @throws ExpectationException
707 */
708 public function checkboxChecked($field, TraversableElement $container = null)
709 {
710 $node = $this->fieldExists($field, $container);
711
712 $this->assert($node->isChecked(), sprintf('Checkbox "%s" is not checked, but it should be.', $field));
713 }
714
715 /**
716 * Checks that specific checkbox is unchecked.
717 *
718 * @param string $field field id|name|label|value
719 * @param TraversableElement $container document to check against
720 *
721 * @throws ExpectationException
722 */
723 public function checkboxNotChecked($field, TraversableElement $container = null)
724 {
725 $node = $this->fieldExists($field, $container);
726
727 $this->assert(!$node->isChecked(), sprintf('Checkbox "%s" is checked, but it should not be.', $field));
728 }
729
730 /**
731 * Gets current url of the page.
732 *
733 * @return string
734 */
735 protected function getCurrentUrlPath()
736 {
737 return $this->cleanUrl($this->session->getCurrentUrl());
738 }
739
740 /**
741 * Trims scriptname from the URL.
742 *
743 * @param string $url
744 *
745 * @return string
746 */
747 protected function cleanUrl($url)
748 {
749 $parts = parse_url($url);
750 $fragment = empty($parts['fragment']) ? '' : '#'.$parts['fragment'];
751 $path = empty($parts['path']) ? '/' : $parts['path'];
752
753 return preg_replace('/^\/[^\.\/]+\.php\//', '/', $path).$fragment;
754 }
755
756 /**
757 * Asserts a condition.
758 *
759 * @param bool $condition
760 * @param string $message Failure message
761 *
762 * @throws ExpectationException when the condition is not fulfilled
763 */
764 private function assert($condition, $message)
765 {
766 if ($condition) {
767 return;
768 }
769
770 throw new ExpectationException($message, $this->session->getDriver());
771 }
772
773 /**
774 * Asserts a condition involving the response text.
775 *
776 * @param bool $condition
777 * @param string $message Failure message
778 *
779 * @throws ResponseTextException when the condition is not fulfilled
780 */
781 private function assertResponseText($condition, $message)
782 {
783 if ($condition) {
784 return;
785 }
786
787 throw new ResponseTextException($message, $this->session->getDriver());
788 }
789
790 /**
791 * Asserts a condition on an element.
792 *
793 * @param bool $condition
794 * @param string $message Failure message
795 * @param Element $element
796 *
797 * @throws ElementHtmlException when the condition is not fulfilled
798 */
799 private function assertElement($condition, $message, Element $element)
800 {
801 if ($condition) {
802 return;
803 }
804
805 throw new ElementHtmlException($message, $this->session->getDriver(), $element);
806 }
807
808 /**
809 * Asserts a condition involving the text of an element.
810 *
811 * @param bool $condition
812 * @param string $message Failure message
813 * @param Element $element
814 *
815 * @throws ElementTextException when the condition is not fulfilled
816 */
817 private function assertElementText($condition, $message, Element $element)
818 {
819 if ($condition) {
820 return;
821 }
822
823 throw new ElementTextException($message, $this->session->getDriver(), $element);
824 }
825
826 /**
827 * @param string $selectorType
828 * @param string|array $selector
829 * @param bool $plural
830 *
831 * @return string
832 */
833 private function getMatchingElementRepresentation($selectorType, $selector, $plural = false)
834 {
835 $pluralization = $plural ? 's' : '';
836
837 if (in_array($selectorType, array('named', 'named_exact', 'named_partial'))
838 && is_array($selector) && 2 === count($selector)
839 ) {
840 return sprintf('%s%s matching locator "%s"', $selector[0], $pluralization, $selector[1]);
841 }
842
843 if (is_array($selector)) {
844 $selector = implode(' ', $selector);
845 }
846
847 return sprintf('element%s matching %s "%s"', $pluralization, $selectorType, $selector);
848 }
849 }