| Línea 12... | Línea 12... | 
          
            | 12 | // GNU General Public License for more details.
 | 12 | // GNU General Public License for more details.
 | 
          
            | 13 | //
 | 13 | //
 | 
          
            | 14 | // You should have received a copy of the GNU General Public License
 | 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/>.
 | 15 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
          
            | Línea 16... | Línea -... | 
          
            | 16 |  
 | - |   | 
          
            | 17 | /**
 | 16 |  
 | 
          
            | 18 |  * Steps definitions to open and close action menus.
 | - |   | 
          
            | 19 |  *
 | - |   | 
          
            | 20 |  * @package    core
 | - |   | 
          
            | 21 |  * @category   test
 | 17 | use Behat\Mink\Exception\DriverException;
 | 
          
            | 22 |  * @copyright  2020 Andrew Nicols <andrew@nicols.co.uk>
 | - |   | 
          
            | 23 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | - |   | 
          
            | 24 |  */
 | - |   | 
          
            | 25 |  
 | 18 | use Behat\Mink\Exception\ExpectationException;
 | 
          
            | Línea 26... | Línea 19... | 
          
            | 26 | use Behat\Mink\Exception\{DriverException, ExpectationException};
 | 19 | use Behat\Mink\Element\NodeElement;
 | 
          
            | Línea 27... | Línea 20... | 
          
            | 27 |  
 | 20 |  
 | 
          
            | Línea 36... | Línea 29... | 
          
            | 36 |  * @category   test
 | 29 |  * @category   test
 | 
          
            | 37 |  * @copyright  2020 Andrew Nicols <andrew@nicols.co.uk>
 | 30 |  * @copyright  2020 Andrew Nicols <andrew@nicols.co.uk>
 | 
          
            | 38 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 31 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
          
            | 39 |  */
 | 32 |  */
 | 
          
            | 40 | class behat_accessibility extends behat_base {
 | 33 | class behat_accessibility extends behat_base {
 | 
          
            | 41 |  
 | - |   | 
          
            | 42 |     /**
 | 34 |     /**
 | 
          
            | 43 |      * Run the axe-core accessibility tests.
 | 35 |      * Run the axe-core accessibility tests.
 | 
          
            | 44 |      *
 | 36 |      *
 | 
          
            | 45 |      * There are standard tags to ensure WCAG 2.1 A, WCAG 2.1 AA, and Section 508 compliance.
 | 37 |      * There are standard tags to ensure WCAG 2.1 A, WCAG 2.1 AA, and Section 508 compliance.
 | 
          
            | 46 |      * It is also possible to specify any desired optional tags.
 | 38 |      * It is also possible to specify any desired optional tags.
 | 
          
            | 47 |      *
 | 39 |      *
 | 
          
            | 48 |      * The list of available tags can be found at
 | - |   | 
          
            | 49 |      * https://github.com/dequelabs/axe-core/blob/v4.8.4/doc/rule-descriptions.md.
 | 40 |      * See {@link https://github.com/dequelabs/axe-core/blob/v4.10.2/doc/rule-descriptions.md} for the list of available tags
 | 
          
            | 50 |      *
 | 41 |      *
 | 
          
            | 51 |      * @Then the page should meet accessibility standards
 | 42 |      * @Then the page should meet accessibility standards
 | 
          
            | 52 |      * @Then the page should meet accessibility standards with :extratags extra tests
 | 43 |      * @Then the page should meet accessibility standards with :extratags extra tests
 | 
          
            | 53 |      * @Then the page should meet :standardtags accessibility standards
 | 44 |      * @Then the page should meet :standardtags accessibility standards
 | 
          
            | 54 |      * @param   string $standardtags Comma-separated list of standard tags to run
 | 45 |      * @param   string $standardtags Comma-separated list of standard tags to run
 | 
          
            | Línea 61... | Línea 52... | 
          
            | 61 |             array_filter(array_map('trim', explode(',', $extratags)))
 | 52 |             array_filter(array_map('trim', explode(',', $extratags)))
 | 
          
            | 62 |         );
 | 53 |         );
 | 
          
            | 63 |     }
 | 54 |     }
 | 
          
            | Línea 64... | Línea 55... | 
          
            | 64 |  
 | 55 |  
 | 
          
            | - |   | 56 |     /**
 | 
          
            | - |   | 57 |      * Run the axe-core accessibility tests for a page region.
 | 
          
            | - |   | 58 |      *
 | 
          
            | - |   | 59 |      * There are standard tags to ensure WCAG 2.1 A, WCAG 2.1 AA, and Section 508 compliance.
 | 
          
            | - |   | 60 |      * It is also possible to specify any desired optional tags.
 | 
          
            | - |   | 61 |      *
 | 
          
            | - |   | 62 |      * See {@link https://github.com/dequelabs/axe-core/blob/v4.10.0/doc/rule-descriptions.md} for the list of available tags
 | 
          
            | - |   | 63 |      *
 | 
          
            | - |   | 64 |      * @Then the :element :selector should meet accessibility standards
 | 
          
            | - |   | 65 |      * @Then the :element :selector should meet accessibility standards with :extratags extra tests
 | 
          
            | - |   | 66 |      * @Then the :element :selector should meet :standardtags accessibility standards
 | 
          
            | - |   | 67 |      * @param  string $element The element to run the tests on
 | 
          
            | - |   | 68 |      * @param  string $selector The selector to use to find the element
 | 
          
            | - |   | 69 |      * @param  string $standardtags Comma-separated list of standard tags to run
 | 
          
            | - |   | 70 |      * @param  string $extratags Comma-separated list of tags to run in addition to the standard tags
 | 
          
            | - |   | 71 |      */
 | 
          
            | - |   | 72 |     public function run_axe_validation_for_tags_within_element(
 | 
          
            | - |   | 73 |         string $element,
 | 
          
            | - |   | 74 |         string $selector,
 | 
          
            | - |   | 75 |         string $standardtags = '',
 | 
          
            | - |   | 76 |         string $extratags = '',
 | 
          
            | - |   | 77 |     ): void {
 | 
          
            | - |   | 78 |         $node = $this->get_selected_node($selector, $element);
 | 
          
            | - |   | 79 |         $this->run_axe_for_tags(
 | 
          
            | - |   | 80 |             // Turn the comma-separated string into an array of trimmed values, filtering out empty values.
 | 
          
            | - |   | 81 |             array_filter(array_map('trim', explode(',', $standardtags))),
 | 
          
            | - |   | 82 |             array_filter(array_map('trim', explode(',', $extratags))),
 | 
          
            | - |   | 83 |             $node,
 | 
          
            | - |   | 84 |         );
 | 
          
            | - |   | 85 |     }
 | 
          
            | - |   | 86 |  
 | 
          
            | 65 |     /**
 | 87 |     /**
 | 
          
            | 66 |      * Run the Axe tests.
 | 88 |      * Run the Axe tests.
 | 
          
            | 67 |      *
 | 89 |      *
 | 
          
            | 68 |      * See https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md for details of the supported
 | - |   | 
          
            | 69 |      * tags.
 | 90 |      * See {@see behat_accessibility::run_axe_validation_for_tags} for details of the supported tags.
 | 
          
            | 70 |      *
 | 91 |      *
 | 
          
            | 71 |      * @param   array $standardtags The list of standard tags to run
 | 92 |      * @param   array $standardtags The list of standard tags to run
 | 
          
            | - |   | 93 |      * @param   array $extratags The list of tags, in addition to the standard tags, to run
 | 
          
            | 72 |      * @param   array $extratags The list of tags, in addition to the standard tags, to run
 | 94 |      * @param null|NodeElement $containerelement The element to run the tests on
 | 
          
            | 73 |      */
 | 95 |      */
 | 
          
            | - |   | 96 |     protected function run_axe_for_tags(
 | 
          
            | - |   | 97 |         array $standardtags = [],
 | 
          
            | - |   | 98 |         array $extratags = [],
 | 
          
            | - |   | 99 |         ?NodeElement $containerelement = null,
 | 
          
            | 74 |     protected function run_axe_for_tags(array $standardtags = [], array $extratags = []): void {
 | 100 |     ): void {
 | 
          
            | 75 |         if (!behat_config_manager::get_behat_run_config_value('axe')) {
 | 101 |         if (!behat_config_manager::get_behat_run_config_value('axe')) {
 | 
          
            | 76 |             return;
 | 102 |             return;
 | 
          
            | Línea 77... | Línea 103... | 
          
            | 77 |         }
 | 103 |         }
 | 
          
            | Línea 84... | Línea 110... | 
          
            | 84 |  
 | 110 |  
 | 
          
            | Línea 85... | Línea 111... | 
          
            | 85 |         $this->require_javascript();
 | 111 |         $this->require_javascript();
 | 
          
            | 86 |  
 | 112 |  
 | 
          
            | - |   | 113 |         $axeurl = (new \moodle_url('/lib/behat/axe/axe.min.js'))->out(false);
 | 
          
            | - |   | 114 |         $axeconfig = $this->get_axe_config_for_tags($standardtags, $extratags);
 | 
          
            | - |   | 115 |         $xpath = '';
 | 
          
            | - |   | 116 |         if ($containerelement) {
 | 
          
            | 87 |         $axeurl = (new \moodle_url('/lib/behat/axe/axe.min.js'))->out(false);
 | 117 |             $xpath = $this->prepare_xpath_for_javascript($containerelement->getXpath());
 | 
          
            | 88 |         $axeconfig = $this->get_axe_config_for_tags($standardtags, $extratags);
 | 118 |         }
 | 
          
            | 89 |         $runaxe = <<<EOF
 | 119 |         $runaxe = <<<EOF
 | 
          
            | 90 | (axeurl => {
 | 120 | (axeurl => {
 | 
          
            | 91 |     const runTests = () => {
 | 121 |     const runTests = () => {
 | 
          
            | Línea -... | Línea 122... | 
          
            | - |   | 122 |         const axeTag = document.querySelector('script[data-purpose="axe"]');
 | 
          
            | - |   | 123 |         axeTag.dataset.results = null;
 | 
          
            | - |   | 124 |  
 | 
          
            | - |   | 125 |         const getRun = () => {
 | 
          
            | - |   | 126 |             const xpath = "{$xpath}";
 | 
          
            | - |   | 127 |             if (xpath.length) {
 | 
          
            | - |   | 128 |                 const targetElements = [];
 | 
          
            | - |   | 129 |                 const results = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
 | 
          
            | - |   | 130 |                 let targetElement = results.iterateNext();
 | 
          
            | - |   | 131 |                 while (targetElement) {
 | 
          
            | - |   | 132 |                     targetElements.push(targetElement);
 | 
          
            | - |   | 133 |                     targetElement = results.iterateNext();
 | 
          
            | - |   | 134 |                 }
 | 
          
            | 92 |         const axeTag = document.querySelector('script[data-purpose="axe"]');
 | 135 |                 return axe.run(targetElements, {$axeconfig});
 | 
          
            | - |   | 136 |             }
 | 
          
            | - |   | 137 |  
 | 
          
            | - |   | 138 |             return axe.run({$axeconfig});
 | 
          
            | 93 |         axeTag.dataset.results = null;
 | 139 |         };
 | 
          
            | 94 |  
 | 140 |  
 | 
          
            | 95 |         axe.run({$axeconfig})
 | 141 |         getRun()
 | 
          
            | 96 |         .then(results => {
 | 142 |         .then(results => {
 | 
          
            | 97 |             axeTag.dataset.results = JSON.stringify({
 | 143 |             axeTag.dataset.results = JSON.stringify({
 | 
          
            | Línea 165... | Línea 211... | 
          
            | 165 |                     implode("\n      ", $node->target)
 | 211 |                     implode("\n      ", $node->target)
 | 
          
            | 166 |                 );
 | 212 |                 );
 | 
          
            | 167 |             }
 | 213 |             }
 | 
          
            | Línea 168... | Línea 214... | 
          
            | 168 |  
 | 214 |  
 | 
          
            | 169 |             $violationdata .= sprintf(
 | 215 |             $violationdata .= sprintf(
 | 
          
            | 170 |                 "  %.03d violations of '%s' (severity: %s)\n%s\n",
 | 216 |                 "  %.03d violations of rule '%s' found (severity: %s)\n",
 | 
          
            | 171 |                 count($violation->nodes),
 | 217 |                 count($violation->nodes),
 | 
          
            | 172 |                 $violation->description,
 | 218 |                 $violation->id,
 | 
          
            | 173 |                 $violation->impact,
 | - |   | 
          
            | 174 |                 $nodedata
 | 219 |                 $violation->impact,
 | 
          
            | - |   | 220 |             );
 | 
          
            | - |   | 221 |             $violationdata .= "  {$violation->help}\n";
 | 
          
            | - |   | 222 |             $violationdata .= "  {$violation->description}\n";
 | 
          
            | - |   | 223 |             $violationdata .= "  {$violation->helpUrl}\n";
 | 
          
            | 175 |             );
 | 224 |             $violationdata .= $nodedata;
 | 
          
            | Línea 176... | Línea 225... | 
          
            | 176 |         }
 | 225 |         }
 | 
          
            | 177 |  
 | 226 |  
 | 
          
            | Línea 178... | Línea 227... | 
          
            | 178 |         throw new ExpectationException($violationdata, $this->getSession());
 | 227 |         throw new ExpectationException($violationdata, $this->getSession());
 | 
          
            | 179 |     }
 | 228 |     }
 | 
          
            | 180 |  
 | 229 |  
 | 
          
            | 181 |     /**
 | 230 |     /**
 | 
          
            | 182 |      * Get the configuration to use with Axe.
 | 231 |      * Get the configuration to use with Axe.
 | 
          
            | 183 |      *
 | 232 |      *
 | 
          
            | 184 |      * See https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md for details of the rules.
 | 233 |      * See {@see behat_accessibility::run_axe_validation_for_tags} for details of the rules.
 | 
          
            | 185 |      *
 | 234 |      *
 | 
          
            | 186 |      * @param   array|null $standardtags The list of standard tags to run
 | 235 |      * @param   array|null $standardtags The list of standard tags to run
 | 
          
            | 187 |      * @param   array|null $extratags The list of tags, in addition to the standard tags, to run
 | 236 |      * @param   array|null $extratags The list of tags, in addition to the standard tags, to run
 | 
          
            | 188 |      * @return  string The JSON-encoded configuration.
 | 237 |      * @return  string The JSON-encoded configuration.
 | 
          
            | 189 |      */
 | 238 |      */
 | 
          
            | 190 |     protected function get_axe_config_for_tags(?array $standardtags = null, ?array $extratags = null): string {
 | 239 |     protected function get_axe_config_for_tags(?array $standardtags = null, ?array $extratags = null): string {
 | 
          
            | - |   | 240 |         if (empty($standardtags)) {
 | 
          
            | - |   | 241 |             $standardtags = [
 | 
          
            | 191 |         if (empty($standardtags)) {
 | 242 |                 // Meet WCAG 2.2 Level A success criteria.
 | 
          
            | Línea 192... | Línea 243... | 
          
            | 192 |             $standardtags = [
 | 243 |                 'wcag2a',
 | 
          
            | - |   | 244 |                 'wcag21a',
 | 
          
            | - |   | 245 |                 'wcag22a',
 | 
          
            | 193 |                 // Meet WCAG 2.2 Level A success criteria.
 | 246 |  
 | 
          
            | Línea 194... | Línea 247... | 
          
            | 194 |                 'wcag22a',
 | 247 |                 // Meet WCAG 2.2 Level AA success criteria.
 | 
          
            | 195 |  
 | 248 |                 'wcag2aa',
 | 
          
            | 196 |                 // Meet WCAG 2.2 Level AA success criteria.
 | 249 |                 'wcag21aa',
 |