weekly release 3.7dev
[moodle.git] / theme / bootstrapbase / tests / behat / behat_theme_bootstrapbase_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  * @package    theme_bootstrapbase
21  * @category   test
22  * @copyright  2016 Damyon Wiese
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
28 require_once(__DIR__ . '/../../../../course/tests/behat/behat_course.php');
30 use Behat\Gherkin\Node\TableNode as TableNode,
31     Behat\Mink\Exception\ExpectationException as ExpectationException,
32     Behat\Mink\Exception\DriverException as DriverException,
33     Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
35 /**
36  * Course-related steps definitions overrides.
37  *
38  * @package    theme_bootstrapbase
39  * @category   test
40  * @copyright  2016 Damyon Wiese
41  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42  */
43 class behat_theme_bootstrapbase_behat_course extends behat_course {
45     public function i_open_actions_menu($activityname) {
47         if (!$this->running_javascript()) {
48             throw new DriverException('Activities actions menu not available when Javascript is disabled');
49         }
51         // If it is already opened we do nothing.
52         $activitynode = $this->get_activity_node($activityname);
53         $classes = array_flip(explode(' ', $activitynode->getAttribute('class')));
54         if (!empty($classes['action-menu-shown'])) {
55             return;
56         }
58         $this->execute('behat_course::i_click_on_in_the_activity',
59                 array("a[role='menuitem']", "css_element", $this->escape($activityname))
60         );
62     }
64     public function i_close_actions_menu($activityname) {
66         if (!$this->running_javascript()) {
67             throw new DriverException('Activities actions menu not available when Javascript is disabled');
68         }
70         // If it is already closed we do nothing.
71         $activitynode = $this->get_activity_node($activityname);
72         $classes = array_flip(explode(' ', $activitynode->getAttribute('class')));
73         if (empty($classes['action-menu-shown'])) {
74             return;
75         }
77         $this->execute('behat_course::i_click_on_in_the_activity',
78                 array("a[role='menuitem']", "css_element", $this->escape($activityname))
79         );
80     }
82     public function actions_menu_should_be_open($activityname) {
84         if (!$this->running_javascript()) {
85             throw new DriverException('Activities actions menu not available when Javascript is disabled');
86         }
88         // If it is already closed we do nothing.
89         $activitynode = $this->get_activity_node($activityname);
90         $classes = array_flip(explode(' ', $activitynode->getAttribute('class')));
91         if (empty($classes['action-menu-shown'])) {
92             throw new ExpectationException(
93                     sprintf("The action menu for '%s' is not open", $activityname), $this->getSession());
94         }
95     }
97     public function i_add_to_section($activity, $section) {
99         if ($this->getSession()->getPage()->find('css', 'body#page-site-index') && (int)$section <= 1) {
100             // We are on the frontpage.
101             if ($section) {
102                 // Section 1 represents the contents on the frontpage.
103                 $sectionxpath = "//body[@id='page-site-index']/descendant::div[contains(concat(' ',normalize-space(@class),' ')," .
104                         "' sitetopic ')]";
105             } else {
106                 // Section 0 represents "Site main menu" block.
107                 $sectionxpath = "//div[contains(concat(' ',normalize-space(@class),' '),' block_site_main_menu ')]";
108             }
109         } else {
110             // We are inside the course.
111             $sectionxpath = "//li[@id='section-" . $section . "']";
112         }
114         $activityliteral = behat_context_helper::escape(ucfirst($activity));
116         if ($this->running_javascript()) {
118             // Clicks add activity or resource section link.
119             $sectionxpath = $sectionxpath . "/descendant::div[@class='section-modchooser']/span/a";
120             $sectionnode = $this->find('xpath', $sectionxpath);
121             $sectionnode->click();
123             // Clicks the selected activity if it exists.
124             $activityxpath = "//div[@id='chooseform']/descendant::label" .
125                     "/descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' typename ')]" .
126                     "[normalize-space(.)=$activityliteral]" .
127                     "/parent::label/child::input";
128             $activitynode = $this->find('xpath', $activityxpath);
129             $activitynode->doubleClick();
131         } else {
132             // Without Javascript.
134             // Selecting the option from the select box which contains the option.
135             $selectxpath = $sectionxpath . "/descendant::div[contains(concat(' ', normalize-space(@class), ' '), " .
136                     "' section_add_menus ')]/descendant::select[option[normalize-space(.)=$activityliteral]]";
137             $selectnode = $this->find('xpath', $selectxpath);
138             $selectnode->selectOption($activity);
140             // Go button.
141             $gobuttonxpath = $selectxpath . "/ancestor::form/descendant::input[@type='submit']";
142             $gobutton = $this->find('xpath', $gobuttonxpath);
143             $gobutton->click();
144         }
146     }
148     public function i_duplicate_activity_editing_the_new_copy_with($activityname, TableNode $data) {
150         $activity = $this->escape($activityname);
151         $activityliteral = behat_context_helper::escape($activityname);
153         $this->execute("behat_course::i_duplicate_activity", $activity);
155         // Determine the future new activity xpath from the former one.
156         $duplicatedxpath = "//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')]" .
157                 "[contains(., $activityliteral)]/following-sibling::li";
158         $duplicatedactionsmenuxpath = $duplicatedxpath . "/descendant::a[@role='menuitem']";
160         if ($this->running_javascript()) {
161             // We wait until the AJAX request finishes and the section is visible again.
162             $hiddenlightboxxpath = "//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')]" .
163                     "[contains(., $activityliteral)]" .
164                     "/ancestor::li[contains(concat(' ', normalize-space(@class), ' '), ' section ')]" .
165                     "/descendant::div[contains(concat(' ', @class, ' '), ' lightbox ')][contains(@style, 'display: none')]";
167             $this->execute("behat_general::wait_until_exists",
168                     array($this->escape($hiddenlightboxxpath), "xpath_element")
169             );
171             // Close the original activity actions menu.
172             $this->i_close_actions_menu($activity);
174             // The next sibling of the former activity will be the duplicated one, so we click on it from it's xpath as, at
175             // this point, it don't even exists in the DOM (the steps are executed when we return them).
176             $this->execute('behat_general::i_click_on',
177                     array($this->escape($duplicatedactionsmenuxpath), "xpath_element")
178             );
179         }
181         // We force the xpath as otherwise mink tries to interact with the former one.
182         $this->execute('behat_general::i_click_on_in_the',
183                 array(get_string('editsettings'), "link", $this->escape($duplicatedxpath), "xpath_element")
184         );
186         $this->execute("behat_forms::i_set_the_following_fields_to_these_values", $data);
187         $this->execute("behat_forms::press_button", get_string('savechangesandreturntocourse'));
189     }
191     public function i_open_section_edit_menu($sectionnumber) {
192         if (!$this->running_javascript()) {
193             throw new DriverException('Section edit menu not available when Javascript is disabled');
194         }
196         // Wait for section to be available, before clicking on the menu.
197         $this->i_wait_until_section_is_available($sectionnumber);
199         // If it is already opened we do nothing.
200         $xpath = $this->section_exists($sectionnumber);
201         $xpath .= "/descendant::div[contains(@class, 'section-actions')]/descendant::a[contains(@class, 'textmenu')]";
203         $exception = new ExpectationException('Section "' . $sectionnumber . '" was not found', $this->getSession());
204         $menu = $this->find('xpath', $xpath, $exception);
205         $menu->click();
206         $this->i_wait_until_section_is_available($sectionnumber);
207     }
209     public function section_should_be_visible($sectionnumber) {
211         $sectionxpath = $this->section_exists($sectionnumber);
213         // Section should not be hidden.
214         $xpath = $sectionxpath . "[not(contains(concat(' ', normalize-space(@class), ' '), ' hidden '))]";
215         if (!$this->getSession()->getPage()->find('xpath', $xpath)) {
216             throw new ExpectationException('The section is hidden', $this->getSession());
217         }
219         // Edit menu should be visible.
220         if ($this->is_course_editor()) {
221             $xpath = $sectionxpath .
222                     "/descendant::div[contains(@class, 'section-actions')]" .
223                     "/descendant::a[contains(@class, 'textmenu')]";
224             if (!$this->getSession()->getPage()->find('xpath', $xpath)) {
225                 throw new ExpectationException('The section edit menu is not available', $this->getSession());
226             }
227         }
228     }
230     protected function user_clicks_on_management_listing_action($listingtype, $listingnode, $action) {
231         $actionsnode = $listingnode->find('xpath',
232                 "//*[contains(concat(' ', normalize-space(@class), ' '), '{$listingtype}-item-actions')]");
233         if (!$actionsnode) {
234             throw new ExpectationException("Could not find the actions for $listingtype", $this->getSession());
235         }
236         $actionnode = $actionsnode->find('css', '.action-'.$action);
237         if (!$actionnode) {
238             throw new ExpectationException("Expected action was not available or not found ($action)", $this->getSession());
239         }
240         if ($this->running_javascript() && !$actionnode->isVisible()) {
241             $actionsnode->find('css', 'a.toggle-display')->click();
242             $actionnode = $actionsnode->find('css', '.action-'.$action);
243         }
244         $actionnode->click();
245     }
247     protected function is_course_editor() {
249         // We don't need to behat_base::spin() here as all is already loaded.
250         if (!$this->getSession()->getPage()->findButton(get_string('turneditingoff')) &&
251                 !$this->getSession()->getPage()->findButton(get_string('turneditingon'))) {
252             return false;
253         }
255         return true;
256     }
258     public function i_navigate_to_course_participants() {
259         $coursestr = behat_context_helper::escape(get_string('courses'));
260         $mycoursestr = behat_context_helper::escape(get_string('mycourses'));
261         $xpath = "//div[contains(@class,'block')]//li[p/*[string(.)=$coursestr or string(.)=$mycoursestr]]";
262         $this->execute('behat_general::i_click_on_in_the', [get_string('participants'), 'link', $xpath, 'xpath_element']);
263     }