Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 403]

   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   * Filemanager and filepicker manipulation steps definitions.
  19   *
  20   * @package    core_filepicker
  21   * @category   test
  22   * @copyright  2013 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__ . '/../../../lib/behat/core_behat_file_helper.php');
  29  
  30  use Behat\Mink\Exception\ExpectationException as ExpectationException,
  31      Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException,
  32      Behat\Gherkin\Node\TableNode as TableNode;
  33  
  34  /**
  35   * Steps definitions to deal with the filemanager and filepicker.
  36   *
  37   * @package    core_filepicker
  38   * @category   test
  39   * @copyright  2013 David MonllaĆ³
  40   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  class behat_filepicker extends behat_base {
  43      use core_behat_file_helper;
  44  
  45      /**
  46       * Creates a folder with specified name in the current folder and in the specified filemanager field.
  47       *
  48       * @Given /^I create "(?P<foldername_string>(?:[^"]|\\")*)" folder in "(?P<filemanager_field_string>(?:[^"]|\\")*)" filemanager$/
  49       * @throws ExpectationException Thrown by behat_base::find
  50       * @param string $foldername
  51       * @param string $filemanagerelement
  52       */
  53      public function i_create_folder_in_filemanager($foldername, $filemanagerelement) {
  54  
  55          $fieldnode = $this->get_filepicker_node($filemanagerelement);
  56  
  57          // Looking for the create folder button inside the specified filemanager.
  58          $exception = new ExpectationException('No folders can be created in "'.$filemanagerelement.'" filemanager',
  59                  $this->getSession());
  60          $newfolder = $this->find('css', 'div.fp-btn-mkdir a', $exception, $fieldnode);
  61          $newfolder->click();
  62  
  63          // Setting the folder name in the modal window.
  64          $exception = new ExpectationException('The dialog to enter the folder name does not appear', $this->getSession());
  65          $dialoginput = $this->find('css', '.fp-mkdir-dlg-text input', $exception);
  66          $dialoginput->setValue($foldername);
  67  
  68          $exception = new ExpectationException('The button for the create folder dialog can not be located', $this->getSession());
  69          $dialognode = $this->find('css', '.moodle-dialogue-focused');
  70          $buttonnode = $this->find('css', '.fp-dlg-butcreate', $exception, $dialognode);
  71          $buttonnode->click();
  72      }
  73  
  74      /**
  75       * Opens the contents of a filemanager folder. It looks for the folder in the current folder and in the path bar.
  76       *
  77       * @Given /^I open "(?P<foldername_string>(?:[^"]|\\")*)" folder from "(?P<filemanager_field_string>(?:[^"]|\\")*)" filemanager$/
  78       * @throws ExpectationException Thrown by behat_base::find
  79       * @param string $foldername
  80       * @param string $filemanagerelement
  81       */
  82      public function i_open_folder_from_filemanager($foldername, $filemanagerelement) {
  83  
  84          $fieldnode = $this->get_filepicker_node($filemanagerelement);
  85  
  86          $exception = new ExpectationException(
  87                  'The "'.$foldername.'" folder can not be found in the "'.$filemanagerelement.'" filemanager',
  88                  $this->getSession()
  89          );
  90  
  91          $folderliteral = behat_context_helper::escape($foldername);
  92  
  93          // We look both in the pathbar and in the contents.
  94          try {
  95  
  96              // In the current folder workspace.
  97              $folder = $this->find(
  98                      'xpath',
  99                      "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-folder ')]" .
 100                      "/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-filename ')]" .
 101                      "[normalize-space(.)=$folderliteral]",
 102                      $exception,
 103                      $fieldnode
 104              );
 105          } catch (ExpectationException $e) {
 106  
 107              // And in the pathbar.
 108              $folder = $this->find(
 109                      'xpath',
 110                      "//a[contains(concat(' ', normalize-space(@class), ' '), ' fp-path-folder-name ')]" .
 111                      "[normalize-space(.)=$folderliteral]",
 112                      $exception,
 113                      $fieldnode
 114              );
 115          }
 116  
 117          // It should be a NodeElement, otherwise an exception would have been thrown.
 118          $folder->click();
 119      }
 120  
 121      /**
 122       * Unzips the specified file from the specified filemanager field. The zip file has to be visible in the current folder.
 123       *
 124       * @Given /^I unzip "(?P<filename_string>(?:[^"]|\\")*)" file from "(?P<filemanager_field_string>(?:[^"]|\\")*)" filemanager$/
 125       * @throws ExpectationException Thrown by behat_base::find
 126       * @param string $filename
 127       * @param string $filemanagerelement
 128       */
 129      public function i_unzip_file_from_filemanager($filename, $filemanagerelement) {
 130  
 131          // Open the contextual menu of the filemanager element.
 132          $this->open_element_contextual_menu($filename, $filemanagerelement);
 133  
 134          // Execute the action.
 135          $exception = new ExpectationException($filename.' element can not be unzipped', $this->getSession());
 136          $this->perform_on_element('unzip', $exception);
 137      }
 138  
 139      /**
 140       * Zips the specified folder from the specified filemanager field. The folder has to be in the current folder.
 141       *
 142       * @Given /^I zip "(?P<filename_string>(?:[^"]|\\")*)" folder from "(?P<filemanager_field_string>(?:[^"]|\\")*)" filemanager$/
 143       * @throws ExpectationException Thrown by behat_base::find
 144       * @param string $foldername
 145       * @param string $filemanagerelement
 146       */
 147      public function i_zip_folder_from_filemanager($foldername, $filemanagerelement) {
 148  
 149          // Open the contextual menu of the filemanager element.
 150          $this->open_element_contextual_menu($foldername, $filemanagerelement);
 151  
 152          // Execute the action.
 153          $exception = new ExpectationException($foldername.' element can not be zipped', $this->getSession());
 154          $this->perform_on_element('zip', $exception);
 155      }
 156  
 157      /**
 158       * Deletes the specified file or folder from the specified filemanager field.
 159       *
 160       * @Given /^I delete "(?P<file_or_folder_name_string>(?:[^"]|\\")*)" from "(?P<filemanager_field_string>(?:[^"]|\\")*)" filemanager$/
 161       * @throws ExpectationException Thrown by behat_base::find
 162       * @param string $name
 163       * @param string $filemanagerelement
 164       */
 165      public function i_delete_file_from_filemanager($name, $filemanagerelement) {
 166  
 167          // Open the contextual menu of the filemanager element.
 168          $this->open_element_contextual_menu($name, $filemanagerelement);
 169  
 170          // Execute the action.
 171          $exception = new ExpectationException($name.' element can not be deleted', $this->getSession());
 172          $this->perform_on_element('delete', $exception);
 173  
 174          // Yes, we are sure.
 175          $this->execute('behat_general::i_click_on_in_the', [get_string('ok'), 'button', get_string('confirm'), 'dialogue']);
 176      }
 177  
 178      /**
 179       * Makes sure user can see the exact number of elements (files in folders) in the filemanager.
 180       *
 181       * @Then /^I should see "(?P<elementscount_number>\d+)" elements in "(?P<filemanagerelement_string>(?:[^"]|\\")*)" filemanager$/
 182       * @throws ExpectationException Thrown by behat_base::find
 183       * @param int $elementscount
 184       * @param string $filemanagerelement
 185       */
 186      public function i_should_see_elements_in_filemanager($elementscount, $filemanagerelement) {
 187          $filemanagernode = $this->get_filepicker_node($filemanagerelement);
 188  
 189          // We count .fp-file elements inside a filemanager not being updated.
 190          $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' filemanager ')]" .
 191                  "[not(contains(concat(' ', normalize-space(@class), ' '), ' fm-updating '))]" .
 192                  "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')]" .
 193                  "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]";
 194  
 195          $elements = $this->find_all('xpath', $xpath, false, $filemanagernode);
 196          if (count($elements) != $elementscount) {
 197              throw new ExpectationException('Found '.count($elements).' elements in filemanager. Expected '.$elementscount,
 198                      $this->getSession());
 199          }
 200      }
 201  
 202      /**
 203       * Picks the file from repository leaving default values in select file dialogue.
 204       *
 205       * @When /^I add "(?P<filepath_string>(?:[^"]|\\")*)" file from "(?P<repository_string>(?:[^"]|\\")*)" to "(?P<filemanagerelement_string>(?:[^"]|\\")*)" filemanager$/
 206       * @throws ExpectationException Thrown by behat_base::find
 207       * @param string $filepath
 208       * @param string $repository
 209       * @param string $filemanagerelement
 210       */
 211      public function i_add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement) {
 212          $this->add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, new TableNode(array()), false);
 213      }
 214  
 215      /**
 216       * Picks the file from repository leaving default values in select file dialogue and confirming to overwrite an existing file.
 217       *
 218       * @When /^I add and overwrite "(?P<filepath_string>(?:[^"]|\\")*)" file from "(?P<repository_string>(?:[^"]|\\")*)" to "(?P<filemanagerelement_string>(?:[^"]|\\")*)" filemanager$/
 219       * @throws ExpectationException Thrown by behat_base::find
 220       * @param string $filepath
 221       * @param string $repository
 222       * @param string $filemanagerelement
 223       */
 224      public function i_add_and_overwrite_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement) {
 225          $this->add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, new TableNode(array()),
 226                  get_string('overwrite', 'repository'));
 227      }
 228  
 229      /**
 230       * Picks the file from repository filling the form in Select file dialogue.
 231       *
 232       * @When /^I add "(?P<filepath_string>(?:[^"]|\\")*)" file from "(?P<repository_string>(?:[^"]|\\")*)" to "(?P<filemanager_field_string>(?:[^"]|\\")*)" filemanager as:$/
 233       * @throws ExpectationException Thrown by behat_base::find
 234       * @param string $filepath
 235       * @param string $repository
 236       * @param string $filemanagerelement
 237       * @param TableNode $data Data to fill the form in Select file dialogue
 238       */
 239      public function i_add_file_from_repository_to_filemanager_as($filepath, $repository, $filemanagerelement, TableNode $data) {
 240          $this->add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, $data, false);
 241      }
 242  
 243      /**
 244       * Picks the file from repository confirming to overwrite an existing file
 245       *
 246       * @When /^I add and overwrite "(?P<filepath_string>(?:[^"]|\\")*)" file from "(?P<repository_string>(?:[^"]|\\")*)" to "(?P<filemanager_field_string>(?:[^"]|\\")*)" filemanager as:$/
 247       * @throws ExpectationException Thrown by behat_base::find
 248       * @param string $filepath
 249       * @param string $repository
 250       * @param string $filemanagerelement
 251       * @param TableNode $data Data to fill the form in Select file dialogue
 252       */
 253      public function i_add_and_overwrite_file_from_repository_to_filemanager_as($filepath, $repository, $filemanagerelement,
 254              TableNode $data) {
 255          $this->add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, $data,
 256                  get_string('overwrite', 'repository'));
 257      }
 258  
 259      /**
 260       * Picks the file from private files repository
 261       *
 262       * @throws ExpectationException Thrown by behat_base::find
 263       * @param string $filepath
 264       * @param string $repository
 265       * @param string $filemanagerelement
 266       * @param TableNode $data Data to fill the form in Select file dialogue
 267       * @param false|string $overwriteaction false if we don't expect that file with the same name already exists,
 268       *     or button text in overwrite dialogue ("Overwrite", "Rename to ...", "Cancel")
 269       */
 270      protected function add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, TableNode $data,
 271              $overwriteaction = false) {
 272          $filemanagernode = $this->get_filepicker_node($filemanagerelement);
 273  
 274          // Opening the select repository window and selecting the upload repository.
 275          $this->open_add_file_window($filemanagernode, $repository);
 276  
 277          $this->open_element_contextual_menu($filepath);
 278  
 279          // Fill the form in Select window.
 280          $datahash = $data->getRowsHash();
 281  
 282          // The action depends on the field type.
 283          foreach ($datahash as $locator => $value) {
 284  
 285              $field = behat_field_manager::get_form_field_from_label($locator, $this);
 286  
 287              // Delegates to the field class.
 288              $field->set_value($value);
 289          }
 290  
 291          $selectfilebutton = $this->find_button(get_string('getfile', 'repository'));
 292          $this->ensure_node_is_visible($selectfilebutton);
 293          $selectfilebutton->click();
 294  
 295          // We wait for all the JS to finish as it is performing an action.
 296          $this->getSession()->wait(self::get_timeout(), self::PAGE_READY_JS);
 297  
 298          if ($overwriteaction !== false) {
 299              $overwritebutton = $this->find_button($overwriteaction);
 300              $this->ensure_node_is_visible($overwritebutton);
 301              $overwritebutton->click();
 302  
 303              // We wait for all the JS to finish.
 304              $this->getSession()->wait(self::get_timeout(), self::PAGE_READY_JS);
 305          }
 306  
 307      }
 308  
 309      /**
 310       * Selects a repository from the repository list in the file picker.
 311       *
 312       * @Then /^I select "(?P<repository_name_string>(?:[^"]|\\")*)" repository in file picker$/
 313       * @throws ExpectationException Thrown by behat_base::find
 314       * @param string $repositoryname
 315       */
 316      public function i_select_filepicker_repository($repositoryname) {
 317          $exception = new ExpectationException(
 318              "The '{$repositoryname}' repository can not be found in the file picker", $this->getSession());
 319          // We look for a repository that matches a certain name in the file picker repository list.
 320          $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' filepicker ')]" .
 321              "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-area ')]" .
 322              "//span[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-name ')]" .
 323              "[normalize-space(.)='{$repositoryname}']";
 324  
 325          $repository = $this->find('xpath', $xpath, $exception);
 326          // If the node exists, click on the node.
 327          $repository->click();
 328      }
 329  
 330      /**
 331       * Makes sure user can see the exact number of elements (files and folders) in the repository content area in
 332       * the file picker.
 333       *
 334       * @Then /^I should see "(?P<elements_number>\d+)" elements in repository content area$/
 335       * @throws ExpectationException Thrown by behat_base::find_all
 336       * @param int $expectedcount
 337       */
 338      public function i_should_see_elements_in_filepicker_repository($expectedcount) {
 339          // We look for all .fp-file elements inside the content area of the file picker repository.
 340          $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]" .
 341              "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')]" .
 342              "//a[contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]";
 343  
 344          try {
 345              $elements = $this->find_all('xpath', $xpath);
 346          } catch (ElementNotFoundException $e) {
 347              $elements = [];
 348          }
 349  
 350          // Make sure the expected number is equal to the actual number of .fp-file elements.
 351          if (count($elements) != $expectedcount) {
 352              throw new ExpectationException("Found " . count($elements) .
 353                  " elements in filepicker repository. Expected {$expectedcount}", $this->getSession());
 354          }
 355      }
 356  
 357      /**
 358       * Returns a specific element (file or folder) in the repository content area in the file picker.
 359       *
 360       * @throws ExpectationException Thrown by behat_base::find
 361       * @param string $elementname The name of the element
 362       * @param string $elementtype The type of the element ("file" or "folder")
 363       * @return NodeElement
 364       */
 365      protected function get_element_in_filepicker_repository($elementname, $elementtype) {
 366          // We look for a .fp-{type} element with a certain name inside the content area of the file picker repository.
 367          $exception = new ExpectationException(
 368              "The '{$elementname}' {$elementtype} can not be found in the repository content area",
 369              $this->getSession());
 370          $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]" .
 371              "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')]" .
 372              "//a[contains(concat(' ', normalize-space(@class), ' '), ' fp-{$elementtype} ')]" .
 373              "[normalize-space(.)='{$elementname}']";
 374  
 375          return $this->find('xpath', $xpath, $exception);
 376      }
 377  
 378      /**
 379       * Makes sure user can see a specific element (file or folder) in the repository content area in the file picker.
 380       *
 381       * @Then /^I should see "(?P<element_name_string>(?:[^"]|\\")*)" "(?P<element_type_string>(?:[^"]|\\")*)" in repository content area$/
 382       * @throws ExpectationException Thrown by behat_base::find
 383       * @param string $elementname The name of the element
 384       * @param string $elementtype The type of the element ("file" or "folder")
 385       */
 386      public function i_should_see_element_in_filepicker_repository($elementname, $elementtype) {
 387          $this->get_element_in_filepicker_repository($elementname, $elementtype);
 388      }
 389  
 390      /**
 391       * Clicks on a specific element (file or folder) in the repository content area in the file picker.
 392       *
 393       * @Then /^I click on "(?P<element_name_string>(?:[^"]|\\")*)" "(?P<element_type_string>(?:[^"]|\\")*)" in repository content area$/
 394       * @throws ExpectationException Thrown by behat_base::find
 395       * @param string $elementname The name of the element
 396       * @param string $elementtype The type of the element ("file" or "folder")
 397       */
 398      public function i_click_on_element_in_filepicker_repository($elementname, $elementtype) {
 399          $element = $this->get_element_in_filepicker_repository($elementname, $elementtype);
 400          $element->click();
 401      }
 402  
 403      /**
 404       * Makes sure the user can see a specific breadcrumb navigation structure in the file picker repository.
 405       *
 406       * @Then /^I should see "(?P<breadcrumb_navigation_string>(?:[^"]|\\")*)" breadcrumb navigation in repository$/
 407       * @throws ExpectationException Thrown by behat_base::find
 408       * @param string $breadcrumbs The breadcrumb navigation structure (ex. "System > Category > Course")
 409       */
 410      public function i_should_see_breadcrumb_navigation_in_filepicker_repository($breadcrumbs) {
 411          $breadcrumbs = preg_split('/\s*>\s*/', trim($breadcrumbs));
 412          foreach ($breadcrumbs as $breadcrumb) {
 413              // We look for a .fp-path-folder element with a certain name inside the breadcrumb navigation area
 414              // in the repository.
 415              $exception = new ExpectationException(
 416                  "The '{$breadcrumb}' node can not be found in the breadcrumb navigation in the repository",
 417                  $this->getSession()
 418              );
 419              $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]" .
 420                  "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-pathbar ')]" .
 421                  "//span[contains(concat(' ', normalize-space(@class), ' '), ' fp-path-folder ')]" .
 422                  "[normalize-space(.)='{$breadcrumb}']";
 423  
 424              $this->find('xpath', $xpath, $exception);
 425          }
 426      }
 427  }