Skip to content

Commit

Permalink
feat #1830: adding role property for aria:ErrorList
Browse files Browse the repository at this point in the history
This feature allows to configure the role property of the aria:ErrorList
widget. It also replaces the default "alert" value by "status"
(when ariaLive is true) because it is much less buggy with Jaws 18 and IE 11.
Especially, this change fixes the bug that makes Jaws read again the error
messages when they are removed from the screen.

PTR 19168056
close #1830
  • Loading branch information
divdavem committed Jul 17, 2020
1 parent 260fa45 commit 131a0b5
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 4 deletions.
6 changes: 5 additions & 1 deletion src/aria/widgets/CfgBeans.js
Expand Up @@ -1675,8 +1675,12 @@ module.exports = Aria.beanDefinitions({
},
"ariaLive" : {
$type : "json:Boolean",
$description : "Specifies whether role=alert and aria-live=assertive are included (true) or omitted (false) on the container element (defaults to true, only used if waiAria is true)",
$description : "Specifies whether the aria-live=assertive property is included (true) or omitted (false) on the container element (defaults to true, only used if waiAria is true)",
$default : true
},
"role": {
$type : "json:String",
$description : "If this property is defined and not an empty string, it specifies the role to use on the container of the ErrorList. Otherwise, it defaults to 'status' if ariaLive is true, and no role otherwise. This property is only used if waiAria is true."
}
}
},
Expand Down
13 changes: 11 additions & 2 deletions src/aria/widgets/errorlist/ErrorList.js
Expand Up @@ -16,6 +16,7 @@ var Aria = require("../../Aria");
require("./ErrorListController");
var ariaWidgetsTemplateBasedWidget = require("../TemplateBasedWidget");
var ariaUtilsJson = require("../../utils/Json");
var ariaUtilsString = require("../../utils/String");


/**
Expand Down Expand Up @@ -44,8 +45,16 @@ module.exports = Aria.classDefinition({
divCfg.margins = "0 0 0 0";
divCfg.id = cfg.id + "_div";

if (cfg.waiAria && cfg.ariaLive) {
this._extraAttributes = ' role="alert" aria-live="assertive" ';
if (cfg.waiAria) {
if (cfg.ariaLive) {
if (!cfg.role) {
cfg.role = "status";
}
this._extraAttributes = ' aria-live="assertive" ';
}
if (cfg.role) {
this._extraAttributes += ' role="' + ariaUtilsString.escapeHTML(cfg.role) + '" ';
}
}

this._initTemplate({
Expand Down
4 changes: 3 additions & 1 deletion test/aria/widgets/wai/errorlist/ListErrorTestCase.js
Expand Up @@ -51,8 +51,10 @@ module.exports = Aria.classDefinition({

$prototype : {
runTemplateTest : function () {
this.assertEquals(this.getWidgetInstance("e1").getDom().getAttribute("role"), "alert", "The role attribute should be %2 instead of %1");
this.assertEquals(this.getWidgetInstance("e1").getDom().getAttribute("role"), "status", "The role attribute should be %2 instead of %1");
this.assertNull(this.getWidgetInstance("e2").getDom().getAttribute("role"), "The role attribute shouldn't be set");
this.assertEquals(this.getWidgetInstance("e3").getDom().getAttribute("role"), "alert", "The role attribute should be %2 instead of %1");
this.assertNull(this.getWidgetInstance("e4").getDom().getAttribute("role"), "The role attribute shouldn't be set");

this.end();
}
Expand Down
28 changes: 28 additions & 0 deletions test/aria/widgets/wai/errorlist/ListErrorTestCaseTpl.tpl
Expand Up @@ -44,6 +44,34 @@
}
}
}/}
{@aria:ErrorList {
id: "e3",
waiAria: true,
role: "alert",
width: 650,
margins: "10 1 10 1",
title: "Success",
bind: {
messages: {
to: "errorMessages",
inside: data
}
}
}/}
{@aria:ErrorList {
id: "e4",
waiAria: true,
ariaLive: false,
width: 650,
margins: "10 1 10 1",
title: "Success",
bind: {
messages: {
to: "errorMessages",
inside: data
}
}
}/}
{/macro}

{/Template}
@@ -0,0 +1,94 @@
/*
* Copyright 2013 Amadeus s.a.s.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

var Aria = require("ariatemplates/Aria");

var JawsTestCase = require("ariatemplates/jsunit/JawsTestCase");
var AppEnvironment = require("ariatemplates/core/AppEnvironment");
var JsonUtils = require("ariatemplates/utils/Json");

require("ariatemplates/utils/validators/CfgBeans"); // just to make sure it is correctly defined
require("ariatemplates/widgets/errorlist/ErrorListTemplate.tpl"); // just to be sure the template is loaded when the test is run, since it depends on its (DOM) content

module.exports = Aria.classDefinition({
$classpath : "test.aria.widgets.wai.errorlist.binding.ErrorListReadOnceJawsTestCase",
$extends : JawsTestCase,

$constructor : function() {
this.$JawsTestCase.constructor.call(this);
this.setTestEnv({
template : "test.aria.widgets.wai.errorlist.binding.ErrorListBindingTpl",
moduleCtrl : {
classpath : 'test.aria.widgets.wai.errorlist.binding.ErrorListBindingCtrl'
}
});
},

$prototype : {
skipClearHistory: true,

run : function () {
AppEnvironment.setEnvironment({
appSettings: {
waiAria: true
}
}, {
scope: this,
fn: this.$JawsTestCase.run
});
},

runTemplateTest : function () {
var emailError = /The email is a required field using a mandatory validator/i;
var repeatErrorsListener = {
match: emailError,
scope: this,
fn: this.lastJawsTextFailure
};
var emailField = this.getInputField("email");
this.execute([
["click", emailField],
["waitFocus", emailField],
["waitForJawsToSay","Email Address colon Edit"],
["type",null,"[down][down]"],
["waitForJawsToSay","Submit Button"],
["type",null,"[space]"],
["waitForJawsToSay","Space"],
["waitForJawsToSay", emailError],
// once the error is read (once), Jaws is not supposed to read it again:
["registerJawsListener", repeatErrorsListener],
["pause", 2000]
], {
fn: function () {
// With role=alert, Jaws was reading messages when they are removed
// from the screen.
// Now let's check that the error messages are not read when they
// are removed from the screen:
this.$logInfo("Clearing messages");
JsonUtils.setValue(this.templateCtxt.data, "errorMessages", []);
this.execute([
["pause", 3000],
["unregisterJawsListener", repeatErrorsListener]
], {
fn: this.end,
scope: this
});
},
scope: this
});

}
}
});

0 comments on commit 131a0b5

Please sign in to comment.