quailjs / quail

Accessibility testing in the browser and on the server.
http://quailjs.org
Other
300 stars 44 forks source link

Test for WCAG technique H94: Ensuring that elements do not contain duplicate attributes #67

Closed kevee closed 10 years ago

kevee commented 10 years ago

Create a test for the following WCAG 2.0 technique: http://www.w3.org/TR/WCAG20-TECHS/H94.html

Tests Procedure

kevee commented 10 years ago

This is going to be difficult, since browsers usually clean this kind of error up in the DOM. I tested this on the following browsers (from http://jsfiddle.net/kevee/f9xeH/2), and they all just remove any duplicate attributes and keep the first instance:

hannolans commented 10 years ago

There are certain tests in WCAG2, especially about parsing (4.1.1), that needs the unrendered file. Is the unrendered file unavailable for QUAIL?

kevee commented 10 years ago

Things like document.documentElement.outerHTML will still fetch the HTML code after the browser has parsed it.

We could add a component to quail where if you are writing a scraper app it could hand quail the string of HTML as an argument, but if it was running client-side it instead made an ajax call to the current page's URL and hopes that it works. That string could then be available to all tests.

The one problem from a client-side content-checking implementation (like integration in a CMS) is that you would then loose the scope of what element of the page you were checking, so tests that implement this couldn't just check code for a part of a page. These tests would require a caveat emptor notice about that.

kevee commented 10 years ago

Added the full-html-source branch with a new component called htmlSource. It's pretty simple so far:

quail.components.htmlSource = function(callback) {
    if(typeof quail.options.htmlSource !== 'undefined' && quail.options.htmlSource) {
        callback(quail.options.htmlSource);
        return;
    }
    var html = '';
    $.get(window.location.href, function(data) {
        callback(data);
    });
}

Basically, we are assuming if you are running this on a server, than you can just pass in htmlSource as an option like we do in the qunit test. If that is not passed, it will try to use a jQuery $.get option. Now, there are a lot of ways just doing a GET call to window.location.href will return HTML code that is different than the current page. Also, finding the current page element with the problem from the HTML code is going to require some very complex regular expressions.

For example, here's a common regular expression for finding attributes of a tag:

(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?

This will work against:

<a href="something.html">
<a href='something.html'>

But it won't work against common typos that a browser just fixes for you, like:

<a href="something.html>
kevee commented 10 years ago

I've been playing with [https://github.com/tautologistics/node-htmlparser](Node HTMLParser) quite a bit, and it seems to be our best option when it comes to turning a string of HTML into something that can be traversed without actually implementing the DOM spec (where attributes are NamedNodeMap and therefore there can be only one).

Sections of the HTMLParser would have to be overridden by quail to have it not fix these kind of errors so we could report on them. We could also use the structure of the object returned to try and re-find the element in the current page's DOM.

hannolans commented 10 years ago

Is that library also usable for the other raw HTML tests, for example the correct use of closing tags: #88 Do we have an overview of WCAG2 tests that require source HTML (and/or source css and source javascript?

kevee commented 10 years ago

Correct, this can be used for the other tests, although it looks like in WCAG these techniques are only applying to SC 4.1.1. The approach I am using now is to load the HTML as a string (describe above) and then try and build a very-specific selector based on the structure from htmlparser and then load that 'element' object from the parser as jQuery data on the node. We can then check that it is within the scope quail is looking at and also report back to the user if used as a client-side feedback tool.

hannolans commented 10 years ago

Interesting area. Besides HTML, we might also need source javascript to analyse javascript techniques (http://www.w3.org/TR/WCAG20-TECHS/client-side-script.html), for example: http://www.w3.org/TR/WCAG20-GENERAL/SCR21

kevee commented 10 years ago

We could definitely do that as well. I am committing a few tests of our new 'shadow DOM to element selector' method, it works well. Because of memory considerations, I'm not duplicating all of the parsed HTML back to jQuery data elements, it caused several "sad tabs."

Instead there is a quail.components.htmlSource.traverse method that can traverse the DOM node and pass off the elements to a callback.

kevee commented 10 years ago

It looks like we are good with duplicate attributes, closing.