a0599fbca11a77b2300ac8673fdef60e3fcbdee2
[moodle.git] / lib / behat / classes / partial_named_selector.php
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/>.
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  */
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 {
36     /**
37      * Creates selector instance.
38      */
39     public function __construct() {
40         foreach (self::$customselectors as $alias => $selectors) {
41             $this->registerNamedXpath($alias, implode(' | ', $selectors));
42         }
44         foreach (static::$moodleselectors as $name => $xpath) {
45             $this->registerNamedXpath($name, $xpath);
46         }
48         foreach (self::$customreplacements as $from => $tos) {
49             $this->registerReplacement($from, implode(' or ', $tos));
50         }
52         $this->registerReplacement('%iconMatch%', "(contains(concat(' ', @class, ' '), ' icon ') or name() = 'img')");
53         $this->registerReplacement('%imgAltMatch%', './/*[%iconMatch% and (%altMatch% or %titleMatch%)]');
54         parent::__construct();
55     }
57     /**
58      * @var array Allowed types when using text selectors arguments.
59      */
60     protected static $allowedtextselectors = array(
61         'activity' => 'activity',
62         'block' => 'block',
63         'css_element' => 'css_element',
64         'dialogue' => 'dialogue',
65         'fieldset' => 'fieldset',
66         'icon' => 'icon',
67         'list_item' => 'list_item',
68         'message_area_region' => 'message_area_region',
69         'message_area_region_content' => 'message_area_region_content',
70         'question' => 'question',
71         'region' => 'region',
72         'section' => 'section',
73         'table' => 'table',
74         'table_row' => 'table_row',
75         'xpath_element' => 'xpath_element',
76         'form_row' => 'form_row',
77     );
79     /**
80      * @var array Allowed types when using selector arguments.
81      */
82     protected static $allowedselectors = array(
83         'activity' => 'activity',
84         'block' => 'block',
85         'button' => 'button',
86         'checkbox' => 'checkbox',
87         'css_element' => 'css_element',
88         'dialogue' => 'dialogue',
89         'field' => 'field',
90         'fieldset' => 'fieldset',
91         'file' => 'file',
92         'filemanager' => 'filemanager',
93         'icon' => 'icon',
94         'link' => 'link',
95         'link_or_button' => 'link_or_button',
96         'list_item' => 'list_item',
97         'message_area_action' => 'message_area_action',
98         'message_area_region' => 'message_area_region',
99         'message_area_region_content' => 'message_area_region_content',
100         'optgroup' => 'optgroup',
101         'option' => 'option',
102         'question' => 'question',
103         'radio' => 'radio',
104         'region' => 'region',
105         'section' => 'section',
106         'select' => 'select',
107         'table' => 'table',
108         'table_row' => 'table_row',
109         'text' => 'text',
110         'xpath_element' => 'xpath_element',
111         'form_row' => 'form_row',
112     );
114     /**
115      * Behat by default comes with XPath, CSS and named selectors,
116      * named selectors are a mapping between names (like button) and
117      * xpaths that represents that names and includes a placeholder that
118      * will be replaced by the locator. These are Moodle's own xpaths.
119      *
120      * @var array XPaths for moodle elements.
121      */
122     protected static $moodleselectors = array(
123         'activity' => <<<XPATH
124 .//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')][normalize-space(.) = %locator% ]
125 XPATH
126         , 'block' => <<<XPATH
127 .//*[@data-block][contains(concat(' ', normalize-space(@class), ' '), concat(' ', %locator%, ' ')) or
128      descendant::*[self::h2|self::h3][normalize-space(.) = %locator%]  or
129      @aria-label = %locator%]
130 XPATH
131         , 'dialogue' => <<<XPATH
132 .//div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue ') and
133     normalize-space(descendant::div[
134         contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue-hd ')
135         ]) = %locator%] |
136 .//div[contains(concat(' ', normalize-space(@class), ' '), ' yui-dialog ') and
137     normalize-space(descendant::div[@class='hd']) = %locator%]
138         |
139 .//div[@data-region='modal' and descendant::*[@data-region='title'] = %locator%]
140 XPATH
141         , 'icon' => <<<XPATH
142 .//*[contains(concat(' ', normalize-space(@class), ' '), ' icon ') and ( contains(normalize-space(@title), %locator%))]
143 XPATH
144         , 'list_item' => <<<XPATH
145 .//li[contains(normalize-space(.), %locator%) and not(.//li[contains(normalize-space(.), %locator%)])]
146 XPATH
147         , 'question' => <<<XPATH
148 .//div[contains(concat(' ', normalize-space(@class), ' '), ' que ')]
149     [contains(div[@class='content']/div[contains(concat(' ', normalize-space(@class), ' '), ' formulation ')], %locator%)]
150 XPATH
151         , 'region' => <<<XPATH
152 .//*[self::div | self::section | self::aside | self::header | self::footer][./@id = %locator%]
153 XPATH
154         , 'section' => <<<XPATH
155 .//li[contains(concat(' ', normalize-space(@class), ' '), ' section ')][./descendant::*[self::h3]
156     [normalize-space(.) = %locator%][contains(concat(' ', normalize-space(@class), ' '), ' sectionname ') or
157     contains(concat(' ', normalize-space(@class), ' '), ' section-title ')]] |
158 .//div[contains(concat(' ', normalize-space(@class), ' '), ' sitetopic ')]
159     [./descendant::*[self::h2][normalize-space(.) = %locator%] or %locator% = 'frontpage']
160 XPATH
161         , 'table' => <<<XPATH
162 .//table[(./@id = %locator% or contains(.//caption, %locator%) or contains(.//th, %locator%) or contains(concat(' ', normalize-space(@class), ' '), %locator% ))]
163 XPATH
164         , 'table_row' => <<<XPATH
165 .//tr[contains(normalize-space(.), %locator%) and not(.//tr[contains(normalize-space(.), %locator%)])]
166 XPATH
167         , 'text' => <<<XPATH
168 .//*[contains(., %locator%) and not(.//*[contains(., %locator%)])]
169 XPATH
170         , 'form_row' => <<<XPATH
171 .//*[self::label or self::div[contains(concat(' ', @class, ' '), ' fstaticlabel ')]][contains(., %locator%)]/ancestor::*[contains(concat(' ', @class, ' '), ' fitem ')]
172 XPATH
173         , 'message_area_region' => <<<XPATH
174 .//div[@data-region='messaging-area']/descendant::*[@data-region = %locator%]
175 XPATH
176         , 'message_area_region_content' => <<<XPATH
177 .//div[@data-region='messaging-area']/descendant::*[@data-region-content = %locator%]
178 XPATH
179         , 'message_area_action' => <<<XPATH
180 .//div[@data-region='messaging-area']/descendant::*[@data-action = %locator%]
181 XPATH
182     );
184     protected static $customselectors = [
185         'field' => [
186             'upstream' => <<<XPATH
187 .//*
188 [%fieldFilterWithPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithPlaceholder%]
190 .//label[%tagTextMatch%]//.//*[%fieldFilterWithPlaceholder%][%notFieldTypeFilter%]
192 .//*
193 [%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithoutPlaceholder%]
195 .//label[%tagTextMatch%]//.//*[%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%]
196 XPATH
197         ,
198             'filemanager' => <<<XPATH
199 .//*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker']
200     /descendant::input[@id = //label[contains(normalize-space(string(.)), %locator%)]/@for]
201 XPATH
202         ,
203              'passwordunmask' => <<<XPATH
204 .//*[@data-passwordunmask='wrapper']
205     /descendant::input[@id = %locator% or @id = //label[contains(normalize-space(string(.)), %locator%)]/@for]
206 XPATH
207         ],
208     ];
210     /**
211      * Mink comes with a number of named replacements.
212      * Sometimes we want to add our own.
213      *
214      * @var array XPaths for moodle elements.
215      */
216     protected static $customreplacements = [
217         '%buttonMatch%' => [
218             'upstream' => '%idOrNameMatch% or %valueMatch% or %titleMatch%',
219             'aria' => '%ariaLabelMatch%',
220         ],
221         '%ariaLabelMatch%' => [
222             'moodle' => 'contains(./@aria-label, %locator%)',
223         ],
224     ];
226     /**
227      * Allowed selectors getter.
228      *
229      * @return array
230      */
231     public static function get_allowed_selectors() {
232         return static::$allowedselectors;
233     }
235     /**
236      * Allowed text selectors getter.
237      *
238      * @return array
239      */
240     public static function get_allowed_text_selectors() {
241         return static::$allowedtextselectors;
242     }