2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Behat course-related steps definitions overrides.
20 * @copyright 2016 Damyon Wiese
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
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;
34 * Course-related steps definitions overrides.
36 * @copyright 2016 Damyon Wiese
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
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');
47 // If it is already opened we do nothing.
48 $activitynode = $this->get_activity_node($activityname);
51 $menunode = $activitynode->find('css', 'a[data-toggle=dropdown]');
53 throw new ExpectationException(sprintf('Could not find actions menu for the activity "%s"', $activityname),
56 $expanded = $menunode->getAttribute('aria-expanded');
57 if ($expanded == 'true') {
61 $this->execute('behat_course::i_click_on_in_the_activity',
62 array("a[data-toggle='dropdown']", "css_element", $this->escape($activityname))
65 $this->actions_menu_should_be_open($activityname);
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');
74 // If it is already closed we do nothing.
75 $activitynode = $this->get_activity_node($activityname);
77 $menunode = $activitynode->find('css', 'a[data-toggle=dropdown]');
79 throw new ExpectationException(sprintf('Could not find actions menu for the activity "%s"', $activityname),
82 $expanded = $menunode->getAttribute('aria-expanded');
83 if ($expanded != 'true') {
87 $this->execute('behat_course::i_click_on_in_the_activity',
88 array("a[data-toggle='dropdown']", "css_element", $this->escape($activityname))
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');
98 $activitynode = $this->get_activity_node($activityname);
100 $menunode = $activitynode->find('css', 'a[data-toggle=dropdown]');
102 throw new ExpectationException(sprintf('Could not find actions menu for the activity "%s"', $activityname),
103 $this->getSession());
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());
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.
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 ')]";
120 // Section 0 represents "Site main menu" block.
121 $sectionxpath = "//*[contains(concat(' ',normalize-space(@class),' '),' block_site_main_menu ')]";
124 // We are inside the course.
125 $sectionxpath = "//li[@id='section-" . $section . "']";
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();
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);
157 $gobuttonxpath = $selectxpath . "/ancestor::form/descendant::input[@type='submit']";
158 $gobutton = $this->find('xpath', $gobuttonxpath);
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")
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")
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")
202 $this->execute("behat_forms::i_set_the_following_fields_to_these_values", $data);
203 $this->execute("behat_forms::press_button", get_string('savechangesandreturntocourse'));
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');
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);
222 $this->i_wait_until_section_is_available($sectionnumber);
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());
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());
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')]");
250 throw new ExpectationException("Could not find the actions for $listingtype", $this->getSession());
252 $actionnode = $actionsnode->find('css', '.action-'.$action);
254 throw new ExpectationException("Expected action was not available or not found ($action)", $this->getSession());
256 if ($this->running_javascript() && !$actionnode->isVisible()) {
257 $actionsnode->find('css', 'a[data-toggle=dropdown]')->click();
258 $actionnode = $actionsnode->find('css', '.action-'.$action);
260 $actionnode->click();
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'))) {
274 public function i_navigate_to_course_participants() {
275 $this->execute('behat_navigation::i_select_from_flat_navigation_drawer', get_string('participants'));