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 * Files interactions with behat. 19 * 20 * Note that steps definitions files can not extend other steps definitions files, so steps definitions which makes use 21 * of file attachments or filepicker should use this behat_file_helper trait. 22 * 23 * @package core 24 * @category test 25 * @copyright 2013 David MonllaĆ³ 26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 */ 28 29 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. 30 31 require_once (__DIR__ . '/behat_base.php'); 32 33 use Behat\Mink\Exception\ExpectationException as ExpectationException, 34 Behat\Mink\Element\NodeElement as NodeElement; 35 36 /** 37 * Files-related actions. 38 * 39 * Steps definitions related with filepicker or repositories should extend use this trait as it provides useful methods 40 * to deal with the common filepicker issues. 41 * 42 * @package core 43 * @category test 44 * @copyright 2013 David MonllaĆ³ 45 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 46 */ 47 trait core_behat_file_helper { 48 49 /** 50 * Gets the NodeElement for filepicker of filemanager moodleform element. 51 * 52 * The filepicker/filemanager element label is pointing to a hidden input which is 53 * not recognized as a named selector, as it is hidden... 54 * 55 * @throws ExpectationException Thrown by behat_base::find 56 * @param string $filepickerelement The filepicker form field label 57 * @return NodeElement The hidden element node. 58 */ 59 60 protected function get_filepicker_node($filepickerelement) { 61 62 // More info about the problem (in case there is a problem). 63 $exception = new ExpectationException('"' . $filepickerelement . '" filepicker can not be found', $this->getSession()); 64 65 // If no file picker label is mentioned take the first file picker from the page. 66 if (empty($filepickerelement)) { 67 $filepickercontainer = $this->find( 68 'xpath', 69 "//*[@data-fieldtype=\"filemanager\"]", 70 $exception 71 ); 72 } else { 73 // Gets the ffilemanager node specified by the locator which contains the filepicker container. 74 $filepickerelement = behat_context_helper::escape($filepickerelement); 75 $filepickercontainer = $this->find( 76 'xpath', 77 "//input[./@id = substring-before(//p[normalize-space(.)=$filepickerelement]/@id, '_label')]" . 78 "//ancestor::*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker']", 79 $exception 80 ); 81 } 82 83 return $filepickercontainer; 84 } 85 86 /** 87 * Performs $action on a filemanager container element (file or folder). 88 * 89 * It works together with open_element_contextual_menu 90 * as this method needs the contextual menu to be opened. 91 * 92 * @throws ExpectationException Thrown by behat_base::find 93 * @param string $action 94 * @param ExpectationException $exception 95 * @return void 96 */ 97 protected function perform_on_element($action, ExpectationException $exception) { 98 99 // Finds the button inside the DOM, is a modal window, so should be unique. 100 $classname = 'fp-file-' . $action; 101 $button = $this->find('css', '.moodle-dialogue-focused button.' . $classname, $exception); 102 103 $this->ensure_node_is_visible($button); 104 $button->click(); 105 } 106 107 /** 108 * Opens the contextual menu of a folder or a file. 109 * 110 * Works both in filemanager elements and when dealing with repository 111 * elements inside filepicker modal window. 112 * 113 * @throws ExpectationException Thrown by behat_base::find 114 * @param string $name The name of the folder/file 115 * @param string $filemanagerelement The filemanager form element locator, the repository items are in filepicker modal window if false 116 * @return void 117 */ 118 protected function open_element_contextual_menu($name, $filemanagerelement = false) { 119 120 // If a filemanager is specified we restrict the search to the descendants of this particular filemanager form element. 121 $containernode = false; 122 $exceptionmsg = '"'.$name.'" element can not be found'; 123 if ($filemanagerelement) { 124 $containernode = $this->get_filepicker_node($filemanagerelement); 125 $exceptionmsg = 'The "'.$filemanagerelement.'" filemanager ' . $exceptionmsg; 126 $locatorprefix = "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')]"; 127 } else { 128 $locatorprefix = "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-items ')]" . 129 "//descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')]"; 130 } 131 132 $exception = new ExpectationException($exceptionmsg, $this->getSession()); 133 134 // Avoid quote-related problems. 135 $name = behat_context_helper::escape($name); 136 137 // Get a filepicker/filemanager element (folder or file). 138 try { 139 140 // First we look at the folder as we need to click on the contextual menu otherwise it would be opened. 141 $node = $this->find( 142 'xpath', 143 $locatorprefix . 144 "//descendant::*[self::div | self::a][contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]" . 145 "[contains(concat(' ', normalize-space(@class), ' '), ' fp-folder ')]" . 146 "[normalize-space(.)=$name]" . 147 "//descendant::a[contains(concat(' ', normalize-space(@class), ' '), ' fp-contextmenu ')]", 148 $exception, 149 $containernode 150 ); 151 152 } catch (ExpectationException $e) { 153 154 // Here the contextual menu is hidden, we click on the thumbnail. 155 $node = $this->find( 156 'xpath', 157 $locatorprefix . 158 "//descendant::*[self::div | self::a][contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]" . 159 "[normalize-space(.)=$name]" . 160 "//descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-filename-field ')]", 161 false, 162 $containernode 163 ); 164 } 165 166 // Click opens the contextual menu when clicking on files. 167 $this->ensure_node_is_visible($node); 168 $node->click(); 169 } 170 171 /** 172 * Opens the filepicker modal window and selects the repository. 173 * 174 * @throws ExpectationException Thrown by behat_base::find 175 * @param NodeElement $filemanagernode The filemanager or filepicker form element DOM node. 176 * @param mixed $repositoryname The repo name. 177 * @return void 178 */ 179 protected function open_add_file_window($filemanagernode, $repositoryname) { 180 $exception = new ExpectationException('No files can be added to the specified filemanager', $this->getSession()); 181 182 // We should deal with single-file and multiple-file filemanagers, 183 // catching the exception thrown by behat_base::find() in case is not multiple 184 $this->execute('behat_general::i_click_on_in_the', [ 185 'div.fp-btn-add a, input.fp-btn-choose', 'css_element', 186 $filemanagernode, 'NodeElement' 187 ]); 188 189 // Wait for the default repository (if any) to load. This checks that 190 // the relevant div exists and that it does not include the loading image. 191 $this->ensure_element_exists( 192 "//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]" . 193 "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')]" . 194 "[not(descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content-loading ')])]", 195 'xpath_element'); 196 197 // Getting the repository link and opening it. 198 $repoexception = new ExpectationException('The "' . $repositoryname . '" repository has not been found', $this->getSession()); 199 200 // Avoid problems with both double and single quotes in the same string. 201 $repositoryname = behat_context_helper::escape($repositoryname); 202 203 // Here we don't need to look inside the selected element because there can only be one modal window. 204 $repositorylink = $this->find( 205 'xpath', 206 "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-area ')]" . 207 "//descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-name ')]" . 208 "[normalize-space(.)=$repositoryname]", 209 $repoexception 210 ); 211 212 // Selecting the repo. 213 $this->ensure_node_is_visible($repositorylink); 214 if (!$repositorylink->getParent()->getParent()->hasClass('active')) { 215 // If the repository link is active, then the repository is already loaded. 216 // Clicking it while it's active causes issues, so only click it when it isn't (see MDL-51014). 217 $this->execute('behat_general::i_click_on', [$repositorylink, 'NodeElement']); 218 } 219 } 220 221 /** 222 * Waits until the file manager modal windows are closed. 223 * 224 * This method is not used by any of our step definitions, 225 * keeping it here for users already using it. 226 * 227 * @throws ExpectationException 228 * @return void 229 */ 230 protected function wait_until_return_to_form() { 231 232 $exception = new ExpectationException('The file manager is taking too much time to finish the current action', $this->getSession()); 233 234 $this->find( 235 'xpath', 236 "//div[contains(concat(' ', @class, ' '), ' moodle-dialogue-lightbox ')][contains(@style, 'display: none;')]", 237 $exception 238 ); 239 } 240 241 /** 242 * Checks that the file manager contents are not being updated. 243 * 244 * This method is not used by any of our step definitions, 245 * keeping it here for users already using it. 246 * 247 * @throws ExpectationException 248 * @param NodeElement $filepickernode The file manager DOM node 249 * @return void 250 */ 251 protected function wait_until_contents_are_updated($filepickernode) { 252 253 $exception = new ExpectationException( 254 'The file manager contents are requiring too much time to be updated', 255 $this->getSession() 256 ); 257 258 // Looks for the loading image not being displayed. For single-file filepickers is 259 // only used when accessing the filepicker, there is no filemanager-loading after selecting the file. 260 $this->find( 261 'xpath', 262 "//div[contains(concat(' ', normalize-space(@class), ' '), ' filemanager ')]" . 263 "[not(contains(concat(' ', normalize-space(@class), ' '), ' fm-updating '))]" . 264 "|" . 265 "//div[contains(concat(' ', normalize-space(@class), ' '), ' filemanager-loading ')]" . 266 "[contains(@style, 'display: none;')]", 267 $exception, 268 $filepickernode 269 ); 270 } 271 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body