From the Blog

Active echolocation for blind mobility
Increase independence and experience the world in a new way

Unit vs Integration Tests

There is not a lot of good information on the Intertubes about unit tests versus integration tests. They both server good purposes, but the key to using them well is to understand their limitations. The largest mis-perception is that 100% coverage with unit tests is all you need. This is not the case. In any system of any complexity, especially ones built on protocols or dynamic languages, this can lead to a false sense of security.

The reason for this is the misunderstanding around the limitations of unit tests. Although all that needs to be said about it is in its name "unit", some developers just don't really get the limitation. Let me illustrate...

Assume you have the following module that forms part of an integrated system:


function Greeting() {
this.greeting = null;
}

Greeting.prototype.getGreeting = function() {
return this.greeting;
};

Greeting.prototype.displayGreeting = function(el) {
el.innerHTML = this.greeting;
};

Greeting.prototype.setGreeting = function(str) {
this.greeting = str;
};

With a simple QUnit test case, we can validate that this works as expected (of course I have abbreviated what would be required for a full test for illustration purposes):


(function(jQuery) {
module( "core - Greeting" );

test( "Test Greeting", function () {
var g = new Greeting(),
fix = jQuery("#greeting");

expect(3);
g.setGreeting("Hello");
equal( g.getGreeting(), "Hello");
equal( fix.text(), "");
g.displayGreeting( fix[0] );
equal( fix.text(), "Hello");
});
}(jQuery));

And in another module, we can use this Greeting class successfully as follows...


var g = new Greeting();

...

g.setGreeting('Hello World');

...

g.displayGreeting(target);

...

Now this consumer module would have its own unit tests and (following unit testing best practices) would mock the Greeting class - perhaps as follows...


function Greeting() {
this.setGreeting = function(str) {
this.msg = str;
};
this.displayGreeting = function (el) {
el.innerHTML = this.msg;
}
}

All unit tests pass and the code coverage metrics exceed 95% - SUPER!!!

Now the Greetings development team decides that the module requires an update to simplify the API because all users of the module always call "new Greeting();" and then "setGreeting()", so setGreeting can be eliminated in favor of a constructor parameter and they refactor the code to:


function Greeting(msg) {
this.greeting = msg;
}

Greeting.prototype.getGreeting = function() {
return this.greeting;
};

Greeting.prototype.displayGreeting = function(el) {
el.innerHTML = this.greeting;
};

A huge improvement and a decrease in lines of code of almost 25%. This breaks the unit tests, so they fix these as follows...


(function(jQuery) {
module( "core - Greeting" );

test( "Test Greeting", function () {
var g = new Greeting("Hello"),
fix = jQuery("#greeting");

expect(3);
equal( g.getGreeting(), "Hello");
equal( fix.text(), "");
g.displayGreeting( fix[0] );
equal( fix.text(), "Hello");
});
}(jQuery));

The UNIT tests all pass and they commit the code. The CI server runs all the tests, they all pass. The code coverage metrics look great!! All is well... Well as you have probably already figured out, the integrated system just failed. This is the limitation of unit tests! They are blind to API changes.

Solutions

The only 100% effective solution is to make sure you have code coverage with your integration tests. Unit tests are great for libraries that are consumed by parties that are distantly related and who have an distinct distrust of one another.

An alternative approach is to build dependency tests. So in this example, if the consumer team had a set of unit tests for the Greeting class that it ran independently, then this issue would have been caught. But if you do this, what you are requiring is:

  • That the producer of a module produces unit tests of their module
  • That a consumer of a module writes a mock of the module they are consuming
  • That the consumer of a module writes unit tests for the portions of a module they rely on
  • That the consumer of the module write unit tests for their own module

You end up writing almost 4 times the code for every module.

Yet another approach is for API providers to publish unit tests separately, in a way that does not get updated automatically (e.g. a separate repository or directory for every release). This set of unit tests could then be run by consumers against the API and detect when they are consuming a version whose API has changed. This works well for internal teams, where the test execution framework is standardized, but is likely to place a large burden on a consuming team where the test frameworks differ.

Even with the above unit test approaches, data, environments and other factors will require a decent amount of integration testing anyway. Ultimately, in my opinion, for code your organization owns, you should always write integration tests before you write unit tests. Unit tests are optional, integration tests are not optional.

Accessible form layout

Most people think of blind users when thinking about accessibility, however there are other disabilities that are impacted by bad form design, following some simple layout principles can address the major issues faced by these disability groups.

The first group is users whose sight is impaired in some way, but who see well enough to be able to use a mouse and screen. The disabilities in this group range from the inability to see color, to the need to magnify the screen in order to be able to perceive form details. The second group is users with cognitive disabilities. Users in this group may have difficulty understanding the requirements for successfully completing the form and/or the reasons why a form submission failed. The third group is users who can see but because of some physical limitation, must use a keyboard or a keyboard equivalent such as a mouth operated pointing device.

Color is an important helper to assist users with cognitive disabilities to understand the reason(s) for a form submission failure, however, relying on color alone excludes those users who can see but cannot distinguish color. For example, a common technique employed by form designers is to turn the border and label of a form field red if the form content failed validation. If your form has a light background, with a dark text color, then two small additional CSS property changes can turn this inaccessible technique into one that works wonderfully. Simply set the label foreground color to white and the background color of the label to a dark red (so that the color contrast ratio exceeds the 4.5:1 ratio required by WCAG 2 Level AA - #8b0000 works well as a dark red). Now if someone cannot see color, they can clearly see the fact that some labels have switched to a light text on a dark background while others have kept the dark text on a light background and they can take action. An alternate approach is to add an additional text (e.g. ERROR) or an icon to convey the error state.

If form labels are left justified and the input fields right justified, then screen magnifier users can easily drift up or down as they traverse from the label to the field and back again using the mouse. This can lead them to associate the label with the wrong form field.

Screen shot showing left justified labels with a required field asterisk right justified and the form fields also right justified
Screen shot showing left justified labels with a required field asterisk right justified and the form fields also right justified
Screen shot showing form field zoomed with a screen magnifier. The label is not visible and must be traversed-to by the user
Screen shot showing form field zoomed with a screen magnifier. The label is not visible and must be traversed-to by the user

Forms, styled in this way also look bad on mobile devices and can lead users with 20/20 vision to also misconstrue which form field is which. Simply placing the label text immediately above the input field can solve this problem for both user scenarios. Alternative approaches are to zebra stripe the background or to center justify all the form labels and form fields. The added advantage of the label positioning above the form field is that when the label color treatment described above is applied for invalid fields, it is also immediately perceivable to screen magnifier users.

Screen shot showing a form with labels placed above the form fields and a border treatment that clearly associates the label with the field below it
Screen shot showing a form with labels placed above the form fields and a border treatment that clearly associates the label with the field below it
Screen shot showing the input field with the label above it zoomed to a high zoom level. The label is clearly visible
Screen shot showing the input field with the label above it zoomed to a high zoom level. The label is clearly visible
The same form displayed on an iPhone device. The labels above the input fields work well and does not require zooming by the user.
The same form displayed on an iPhone device. The labels above the input fields work well and does not require zooming by the user.

Similar approaches can be used for additional instructional text, tooltips and help links.

DOM, tab and reading order

Using explicit tabindex values may seem like a good idea where the main purpose of a page is the form itself. It allows users to tab into the page and be immediately placed on the first input field. The problem with this technique is, if not applied correctly, it can lead to an almost impossible experience for sighted keyboard users. A common problem is that the tabindex only gets applied to the input fields themselves and not to things like help icons or help links that might appear in the form. When this is the case, a sighted keyboard user is forced to tab through the entire form, all the way to the top of the page navigation (hopefully then use the skip nav link to move to the form itself), and then will be able to tab to the help link they want to activate. After having viewed the help text, the user is now forced to repeat the entire process to get back to the form field itself (which may be the 10th field on the form). This makes the form almost impossible to use for a user of a stick input device or equivalent because each and every keyboard stroke requires significant effort.

Of course it is possible to set up the tabindexes correctly, but they are prone to breakage on modifying the page and really provide no real advantage if you have made consideration for keyboard only users - so my recommendation is to simply get rid of them entirely. If you need your focus to go to the first form field automatically, simply use JavaScript to achieve this, or better yet, supply a skip navigation link at the top of the page.

Unnecessary JavaScript Focus Management

Another common problem is the use of JavaScript to automatically advance the keyboard focus when the user enters data into a form field. Social security numbers and dates are commonly treated this way. The problems this can lead to include making it more difficult for keyboard only users to correct a data entry problem (because the focus has already skipped to the next field), making it difficult for screen magnification users to see the data they entered and check it for validity and it is a very common source of keyboard traps. The keyboard traps result when the focus or keyup handler (depending on when the validation is performed) checks the form value and (noticing that it has the required length) auto advances the focus to the next field. U user trying to shift-tab back into the field will end up having their focus consistently being advanced to the next field.

The recommendation for fields like this is to simply allow the user themselves to control when they skip to the next field. The exception is for business-internal applications (such as data entry) where the user is an expert, knows the system well and has been trained to expect this behavior.

Accessible Form Labeling Basics

The most basic and important aspect of making forms accessible is to ensure that the form fields have perceivable labels and that all instructions and error messages are programmatically associated with the form field. This is important because it ensures that users of screen readers can be reliably and accurately informed of the labels, errors and instructions for the fields as they navigate through them. It also allows screen reader users to choose the navigation method that they prefer (i.e. you are not forcing the user to use DOM navigation to try to decipher the form) and it allows the form designer more flexibility with form layout without having to sacrifice any accessibility.

It is also a best practice to ensure that the labels, instructions and error messages are closely and visually associated with the input. This allows users of screen magnification software to easily track the associations between form fields and their instructional information with ease. It eliminates the the errors that can occur when traversing the space between the label and the form field, that sometimes result in the wrong form field receiving the input - which can have unintended consequences including but not limited to the exposure of password information.

Simple Labels and Error Messages

The preferred mechanism for associating labels (and error messages) with form fields is the for-id mechanism. It is simple. Attach a unique id to the form field and then use a "for" attribute on the label to point to that input field. Here is some example HTML code.


<label for=“myinputid”>Label Text</label>
<input id=“myinputid” type=“text” />

This label can then also be utilized for adding error information if validation fails as shown below. The advantage of this mechanism is it is supported by all ATs even those that are many years old.


<label for=“myinputid”>Label Text
<span> (this field can only contain moon runes)</span>
</label>
<input id=“myinputid” type=“text” />

A couple of years ago, I would have recommended the label wrapping mechanism as the best mechanism for labeling, but I have recently seen some bad treatment of labels using this mechanism by some ATs including double-announcing the label as well as sometimes not announcing the label at all. These are obviously AT bugs, but I like to use the most robust techniques, so I have stopped recommending label wrapping. Here is an example for completeness' sake.


<label for=“myinputid”>Label Text
<input id=“myinputid” type=“text” />
<span> (this field can only contain moon runes)</span>
</label>

As you can see, the advantage of this is it allows the label and error message to be split visually between above and below the field. However there is now a newer, more flexible mechanism for achieving this, using the WAI-ARIA aria-labelledby attribute. This works by attaching unique IDs to all of the label elements (you can have any number of elements serving as labels) and then adding the aria-labelledby attribute to the input field with the IDs, separated by spaces, in the order that you would like them to be announced by the screen reader. Here is an example.


<label id=“mylabelid”>Label Text</label>
<input aria-labelledby=“mylabelid” type=“text” />

Of course, the same technique can then be used to add the programmatic association between the input field and the error message as shown below. Because the label's id is first, it will be read out before the error message.


<label id=“mylabelid”>Label Text</label>
<input aria-labelledby=“mylabelid myerrorid” type=“text” />
<span id="myerrorid"> (this field can only contain moon runes)</span>

The final example of simple labeling is the use of the title or the aria-label attribute. This technique should be used only if there is a persistently visible label for sighted users i.e. it does not require users (who might have cognitive disabilities) to remember which form field they are on once the form field receives focus. A common, good example of use is a search field that appears in the header of a web site. In this scenario, the "search" button (often represented with a well understood "magnifying glass" icon) serves as the persistent visual label. In this scenario, the title attribute (or the aria-label attribute) can be supplied to provide a label for screen readers. An example is given below. Note: the title attribute is slightly preferred over aria-label due to having wider AT support as of October, 2013. This may (will) change in the future.


<input id=“search” type=“text” title=“Search” placeholder=“Search”/>
<button>Search</button>

Multiple labels

The aria-labelledby technique shown previously can obviously be used for attaching multiple labels to fields. It is particularly useful if you want to control the exact order in which the labels are read out, regardless of which assistive technology is being used by the user. The reason this might be important is that the older techniques for assigning multiple labels are not consistently interpreted by AT. An example of this is the <fieldset> and <legend>. The example below shows its use to apply two labels to the components of the social security number. The problem with this is that some screen readers will read out the group label on every single input element in the group, whereas others will only read it out when the first element in the group receives focus. This also goes for any anchor tags that appear in the group - which means that the group label may not be remembered by the user (if the AT only reads it once), or it may be irritating (if read out all the time). Below is an example of the SSN group markup using titles for the second label because the legend serves as a sufficient label for the sighted user.


<fieldset>
<legend>Social Security Number</legend>
<input type="text" name="ssn1" id="ssn1” title="first three digits"/> -
<input type="text" name="ssn2" id="ssn2” title="middle two digits"/> -
<input type="text" name="ssn3" id="ssn3” title="last four digits"/>
</fieldset>

Additional Instructions

Often, forms will include additional instructions that help the user in filling out the form accurately and successfully. For example, when filling in a name on a government web site, it might be important to ensure that the name matches precisely the name on some form of government issued id. Other common examples are the formats for dates, numbers and currency or the maximum length of an input field. Prior to ARIA, including this sort of information was only possible through the title attribute. This meant that the information was doubled in the page. ARIA has given us a new, much more flexible option - aria-describedby. It is similar to aria-labelledby in that it contains the ids, separated by spaces but it is read by the ATs after the label, the type and the value. The example below shows an example of a date input field with formatting instructions.


<label for=“mybirthdateid”>Date of Birth</label>
<input id=“mybirthdateid” type=“text” aria-describedby=“datefmt”/>
<span id=“datefmt”>format: dd/mm/yyyy</span>

aria-describedby can also be used as an alternative for attaching error messages if, for some reason, aria-labelledby cannot be used and the error message cannot be inserted into the label. Just be aware that on VoiceOver on OS X, the default setting causes VO to pause for 8s. This setting can be changed by the user and it is likely that most users will change it, but just be aware of this potential limitation.

Accessible Dynamic Forms and Form Validation – Part I: Commonly Violated WCAG 2 Guidelines

Forms are some of the most important pieces of most web sites, without them, we would not be able to log in, sign up, purchase, comment, post or do many of the things we take for granted every day. Given the importance of forms, it is quite shocking that you can go to almost any Fortune 100 company's web site - including many financial services web sites - and find forms that have the most basic accessibility issues. That is why, when we hosted our recent jQuery Accessibility Summit, I insisted on having a session on forms and form validation and when nobody else stepped up to give it, I decide to give the presentation myself.

You can view the presentation slides on Slideshare and embedded at the bottom of this posting. I am going to do a series of blog posts here that add the detail that the slides cannot convey. This first post in the series covers...

The WCAG 2.0 Level AA Guidelines that are Commonly Violated in forms

Firsty, let me say that ALL WCAG 2 guidelines are potentially applicable to forms, but there are some that are more common and these are:

  • Perceivable

    • 1.3.1 (A) Associate labels programmatically with their input fields

    • 1.3.1 (A) Associate error messages programmatically with their input fields

    • 1.4.1 (A) Do not use color alone to indicate differences between fields (required, errors etc.)

    • 1.4.3 (AA) Ensure sufficient contrast between foreground and background (labels, instructions, errors etc.)

    • Best Practice: visually associate labels, instructions and errors with their input fields

  • Operable

    • 2.1.1 (A) If you take action to allow mouse users to easily identify error fields, an equivalent must be provided for keyboard only users

    • 2.1.1 (A) Everything must be operable with the keyboard only

    • 2.1.2 (A) No keyboard trap

    • 2.4.3 (A) Error messages that appear and apply to the whole form should be announced automatically

    • 2.4.3 (A) Instructions that change or appear dynamically must be announced automatically

    • 2.4.3 (A) The focus order of the elements in the form must match the visual order

    • 2.4.7 (AA) There must be a visual focus indicator to show keyboard users where the focus is at all times

  • Understandable

    • 3.2.1 (A) On Focus events should not do things to confuse or disorient the user

    • 3.2.2 (A) Changes that occur based on input should not confuse or disorient the user

    • 3.3.3 (AA) Error messages should provide suggestions as to how to correct the errors wherever this is feasible and does not compromise security

    • 3.3.4 (AA) If the form is on a financial or testing site or has legal ramifications, then the user must be given a chance to review their form inputs prior to submission

  • Robust

    • 4.2.1 (A) Role, Value, Name and State of all form elements should be accurate during all dynamic states of the form

In upcoming posts, I will elaborate on some of the tricks and techniques to help you to adhere to these guidelines.

from

a11yfy jQuery library implements WAI-ARIA menu

There was a great amount of chatter in the Twittersphere when Adobe open sourced their accessible mega menu implementation. I was a bit disappointed by the choices that Adobe made with that implementation. Kudos to Adobe for putting as much thought into their solution as they did, however given that the community has been putting a lot of effort into the WAI-ARIA menu authoring guidelines (previously known as the AOL DHTML style giude), I would have liked to have seen a compliant implementation and some activity to work with the community on changing the guidelines if they think they need improvement.

So I decided to implement a menu implementation that supports both mega-menus and more traditional menus but that adheres to the WAI-ARIA authoring guidelines for the menu roles. It has been included in the a11yfy core jQuery library and is implemented in a relatively light 220 lines of JavaScript code plus about 120 lines of CSS code, so if you don't want the full weight of the a11yfy core library (currently 21K unminified), you can easily pull out that code and have something general purpose that is very small.

Utilizing the library is very straightforward, simply set up a set of embedded unordered lists. Just be sure to include an anchor tag in the leaf menu items and away you go. The following is an example of the HTML required for a multi-level menu.


<ul id="mymenu">
<li>One
<ul>
<li><a href="oneone">One One</a></li>
<li><a href="onetwo">One Two</a></li>
<li><a href="onethree">One Three</a></li>
<li><a href="onefour">One Four</a></li>
</ul>
</li>
<li>Two
<ul>
<li>Two One
<ul>
<li><a href="twooneone">Two One One</a></li>
<li><a href="twoonetwo">Two One Two</a></li>
<li><a href="twoonethree">Two One Three</a></li>
<li><a href="twoonefour">Two One Four</a></li>
</ul>
</li>
<li><a href="onetwo">Two Two</a></li>
<li><a href="onethree">Two Three</a></li>
<li><a href="onefour">Two Four</a></li>
</ul>
</li>
<li><a href="three">Three</a></li>
<li><a href="four">Four</a></li>
</ul>

To turn these unordered lists into a horizontal menu, simply use the following line of jQuery code:


jQuery("#mymenu").a11yfy("menu");

The a11yfy GitHub project contains two examples for you to base your code on. One of these is a normal WAI-ARIA JavaScript menu and one is a WAI-ARIA JavaScript mega menu. The examples make use of the builtin CSS for styling, but it is really straightforward for you to replace this CSS with styling that fits your site.

Automated Testing of the WAI-ARIA Menu Keyboard and Focus Functionality

One of the nicer pieces of the a11yfy implementation is that fact that the testing of the WAI-ARIA compliant keyboard and focus functionality has been automated with QUnit unit tests and achieves a coverage of 95% as measure by the blanket JavaScript code coverage tool. I do not know of another example of a fully automated test of an ARIA compliant UI widget - at least not an open source one.

QUnit, Blanket, PhantomJS and Grunt: Complete Coverage and Unit Testing for Jenkins

At the Labs I have been putting a lot of focus on automated unit testing and code coverage lately. We had found solutions for our Node.js based server and our Groovy-based server but were still lacking something that would work well for front end UI code. We needed a solution that would allow for interactive coverage analysis as well as automated coverage analysis and would also integrate well with Jenkins.

Everyone is really heads-down on a big release right now, so I decided to roll up my sleeves and find/build a solution that the team can use. We use jQuery for most of our web UI, so I needed a solution that works well with that. I did some research and there seemed to be 2 viable solutions - JSCover and Blanket.

I evaluate JSCover first and it worked reasonably well for interactive analysis but it requires a whole new server and there seemed to be some substantial unsolved problems related to integrating it with Grunt and grunt-contrib-qunit in combination with PhantomJS. There might be solutions out there somewhere but they did not present themselves to me.

So I turned to blanket and after a bit of persistence struck a rich vein of coverage gold. Firstly, the solution is really elegant in that simple attributes, applied to script tags drive a lot of the behavior. For example, adding "data-cover" to a script tag will enable instrumentation for that file. No need to exclude files, simply tell Blanket what you actually want to measure. The paradigm fits really well with the overall HTML-JavaScript paradigm and is also robust against future changes to your dependencies.

Blanket also comes with a built-in qunit runner which plays really well with the qunit UI and allows coverage to be toggled from within the Browser interactively. There is also a nice, clean UI for displaying and analyzing coverage results. I was also able to quickly figure out how to run the coverage tests automatically when running through grunt-contrib-qunit, but it took a little bit of custom code. The first bit of custom code was required to insert the blanket script into the HTML test suite file. The reason for this is that the interactive testing requires the developer/tester to be able to toggle coverage on and off through the QUnit UI, while the Grunt testing needs to be able to run the coverage automatically as well as report the coverage results back to Jenkins. I call this little script "cover-with-blanket.js":



(function() {
/*
* This little function inserts the blanket into the QUnit HTML suite in such a way that interactive
* coverage tests can be used when in a real browser and automatic coverage testing performed
* when using PhantomJS. Another solution would be to use a custom Blanket adapter but that is more
* work, so being saved for a rainy day
*/
var $script = jQuery("<script src=\"../../../bower_components/blanket/dist/qunit/blanket.js\">");
if (window && window.navigator.userAgent.indexOf("antom") !== -1) {
$script.attr("data-cover-reporter", "../../creporter.js").attr("data-cover-flags", " autoStart ");
}
jQuery("script").last().after($script);
}());

The magic here is in the conditional addition of the "autoStart" option to the data-cover-flags attribute and the conditional addition of a customized reporter through the "data-cover-reporter" attribute. This custom reporter is what allows me to get the coverage data back into my Grunt task so I can output it in a format that can be consumed by Jenkins. Here is the final code for the creporter.js file.



(function (){
/*
* This sendMessage function piggy backs off grunt-contrib-qunit's use of the
* builtin PhantomJS bridge (alert) to pass messages back to Grunt.
*/
function sendMessage() {
var args = [].slice.call(arguments);
alert(JSON.stringify(args));
}
// Simple console reporter
if (window && window.navigator.userAgent.indexOf("antom") !== -1) {
blanket.customReporter = function (coverageData) {
var lines, covered, file, i;

/*
* Process the data to calcuate the three pieces of information we want to distill
* for grunt/Jenkins. There is a lot more information here that might be of interest in the future
*/
for (file in coverageData.files) {
lines = 0, covered = 0;
for (i in coverageData.files[file]) {
if (coverageData.files[file][i] !== null && i !== "source") {
lines += 1;
if (coverageData.files[file][i] > 0) {
covered += 1;
}
}
}
}
/*
* The message "channel" must start with "qunit" in order to ensure that it is re-broadcast
* by grunt-contrib-qunit
*/
sendMessage("qunit.coverage", {
coverageData: {
lines : lines,
covered : covered,
percentage : (covered/lines)*100
},
a11yfyTestUnit : a11yfyTestUnit
});
};
}
})();

On the Grunt side, we need a bit of code to capture the coverage data and then aggregate it into a format that can be consumed by Jenkins. The first bit of code is the receiver for the PhantomJS bridge call in the code above. This code writes the coverage data in JSON format into files in the "coverage" directory.



// listen for events from the report writer
grunt.event.on('qunit.coverage', function (data) {
var fs = require("fs");
try {
fs.mkdirSync("coverage");
} catch( err) {}
fs.writeFileSync("coverage/" + data.a11yfyTestUnit + ".txt", JSON.stringify(data.coverageData));
console.log("lines : " + data.coverageData.lines + ", covered : " + data.coverageData.covered + ", percentage : " + data.coverageData.percentage + "\n");
});

The second piece of code is a "coverage aggregator" Grunt task that sums up all the coverage data and creates an HTML report in the CodeCover report format. I chose this format because there is a standard Jenkins plugin for this format that I could utilize to display the data and set healthy/unhealthy/failed status on my Jenkins job(s).



grunt.registerTask("coverage_aggregate", "Aggregate coverage reports into report.html", function() {
var fs = require("fs"),
data,
coverageFiles,
summaryData = {
lines : 0,
covered: 0,
percentage : undefined
};

data = fs.readFileSync("report-template.html").toString();
coverageFiles = fs.readdirSync("coverage");
coverageFiles.forEach(function(file) {
var cData = JSON.parse(fs.readFileSync("coverage/" + file));
summaryData.lines += cData.lines;
summaryData.covered += cData.covered;
});
summaryData.percentage = (summaryData.covered/summaryData.lines)*100;
data = data.replace(/\{\{lines\}\}/gi, summaryData.lines);
data = data.replace(/\{\{covered\}\}/gi, summaryData.covered);
data = data.replace(/\{\{percentage\}\}/gi, summaryData.percentage);
data = data.replace(/\{\{creationDate\}\}/gi, new Date().toString());
fs.writeFileSync("report.html", data);
});

As you can see, I am making use of a report-template.html file and inserting my aggregated data into that template when generating the coverage report. You will also notice that I am only generating statement coverage data and am therefore duplicating the data for all the data points in the CodeCover report.

Using these simple adaptations in combination with the grunt-qunit-junit grunt module allows me to get both QUnit test results in my Jenkins job as well as the code coverage report. I also am able to set thresholds for both code coverage and tests and the resulting Jenkins integration is really, really nice. Of course I had to enable the Jenkins JUnit and CodeCover modules.

I have implemented this solution fully in the a11yfy project, clone it on GitHub and then add the following shell commands to your Jenkins job to see the magic:



npm install
grunt all

jQuery a11yfy plugin implements accessible responsive data tables

In my previous post on responsive accessible data tables, I showed a full solution to accessible responsive data tables. The problem with that posting is that it made use of handlebars templates. That solution is not likely to be acceptable to a lot of applications. Also the CSS needed to be synced up with the JavaScript code manually.

So I took those concepts and implemented a jQuery plugin that allows the calling JavaScript to apply responsiveness to an existing table and creates the CSS automatically if required. The code can be found at the a11yfy GitHub page. Here is a synopsis of the important bits.

As I wrote in the original posting on responsive tables, the two problems other postings on accessible data tables have left unsolved are:

  • When the tables get rendered in the format for the smartphone sized device, they no longer appear to the AT as a table and the user then loses important abilities to easily navigate the table from column-to-column and row-to-row
  • The responsive tables can only be layed out in a row format. I.e. it is not possible to create a responsive table layed out in columnar format on a desktop and columnar sequential format on a smartphone sized device by purely using CSS.
The a11yfy jQuery plugin solves these problems but you may still want to read the accessible culture posting because that solution utilizes :before content to add visible headers to every cell and you might be interested in that technique. If you do modify the a11yfy jQuery plugin to support :before content, be sure to submit a pull request so I can integrate your changes.
In order to solve the aforementioned problems, a11yfy needs to:
  1. Get the AT to treat a sequentially laid-out table as a table, and
  2. Get columnar tables to switch from columnar format on the desktop to row format on a smartphone at the responsive breakpoint

CSS changes to reflow a table accessibly

It turns out that ATs look at the display property when deciding whether or not to treat a table as a table. This does not make any sense to me, but it is the current situation. So the CSS generated by the a11yfy plugin (based on the accessible culture CSS) changes the td and th cells to display:block. Also, in order for the AT to recognize the table as a table, it needs to have both a <thead> element and a <tbody> element. Omitting either of these will cause the AT to not recognize the table correctly. However, when the responsive CSS is applied, the <thead> elements will not be interpreted properly by the AT (at least not consistently). For this reason, the generated CSS also hides any <tr> elements inside the <thead> These two changes allow the table to be flowed responsively and still be recognized by the AT as a table - maintaining the header announcement and table navigation in both layouts.

Here is the generated CSS for a breakpoint of 980px width.



(max-width: 980px) {
/* Force table to not be like tables anymore but still be navigable as a table */
table, thead, tbody, tr {
width: 100%;
}
td, th {
display: block;
}
/* Hide table headers with display: none because accessibility APIs do not pick up reliably on these headers anyway */
thead tr {
display:none;
}
tr { border: 1px solid #ccc; }
td, th {
/* Behave like a "row" */
border: none;
border-bottom: 1px solid #eee;
position: relative;
}
td:before, th:before {
/* Now like a table header */
position: absolute;
/* Top/left values mimic padding */
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
}
}

Switching from columnar to row at the breakpoints

The problem of switching from columnar to row structure at the appropriate breakpoint is solved by a11yfy with JavaScript that

  1. Detects the size of the window when the table is "a11yfied" and draws the appropriate table structure, and
  2. Attaches to the resize events of the window and then redraws the table appropriately depending on the new window dimensions

Here is a snippet of code showing the important bits of this. You will also notice that a11yfy sets a timeout that is cancelled on subsequent resize event so that the table is not redrawn until the resize events stop being generated for at least 50 milliseconds. This is to avoid constant redraws as the user drags the window to resize it.


dimensions = getDimensions();
drawTable( $table, data, headers, dimensions, opts);
jQuery(window).on("resize", function () {
newDimensions = getDimensions();
if (!equalDimensions(newDimensions, dimensions)) {
if (resizeTimer) {
clearTimeout(resizeTimer);
resizeTimer = undefined;
}
dimensions = newDimensions;
resizeTimer = setTimeout(function () {
drawTable( $table, data, headers, newDimensions, opts);
}, 50);
}
});

Using a11yfy against an existing table is quite simple and well documented. Here is some code that shows its use with a small version of the table used in the posting on sortable/filterable tables.


<!DOCTYPE html>
<html>
<head>
<script src="../tests/jquery.min.js"></script>
<script src="../a11yfy/jquery.a11yfy.core.js"></script>
<script src="jquery.a11yfy.tables.js"></script>
<script src="../i18n/jquery.a11yfy.i18n-de.js"></script>
</head>
<body>
<table id="responsive">
<thead>
<tr>
<th scope="col">Nelson Mandela</th>
<th scope="col">Steve Nash</th>
<th scope="col">Sasha Pieterse</th>
<th scope="col">J.R.R. Tolkien</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>95</td>
<td>39</td>
<td>17</td>
<td>81</td>
</tr>
<tr>
<td>Former political prisoner who upon his release was elected president of South Africa in 1994.</td>
<td>NBA legend who won the MVP in 2005 and 2006 with the Phoenix Suns, and played in eight NBA All-Star games.</td>
<td>Teen actress who played Alison DiLaurentis on the hit ABC Family series Pretty Little Liars.</td>
<td>English author, poet, and professor who created The Hobbit and The Lord of the Rings trilogy.</td>
</tr>
</tbody>
</table>

<script>
jQuery(document).ready(function (e) {
jQuery('#responsive').tables({
sortFilter: 'none',
responsive: {
breakPoint: 980,
css: true
}
});
});

</script>
</body>
</html>

There is a bit more to the a11yfy plugin, for example it also implements the sortable/filterable solution in a previous post, has functions for portable aria-live announcements and for managing focus in a reliable way when VoiceOver is turned on on an iOS device. Read the details on the GitHub page.

Messed Up iOS Focus Management with VoiceOver

Focus management on iOS with Voiceover is really messed up. If you are trying to implement an accessible dialog box, where the dialog box appears and is inserted into the page dynamically, it is necessary to manage focus actively and set the focus into the dialog box when it appears and send it back to where it was after the dialog box is dismissed.

On iOS, however, focus is so messed up, that the only way to get ANY focus to go into the newly added elements is to set a timeout to set focus into the dialog content. Any attempt to set focus into dynamically inserted content on iOS will fail without this. You would think that a timeout of 0 would work nicely and you would be horribly wrong. A timeout of 100ms, quite sufficient for most ugly JavaScript hacks, does not work either. No, you need a whole 1000ms (1s) timeout in order for the focus to reliably go anywhere close to where you intend it to go.

You can play around with this yourself by visiting the messed up iOS focus management with VoiceOver demo page and following the instructions. Any value above 0 will first set a timeout of 1000ms which simulates a decision process that might take place to decide whether the given user is a candidate for a survey. Once the content for the survey is inserted into the page, a second timeout will be set for the number of milliseconds you enter in the input field. When this timeout triggers, the focus is then supposed to end up on the "No Thanks" button. Instead, depending on the value of the timeout for the second setTimeout call, it will end up somewhere between the top of the document and the targeted button, most frequently on the button preceding the targeted button. Try it with values like 1000, 100 and 0. Remember to turn VoiceOver on and refresh the page between attempts.

The problem with this behavior is the fact that it is not possible to tell when VoiceOver is running. This means that you have to mess up the user experience of all your other iOS users in order to get this dialog to function correctly on iOS devices for VoiceOver users.

UPDATED 11/24/2013: Moved the demo to github due to conflicts when multiple demos are active on a single Blogger page. Also updated the text of the posting to represent the moving of the demo.

Accessible Sortable/Filterable Table

This example builds on my previous posting in that it adds accessible filtering to a sortable/filterable table. It adds a filtering option to the Age column and shows how mouseover, mouseout and focus, blur can be used to hide the controls from the screen reader when navigating the table data, but exposes them to mouse and keyboard users when needed. Once again, tested only in Safari with VoiceOver.

UPDATE 11/24/2013: I moved the demo of an accessible sortable filterable table to dylanb.github.io because the Blogger templates cause my demos to fail on the multi-listing views.

Accessible Sortable Table

Continuing my series on Accessible tables, today I would like to show a solution for getting rid of annoying messages that get announced when traversing an accessible sortable table that has UI controls in the header cells that allow for the sorting and filtering.

The problem is that when a table is made sortable/filterable, it often contains UI controls that have alt text to tell the screen reader user which direction the column/row is sorted and if it is filtered, which value is the current filter value. This information is unfortunately read out as the user traverses the table from column to column or row to row making the table data much more difficult to read and understand. This is really made worse when the table filtering is achieved with a <select> because all of the option elements are also announced.

The technique is quite simple - make the UI controls show up on focus (and optionally mouseover) and disappear on blur (and mouseout). This provides a much more usable table for a screen reader user, while not detracting from the mouse users experience at all. In fact, the technique can be varied as required to still show styling for the sighted mouse user - for example using background images so that a sighted mouse user would not notice any difference at all from the experience of the table that contains a lot of redundant information for screen reader user.

The example below applies sorting to the table by attaching an anchor around each <th> in the table and using the focus/blur events to apply the UI controls. The UI controls in this case consist of off screen text indicating the sortability and sorting state of the column. It also uses ARIA live regions to announce when the sorting occurs as feedback for the user because changing off screen text does not immediately announce. The example has only been tested in Safari on Mac OS X with VoiceOver.

Example

Accessible, Sortable Table of Famous People Born in South Africa
Famouseness Rank Name Age / Years of Birth and Death Description
1 NELSON MANDELA 95 Former political prisoner who upon his release was elected president of South Africa in 1994.
2 STEVE NASH 39 NBA legend who won the MVP in 2005 and 2006 with the Phoenix Suns, and played in eight NBA All-Star games.
3 SASHA PIETERSE 17 Teen actress who played Alison DiLaurentis on the hit ABC Family series Pretty Little Liars.
4 J.R.R. TOLKIEN (1892-1973) English author, poet, and professor who created The Hobbit and The Lord of the Rings trilogy.
5 CARIBA HEINE 24.1 South African television actress and dancer, most well known as Rikki Chadwick on Australia's H20: Just Add Water.
6 CHARLIZE THERON 37 She hit the spotlight in The Devil's Advocate, and won an Academy Award for Best Actress for her role as a disturbed murderer in the 2003 film, Monster.
7 CANDICE SWANEPOEL 24.2 Famous for being a Victoria Secret model.
8 BETH TWEDDLE 28.5 British gymnastics champion who also competed in three Olympic games.
9 DAVE MATTHEWS 46 Singer and guitar player for the Dave Matthews Band, he won a Grammy Award for the song, So Much To Say.
10 OSCAR PISTORIUS 26 South African sprint runner who is a double amputee, and has competed in the Olympics, widely known as the blade runner.
11 JUSTIN GABRIEL 32 Works for WWE SmackDown; known for being the next 'Breakout Superstar' after competing in 2010.
12 TAMMIN SURSOK 29 Plays the role of Jenna on 'Pretty Little Liars' alongside Ashley Benson.
13 DEAN GEYER 27 Singer-songwriter who placed third in Australia's version of American Idol; plays the role of Brody Weston on Glee.
14 LUOL DENG 28.1 Chicago bulls swing man who played in the 2012 NBA All-Star game.
15 CHRISTIAN BENTEKE 22 Belgian footballer who became known as a player for Aston Villa and the Belgian national team.
16 BISHOP DESMOND TUTU 81 Anglican Archbishop who urged equality of black South Africans.
17 ELON MUSK 42 American Engineer who founded PayPal, SpaceX, and Tesla Motors.
18 DALE STEYN 30 South African cricket star who represents the South African national team and Cape Cobras.
19 MIRIAM MAKEBA (1932-2008) South African singer whose music was embraced worldwide.
20 WILFRIED ZAHA 20 Winger and striker for Crystal Palace and Manchester United.

The one residual issue that this leaves is that the last UI control to receive focus will still have the chatty information exposed. The solution to this is to use timeouts to hide the UI controls if the user does not interact with them for a period of time. For simple sorting, I think this is not necessary, but for filtering it is.