Commit | Line | Data |
---|---|---|
786ea937 DM |
1 | <?php |
2 | // This file is part of Moodle - http://moodle.org/ | |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License | |
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
17 | /** | |
18 | * General use steps definitions. | |
19 | * | |
20 | * @package core | |
21 | * @category test | |
22 | * @copyright 2012 David Monllaó | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | ||
26 | // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. | |
27 | ||
28 | require_once(__DIR__ . '/../../behat/behat_base.php'); | |
29 | ||
ca4f33a7 | 30 | use Behat\Mink\Exception\ExpectationException as ExpectationException, |
d0a9a29b | 31 | Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException, |
bda1dea4 | 32 | Behat\Mink\Exception\DriverException as DriverException, |
39ec8285 DM |
33 | WebDriver\Exception\NoSuchElement as NoSuchElement, |
34 | WebDriver\Exception\StaleElementReference as StaleElementReference; | |
786ea937 DM |
35 | |
36 | /** | |
37 | * Cross component steps definitions. | |
38 | * | |
39 | * Basic web application definitions from MinkExtension and | |
40 | * BehatchExtension. Definitions modified according to our needs | |
41 | * when necessary and including only the ones we need to avoid | |
42 | * overlapping and confusion. | |
43 | * | |
44 | * @package core | |
45 | * @category test | |
46 | * @copyright 2012 David Monllaó | |
47 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
48 | */ | |
49 | class behat_general extends behat_base { | |
50 | ||
51 | /** | |
52 | * Opens Moodle homepage. | |
53 | * | |
786ea937 DM |
54 | * @Given /^I am on homepage$/ |
55 | */ | |
56 | public function i_am_on_homepage() { | |
40923977 | 57 | $this->getSession()->visit($this->locate_path('/')); |
786ea937 DM |
58 | } |
59 | ||
18c84063 DM |
60 | /** |
61 | * Reloads the current page. | |
62 | * | |
63 | * @Given /^I reload the page$/ | |
64 | */ | |
65 | public function reload() { | |
66 | $this->getSession()->reload(); | |
67 | } | |
68 | ||
d0a9a29b DM |
69 | /** |
70 | * Follows the page redirection. Use this step after any action that shows a message and waits for a redirection | |
71 | * | |
72 | * @Given /^I wait to be redirected$/ | |
73 | */ | |
74 | public function i_wait_to_be_redirected() { | |
75 | ||
76 | // Xpath and processes based on core_renderer::redirect_message(), core_renderer::$metarefreshtag and | |
77 | // moodle_page::$periodicrefreshdelay possible values. | |
78 | if (!$metarefresh = $this->getSession()->getPage()->find('xpath', "//head/descendant::meta[@http-equiv='refresh']")) { | |
79 | // We don't fail the scenario if no redirection with message is found to avoid race condition false failures. | |
80 | return false; | |
81 | } | |
82 | ||
bda1dea4 DM |
83 | // Wrapped in try & catch in case the redirection has already been executed. |
84 | try { | |
85 | $content = $metarefresh->getAttribute('content'); | |
86 | } catch (NoSuchElement $e) { | |
87 | return false; | |
39ec8285 DM |
88 | } catch (StaleElementReference $e) { |
89 | return false; | |
bda1dea4 DM |
90 | } |
91 | ||
92 | // Getting the refresh time and the url if present. | |
d0a9a29b DM |
93 | if (strstr($content, 'url') != false) { |
94 | ||
bda1dea4 | 95 | list($waittime, $url) = explode(';', $content); |
d0a9a29b DM |
96 | |
97 | // Cleaning the URL value. | |
98 | $url = trim(substr($url, strpos($url, 'http'))); | |
99 | ||
100 | } else { | |
101 | // Just wait then. | |
102 | $waittime = $content; | |
103 | } | |
104 | ||
105 | ||
106 | // Wait until the URL change is executed. | |
107 | if ($this->running_javascript()) { | |
108 | $this->getSession()->wait($waittime * 1000, false); | |
109 | ||
110 | } else if (!empty($url)) { | |
111 | // We redirect directly as we can not wait for an automatic redirection. | |
112 | $this->getSession()->getDriver()->getClient()->request('get', $url); | |
113 | ||
114 | } else { | |
115 | // Reload the page if no URL was provided. | |
116 | $this->getSession()->getDriver()->reload(); | |
117 | } | |
118 | } | |
119 | ||
e5eff0b6 AA |
120 | /** |
121 | * Switches to the specified iframe. | |
122 | * | |
123 | * @Given /^I switch to "(?P<iframe_name_string>(?:[^"]|\\")*)" iframe$/ | |
124 | * @param string $iframename | |
125 | */ | |
126 | public function switch_to_iframe($iframename) { | |
127 | $this->getSession()->switchToIFrame($iframename); | |
128 | } | |
129 | ||
130 | /** | |
131 | * Switches to the main Moodle frame. | |
132 | * | |
133 | * @Given /^I switch to the main frame$/ | |
134 | */ | |
135 | public function switch_to_the_main_frame() { | |
136 | $this->getSession()->switchToIFrame(); | |
137 | } | |
138 | ||
1303eb29 DM |
139 | /** |
140 | * Switches to the specified window. Useful when interacting with popup windows. | |
141 | * | |
142 | * @Given /^I switch to "(?P<window_name_string>(?:[^"]|\\")*)" window$/ | |
143 | * @param string $windowname | |
144 | */ | |
145 | public function switch_to_window($windowname) { | |
146 | $this->getSession()->switchToWindow($windowname); | |
147 | } | |
148 | ||
149 | /** | |
150 | * Switches to the main Moodle window. Useful when you finish interacting with popup windows. | |
151 | * | |
152 | * @Given /^I switch to the main window$/ | |
153 | */ | |
154 | public function switch_to_the_main_window() { | |
155 | $this->getSession()->switchToWindow(); | |
156 | } | |
157 | ||
563514b1 | 158 | /** |
7daab401 | 159 | * Accepts the currently displayed alert dialog. This step does not work in all the browsers, consider it experimental. |
563514b1 DM |
160 | * @Given /^I accept the currently displayed dialog$/ |
161 | */ | |
162 | public function accept_currently_displayed_alert_dialog() { | |
163 | $this->getSession()->getDriver()->getWebDriverSession()->accept_alert(); | |
164 | } | |
165 | ||
786ea937 DM |
166 | /** |
167 | * Clicks link with specified id|title|alt|text. | |
168 | * | |
786ea937 | 169 | * @When /^I follow "(?P<link_string>(?:[^"]|\\")*)"$/ |
1f9ffbdb | 170 | * @throws ElementNotFoundException Thrown by behat_base::find |
40923977 | 171 | * @param string $link |
786ea937 DM |
172 | */ |
173 | public function click_link($link) { | |
1f9ffbdb DM |
174 | |
175 | $linknode = $this->find_link($link); | |
176 | $linknode->click(); | |
786ea937 DM |
177 | } |
178 | ||
179 | /** | |
180 | * Waits X seconds. Required after an action that requires data from an AJAX request. | |
181 | * | |
182 | * @Then /^I wait "(?P<seconds_number>\d+)" seconds$/ | |
183 | * @param int $seconds | |
184 | */ | |
185 | public function i_wait_seconds($seconds) { | |
d0a9a29b DM |
186 | |
187 | if (!$this->running_javascript()) { | |
188 | throw new DriverException('Waits are disabled in scenarios without Javascript support'); | |
189 | } | |
190 | ||
786ea937 DM |
191 | $this->getSession()->wait($seconds * 1000, false); |
192 | } | |
193 | ||
194 | /** | |
195 | * Waits until the page is completely loaded. This step is auto-executed after every step. | |
196 | * | |
197 | * @Given /^I wait until the page is ready$/ | |
198 | */ | |
199 | public function wait_until_the_page_is_ready() { | |
d0a9a29b DM |
200 | |
201 | if (!$this->running_javascript()) { | |
202 | throw new DriverException('Waits are disabled in scenarios without Javascript support'); | |
203 | } | |
204 | ||
786ea937 DM |
205 | $this->getSession()->wait(self::TIMEOUT, '(document.readyState === "complete")'); |
206 | } | |
207 | ||
208 | /** | |
40923977 | 209 | * Generic mouse over action. Mouse over a element of the specified type. |
786ea937 | 210 | * |
40923977 DM |
211 | * @When /^I hover "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)"$/ |
212 | * @param string $element Element we look for | |
213 | * @param string $selectortype The type of what we look for | |
786ea937 | 214 | */ |
40923977 | 215 | public function i_hover($element, $selectortype) { |
1f9ffbdb | 216 | |
40923977 DM |
217 | // Gets the node based on the requested selector type and locator. |
218 | $node = $this->get_selected_node($selectortype, $element); | |
786ea937 DM |
219 | $node->mouseOver(); |
220 | } | |
221 | ||
40923977 DM |
222 | /** |
223 | * Generic click action. Click on the element of the specified type. | |
224 | * | |
225 | * @When /^I click on "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)"$/ | |
226 | * @param string $element Element we look for | |
227 | * @param string $selectortype The type of what we look for | |
228 | */ | |
229 | public function i_click_on($element, $selectortype) { | |
230 | ||
231 | // Gets the node based on the requested selector type and locator. | |
232 | $node = $this->get_selected_node($selectortype, $element); | |
233 | $node->click(); | |
234 | } | |
235 | ||
072f67fc DM |
236 | /** |
237 | * Click on the element of the specified type which is located inside the second element. | |
238 | * | |
239 | * @When /^I click on "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)"$/ | |
240 | * @param string $element Element we look for | |
241 | * @param string $selectortype The type of what we look for | |
242 | * @param string $nodeelement Element we look in | |
243 | * @param string $nodeselectortype The type of selector where we look in | |
244 | */ | |
245 | public function i_click_on_in_the($element, $selectortype, $nodeelement, $nodeselectortype) { | |
246 | ||
247 | $node = $this->get_node_in_container($selectortype, $element, $nodeselectortype, $nodeelement); | |
248 | $node->click(); | |
249 | } | |
250 | ||
563514b1 | 251 | /** |
7daab401 | 252 | * Drags and drops the specified element to the specified container. This step does not work in all the browsers, consider it experimental. |
563514b1 DM |
253 | * |
254 | * The steps definitions calling this step as part of them should | |
255 | * manage the wait times by themselves as the times and when the | |
256 | * waits should be done depends on what is being dragged & dropper. | |
257 | * | |
258 | * @Given /^I drag "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector1_string>(?:[^"]|\\")*)" and I drop it in "(?P<container_element_string>(?:[^"]|\\")*)" "(?P<selector2_string>(?:[^"]|\\")*)"$/ | |
259 | * @param string $element | |
260 | * @param string $selectortype | |
261 | * @param string $containerelement | |
262 | * @param string $containerselectortype | |
263 | */ | |
264 | public function i_drag_and_i_drop_it_in($element, $selectortype, $containerelement, $containerselectortype) { | |
265 | ||
266 | list($sourceselector, $sourcelocator) = $this->transform_selector($selectortype, $element); | |
267 | $sourcexpath = $this->getSession()->getSelectorsHandler()->selectorToXpath($sourceselector, $sourcelocator); | |
268 | ||
269 | list($containerselector, $containerlocator) = $this->transform_selector($containerselectortype, $containerelement); | |
270 | $destinationxpath = $this->getSession()->getSelectorsHandler()->selectorToXpath($containerselector, $containerlocator); | |
271 | ||
272 | $this->getSession()->getDriver()->dragTo($sourcexpath, $destinationxpath); | |
273 | } | |
274 | ||
63950e4d DM |
275 | /** |
276 | * Checks, that the specified element is visible. Only available in tests using Javascript. | |
277 | * | |
278 | * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>(?:[^"]|\\")*)" should be visible$/ | |
279 | * @throws ElementNotFoundException | |
280 | * @throws ExpectationException | |
281 | * @throws DriverException | |
282 | * @param string $element | |
283 | * @param string $selectortype | |
284 | * @return void | |
285 | */ | |
286 | public function should_be_visible($element, $selectortype) { | |
287 | ||
288 | if (!$this->running_javascript()) { | |
289 | throw new DriverException('Visible checks are disabled in scenarios without Javascript support'); | |
290 | } | |
291 | ||
292 | $node = $this->get_selected_node($selectortype, $element); | |
293 | if (!$node->isVisible()) { | |
294 | throw new ExpectationException('"' . $element . '" "' . $selectortype . '" is not visible', $this->getSession()); | |
295 | } | |
296 | } | |
297 | ||
298 | /** | |
299 | * Checks, that the specified element is not visible. Only available in tests using Javascript. | |
300 | * | |
301 | * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>(?:[^"]|\\")*)" should not be visible$/ | |
302 | * @throws ElementNotFoundException | |
303 | * @throws ExpectationException | |
304 | * @param string $element | |
305 | * @param string $selectortype | |
306 | * @return void | |
307 | */ | |
308 | public function should_not_be_visible($element, $selectortype) { | |
309 | ||
310 | try { | |
311 | $this->should_be_visible($element, $selectortype); | |
312 | throw new ExpectationException('"' . $element . '" "' . $selectortype . '" is visible', $this->getSession()); | |
313 | } catch (ExpectationException $e) { | |
314 | // All as expected. | |
315 | } | |
316 | } | |
317 | ||
318 | /** | |
319 | * Checks, that the specified element is visible inside the specified container. Only available in tests using Javascript. | |
320 | * | |
321 | * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)" should be visible$/ | |
322 | * @throws ElementNotFoundException | |
323 | * @throws DriverException | |
324 | * @throws ExpectationException | |
325 | * @param string $element Element we look for | |
326 | * @param string $selectortype The type of what we look for | |
327 | * @param string $nodeelement Element we look in | |
328 | * @param string $nodeselectortype The type of selector where we look in | |
329 | */ | |
330 | public function in_the_should_be_visible($element, $selectortype, $nodeelement, $nodeselectortype) { | |
331 | ||
332 | if (!$this->running_javascript()) { | |
333 | throw new DriverException('Visible checks are disabled in scenarios without Javascript support'); | |
334 | } | |
335 | ||
336 | $node = $this->get_node_in_container($selectortype, $element, $nodeselectortype, $nodeelement); | |
337 | if (!$node->isVisible()) { | |
338 | throw new ExpectationException( | |
339 | '"' . $element . '" "' . $selectortype . '" in the "' . $nodeelement . '" "' . $nodeselectortype . '" is not visible', | |
340 | $this->getSession() | |
341 | ); | |
342 | } | |
343 | } | |
344 | ||
345 | /** | |
346 | * Checks, that the specified element is not visible inside the specified container. Only available in tests using Javascript. | |
347 | * | |
348 | * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)" should not be visible$/ | |
349 | * @throws ElementNotFoundException | |
350 | * @throws ExpectationException | |
351 | * @param string $element Element we look for | |
352 | * @param string $selectortype The type of what we look for | |
353 | * @param string $nodeelement Element we look in | |
354 | * @param string $nodeselectortype The type of selector where we look in | |
355 | */ | |
356 | public function in_the_should_not_be_visible($element, $selectortype, $nodeelement, $nodeselectortype) { | |
357 | ||
358 | try { | |
359 | $this->in_the_should_be_visible($element, $selectortype, $nodeelement, $nodeselectortype); | |
360 | throw new ExpectationException( | |
361 | '"' . $element . '" "' . $selectortype . '" in the "' . $nodeelement . '" "' . $nodeselectortype . '" is visible', | |
362 | $this->getSession() | |
363 | ); | |
364 | } catch (ExpectationException $e) { | |
365 | // All as expected. | |
366 | } | |
367 | } | |
368 | ||
786ea937 | 369 | /** |
e9af3ed3 | 370 | * Checks, that page contains specified text. It also checks if the text is visible when running Javascript tests. |
786ea937 | 371 | * |
786ea937 | 372 | * @Then /^I should see "(?P<text_string>(?:[^"]|\\")*)"$/ |
9a1f4922 | 373 | * @throws ExpectationException |
40923977 | 374 | * @param string $text |
786ea937 DM |
375 | */ |
376 | public function assert_page_contains_text($text) { | |
9a1f4922 | 377 | |
e9af3ed3 DM |
378 | // Looking for all the matching nodes without any other descendant matching the |
379 | // same xpath (we are using contains(., ....). | |
9a1f4922 | 380 | $xpathliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($text); |
e9af3ed3 DM |
381 | $xpath = "/descendant-or-self::*[contains(., $xpathliteral)]" . |
382 | "[count(descendant::*[contains(., $xpathliteral)]) = 0]"; | |
9a1f4922 DM |
383 | |
384 | // Wait until it finds the text, otherwise custom exception. | |
385 | try { | |
e9af3ed3 DM |
386 | $nodes = $this->find_all('xpath', $xpath); |
387 | ||
388 | // We also check for the element visibility when running JS tests. | |
389 | if ($this->running_javascript()) { | |
390 | foreach ($nodes as $node) { | |
391 | if ($node->isVisible()) { | |
392 | return; | |
393 | } | |
394 | } | |
395 | ||
396 | throw new ExpectationException("'{$text}' text was found but was not visible", $this->getSession()); | |
397 | } | |
398 | ||
9a1f4922 DM |
399 | } catch (ElementNotFoundException $e) { |
400 | throw new ExpectationException('"' . $text . '" text was not found in the page', $this->getSession()); | |
401 | } | |
786ea937 DM |
402 | } |
403 | ||
404 | /** | |
e9af3ed3 | 405 | * Checks, that page doesn't contain specified text. When running Javascript tests it also considers that texts may be hidden. |
786ea937 | 406 | * |
786ea937 | 407 | * @Then /^I should not see "(?P<text_string>(?:[^"]|\\")*)"$/ |
9a1f4922 | 408 | * @throws ExpectationException |
40923977 | 409 | * @param string $text |
786ea937 DM |
410 | */ |
411 | public function assert_page_not_contains_text($text) { | |
9a1f4922 | 412 | |
5458ab3e | 413 | // Delegating the process to assert_page_contains_text. |
9a1f4922 | 414 | try { |
5458ab3e DM |
415 | $this->assert_page_contains_text($text); |
416 | } catch (ExpectationException $e) { | |
417 | // It should not appear, so this is good. | |
418 | return; | |
9a1f4922 | 419 | } |
5458ab3e DM |
420 | |
421 | // If the page contains the text this is failing. | |
422 | throw new ExpectationException('"' . $text . '" text was found in the page', $this->getSession()); | |
786ea937 DM |
423 | } |
424 | ||
425 | /** | |
e9af3ed3 | 426 | * Checks, that the specified element contains the specified text. When running Javascript tests it also considers that texts may be hidden. |
786ea937 | 427 | * |
40923977 | 428 | * @Then /^I should see "(?P<text_string>(?:[^"]|\\")*)" in the "(?P<element_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)"$/ |
5458ab3e DM |
429 | * @throws ElementNotFoundException |
430 | * @throws ExpectationException | |
40923977 DM |
431 | * @param string $text |
432 | * @param string $element Element we look in. | |
433 | * @param string $selectortype The type of element where we are looking in. | |
786ea937 | 434 | */ |
40923977 DM |
435 | public function assert_element_contains_text($text, $element, $selectortype) { |
436 | ||
5458ab3e DM |
437 | // Getting the container where the text should be found. |
438 | $container = $this->get_selected_node($selectortype, $element); | |
439 | ||
e9af3ed3 DM |
440 | // Looking for all the matching nodes without any other descendant matching the |
441 | // same xpath (we are using contains(., ....). | |
5458ab3e | 442 | $xpathliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($text); |
e9af3ed3 DM |
443 | $xpath = "/descendant-or-self::*[contains(., $xpathliteral)]" . |
444 | "[count(descendant::*[contains(., $xpathliteral)]) = 0]"; | |
5458ab3e DM |
445 | |
446 | // Wait until it finds the text inside the container, otherwise custom exception. | |
447 | try { | |
e9af3ed3 DM |
448 | $nodes = $this->find_all('xpath', $xpath, false, $container); |
449 | ||
450 | // We also check for the element visibility when running JS tests. | |
451 | if ($this->running_javascript()) { | |
452 | foreach ($nodes as $node) { | |
453 | if ($node->isVisible()) { | |
454 | return; | |
455 | } | |
456 | } | |
457 | ||
458 | throw new ExpectationException("'{$text}' text was found in the {$element} element but was not visible", $this->getSession()); | |
459 | } | |
460 | ||
5458ab3e DM |
461 | } catch (ElementNotFoundException $e) { |
462 | throw new ExpectationException('"' . $text . '" text was not found in the ' . $element . ' element', $this->getSession()); | |
463 | } | |
464 | ||
786ea937 DM |
465 | } |
466 | ||
467 | /** | |
e9af3ed3 | 468 | * Checks, that the specified element does not contain the specified text. When running Javascript tests it also considers that texts may be hidden. |
786ea937 | 469 | * |
40923977 | 470 | * @Then /^I should not see "(?P<text_string>(?:[^"]|\\")*)" in the "(?P<element_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)"$/ |
5458ab3e DM |
471 | * @throws ElementNotFoundException |
472 | * @throws ExpectationException | |
40923977 DM |
473 | * @param string $text |
474 | * @param string $element Element we look in. | |
475 | * @param string $selectortype The type of element where we are looking in. | |
786ea937 | 476 | */ |
40923977 DM |
477 | public function assert_element_not_contains_text($text, $element, $selectortype) { |
478 | ||
5458ab3e DM |
479 | // Delegating the process to assert_element_contains_text. |
480 | try { | |
481 | $this->assert_element_contains_text($text, $element, $selectortype); | |
482 | } catch (ExpectationException $e) { | |
483 | // It should not appear, so this is good. | |
484 | // We only catch ExpectationException as ElementNotFoundException | |
485 | // will be thrown if the container does not exist. | |
486 | return; | |
487 | } | |
488 | ||
489 | // If the element contains the text this is failing. | |
490 | throw new ExpectationException('"' . $text . '" text was found in the ' . $element . ' element', $this->getSession()); | |
786ea937 DM |
491 | } |
492 | ||
60054942 DM |
493 | /** |
494 | * Checks, that the first specified element appears before the second one. | |
495 | * | |
496 | * @Given /^"(?P<preceding_element_string>(?:[^"]|\\")*)" "(?P<selector1_string>(?:[^"]|\\")*)" should appear before "(?P<following_element_string>(?:[^"]|\\")*)" "(?P<selector2_string>(?:[^"]|\\")*)"$/ | |
497 | * @throws ExpectationException | |
498 | * @param string $preelement The locator of the preceding element | |
499 | * @param string $preselectortype The locator of the preceding element | |
500 | * @param string $postelement The locator of the latest element | |
501 | * @param string $postselectortype The selector type of the latest element | |
502 | */ | |
503 | public function should_appear_before($preelement, $preselectortype, $postelement, $postselectortype) { | |
504 | ||
505 | // We allow postselectortype as a non-text based selector. | |
506 | list($preselector, $prelocator) = $this->transform_selector($preselectortype, $preelement); | |
507 | list($postselector, $postlocator) = $this->transform_selector($postselectortype, $postelement); | |
508 | ||
509 | $prexpath = $this->find($preselector, $prelocator)->getXpath(); | |
510 | $postxpath = $this->find($postselector, $postlocator)->getXpath(); | |
511 | ||
512 | // Using following xpath axe to find it. | |
513 | $msg = '"'.$preelement.'" "'.$preselectortype.'" does not appear before "'.$postelement.'" "'.$postselectortype.'"'; | |
514 | $xpath = $prexpath.'/following::*[contains(., '.$postxpath.')]'; | |
515 | if (!$this->getSession()->getDriver()->find($xpath)) { | |
516 | throw new ExpectationException($msg, $this->getSession()); | |
517 | } | |
518 | } | |
519 | ||
520 | /** | |
521 | * Checks, that the first specified element appears after the second one. | |
522 | * | |
523 | * @Given /^"(?P<following_element_string>(?:[^"]|\\")*)" "(?P<selector1_string>(?:[^"]|\\")*)" should appear after "(?P<preceding_element_string>(?:[^"]|\\")*)" "(?P<selector2_string>(?:[^"]|\\")*)"$/ | |
524 | * @throws ExpectationException | |
525 | * @param string $postelement The locator of the latest element | |
526 | * @param string $postselectortype The selector type of the latest element | |
527 | * @param string $preelement The locator of the preceding element | |
528 | * @param string $preselectortype The locator of the preceding element | |
529 | */ | |
530 | public function should_appear_after($postelement, $postselectortype, $preelement, $preselectortype) { | |
531 | ||
532 | // We allow postselectortype as a non-text based selector. | |
533 | list($postselector, $postlocator) = $this->transform_selector($postselectortype, $postelement); | |
534 | list($preselector, $prelocator) = $this->transform_selector($preselectortype, $preelement); | |
535 | ||
536 | $postxpath = $this->find($postselector, $postlocator)->getXpath(); | |
537 | $prexpath = $this->find($preselector, $prelocator)->getXpath(); | |
538 | ||
539 | // Using preceding xpath axe to find it. | |
540 | $msg = '"'.$postelement.'" "'.$postselectortype.'" does not appear after "'.$preelement.'" "'.$preselectortype.'"'; | |
541 | $xpath = $postxpath.'/preceding::*[contains(., '.$prexpath.')]'; | |
542 | if (!$this->getSession()->getDriver()->find($xpath)) { | |
543 | throw new ExpectationException($msg, $this->getSession()); | |
544 | } | |
545 | } | |
546 | ||
786ea937 | 547 | /** |
40923977 | 548 | * Checks, that element of specified type is disabled. |
786ea937 | 549 | * |
40923977 | 550 | * @Then /^the "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should be disabled$/ |
1f9ffbdb | 551 | * @throws ExpectationException Thrown by behat_base::find |
40923977 DM |
552 | * @param string $element Element we look in |
553 | * @param string $selectortype The type of element where we are looking in. | |
786ea937 | 554 | */ |
40923977 | 555 | public function the_element_should_be_disabled($element, $selectortype) { |
786ea937 | 556 | |
40923977 DM |
557 | // Transforming from steps definitions selector/locator format to Mink format and getting the NodeElement. |
558 | $node = $this->get_selected_node($selectortype, $element); | |
786ea937 DM |
559 | |
560 | if (!$node->hasAttribute('disabled')) { | |
561 | throw new ExpectationException('The element "' . $element . '" is not disabled', $this->getSession()); | |
562 | } | |
563 | } | |
564 | ||
565 | /** | |
40923977 | 566 | * Checks, that element of specified type is enabled. |
786ea937 | 567 | * |
40923977 | 568 | * @Then /^the "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should be enabled$/ |
1f9ffbdb | 569 | * @throws ExpectationException Thrown by behat_base::find |
40923977 DM |
570 | * @param string $element Element we look on |
571 | * @param string $selectortype The type of where we look | |
786ea937 | 572 | */ |
40923977 | 573 | public function the_element_should_be_enabled($element, $selectortype) { |
1f9ffbdb | 574 | |
40923977 DM |
575 | // Transforming from steps definitions selector/locator format to mink format and getting the NodeElement. |
576 | $node = $this->get_selected_node($selectortype, $element); | |
786ea937 DM |
577 | |
578 | if ($node->hasAttribute('disabled')) { | |
579 | throw new ExpectationException('The element "' . $element . '" is not enabled', $this->getSession()); | |
580 | } | |
581 | } | |
582 | ||
a2d3e3b6 MN |
583 | /** |
584 | * Checks the provided element and selector type are readonly on the current page. | |
585 | * | |
586 | * @Then /^the "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should be readonly$/ | |
587 | * @throws ExpectationException Thrown by behat_base::find | |
588 | * @param string $element Element we look in | |
589 | * @param string $selectortype The type of element where we are looking in. | |
590 | */ | |
591 | public function the_element_should_be_readonly($element, $selectortype) { | |
592 | // Transforming from steps definitions selector/locator format to Mink format and getting the NodeElement. | |
593 | $node = $this->get_selected_node($selectortype, $element); | |
594 | ||
595 | if (!$node->hasAttribute('readonly')) { | |
596 | throw new ExpectationException('The element "' . $element . '" is not readonly', $this->getSession()); | |
597 | } | |
598 | } | |
599 | ||
600 | /** | |
601 | * Checks the provided element and selector type are not readonly on the current page. | |
602 | * | |
603 | * @Then /^the "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should not be readonly$/ | |
604 | * @throws ExpectationException Thrown by behat_base::find | |
605 | * @param string $element Element we look in | |
606 | * @param string $selectortype The type of element where we are looking in. | |
607 | */ | |
608 | public function the_element_should_not_be_readonly($element, $selectortype) { | |
609 | // Transforming from steps definitions selector/locator format to Mink format and getting the NodeElement. | |
610 | $node = $this->get_selected_node($selectortype, $element); | |
611 | ||
612 | if ($node->hasAttribute('readonly')) { | |
613 | throw new ExpectationException('The element "' . $element . '" is readonly', $this->getSession()); | |
614 | } | |
615 | } | |
616 | ||
ca4f33a7 | 617 | /** |
62eb5c46 EL |
618 | * Checks the provided element and selector type exists in the current page. |
619 | * | |
620 | * This step is for advanced users, use it if you don't find anything else suitable for what you need. | |
ca4f33a7 DM |
621 | * |
622 | * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should exists$/ | |
623 | * @throws ElementNotFoundException Thrown by behat_base::find | |
624 | * @param string $element The locator of the specified selector | |
625 | * @param string $selectortype The selector type | |
626 | */ | |
627 | public function should_exists($element, $selectortype) { | |
628 | ||
629 | // Getting Mink selector and locator. | |
630 | list($selector, $locator) = $this->transform_selector($selectortype, $element); | |
631 | ||
632 | // Will throw an ElementNotFoundException if it does not exist. | |
633 | $this->find($selector, $locator); | |
634 | } | |
635 | ||
636 | /** | |
62eb5c46 EL |
637 | * Checks that the provided element and selector type not exists in the current page. |
638 | * | |
639 | * This step is for advanced users, use it if you don't find anything else suitable for what you need. | |
ca4f33a7 DM |
640 | * |
641 | * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should not exists$/ | |
642 | * @throws ExpectationException | |
643 | * @param string $element The locator of the specified selector | |
644 | * @param string $selectortype The selector type | |
645 | */ | |
646 | public function should_not_exists($element, $selectortype) { | |
647 | ||
648 | try { | |
649 | $this->should_exists($element, $selectortype); | |
650 | throw new ExpectationException('The "' . $element . '" "' . $selectortype . '" exists in the current page', $this->getSession()); | |
62eb5c46 | 651 | } catch (ElementNotFoundException $e) { |
ca4f33a7 DM |
652 | // It passes. |
653 | return; | |
654 | } | |
655 | } | |
656 | ||
066ef320 JM |
657 | /** |
658 | * This step triggers cron like a user would do going to admin/cron.php. | |
659 | * | |
660 | * @Given /^I trigger cron$/ | |
661 | */ | |
662 | public function i_trigger_cron() { | |
663 | $this->getSession()->visit($this->locate_path('/admin/cron.php')); | |
664 | } | |
665 | ||
a2d3e3b6 MN |
666 | /** |
667 | * Checks that an element and selector type exists in another element and selector type on the current page. | |
668 | * | |
669 | * This step is for advanced users, use it if you don't find anything else suitable for what you need. | |
670 | * | |
671 | * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should exist in the "(?P<element2_string>(?:[^"]|\\")*)" "(?P<selector2_string>[^"]*)"$/ | |
672 | * @throws ElementNotFoundException Thrown by behat_base::find | |
673 | * @param string $element The locator of the specified selector | |
674 | * @param string $selectortype The selector type | |
675 | * @param string $containerelement The container selector type | |
676 | * @param string $containerselectortype The container locator | |
677 | */ | |
678 | public function should_exist_in_the($element, $selectortype, $containerelement, $containerselectortype) { | |
679 | // Get the container node. | |
680 | $containernode = $this->get_selected_node($containerselectortype, $containerelement); | |
681 | ||
682 | list($selector, $locator) = $this->transform_selector($selectortype, $element); | |
683 | ||
684 | // Specific exception giving info about where can't we find the element. | |
685 | $locatorexceptionmsg = $element . '" in the "' . $containerelement. '" "' . $containerselectortype. '"'; | |
686 | $exception = new ElementNotFoundException($this->getSession(), $selectortype, null, $locatorexceptionmsg); | |
687 | ||
688 | // Looks for the requested node inside the container node. | |
689 | $this->find($selector, $locator, $exception, $containernode); | |
690 | } | |
691 | ||
692 | /** | |
693 | * Checks that an element and selector type does not exist in another element and selector type on the current page. | |
694 | * | |
695 | * This step is for advanced users, use it if you don't find anything else suitable for what you need. | |
696 | * | |
697 | * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should not exist in the "(?P<element2_string>(?:[^"]|\\")*)" "(?P<selector2_string>[^"]*)"$/ | |
698 | * @throws ExpectationException | |
699 | * @param string $element The locator of the specified selector | |
700 | * @param string $selectortype The selector type | |
701 | * @param string $containerelement The container selector type | |
702 | * @param string $containerselectortype The container locator | |
703 | */ | |
704 | public function should_not_exist_in_the($element, $selectortype, $containerelement, $containerselectortype) { | |
705 | try { | |
706 | $this->should_exist_in_the($element, $selectortype, $containerelement, $containerselectortype); | |
707 | throw new ExpectationException('The "' . $element . '" "' . $selectortype . '" exists in the "' . | |
708 | $containerelement . '" "' . $containerselectortype . '"', $this->getSession()); | |
709 | } catch (ElementNotFoundException $e) { | |
710 | // It passes. | |
711 | return; | |
712 | } | |
713 | } | |
786ea937 | 714 | } |