diff --git a/admin/tool/behat/renderer.php b/admin/tool/behat/renderer.php index db94c85942b..0f5ac5e11dc 100644 --- a/admin/tool/behat/renderer.php +++ b/admin/tool/behat/renderer.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; -require_once($CFG->libdir . '/behat/classes/behat_command.php'); +require_once($CFG->libdir . '/behat/classes/behat_selectors.php'); /** * Renderer for behat tool web features @@ -92,7 +92,7 @@ class tool_behat_renderer extends plugin_renderer_base { // Replace text selector type arguments with a user-friendly select. $stepsdefinitions = preg_replace_callback('/(TEXT_SELECTOR\d?_STRING)/', function ($matches) { - return html_writer::select(behat_command::$allowedtextselectors, uniqid()); + return html_writer::select(behat_selectors::get_allowed_text_selectors(), uniqid()); }, $stepsdefinitions ); @@ -100,7 +100,7 @@ class tool_behat_renderer extends plugin_renderer_base { // Replace selector type arguments with a user-friendly select. $stepsdefinitions = preg_replace_callback('/(SELECTOR\d?_STRING)/', function ($matches) { - return html_writer::select(behat_command::$allowedselectors, uniqid()); + return html_writer::select(behat_selectors::get_allowed_selectors(), uniqid()); }, $stepsdefinitions ); diff --git a/admin/tool/behat/tests/behat/basic_actions.feature b/admin/tool/behat/tests/behat/basic_actions.feature index 637086f20a8..4ec803d8e21 100644 --- a/admin/tool/behat/tests/behat/basic_actions.feature +++ b/admin/tool/behat/tests/behat/basic_actions.feature @@ -35,7 +35,7 @@ Feature: Page contents assertions | Course 1 | C1 | 0 | And I log in as "admin" And I follow "Course 1" - When I click on "Move this to the dock" "button" in the ".block_settings" "css_element" + When I click on "Move this to the dock" "button" in the "Administration" "block" Then I should not see "Question bank" And I click on "//div[@id='dock']/descendant::h2[normalize-space(.)='Administration']" "xpath_element" @@ -45,5 +45,5 @@ Feature: Page contents assertions | fullname | shortname | category | | Course 1 | C1 | 0 | And I log in as "admin" - When I click on "Move this to the dock" "button" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' block_settings ')]" "xpath_element" + When I click on "Move this to the dock" "button" in the "Administration" "block" Then I should not see "Turn editing on" diff --git a/backup/util/ui/tests/behat/backup_courses.feature b/backup/util/ui/tests/behat/backup_courses.feature index f8b85d75f0b..67321949996 100644 --- a/backup/util/ui/tests/behat/backup_courses.feature +++ b/backup/util/ui/tests/behat/backup_courses.feature @@ -13,8 +13,9 @@ Feature: Backup Moodle courses @javascript Scenario: Backup a course providing options When I backup "Course 1" course using this options: + | Filename | test_backup.mbz | Then I should see "Restore" - And I click on "Restore" "link" in the ".backup-files-table" "css_element" + And I click on "Restore" "link" in the "test_backup.mbz" "table_row" And I should see "URL of backup" And I should see "Anonymize user information" @@ -27,11 +28,11 @@ Feature: Backup Moodle courses | setting_section_section_5_userinfo | 0 | | setting_section_section_5_included | 0 | Then I should see "Restore" - And I click on "Restore" "link" in the ".backup-files-table" "css_element" + And I click on "Restore" "link" in the "test_backup.mbz" "table_row" And I should not see "Section 3" And I press "Continue" And I click on "Continue" "button" in the ".bcs-current-course" "css_element" And "//div[contains(concat(' ', normalize-space(@class), ' '), ' fitem ')][contains(., 'Include calendar events')]/descendant::img" "xpath_element" should exists And I check "Include course logs" And I press "Cancel" - And I click on "Cancel" "button" in the ".confirmation-dialogue" "css_element" + And I click on "Cancel" "button" in the "Cancel backup" "dialogue" diff --git a/blocks/navigation/tests/behat/view_my_courses.feature b/blocks/navigation/tests/behat/view_my_courses.feature index 567250b0e4d..6287bad3d15 100644 --- a/blocks/navigation/tests/behat/view_my_courses.feature +++ b/blocks/navigation/tests/behat/view_my_courses.feature @@ -38,14 +38,14 @@ Feature: View my courses in navigation block And I log out And I log in as "student1" When I follow "My home" - Then I should not see "cat1" in the "div.block_navigation .type_system" "css_element" - And I should not see "cat2" in the "div.block_navigation .type_system" "css_element" - And I should see "c1" in the "div.block_navigation .type_system" "css_element" - And I should see "c31" in the "div.block_navigation .type_system" "css_element" - And I should see "c331" in the "div.block_navigation .type_system" "css_element" - And I should not see "c2" in the "div.block_navigation .type_system" "css_element" - And I should not see "c32" in the "div.block_navigation .type_system" "css_element" - And I should not see "c332" in the "div.block_navigation .type_system" "css_element" + Then I should not see "cat1" in the "Navigation" "block" + And I should not see "cat2" in the "Navigation" "block" + And I should see "c1" in the "Navigation" "block" + And I should see "c31" in the "Navigation" "block" + And I should see "c331" in the "Navigation" "block" + And I should not see "c2" in the "Navigation" "block" + And I should not see "c32" in the "Navigation" "block" + And I should not see "c332" in the "Navigation" "block" @javascript Scenario: The nested list of enrolled courses is shown @@ -54,18 +54,18 @@ Feature: View my courses in navigation block And I log out And I log in as "student1" When I follow "My home" - Then I should see "cat1" in the "div.block_navigation .type_system" "css_element" - And I should see "cat3" in the "div.block_navigation .type_system" "css_element" - And I should not see "cat2" in the "div.block_navigation .type_system" "css_element" + Then I should see "cat1" in the "Navigation" "block" + And I should see "cat3" in the "Navigation" "block" + And I should not see "cat2" in the "Navigation" "block" And I expand "cat3" node And I wait "2" seconds - And I should see "cat31" in the "div.block_navigation .type_system" "css_element" - And I should see "cat33" in the "div.block_navigation .type_system" "css_element" - And I should not see "cat32" in the "div.block_navigation .type_system" "css_element" + And I should see "cat31" in the "Navigation" "block" + And I should see "cat33" in the "Navigation" "block" + And I should not see "cat32" in the "Navigation" "block" And I expand "cat31" node And I wait "2" seconds - And I should see "c31" in the "div.block_navigation .type_system" "css_element" + And I should see "c31" in the "Navigation" "block" And I expand "cat33" node And I wait "2" seconds - And I should see "c331" in the "div.block_navigation .type_system" "css_element" - And I should not see "c332" in the "div.block_navigation .type_system" "css_element" + And I should see "c331" in the "Navigation" "block" + And I should not see "c332" in the "Navigation" "block" diff --git a/course/tests/behat/course_controls.feature b/course/tests/behat/course_controls.feature index 8b2ef826420..98f41c0c1ff 100644 --- a/course/tests/behat/course_controls.feature +++ b/course/tests/behat/course_controls.feature @@ -40,7 +40,7 @@ Feature: Course activity controls works as expected And I should see "Turn editing on" And "Turn editing on" "button" should exists And I turn editing mode on - And I click on "Actions" "link" in the ".block_recent_activity" "css_element" + And I click on "Actions" "link" in the "Recent activity" "block" And I click on "Delete Recent activity block" "link" And I press "Yes" And "#section-2" "css_element" exists @@ -77,8 +77,8 @@ Feature: Course activity controls works as expected And section "1" should be visible And I add the "Section links" block And "#section-2" "css_element" exists - And I should see "1 2 3 4 5" in the ".block_section_links" "css_element" - And I click on "2" "link" in the ".block_section_links" "css_element" + And I should see "1 2 3 4 5" in the "Section links" "block" + And I click on "2" "link" in the "Section links" "block" And I see "Test forum name 2" Examples: @@ -114,7 +114,7 @@ Feature: Course activity controls works as expected And I should see "Turn editing on" And "Turn editing on" "button" should exists And I turn editing mode on - And I click on "Actions" "link" in the ".block_recent_activity" "css_element" + And I click on "Actions" "link" in the "Recent activity" "block" And I click on "Delete Recent activity block" "link" And I press "Yes" And "#section-2" "css_element" exists @@ -154,8 +154,8 @@ Feature: Course activity controls works as expected And section "1" should be visible And I add the "Section links" block And "#section-2" "css_element" exists - And I should see "1 2 3 4 5" in the ".block_section_links" "css_element" - And I click on "2" "link" in the ".block_section_links" "css_element" + And I should see "1 2 3 4 5" in the "Section links" "block" + And I click on "2" "link" in the "Section links" "block" And I see "Test forum name 2" Examples: diff --git a/lib/behat/behat_base.php b/lib/behat/behat_base.php index 02b968fec30..667273f6b89 100644 --- a/lib/behat/behat_base.php +++ b/lib/behat/behat_base.php @@ -367,22 +367,13 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext { */ protected function transform_selector($selectortype, $element) { - // Here we don't know if a $allowedtextselector is used. - if (!isset(behat_command::$allowedselectors[$selectortype])) { + // Here we don't know if an allowed text selector is being used. + $selectors = behat_selectors::get_allowed_selectors(); + if (!isset($selectors[$selectortype])) { throw new ExpectationException('The "' . $selectortype . '" selector type does not exist', $this->getSession()); } - // CSS and XPath selectors locator is one single argument. - if ($selectortype == 'css_element' || $selectortype == 'xpath_element') { - $selector = str_replace('_element', '', $selectortype); - $locator = $element; - } else { - // Named selectors uses arrays as locators including the type of named selector. - $locator = array($selectortype, $this->getSession()->getSelectorsHandler()->xpathLiteral($element)); - $selector = 'named'; - } - - return array($selector, $locator); + return behat_selectors::get_behat_selector($selectortype, $element, $this->getSession()); } /** @@ -398,7 +389,8 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext { */ protected function transform_text_selector($selectortype, $element) { - if ($selectortype != 'css_element' && $selectortype != 'xpath_element') { + $selectors = behat_selectors::get_allowed_text_selectors(); + if (empty($selectors[$selectortype])) { throw new ExpectationException('The "' . $selectortype . '" selector can not be used to select text nodes', $this->getSession()); } diff --git a/lib/behat/classes/behat_command.php b/lib/behat/classes/behat_command.php index 67a3812f533..fb149ad4ffa 100644 --- a/lib/behat/classes/behat_command.php +++ b/lib/behat/classes/behat_command.php @@ -42,34 +42,6 @@ class behat_command { */ const DOCS_URL = 'http://docs.moodle.org/dev/Acceptance_testing'; - /** - * @var Allowed types when using text selectors arguments. - */ - public static $allowedtextselectors = array( - 'css_element' => 'css_element', - 'xpath_element' => 'xpath_element' - ); - - /** - * @var Allowed types when using selector arguments. - */ - public static $allowedselectors = array( - 'link' => 'link', - 'button' => 'button', - 'link_or_button' => 'link_or_button', - 'select' => 'select', - 'checkbox' => 'checkbox', - 'radio' => 'radio', - 'file' => 'file', - 'optgroup' => 'optgroup', - 'option' => 'option', - 'table' => 'table', - 'field' => 'field', - 'fieldset' => 'fieldset', - 'css_element' => 'css_element', - 'xpath_element' => 'xpath_element' - ); - /** * Ensures the behat dir exists in moodledata * @return string Full path diff --git a/lib/behat/classes/behat_selectors.php b/lib/behat/classes/behat_selectors.php new file mode 100644 index 00000000000..e92131de93b --- /dev/null +++ b/lib/behat/classes/behat_selectors.php @@ -0,0 +1,161 @@ +. + +/** + * Moodle-specific selectors. + * + * @package core + * @category test + * @copyright 2013 David Monllaó + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Moodle selectors manager. + * + * @package core + * @category test + * @copyright 2013 David Monllaó + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_selectors { + + /** + * @var Allowed types when using text selectors arguments. + */ + protected static $allowedtextselectors = array( + 'dialogue' => 'dialogue', + 'block' => 'block', + 'region' => 'region', + 'table_row' => 'table_row', + 'table' => 'table', + 'fieldset' => 'fieldset', + 'css_element' => 'css_element', + 'xpath_element' => 'xpath_element' + ); + + /** + * @var Allowed types when using selector arguments. + */ + protected static $allowedselectors = array( + 'dialogue' => 'dialogue', + 'block' => 'block', + 'region' => 'region', + 'table_row' => 'table_row', + 'link' => 'link', + 'button' => 'button', + 'link_or_button' => 'link_or_button', + 'select' => 'select', + 'checkbox' => 'checkbox', + 'radio' => 'radio', + 'file' => 'file', + 'optgroup' => 'optgroup', + 'option' => 'option', + 'table' => 'table', + 'field' => 'field', + 'fieldset' => 'fieldset', + 'css_element' => 'css_element', + 'xpath_element' => 'xpath_element' + ); + + /** + * Behat by default comes with XPath, CSS and named selectors, + * named selectors are a mapping between names (like button) and + * xpaths that represents that names and includes a placeholder that + * will be replaced by the locator. These are Moodle's own xpaths. + * + * @var XPaths for moodle elements. + */ + protected static $moodleselectors = array( + 'dialogue' => << << << <<getSelectorsHandler()->xpathLiteral($element)); + $selector = 'named'; + } + + return array($selector, $locator); + } + + /** + * Adds moodle selectors as behat named selectors. + * + * @param Session $session The mink session + * @return void + */ + public static function register_moodle_selectors(Behat\Mink\Session $session) { + + foreach (self::get_moodle_selectors() as $name => $xpath) { + $session->getSelectorsHandler()->getSelector('named')->registerNamedXpath($name, $xpath); + } + } + + /** + * Allowed selectors getter. + * + * @return array + */ + public static function get_allowed_selectors() { + return self::$allowedselectors; + } + + /** + * Allowed text selectors getter. + * + * @return array + */ + public static function get_allowed_text_selectors() { + return self::$allowedtextselectors; + } + + /** + * Moodle selectors attribute accessor. + * + * @return array + */ + protected static function get_moodle_selectors() { + return self::$moodleselectors; + } +} diff --git a/lib/tests/behat/behat_hooks.php b/lib/tests/behat/behat_hooks.php index bf8ba91e998..6dbf3860253 100644 --- a/lib/tests/behat/behat_hooks.php +++ b/lib/tests/behat/behat_hooks.php @@ -89,6 +89,7 @@ class behat_hooks extends behat_base { // 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/util.php'); require_once(__DIR__ . '/../../testing/classes/test_lock.php'); require_once(__DIR__ . '/../../testing/classes/nasty_strings.php'); @@ -138,6 +139,11 @@ class behat_hooks extends behat_base { throw new coding_exception('Behat only can modify the test database and the test dataroot!'); } + // 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($this->getSession()); + } + // Avoid some notices / warnings. $SESSION = new stdClass(); diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 2e017654204..61f80d1d7a9 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -19,6 +19,8 @@ information provided here is intended especially for developers. * Use $CFG->debugdeveloper instead of debugging('', DEBUG_DEVELOPER). * Use set_debugging(DEBUG_xxx) when changing debugging level for current request. * Function moveto_module() does not modify $mod argument and instead now returns the new module visibility value. +* Use behat_selectors::get_allowed_text_selectors() and behat_selectors::get_allowed_selectors() instead of + behat_command::$allowedtextselectors and behat_command::$allowedselectors DEPRECATIONS: Various previously deprecated functions have now been altered to throw DEBUG_DEVELOPER debugging notices