weekly release 3.7dev
[moodle.git] / theme / boost / tests / behat / behat_theme_boost_behat_course.php
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/>.
17 /**
18  * Behat course-related steps definitions overrides.
19  *
20  * @copyright  2016 Damyon Wiese
21  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22  */
24 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
26 require_once(__DIR__ . '/../../../../course/tests/behat/behat_course.php');
28 use Behat\Gherkin\Node\TableNode as TableNode,
29     Behat\Mink\Exception\ExpectationException as ExpectationException,
30     Behat\Mink\Exception\DriverException as DriverException,
31     Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
33 /**
34  * Course-related steps definitions overrides.
35  *
36  * @copyright  2016 Damyon Wiese
37  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class behat_theme_boost_behat_course extends behat_course {
41     public function i_open_actions_menu($activityname) {
43         if (!$this->running_javascript()) {
44             throw new DriverException('Activities actions menu not available when Javascript is disabled');
45         }
47         // If it is already opened we do nothing.
48         $activitynode = $this->get_activity_node($activityname);
50         // Find the menu.
51         $menunode = $activitynode->find('css', 'a[data-toggle=dropdown]');
52         if (!$menunode) {
53             throw new ExpectationException(sprintf('Could not find actions menu for the activity "%s"', $activityname),
54                     $this->getSession());
55         }
56         $expanded = $menunode->getAttribute('aria-expanded');
57         if ($expanded == 'true') {
58             return;
59         }
61         $this->execute('behat_course::i_click_on_in_the_activity',
62             array("a[data-toggle='dropdown']", "css_element", $this->escape($activityname))
63         );
65         $this->actions_menu_should_be_open($activityname);
66     }
68     public function i_close_actions_menu($activityname) {
70         if (!$this->running_javascript()) {
71             throw new DriverException('Activities actions menu not available when Javascript is disabled');
72         }
74         // If it is already closed we do nothing.
75         $activitynode = $this->get_activity_node($activityname);
76         // Find the menu.
77         $menunode = $activitynode->find('css', 'a[data-toggle=dropdown]');
78         if (!$menunode) {
79             throw new ExpectationException(sprintf('Could not find actions menu for the activity "%s"', $activityname),
80                     $this->getSession());
81         }
82         $expanded = $menunode->getAttribute('aria-expanded');
83         if ($expanded != 'true') {
84             return;
85         }
87         $this->execute('behat_course::i_click_on_in_the_activity',
88             array("a[data-toggle='dropdown']", "css_element", $this->escape($activityname))
89         );
90     }
92     public function actions_menu_should_be_open($activityname) {
94         if (!$this->running_javascript()) {
95             throw new DriverException('Activities actions menu not available when Javascript is disabled');
96         }
98         $activitynode = $this->get_activity_node($activityname);
99         // Find the menu.
100         $menunode = $activitynode->find('css', 'a[data-toggle=dropdown]');
101         if (!$menunode) {
102             throw new ExpectationException(sprintf('Could not find actions menu for the activity "%s"', $activityname),
103                     $this->getSession());
104         }
105         $expanded = $menunode->getAttribute('aria-expanded');
106         if ($expanded != 'true') {
107             throw new ExpectationException(sprintf("The action menu for '%s' is not open", $activityname), $this->getSession());
108         }
109     }
111     public function i_add_to_section($activity, $section) {
113         if ($this->getSession()->getPage()->find('css', 'body#page-site-index') && (int)$section <= 1) {
114             // We are on the frontpage.
115             if ($section) {
116                 // Section 1 represents the contents on the frontpage.
117                 $sectionxpath = "//body[@id='page-site-index']" .
118                     "/descendant::div[contains(concat(' ',normalize-space(@class),' '),' sitetopic ')]";
119             } else {
120                 // Section 0 represents "Site main menu" block.
121                 $sectionxpath = "//*[contains(concat(' ',normalize-space(@class),' '),' block_site_main_menu ')]";
122             }
123         } else {
124             // We are inside the course.
125             $sectionxpath = "//li[@id='section-" . $section . "']";
126         }
128         $activityliteral = behat_context_helper::escape(ucfirst($activity));
130         if ($this->running_javascript()) {
132             // Clicks add activity or resource section link.
133             $sectionxpath = $sectionxpath . "/descendant::div" .
134                 "[contains(concat(' ', normalize-space(@class) , ' '), ' section-modchooser ')]/span/a";
135             $sectionnode = $this->find('xpath', $sectionxpath);
136             $sectionnode->click();
138             // Clicks the selected activity if it exists.
139             $activityxpath = "//div[@id='chooseform']/descendant::label" .
140                 "/descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' typename ')]" .
141                 "[normalize-space(.)=$activityliteral]" .
142                 "/parent::label/child::input";
143             $activitynode = $this->find('xpath', $activityxpath);
144             $activitynode->doubleClick();
146         } else {
147             // Without Javascript.
149             // Selecting the option from the select box which contains the option.
150             $selectxpath = $sectionxpath . "/descendant::div" .
151                 "[contains(concat(' ', normalize-space(@class), ' '), ' section_add_menus ')]" .
152                 "/descendant::select[option[normalize-space(.)=$activityliteral]]";
153             $selectnode = $this->find('xpath', $selectxpath);
154             $selectnode->selectOption($activity);
156             // Go button.
157             $gobuttonxpath = $selectxpath . "/ancestor::form/descendant::input[@type='submit']";
158             $gobutton = $this->find('xpath', $gobuttonxpath);
159             $gobutton->click();
160         }
162     }
164     public function i_duplicate_activity_editing_the_new_copy_with($activityname, TableNode $data) {
166         $activity = $this->escape($activityname);
167         $activityliteral = behat_context_helper::escape($activityname);
169         $this->execute("behat_course::i_duplicate_activity", $activity);
171         // Determine the future new activity xpath from the former one.
172         $duplicatedxpath = "//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')]" .
173             "[contains(., $activityliteral)]/following-sibling::li";
174         $duplicatedactionsmenuxpath = $duplicatedxpath . "/descendant::a[@data-toggle='dropdown']";
176         if ($this->running_javascript()) {
177             // We wait until the AJAX request finishes and the section is visible again.
178             $hiddenlightboxxpath = "//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')]" .
179                 "[contains(., $activityliteral)]" .
180                 "/ancestor::li[contains(concat(' ', normalize-space(@class), ' '), ' section ')]" .
181                 "/descendant::div[contains(concat(' ', @class, ' '), ' lightbox ')][contains(@style, 'display: none')]";
183             $this->execute("behat_general::wait_until_exists",
184                 array($this->escape($hiddenlightboxxpath), "xpath_element")
185             );
187             // Close the original activity actions menu.
188             $this->i_close_actions_menu($activity);
190             // The next sibling of the former activity will be the duplicated one, so we click on it from it's xpath as, at
191             // this point, it don't even exists in the DOM (the steps are executed when we return them).
192             $this->execute('behat_general::i_click_on',
193                 array($this->escape($duplicatedactionsmenuxpath), "xpath_element")
194             );
195         }
197         // We force the xpath as otherwise mink tries to interact with the former one.
198         $this->execute('behat_general::i_click_on_in_the',
199             array(get_string('editsettings'), "link", $this->escape($duplicatedxpath), "xpath_element")
200         );
202         $this->execute("behat_forms::i_set_the_following_fields_to_these_values", $data);
203         $this->execute("behat_forms::press_button", get_string('savechangesandreturntocourse'));
205     }
207     public function i_open_section_edit_menu($sectionnumber) {
208         if (!$this->running_javascript()) {
209             throw new DriverException('Section edit menu not available when Javascript is disabled');
210         }
212         // Wait for section to be available, before clicking on the menu.
213         $this->i_wait_until_section_is_available($sectionnumber);
215         // If it is already opened we do nothing.
216         $xpath = $this->section_exists($sectionnumber);
217         $xpath .= "/descendant::div[contains(@class, 'section-actions')]/descendant::a[contains(@data-toggle, 'dropdown')]";
219         $exception = new ExpectationException('Section "' . $sectionnumber . '" was not found', $this->getSession());
220         $menu = $this->find('xpath', $xpath, $exception);
221         $menu->click();
222         $this->i_wait_until_section_is_available($sectionnumber);
223     }
225     public function section_should_be_visible($sectionnumber) {
227         $sectionxpath = $this->section_exists($sectionnumber);
229         // Section should not be hidden.
230         $xpath = $sectionxpath . "[not(contains(concat(' ', normalize-space(@class), ' '), ' hidden '))]";
231         if (!$this->getSession()->getPage()->find('xpath', $xpath)) {
232             throw new ExpectationException('The section is hidden', $this->getSession());
233         }
235         // Edit menu should be visible.
236         if ($this->is_course_editor()) {
237             $xpath = $sectionxpath .
238                      "/descendant::div[contains(@class, 'section-actions')]" .
239                      "/descendant::a[contains(@data-toggle, 'dropdown')]";
240             if (!$this->getSession()->getPage()->find('xpath', $xpath)) {
241                 throw new ExpectationException('The section edit menu is not available', $this->getSession());
242             }
243         }
244     }
246     protected function user_clicks_on_management_listing_action($listingtype, $listingnode, $action) {
247         $actionsnode = $listingnode->find('xpath', "//*" .
248             "[contains(concat(' ', normalize-space(@class), ' '), '{$listingtype}-item-actions')]");
249         if (!$actionsnode) {
250             throw new ExpectationException("Could not find the actions for $listingtype", $this->getSession());
251         }
252         $actionnode = $actionsnode->find('css', '.action-'.$action);
253         if (!$actionnode) {
254             throw new ExpectationException("Expected action was not available or not found ($action)", $this->getSession());
255         }
256         if ($this->running_javascript() && !$actionnode->isVisible()) {
257             $actionsnode->find('css', 'a[data-toggle=dropdown]')->click();
258             $actionnode = $actionsnode->find('css', '.action-'.$action);
259         }
260         $actionnode->click();
261     }
263     protected function is_course_editor() {
265         // We don't need to behat_base::spin() here as all is already loaded.
266         if (!$this->getSession()->getPage()->findLink(get_string('turneditingoff')) &&
267                 !$this->getSession()->getPage()->findLink(get_string('turneditingon'))) {
268             return false;
269         }
271         return true;
272     }
274     public function i_navigate_to_course_participants() {
275         $this->execute('behat_navigation::i_select_from_flat_navigation_drawer', get_string('participants'));
276     }