Security update for permissions_by_term
[yaffs-website] / vendor / drupal / drupal-extension / src / Drupal / DrupalExtension / Context / MinkContext.php
1 <?php
2
3 namespace Drupal\DrupalExtension\Context;
4
5 use Behat\Behat\Context\TranslatableContext;
6 use Behat\Mink\Exception\UnsupportedDriverActionException;
7 use Behat\MinkExtension\Context\MinkContext as MinkExtension;
8
9 /**
10  * Extensions to the Mink Extension.
11  */
12 class MinkContext extends MinkExtension implements TranslatableContext {
13
14   /**
15    * Returns list of definition translation resources paths.
16    *
17    * @return array
18    */
19   public static function getTranslationResources() {
20     return self::getMinkTranslationResources() + glob(__DIR__ . '/../../../../i18n/*.xliff');
21   }
22
23   /**
24    * Return a region from the current page.
25    *
26    * @throws \Exception
27    *   If region cannot be found.
28    *
29    * @param string $region
30    *   The machine name of the region to return.
31    *
32    * @return \Behat\Mink\Element\NodeElement
33    */
34   public function getRegion($region) {
35     $session = $this->getSession();
36     $regionObj = $session->getPage()->find('region', $region);
37     if (!$regionObj) {
38       throw new \Exception(sprintf('No region "%s" found on the page %s.', $region, $session->getCurrentUrl()));
39     }
40
41     return $regionObj;
42   }
43
44   /**
45    * Visit a given path, and additionally check for HTTP response code 200.
46    *
47    * @Given I am at :path
48    * @When I visit :path
49    *
50    * @throws UnsupportedDriverActionException
51    */
52   public function assertAtPath($path) {
53     $this->getSession()->visit($this->locatePath($path));
54
55     // If available, add extra validation that this is a 200 response.
56     try {
57       $this->getSession()->getStatusCode();
58       $this->assertHttpResponse('200');
59     }
60     catch (UnsupportedDriverActionException $e) {
61       // Simply continue on, as this driver doesn't support HTTP response codes.
62     }
63   }
64
65   /**
66    * @When I click :link
67    */
68   public function assertClick($link) {
69     // Use the Mink Extenstion step definition.
70     $this->clickLink($link);
71   }
72
73   /**
74    * @Given for :field I enter :value
75    * @Given I enter :value for :field
76    */
77   public function assertEnterField($field, $value) {
78     // Use the Mink Extenstion step definition.
79     $this->fillField($field, $value);
80   }
81
82   /**
83    * For javascript enabled scenarios, always wait for AJAX before clicking.
84    *
85    * @BeforeStep
86    */
87   public function beforeJavascriptStep($event) {
88     /** @var \Behat\Behat\Hook\Scope\BeforeStepScope $event */
89     $tags = $event->getFeature()->getTags();
90     if (!in_array('javascript', $tags)) {
91       return;
92     }
93     $text = $event->getStep()->getText();
94     if (preg_match('/(follow|press|click|submit)/i', $text)) {
95       $this->iWaitForAjaxToFinish();
96     }
97   }
98
99   /**
100    * For javascript enabled scenarios, always wait for AJAX after clicking.
101    *
102    * @AfterStep
103    */
104   public function afterJavascriptStep($event) {
105     /** @var \Behat\Behat\Hook\Scope\BeforeStepScope $event */
106     $tags = $event->getFeature()->getTags();
107     if (!in_array('javascript', $tags)) {
108       return;
109     }
110     $text = $event->getStep()->getText();
111     if (preg_match('/(follow|press|click|submit)/i', $text)) {
112       $this->iWaitForAjaxToFinish();
113     }
114   }
115
116   /**
117    * Wait for AJAX to finish.
118    *
119    * @see \Drupal\FunctionalJavascriptTests\JSWebAssert::assertWaitOnAjaxRequest()
120    *
121    * @Given I wait for AJAX to finish
122    */
123   public function iWaitForAjaxToFinish() {
124     $condition = <<<JS
125     (function() {
126       function isAjaxing(instance) {
127         return instance && instance.ajaxing === true;
128       }
129       return (
130         // Assert no AJAX request is running (via jQuery or Drupal) and no
131         // animation is running.
132         (typeof jQuery === 'undefined' || (jQuery.active === 0 && jQuery(':animated').length === 0)) &&
133         (typeof Drupal === 'undefined' || typeof Drupal.ajax === 'undefined' || !Drupal.ajax.instances.some(isAjaxing))
134       );
135     }());
136 JS;
137     $result = $this->getSession()->wait(5000, $condition);
138     if (!$result) {
139       throw new \RuntimeException('Unable to complete AJAX request.');
140     }
141   }
142   /**
143    * Presses button with specified id|name|title|alt|value.
144    *
145    * @When I press the :button button
146    */
147   public function pressButton($button) {
148     // Wait for any open autocomplete boxes to finish closing.  They block
149     // form-submission if they are still open.
150     // Use a step 'I press the "Esc" key in the "LABEL" field' to close
151     // autocomplete suggestion boxes with Mink.  "Click" events on the
152     // autocomplete suggestion do not work.
153     try {
154       $this->getSession()->wait(1000, 'typeof(jQuery)=="undefined" || jQuery("#autocomplete").length === 0');
155     }
156     catch (UnsupportedDriverActionException $e) {
157       // The jQuery probably failed because the driver does not support
158       // javascript.  That is okay, because if the driver does not support
159       // javascript, it does not support autocomplete boxes either.
160     }
161
162     // Use the Mink Extension step definition.
163     return parent::pressButton($button);
164   }
165
166   /**
167    * @Given I press the :char key in the :field field
168    *
169    * @param mixed $char could be either char ('b') or char-code (98)
170    * @throws \Exception
171    */
172   public function pressKey($char, $field) {
173     static $keys = array(
174       'backspace' => 8,
175       'tab' => 9,
176       'enter' => 13,
177       'shift' => 16,
178       'ctrl' =>  17,
179       'alt' => 18,
180       'pause' => 19,
181       'break' => 19,
182       'escape' =>  27,
183       'esc' =>  27,
184       'end' => 35,
185       'home' =>  36,
186       'left' => 37,
187       'up' => 38,
188       'right' =>39,
189       'down' => 40,
190       'insert' =>  45,
191       'delete' =>  46,
192       'pageup' => 33,
193       'pagedown' => 34,
194       'capslock' => 20,
195     );
196
197     if (is_string($char)) {
198       if (strlen($char) < 1) {
199         throw new \Exception('FeatureContext->keyPress($char, $field) was invoked but the $char parameter was empty.');
200       }
201       elseif (strlen($char) > 1) {
202         // Support for all variations, e.g. ESC, Esc, page up, pageup.
203         $char = $keys[strtolower(str_replace(' ', '', $char))];
204       }
205     }
206
207     $element = $this->getSession()->getPage()->findField($field);
208     if (!$element) {
209       throw new \Exception("Field '$field' not found");
210     }
211
212     $driver = $this->getSession()->getDriver();
213     // $driver->keyPress($element->getXpath(), $char);
214     // This alternative to Driver->keyPress() handles cases that depend on
215     // javascript which binds to key down/up events directly, such as Drupal's
216     // autocomplete.js.
217     $driver->keyDown($element->getXpath(), $char);
218     $driver->keyUp($element->getXpath(), $char);
219   }
220
221   /**
222    * @Then I should see the link :link
223    */
224   public function assertLinkVisible($link) {
225     $element = $this->getSession()->getPage();
226     $result = $element->findLink($link);
227
228     try {
229       if ($result && !$result->isVisible()) {
230         throw new \Exception(sprintf("No link to '%s' on the page %s", $link, $this->getSession()->getCurrentUrl()));
231       }
232     }
233     catch (UnsupportedDriverActionException $e) {
234       // We catch the UnsupportedDriverActionException exception in case
235       // this step is not being performed by a driver that supports javascript.
236       // All other exceptions are valid.
237     }
238
239     if (empty($result)) {
240       throw new \Exception(sprintf("No link to '%s' on the page %s", $link, $this->getSession()->getCurrentUrl()));
241     }
242   }
243
244   /**
245    * Links are not loaded on the page.
246    *
247    * @Then I should not see the link :link
248    */
249   public function assertNotLinkVisible($link) {
250     $element = $this->getSession()->getPage();
251     $result = $element->findLink($link);
252
253     try {
254       if ($result && $result->isVisible()) {
255         throw new \Exception(sprintf("The link '%s' was present on the page %s and was not supposed to be", $link, $this->getSession()->getCurrentUrl()));
256       }
257     }
258     catch (UnsupportedDriverActionException $e) {
259       // We catch the UnsupportedDriverActionException exception in case
260       // this step is not being performed by a driver that supports javascript.
261       // All other exceptions are valid.
262     }
263
264     if ($result) {
265       throw new \Exception(sprintf("The link '%s' was present on the page %s and was not supposed to be", $link, $this->getSession()->getCurrentUrl()));
266     }
267   }
268
269   /**
270    * Links are loaded but not visually visible (e.g they have display: hidden applied).
271    *
272    * @Then I should not visibly see the link :link
273    */
274   public function assertNotLinkVisuallyVisible($link) {
275     $element = $this->getSession()->getPage();
276     $result = $element->findLink($link);
277
278     try {
279       if ($result && $result->isVisible()) {
280         throw new \Exception(sprintf("The link '%s' was visually visible on the page %s and was not supposed to be", $link, $this->getSession()->getCurrentUrl()));
281       }
282     }
283     catch (UnsupportedDriverActionException $e) {
284       // We catch the UnsupportedDriverActionException exception in case
285       // this step is not being performed by a driver that supports javascript.
286       // All other exceptions are valid.
287     }
288
289     if (!$result) {
290       throw new \Exception(sprintf("The link '%s' was not loaded on the page %s at all", $link, $this->getSession()->getCurrentUrl()));
291     }
292
293   }
294
295   /**
296    * @Then I (should )see the heading :heading
297    */
298   public function assertHeading($heading) {
299     $element = $this->getSession()->getPage();
300     foreach (array('h1', 'h2', 'h3', 'h4', 'h5', 'h6') as $tag) {
301       $results = $element->findAll('css', $tag);
302       foreach ($results as $result) {
303         if ($result->getText() == $heading) {
304           return;
305         }
306       }
307     }
308     throw new \Exception(sprintf("The text '%s' was not found in any heading on the page %s", $heading, $this->getSession()->getCurrentUrl()));
309   }
310
311   /**
312    * @Then I (should )not see the heading :heading
313    */
314   public function assertNotHeading($heading) {
315     $element = $this->getSession()->getPage();
316     foreach (array('h1', 'h2', 'h3', 'h4', 'h5', 'h6') as $tag) {
317       $results = $element->findAll('css', $tag);
318       foreach ($results as $result) {
319         if ($result->getText() == $heading) {
320           throw new \Exception(sprintf("The text '%s' was found in a heading on the page %s", $heading, $this->getSession()->getCurrentUrl()));
321         }
322       }
323     }
324   }
325
326   /**
327    * @Then I (should ) see the button :button
328    * @Then I (should ) see the :button button
329    */
330   public function assertButton($button) {
331     $element = $this->getSession()->getPage();
332     $buttonObj = $element->findButton($button);
333     if (empty($buttonObj)) {
334       throw new \Exception(sprintf("The button '%s' was not found on the page %s", $button, $this->getSession()->getCurrentUrl()));
335     }
336   }
337
338   /**
339    * @Then I should not see the button :button
340    * @Then I should not see the :button button
341    */
342   public function assertNotButton($button) {
343     $element = $this->getSession()->getPage();
344     $buttonObj = $element->findButton($button);
345     if (!empty($buttonObj)) {
346       throw new \Exception(sprintf("The button '%s' was found on the page %s", $button, $this->getSession()->getCurrentUrl()));
347     }
348   }
349
350   /**
351    * @When I follow/click :link in the :region( region)
352    *
353    * @throws \Exception
354    *   If region or link within it cannot be found.
355    */
356   public function assertRegionLinkFollow($link, $region) {
357     $regionObj = $this->getRegion($region);
358
359     // Find the link within the region
360     $linkObj = $regionObj->findLink($link);
361     if (empty($linkObj)) {
362       throw new \Exception(sprintf('The link "%s" was not found in the region "%s" on the page %s', $link, $region, $this->getSession()->getCurrentUrl()));
363     }
364     $linkObj->click();
365   }
366
367   /**
368    * Checks, if a button with id|name|title|alt|value exists or not and pressess the same
369    *
370    * @Given I press :button in the :region( region)
371    *
372    * @param $button
373    *   string The id|name|title|alt|value of the button to be pressed
374    * @param $region
375    *   string The region in which the button should be pressed
376    *
377    * @throws \Exception
378    *   If region or button within it cannot be found.
379    */
380   public function assertRegionPressButton($button, $region) {
381     $regionObj = $this->getRegion($region);
382
383     $buttonObj = $regionObj->findButton($button);
384     if (empty($buttonObj)) {
385       throw new \Exception(sprintf("The button '%s' was not found in the region '%s' on the page %s", $button, $region, $this->getSession()->getCurrentUrl()));
386     }
387     $regionObj->pressButton($button);
388   }
389
390   /**
391    * Fills in a form field with id|name|title|alt|value in the specified region.
392    *
393    * @Given I fill in :value for :field in the :region( region)
394    * @Given I fill in :field with :value in the :region( region)
395    *
396    * @throws \Exception
397    *   If region cannot be found.
398    */
399   public function regionFillField($field, $value, $region) {
400     $field = $this->fixStepArgument($field);
401     $value = $this->fixStepArgument($value);
402     $regionObj = $this->getRegion($region);
403     $regionObj->fillField($field, $value);
404   }
405
406   /**
407    * Find a heading in a specific region.
408    *
409    * @Then I should see the heading :heading in the :region( region)
410    * @Then I should see the :heading heading in the :region( region)
411    *
412    * @throws \Exception
413    *   If region or header within it cannot be found.
414    */
415   public function assertRegionHeading($heading, $region) {
416     $regionObj = $this->getRegion($region);
417
418     foreach (array('h1', 'h2', 'h3', 'h4', 'h5', 'h6') as $tag) {
419       $elements = $regionObj->findAll('css', $tag);
420       if (!empty($elements)) {
421         foreach ($elements as $element) {
422           if (trim($element->getText()) === $heading) {
423             return;
424           }
425         }
426       }
427     }
428
429     throw new \Exception(sprintf('The heading "%s" was not found in the "%s" region on the page %s', $heading, $region, $this->getSession()->getCurrentUrl()));
430   }
431
432   /**
433    * @Then I should see the link :link in the :region( region)
434    *
435    * @throws \Exception
436    *   If region or link within it cannot be found.
437    */
438   public function assertLinkRegion($link, $region) {
439     $regionObj = $this->getRegion($region);
440
441     $result = $regionObj->findLink($link);
442     if (empty($result)) {
443       throw new \Exception(sprintf('No link to "%s" in the "%s" region on the page %s', $link, $region, $this->getSession()->getCurrentUrl()));
444     }
445   }
446
447   /**
448    * @Then I should not see the link :link in the :region( region)
449    *
450    * @throws \Exception
451    *   If region or link within it cannot be found.
452    */
453   public function assertNotLinkRegion($link, $region) {
454     $regionObj = $this->getRegion($region);
455
456     $result = $regionObj->findLink($link);
457     if (!empty($result)) {
458       throw new \Exception(sprintf('Link to "%s" in the "%s" region on the page %s', $link, $region, $this->getSession()->getCurrentUrl()));
459     }
460   }
461
462   /**
463    * @Then I should see( the text) :text in the :region( region)
464    *
465    * @throws \Exception
466    *   If region or text within it cannot be found.
467    */
468   public function assertRegionText($text, $region) {
469     $regionObj = $this->getRegion($region);
470
471     // Find the text within the region
472     $regionText = $regionObj->getText();
473     if (strpos($regionText, $text) === FALSE) {
474       throw new \Exception(sprintf("The text '%s' was not found in the region '%s' on the page %s", $text, $region, $this->getSession()->getCurrentUrl()));
475     }
476   }
477
478   /**
479    * @Then I should not see( the text) :text in the :region( region)
480    *
481    * @throws \Exception
482    *   If region or text within it cannot be found.
483    */
484   public function assertNotRegionText($text, $region) {
485     $regionObj = $this->getRegion($region);
486
487     // Find the text within the region.
488     $regionText = $regionObj->getText();
489     if (strpos($regionText, $text) !== FALSE) {
490       throw new \Exception(sprintf('The text "%s" was found in the region "%s" on the page %s', $text, $region, $this->getSession()->getCurrentUrl()));
491     }
492   }
493
494   /**
495    * @Then I (should )see the text :text
496    */
497   public function assertTextVisible($text) {
498     // Use the Mink Extension step definition.
499     $this->assertPageContainsText($text);
500   }
501
502   /**
503    * @Then I should not see the text :text
504    */
505   public function assertNotTextVisible($text) {
506     // Use the Mink Extension step definition.
507     $this->assertPageNotContainsText($text);
508   }
509
510   /**
511    * @Then I should get a :code HTTP response
512    */
513   public function assertHttpResponse($code) {
514     // Use the Mink Extension step definition.
515     $this->assertResponseStatus($code);
516   }
517
518   /**
519    * @Then I should not get a :code HTTP response
520    */
521   public function assertNotHttpResponse($code) {
522     // Use the Mink Extension step definition.
523     $this->assertResponseStatusIsNot($code);
524   }
525
526   /**
527    * @Given I check the box :checkbox
528    */
529   public function assertCheckBox($checkbox) {
530     // Use the Mink Extension step definition.
531     $this->checkOption($checkbox);
532   }
533
534   /**
535    * @Given I uncheck the box :checkbox
536    */
537   public function assertUncheckBox($checkbox) {
538     // Use the Mink Extension step definition.
539     $this->uncheckOption($checkbox);
540   }
541
542   /**
543    * @When I select the radio button :label with the id :id
544    * @When I select the radio button :label
545    *
546    * @TODO convert to mink extension.
547    */
548   public function assertSelectRadioById($label, $id = '') {
549     $element = $this->getSession()->getPage();
550     $radiobutton = $id ? $element->findById($id) : $element->find('named', array('radio', $this->getSession()->getSelectorsHandler()->xpathLiteral($label)));
551     if ($radiobutton === NULL) {
552       throw new \Exception(sprintf('The radio button with "%s" was not found on the page %s', $id ? $id : $label, $this->getSession()->getCurrentUrl()));
553     }
554     $value = $radiobutton->getAttribute('value');
555     $labelonpage = $radiobutton->getParent()->getText();
556     if ($label != $labelonpage) {
557       throw new \Exception(sprintf("Button with id '%s' has label '%s' instead of '%s' on the page %s", $id, $labelonpage, $label, $this->getSession()->getCurrentUrl()));
558     }
559     $radiobutton->selectOption($value, FALSE);
560   }
561
562   /**
563    * @} End of defgroup "mink extensions"
564    */
565
566
567 }