diff --git a/backup/util/ui/tests/behat/behat_backup.php b/backup/util/ui/tests/behat/behat_backup.php index 463f278e97c91..21f82f8c19015 100644 --- a/backup/util/ui/tests/behat/behat_backup.php +++ b/backup/util/ui/tests/behat/behat_backup.php @@ -349,9 +349,7 @@ protected function fill_backup_restore_form($options) { foreach ($datahash as $locator => $value) { try { - // Using $this->find* to enforce stability over speed. - $fieldnode = $this->find_field($locator); - $field = behat_field_manager::get_form_field($fieldnode, $this->getSession()); + $field = behat_field_manager::get_form_field_from_label($locator, $this); $field->set_value($value); } catch (ElementNotFoundException $e) { diff --git a/lib/behat/behat_field_manager.php b/lib/behat/behat_field_manager.php index 6bbc39ea5f4ce..d2e8c7f7dde71 100644 --- a/lib/behat/behat_field_manager.php +++ b/lib/behat/behat_field_manager.php @@ -26,7 +26,9 @@ // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. use Behat\Mink\Session as Session, - Behat\Mink\Element\NodeElement as NodeElement; + Behat\Mink\Element\NodeElement as NodeElement, + Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException, + Behat\MinkExtension\Context\RawMinkContext as RawMinkContext; /** * Helper to interact with form fields. @@ -38,6 +40,30 @@ */ class behat_field_manager { + /** + * Gets an instance of the form field from it's label + * + * @param string $label + * @param RawMinkContext $context + * @return behat_form_field + */ + public static function get_form_field_from_label($label, RawMinkContext $context) { + + // There are moodle form elements that are not directly related with + // a basic HTML form field, we should also take care of them. + try { + // The DOM node. + $fieldnode = $context->find_field($label); + } catch (ElementNotFoundException $e) { + + // Looking for labels that points to filemanagers. + $fieldnode = $context->find_filemanager($label); + } + + // The behat field manager. + return self::get_form_field($fieldnode, $context->getSession()); + } + /** * Gets an instance of the form field. * @@ -217,6 +243,7 @@ protected static function get_field_node_type(NodeElement $fieldnode, Session $s * @todo MDL-XXXXX This will be deleted in Moodle 2.8 * @see behat_field_manager::get_form_field() * @param NodeElement $fieldnode + * @param string $locator * @param Session $session The behat browser session * @return behat_form_field */ @@ -237,6 +264,7 @@ public static function get_field(NodeElement $fieldnode, $locator, Session $sess * @todo MDL-XXXXX This will be deleted in Moodle 2.8 * @see behat_field_manager::get_field_node_type() * @param NodeElement $fieldnode The current node. + * @param string $locator * @param Session $session The behat browser session * @return mixed A NodeElement if we continue looking for the element type and String or false when we are done. */ diff --git a/lib/behat/classes/behat_context_helper.php b/lib/behat/classes/behat_context_helper.php index c2b336a7008da..cdeea57cbbc61 100644 --- a/lib/behat/classes/behat_context_helper.php +++ b/lib/behat/classes/behat_context_helper.php @@ -18,7 +18,7 @@ * Helper to initialise behat contexts from moodle code. * * @package core - * @category testing + * @category test * @copyright 2014 David MonllaĆ³ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -32,7 +32,7 @@ * Helper to get behat contexts. * * @package core - * @category testing + * @category test * @copyright 2014 David MonllaĆ³ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -71,7 +71,7 @@ public static function set_session(Session $session) { * can not be executed like this. * * @throws coding_exception - * @param string Context identifier (the class name). + * @param string $classname Context identifier (the class name). * @return behat_base */ public static function get($classname) { diff --git a/lib/behat/classes/behat_selectors.php b/lib/behat/classes/behat_selectors.php index cedf70eac3063..2d90700358cd6 100644 --- a/lib/behat/classes/behat_selectors.php +++ b/lib/behat/classes/behat_selectors.php @@ -64,6 +64,7 @@ class behat_selectors { 'checkbox' => 'checkbox', 'radio' => 'radio', 'file' => 'file', + 'filemanager' => 'filemanager', 'optgroup' => 'optgroup', 'option' => 'option', 'table' => 'table', @@ -98,6 +99,9 @@ class behat_selectors { XPATH , 'table_row' => << <<fieldlocator)) { + return $this->fieldlocator; + } + + $fieldid = $this->field->getAttribute('id'); + + // Defaults to label. + if ($locatortype == 'label' || $locatortype == false) { + + $labelnode = $this->session->getPage()->find('xpath', '//label[@for="' . $fieldid . '"]'); + + // Exception only if $locatortype was specified. + if (!$labelnode && $locatortype == 'label') { + throw new coding_exception('Field with "' . $fieldid . '" id does not have a label.'); + } + + $this->fieldlocator = $labelnode->getText(); + } + + // Let's look for the name as a second option (more popular than + // id's when pointing to fields). + if (($locatortype == 'name' || $locatortype == false) && + empty($this->fieldlocator)) { + + $name = $this->field->getAttribute('name'); + + // Exception only if $locatortype was specified. + if (!$name && $locatortype == 'name') { + throw new coding_exception('Field with "' . $fieldid . '" id does not have a name attribute.'); + } + + $this->fieldlocator = $name; + } + + // Otherwise returns the id if no specific locator type was provided. + if (empty($this->fieldlocator)) { + $this->fieldlocator = $fieldid; + } + + return $this->fieldlocator; + } + } diff --git a/lib/behat/form_field/behat_form_filemanager.php b/lib/behat/form_field/behat_form_filemanager.php index 4e6887084bcaa..055efbf358240 100644 --- a/lib/behat/form_field/behat_form_filemanager.php +++ b/lib/behat/form_field/behat_form_filemanager.php @@ -41,7 +41,7 @@ * * This field manager allows you to: * - Get: A comma-separated list of the root directory - file names, including folders. + * file names, including folders. * - Set: Add a file, in case you want to add more than * one file you can always set two table rows using * the same locator. diff --git a/lib/tests/behat/behat_forms.php b/lib/tests/behat/behat_forms.php index 127b74f758864..b686efbdc6d33 100644 --- a/lib/tests/behat/behat_forms.php +++ b/lib/tests/behat/behat_forms.php @@ -166,10 +166,8 @@ public function i_set_the_field_to($field, $value) { */ public function the_field_matches_value($field, $value) { - $fieldnode = $this->find_field($field); - // Get the field. - $formfield = behat_field_manager::get_form_field($fieldnode, $this->getSession()); + $formfield = behat_field_manager::get_form_field_from_label($field, $this); // Checks if the provided value matches the current field value. if (!$formfield->matches($value)) { @@ -193,10 +191,8 @@ public function the_field_matches_value($field, $value) { */ public function the_field_does_not_match_value($field, $value) { - $fieldnode = $this->find_field($field); - // Get the field. - $formfield = behat_field_manager::get_form_field($fieldnode, $this->getSession()); + $formfield = behat_field_manager::get_form_field_from_label($field, $this); // Checks if the provided value matches the current field value. if ($formfield->matches($value)) { @@ -348,11 +344,9 @@ public function the_select_box_should_not_contain($select, $option) { */ protected function set_field_value($fieldlocator, $value) { - $node = $this->find_field($fieldlocator); - // We delegate to behat_form_field class, it will // guess the type properly as it is a select tag. - $field = behat_field_manager::get_form_field($node, $this->getSession()); + $field = behat_field_manager::get_form_field_from_label($fieldlocator, $this); $field->set_value($value); } diff --git a/lib/tests/behat/behat_hooks.php b/lib/tests/behat/behat_hooks.php index e8caf66158fec..51c47c95978b3 100644 --- a/lib/tests/behat/behat_hooks.php +++ b/lib/tests/behat/behat_hooks.php @@ -110,6 +110,7 @@ public static function before_suite($event) { // Now that we are MOODLE_INTERNAL. require_once(__DIR__ . '/../../behat/classes/behat_command.php'); require_once(__DIR__ . '/../../behat/classes/behat_selectors.php'); + require_once(__DIR__ . '/../../behat/classes/behat_context_helper.php'); require_once(__DIR__ . '/../../behat/classes/util.php'); require_once(__DIR__ . '/../../testing/classes/test_lock.php'); require_once(__DIR__ . '/../../testing/classes/nasty_strings.php'); @@ -184,6 +185,7 @@ public function before_scenario($event) { // We need the Mink session to do it and we do it only before the first scenario. if (self::is_first_scenario()) { behat_selectors::register_moodle_selectors($session); + behat_context_helper::set_session($session); } // Reset $SESSION. diff --git a/mod/forum/tests/behat/add_forum.feature b/mod/forum/tests/behat/add_forum.feature index c8515f0b1a5b5..690ddafb51740 100644 --- a/mod/forum/tests/behat/add_forum.feature +++ b/mod/forum/tests/behat/add_forum.feature @@ -1,20 +1,22 @@ -@mod @mod_forum +@mod @mod_forum @_file_upload Feature: Add forum activities and discussions In order to discuss topics with other users As a teacher I need to add forum activities to moodle courses @javascript - Scenario: Add a forum and a discussion + Scenario: Add a forum and a discussion attaching files Given the following "users" exist: | username | firstname | lastname | email | | teacher1 | Teacher | 1 | teacher1@asd.com | + | student1 | Student | 1 | student1@asd.com | And the following "courses" exist: | fullname | shortname | category | | Course 1 | C1 | 0 | And the following "course enrolments" exist: | user | course | role | | teacher1 | C1 | editingteacher | + | student1 | C1 | student | And I log in as "teacher1" And I follow "Course 1" And I turn editing mode on @@ -22,7 +24,24 @@ Feature: Add forum activities and discussions | Forum name | Test forum name | | Forum type | Standard forum for general use | | Description | Test forum description | - When I add a new discussion to "Test forum name" forum with: + And I add a new discussion to "Test forum name" forum with: | Subject | Forum post 1 | | Message | This is the body | - Then I should see "Test forum name" + And I log out + And I log in as "student1" + And I follow "Course 1" + When I add a new discussion to "Test forum name" forum with: + | Subject | Post with attachment | + | Message | This is the body | + | Attachment | lib/tests/fixtures/empty.txt | + And I reply "Forum post 1" post from "Test forum name" forum with: + | Subject | Reply with attachment | + | Message | This is the body | + | Attachment | lib/tests/fixtures/upload_users.csv | + Then I should see "Reply with attachment" + And I should see "upload_users.csv" + And I follow "Test forum name" + And I follow "Post with attachment" + And I should see "empty.txt" + And I follow "Edit" + And the field "Attachment" matches value "empty.txt" diff --git a/repository/tests/behat/behat_filepicker.php b/repository/tests/behat/behat_filepicker.php index ced8bffa8b9d4..0203d7386c9c8 100644 --- a/repository/tests/behat/behat_filepicker.php +++ b/repository/tests/behat/behat_filepicker.php @@ -281,11 +281,8 @@ protected function add_file_from_repository_to_filemanager($filepath, $repositor // The action depends on the field type. foreach ($datahash as $locator => $value) { - // Getting the node element pointed by the label. - $fieldnode = $this->find_field($locator); - // Gets the field type from a parent node. - $field = behat_field_manager::get_form_field($fieldnode, $this->getSession()); + $field = behat_field_manager::get_form_field_from_label($locator, $this); // Delegates to the field class. $field->set_value($value); diff --git a/repository/upload/tests/behat/behat_repository_upload.php b/repository/upload/tests/behat/behat_repository_upload.php index 48bc15545a0ee..d5197fd045177 100644 --- a/repository/upload/tests/behat/behat_repository_upload.php +++ b/repository/upload/tests/behat/behat_repository_upload.php @@ -143,11 +143,8 @@ protected function upload_file_to_filemanager($filepath, $filemanagerelement, Ta // The action depends on the field type. foreach ($datahash as $locator => $value) { - // Getting the node element pointed by the label. - $fieldnode = $this->find_field($locator); - // Gets the field type from a parent node. - $field = behat_field_manager::get_form_field($fieldnode, $this->getSession()); + $field = behat_field_manager::get_form_field_from_label($locator, $this); // Delegates to the field class. $field->set_value($value);