Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
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 * Moodle-specific selectors. 19 * 20 * @package core 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 /** 27 * Moodle selectors manager. 28 * 29 * @package core 30 * @category test 31 * @copyright 2013 David MonllaĆ³ 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class behat_partial_named_selector extends \Behat\Mink\Selector\PartialNamedSelector { 35 36 // Use the named selector trait. 37 use behat_named_selector; 38 39 /** 40 * Creates selector instance. 41 */ 42 public function __construct() { 43 foreach (self::$customselectors as $alias => $selectors) { 44 $this->registerNamedXpath($alias, implode(' | ', $selectors)); 45 } 46 47 foreach (static::$moodleselectors as $name => $xpath) { 48 $this->registerNamedXpath($name, $xpath); 49 } 50 51 foreach (self::$customreplacements as $from => $tos) { 52 $this->registerReplacement($from, implode(' or ', $tos)); 53 } 54 55 $this->registerReplacement('%iconMatch%', "(contains(concat(' ', @class, ' '), ' icon ') or self::img)"); 56 $this->registerReplacement('%imgAltMatch%', './/*[%iconMatch% and (%altMatch% or %titleMatch%)]'); 57 parent::__construct(); 58 } 59 60 /** 61 * @var array Allowed types when using text selectors arguments. 62 */ 63 protected static $allowedtextselectors = array( 64 'activity' => 'activity', 65 'block' => 'block', 66 'css_element' => 'css_element', 67 'dialogue' => 'dialogue', 68 'fieldset' => 'fieldset', 69 'icon' => 'icon', 70 'list_item' => 'list_item', 71 'question' => 'question', 72 'region' => 'region', 73 'section' => 'section', 74 'table' => 'table', 75 'table_row' => 'table_row', 76 'xpath_element' => 'xpath_element', 77 'form_row' => 'form_row', 78 'group_message_header' => 'group_message_header', 79 'group_message' => 'group_message', 80 'autocomplete' => 'autocomplete', 81 'iframe' => 'iframe', 82 ); 83 84 /** 85 * @var array Allowed types when using selector arguments. 86 */ 87 protected static $allowedselectors = array( 88 'activity' => 'activity', 89 'block' => 'block', 90 'button' => 'button', 91 'checkbox' => 'checkbox', 92 'css_element' => 'css_element', 93 'dialogue' => 'dialogue', 94 'field' => 'field', 95 'fieldset' => 'fieldset', 96 'file' => 'file', 97 'filemanager' => 'filemanager', 98 'group_message' => 'group_message', 99 'group_message_conversation' => 'group_message_conversation', 100 'group_message_header' => 'group_message_header', 101 'group_message_member' => 'group_message_member', 102 'group_message_tab' => 'group_message_tab', 103 'group_message_list_area' => 'group_message_list_area', 104 'group_message_message_content' => 'group_message_message_content', 105 'icon_container' => 'icon_container', 106 'icon' => 'icon', 107 'link' => 'link', 108 'link_or_button' => 'link_or_button', 109 'list_item' => 'list_item', 110 'optgroup' => 'optgroup', 111 'option' => 'option', 112 'question' => 'question', 113 'radio' => 'radio', 114 'region' => 'region', 115 'section' => 'section', 116 'select' => 'select', 117 'table' => 'table', 118 'table_row' => 'table_row', 119 'text' => 'text', 120 'xpath_element' => 'xpath_element', 121 'form_row' => 'form_row', 122 'autocomplete_selection' => 'autocomplete_selection', 123 'autocomplete_suggestions' => 'autocomplete_suggestions', 124 'autocomplete' => 'autocomplete', 125 'iframe' => 'iframe', 126 ); 127 128 /** 129 * Behat by default comes with XPath, CSS and named selectors, 130 * named selectors are a mapping between names (like button) and 131 * xpaths that represents that names and includes a placeholder that 132 * will be replaced by the locator. These are Moodle's own xpaths. 133 * 134 * @var array XPaths for moodle elements. 135 */ 136 protected static $moodleselectors = array( 137 'activity' => <<<XPATH 138 .//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')][descendant::*[contains(normalize-space(.), %locator%)]] 139 XPATH 140 , 'block' => <<<XPATH 141 .//*[@data-block][contains(concat(' ', normalize-space(@class), ' '), concat(' ', %locator%, ' ')) or 142 descendant::*[self::h2|self::h3|self::h4|self::h5][normalize-space(.) = %locator%] or 143 @aria-label = %locator%] 144 XPATH 145 , 'dialogue' => <<<XPATH 146 .//div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue ') and 147 normalize-space(descendant::div[ 148 contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue-hd ') 149 ]) = %locator%] | 150 .//div[contains(concat(' ', normalize-space(@class), ' '), ' yui-dialog ') and 151 normalize-space(descendant::div[@class='hd']) = %locator%] 152 | 153 .//div[@data-region='modal' and descendant::*[@data-region='title'] = %locator%] 154 | 155 .//div[ 156 contains(concat(' ', normalize-space(@class), ' '), ' modal-content ') 157 and 158 normalize-space(descendant::*[self::h4 or self::h5][contains(concat(' ', normalize-space(@class), ' '), ' modal-title ')]) = %locator% 159 ] 160 | 161 .//div[ 162 contains(concat(' ', normalize-space(@class), ' '), ' modal ') 163 and 164 normalize-space(descendant::*[contains(concat(' ', normalize-space(@class), ' '), ' modal-header ')]) = %locator% 165 ] 166 XPATH 167 , 'group_message' => <<<XPATH 168 .//*[@data-conversation-id]//img[contains(@alt, %locator%)]/.. 169 XPATH 170 , 'group_message_conversation' => <<<XPATH 171 .//*[@data-region='message-drawer' and contains(., %locator%)]//div[@data-region='content-message-container'] 172 XPATH 173 , 'group_message_header' => <<<XPATH 174 .//*[@data-region='message-drawer']//div[@data-region='header-content' and contains(., %locator%)] 175 XPATH 176 , 'group_message_member' => <<<XPATH 177 .//*[@data-region='message-drawer']//div[@data-region='group-info-content-container'] 178 //div[@class='list-group' and not(contains(@class, 'hidden'))]//*[text()[contains(., %locator%)]] | 179 .//*[@data-region='message-drawer']//div[@data-region='group-info-content-container'] 180 //div[@data-region='empty-message-container' and not(contains(@class, 'hidden')) and contains(., %locator%)] 181 XPATH 182 , 'group_message_tab' => <<<XPATH 183 .//*[@data-region='message-drawer']//button[@data-toggle='collapse' and contains(string(), %locator%)] 184 XPATH 185 , 'group_message_list_area' => <<<XPATH 186 .//*[@data-region='message-drawer']//*[contains(@data-region, concat('view-overview-', %locator%))] 187 XPATH 188 , 'group_message_message_content' => <<<XPATH 189 .//*[@data-region='message-drawer']//*[@data-region='message' and @data-message-id and contains(., %locator%)] 190 XPATH 191 , 'icon_container' => <<<XPATH 192 .//span[contains(@data-region, concat(%locator%,'-icon-container'))] 193 XPATH 194 , 'icon' => <<<XPATH 195 .//*[contains(concat(' ', normalize-space(@class), ' '), ' icon ') and ( contains(normalize-space(@title), %locator%))] 196 XPATH 197 , 'list_item' => <<<XPATH 198 .//li[contains(normalize-space(.), %locator%) and not(.//li[contains(normalize-space(.), %locator%)])] 199 XPATH 200 , 'question' => <<<XPATH 201 .//div[contains(concat(' ', normalize-space(@class), ' '), ' que ')] 202 [contains(div[@class='content']/div[contains(concat(' ', normalize-space(@class), ' '), ' formulation ')], %locator%)] 203 XPATH 204 , 'region' => <<<XPATH 205 .//*[self::div | self::section | self::aside | self::header | self::footer][./@id = %locator%] 206 XPATH 207 , 'section' => <<<XPATH 208 .//li[contains(concat(' ', normalize-space(@class), ' '), ' section ')][./descendant::*[self::h3] 209 [normalize-space(.) = %locator%][contains(concat(' ', normalize-space(@class), ' '), ' sectionname ') or 210 contains(concat(' ', normalize-space(@class), ' '), ' section-title ')]] | 211 .//div[contains(concat(' ', normalize-space(@class), ' '), ' sitetopic ')] 212 [./descendant::*[self::h2][normalize-space(.) = %locator%] or %locator% = 'frontpage'] 213 XPATH 214 , 'table' => <<<XPATH 215 .//table[(./@id = %locator% or contains(.//caption, %locator%) or contains(.//th, %locator%) or contains(concat(' ', normalize-space(@class), ' '), %locator% ))] 216 XPATH 217 , 'table_row' => <<<XPATH 218 .//tr[contains(normalize-space(.), %locator%) and not(.//tr[contains(normalize-space(.), %locator%)])] 219 XPATH 220 , 'text' => <<<XPATH 221 .//*[contains(., %locator%) and not(.//*[contains(., %locator%)])] 222 XPATH 223 , 'form_row' => <<<XPATH 224 .//*[contains(concat(' ', @class, ' '), ' col-form-label ')] 225 [normalize-space(.)= %locator%] 226 /ancestor::*[contains(concat(' ', @class, ' '), ' fitem ')] 227 XPATH 228 , 'autocomplete_selection' => <<<XPATH 229 .//div[contains(concat(' ', normalize-space(@class), ' '), concat(' ', 'form-autocomplete-selection', ' '))]/span[@role='option'][contains(normalize-space(.), %locator%)] 230 XPATH 231 , 'autocomplete_suggestions' => <<<XPATH 232 .//ul[contains(concat(' ', normalize-space(@class), ' '), concat(' ', 'form-autocomplete-suggestions', ' '))]/li[@role='option'][contains(normalize-space(.), %locator%)] 233 XPATH 234 , 'autocomplete' => <<<XPATH 235 .//descendant::input[@id = //label[contains(normalize-space(string(.)), %locator%)]/@for]/ancestor::*[@data-fieldtype = 'autocomplete'] 236 XPATH 237 , 'iframe' => <<<XPATH 238 .//iframe[(%idOrNameMatch% or (contains(concat(' ', normalize-space(@class), ' '), %locator% )))] 239 XPATH 240 ); 241 242 protected static $customselectors = [ 243 'field' => [ 244 'upstream' => <<<XPATH 245 .//* 246 [%fieldFilterWithPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithPlaceholder%] 247 | 248 .//label[%tagTextMatch%]//.//*[%fieldFilterWithPlaceholder%][%notFieldTypeFilter%] 249 | 250 .//* 251 [%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithoutPlaceholder%] 252 | 253 .//label[%tagTextMatch%]//.//*[%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%] 254 XPATH 255 , 256 'filemanager' => <<<XPATH 257 .//*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker'] 258 /descendant::input[@id = substring-before(//p[contains(normalize-space(string(.)), %locator%)]/@id, '_label')] 259 XPATH 260 , 261 'passwordunmask' => <<<XPATH 262 .//*[@data-passwordunmask='wrapper'] 263 /descendant::input[@id = %locator% or @id = //label[contains(normalize-space(string(.)), %locator%)]/@for] 264 XPATH 265 , 266 'inplaceeditable' => <<<XPATH 267 .//descendant::span[@data-inplaceeditable][descendant::a[%titleMatch%]] 268 XPATH 269 , 270 'date_time' => <<<XPATH 271 .//fieldset[(%idMatch% or ./legend[%exactTagTextMatch%]) and (@data-fieldtype='date' or @data-fieldtype='date_time')] 272 XPATH 273 ], 274 ]; 275 276 /** 277 * Mink comes with a number of named replacements. 278 * Sometimes we want to add our own. 279 * 280 * @var array XPaths for moodle elements. 281 */ 282 protected static $customreplacements = [ 283 '%buttonMatch%' => [ 284 'upstream' => '%idOrNameMatch% or %valueMatch% or %titleMatch%', 285 'aria' => '%ariaLabelMatch%', 286 ], 287 '%ariaLabelMatch%' => [ 288 'moodle' => 'contains(./@aria-label, %locator%)', 289 ], 290 '%exactTagTextMatch%' => [ 291 // This is based upon the upstream tagTextMatch but performs an exact match rather than a loose match using 292 // contains(). 293 // If possible we should only use exact matches for any new form fields that we add. 294 'moodle' => 'normalize-space(text())=%locator%', 295 ], 296 ]; 297 298 /** @var List of deprecated selectors */ 299 protected static $deprecatedselectors = [ 300 'group_message' => 'core_message > Message', 301 'group_message_member' => 'core_message > Message member', 302 'group_message_tab' => 'core_message > Message tab', 303 'group_message_list_area' => 'core_message > Message list area', 304 'group_message_message_content' => 'core_message > Message content', 305 ]; 306 307 /** 308 * Allowed selectors getter. 309 * 310 * @return array 311 */ 312 public static function get_allowed_selectors() { 313 return static::$allowedselectors; 314 } 315 316 /** 317 * Allowed text selectors getter. 318 * 319 * @return array 320 */ 321 public static function get_allowed_text_selectors() { 322 return static::$allowedtextselectors; 323 } 324 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body