Bug 1737944 - P12: Add better todo support to attribute tests, and todo failing cache tests. r=Jamie

Changed how our attributes tests work a bit to be single "is" test
instead of comparing each attribute separately. This allows passing a
todo option without it failing on attributes that are identical.

Differential Revision: https://phabricator.services.mozilla.com/D134974
This commit is contained in:
Eitan Isaacson 2022-01-04 21:01:39 +00:00
Родитель 965646877d
Коммит 654a0be767
4 изменённых файлов: 122 добавлений и 101 удалений

Просмотреть файл

@ -7,6 +7,11 @@
/* import-globals-from ../../mochitest/attributes.js */
loadScripts({ name: "attributes.js", dir: MOCHITESTS_DIR });
const isCacheEnabled = Services.prefs.getBoolPref(
"accessibility.cache.enabled",
false
);
/**
* select elements
*/
@ -398,7 +403,7 @@ addAccessibleTask(
testGroupAttrs(getAcc("grid_row2"), 2, 2);
testAbsentAttrs(getAcc("grid_cell3"), { posinset: "", setsize: "" });
testAbsentAttrs(getAcc("grid_cell4"), { posinset: "", setsize: "" });
testGroupParentAttrs(getAcc("grid"), 2, false);
testGroupParentAttrs(getAcc("grid"), 2, false, isCacheEnabled);
}
);
@ -436,7 +441,7 @@ addAccessibleTask(
testGroupParentAttrs(getAcc("treegrid"), 2, true);
// row child item count provided by parent grid's aria-colcount
testGroupParentAttrs(getAcc("treegrid_row1"), 4, false);
testGroupParentAttrs(getAcc("treegrid_row1"), 4, false, isCacheEnabled);
}
);
@ -498,13 +503,13 @@ addAccessibleTask(
// ////////////////////////////////////////////////////////////////////////
// ARIA table
testGroupAttrs(getAcc("table_cell"), 3, 4);
testGroupAttrs(getAcc("table_row"), 2, 2);
testGroupAttrs(getAcc("table_cell"), 3, 4, null, isCacheEnabled);
testGroupAttrs(getAcc("table_row"), 2, 2, null, isCacheEnabled);
// grid child item count provided by aria-rowcount
testGroupParentAttrs(getAcc("table"), 2, false);
testGroupParentAttrs(getAcc("table"), 2, false, isCacheEnabled);
// row child item count provided by parent grid's aria-colcount
testGroupParentAttrs(getAcc("table_row"), 4, false);
testGroupParentAttrs(getAcc("table_row"), 4, false, isCacheEnabled);
}
);
@ -525,8 +530,8 @@ addAccessibleTask(
let getAcc = id => findAccessibleChildByID(accDoc, id);
// Attributes calculated even when row is wrapped in a div.
testGroupAttrs(getAcc("wrapped_row_1"), 1, 2);
testGroupAttrs(getAcc("wrapped_row_2"), 2, 2);
testGroupAttrs(getAcc("wrapped_row_1"), 1, 2, null, isCacheEnabled);
testGroupAttrs(getAcc("wrapped_row_2"), 2, 2, null, isCacheEnabled);
}
);

Просмотреть файл

@ -11,9 +11,10 @@
* (name/value pairs)
* @param aSkipUnexpectedAttrs [in] points this function doesn't fail if
* unexpected attribute is encountered
* @param aTodo [in] true if this is a 'todo'
*/
function testAttrs(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs) {
testAttrsInternal(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs);
function testAttrs(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs, aTodo) {
testAttrsInternal(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs, null, aTodo);
}
/**
@ -22,9 +23,10 @@ function testAttrs(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs) {
* @param aAccOrElmOrID [in] the accessible identifier
* @param aAbsentAttrs [in] map of attributes that should not be
* present (name/value pairs)
* @param aTodo [in] true if this is a 'todo'
*/
function testAbsentAttrs(aAccOrElmOrID, aAbsentAttrs) {
testAttrsInternal(aAccOrElmOrID, {}, true, aAbsentAttrs);
function testAbsentAttrs(aAccOrElmOrID, aAbsentAttrs, aTodo) {
testAttrsInternal(aAccOrElmOrID, {}, true, aAbsentAttrs, aTodo);
}
/**
@ -35,17 +37,12 @@ function testAbsentAttrs(aAccOrElmOrID, aAbsentAttrs) {
* @param aExpectedValue [in] expected attribute value
*/
function todoAttr(aAccOrElmOrID, aKey, aExpectedValue) {
var accessible = getAccessible(aAccOrElmOrID);
if (!accessible) {
return;
}
var attrs = null;
try {
attrs = accessible.attributes;
} catch (e) {}
todo_is(attrs.getStringProperty(aKey), aExpectedValue, "attributes match");
testAttrs(
aAccOrElmOrID,
Object.fromEntries([[aKey, aExpectedValue]]),
true,
true
);
}
/**
@ -92,53 +89,56 @@ function testAbsentCSSAttrs(aID) {
* @param aSetSize [in] the value of 'setsize' attribute
* @param aLevel [in, optional] the value of 'level' attribute
*/
function testGroupAttrs(aAccOrElmOrID, aPosInSet, aSetSize, aLevel) {
function testGroupAttrs(aAccOrElmOrID, aPosInSet, aSetSize, aLevel, aTodo) {
var acc = getAccessible(aAccOrElmOrID);
var levelObj = {},
posInSetObj = {},
setSizeObj = {};
acc.groupPosition(levelObj, setSizeObj, posInSetObj);
if (aPosInSet && aSetSize) {
is(
posInSetObj.value,
aPosInSet,
"Wrong group position (posinset) for " + prettyName(aAccOrElmOrID)
);
is(
setSizeObj.value,
aSetSize,
"Wrong size of the group (setsize) for " + prettyName(aAccOrElmOrID)
);
let groupPos = {},
expectedGroupPos = {};
let attrs = {
posinset: String(aPosInSet),
setsize: String(aSetSize),
};
testAttrs(aAccOrElmOrID, attrs, true);
if (aPosInSet && aSetSize) {
groupPos.setsize = String(setSizeObj.value);
groupPos.posinset = String(posInSetObj.value);
expectedGroupPos.setsize = String(aSetSize);
expectedGroupPos.posinset = String(aPosInSet);
}
if (aLevel) {
is(
levelObj.value,
aLevel,
"Wrong group level for " + prettyName(aAccOrElmOrID)
);
groupPos.level = String(levelObj.value);
let attrs = { level: String(aLevel) };
testAttrs(aAccOrElmOrID, attrs, true);
expectedGroupPos.level = String(aLevel);
}
compareSimpleObjects(
groupPos,
expectedGroupPos,
false,
"wrong groupPos",
aTodo
);
testAttrs(aAccOrElmOrID, expectedGroupPos, true, aTodo);
}
function testGroupParentAttrs(aAccOrElmOrID, aChildItemCount, aIsHierarchical) {
function testGroupParentAttrs(
aAccOrElmOrID,
aChildItemCount,
aIsHierarchical,
aTodo
) {
testAttrs(
aAccOrElmOrID,
{ "child-item-count": String(aChildItemCount) },
true
true,
aTodo
);
if (aIsHierarchical) {
testAttrs(aAccOrElmOrID, { tree: "true" }, true);
testAttrs(aAccOrElmOrID, { tree: "true" }, true, aTodo);
} else {
testAbsentAttrs(aAccOrElmOrID, { tree: "true" });
}
@ -414,7 +414,8 @@ function testAttrsInternal(
aAccOrElmOrID,
aAttrs,
aSkipUnexpectedAttrs,
aAbsentAttrs
aAbsentAttrs,
aTodo
) {
var accessible = getAccessible(aAccOrElmOrID);
if (!accessible) {
@ -432,7 +433,14 @@ function testAttrsInternal(
}
var errorMsg = " for " + prettyName(aAccOrElmOrID);
compareAttrs(errorMsg, attrs, aAttrs, aSkipUnexpectedAttrs, aAbsentAttrs);
compareAttrs(
errorMsg,
attrs,
aAttrs,
aSkipUnexpectedAttrs,
aAbsentAttrs,
aTodo
);
}
function compareAttrs(
@ -440,61 +448,69 @@ function compareAttrs(
aAttrs,
aExpectedAttrs,
aSkipUnexpectedAttrs,
aAbsentAttrs
aAbsentAttrs,
aTodo
) {
// Check if all obtained attributes are expected and have expected value.
let attrObject = {};
for (let prop of aAttrs.enumerate()) {
if (!(prop.key in aExpectedAttrs)) {
if (!aSkipUnexpectedAttrs) {
ok(
false,
"Unexpected attribute '" +
prop.key +
"' having '" +
prop.value +
"'" +
aErrorMsg
);
}
} else {
var msg = "Attribute '" + prop.key + "' has wrong value" + aErrorMsg;
var expectedValue = aExpectedAttrs[prop.key];
if (typeof expectedValue == "function") {
ok(expectedValue(prop.value), msg);
} else {
is(prop.value, expectedValue, msg);
}
}
attrObject[prop.key] = prop.value;
}
// Check if all expected attributes are presented.
for (let name in aExpectedAttrs) {
var value = "";
try {
value = aAttrs.getStringProperty(name);
} catch (e) {}
// Create expected attributes set by using the return values from
// embedded functions to determine the entry's value.
let expectedObj = Object.fromEntries(
Object.entries(aExpectedAttrs).map(([k, v]) => {
if (v instanceof Function) {
// If value is a function that returns true given the received
// attribute value, assign the attribute value to the entry.
// If it is false, stringify the function for good error reporting.
let value = v(attrObject[k]) ? attrObject[k] : v.toString();
return [k, value];
}
if (!value) {
ok(false, "There is no expected attribute '" + name + "' " + aErrorMsg);
}
}
return [k, v];
})
);
compareSimpleObjects(
attrObject,
expectedObj,
aSkipUnexpectedAttrs,
aErrorMsg,
aTodo
);
// Check if all unexpected attributes are absent.
if (aAbsentAttrs) {
for (var name in aAbsentAttrs) {
var wasFound = false;
for (let prop of aAttrs.enumerate()) {
if (prop.key == name) {
wasFound = true;
}
}
}
ok(
!wasFound,
"There is an unexpected attribute '" + name + "' " + aErrorMsg
let presentAttrs = Object.keys(attrObject).filter(
k => aAbsentAttrs[k] !== undefined
);
if (presentAttrs.length) {
(aTodo ? todo : ok)(
false,
`There were unexpected attributes: ${presentAttrs}`
);
}
}
}
function compareSimpleObjects(
aObj,
aExpectedObj,
aSkipUnexpectedAttrs,
aMessage,
aTodo
) {
let keys = aSkipUnexpectedAttrs
? Object.keys(aExpectedObj).sort()
: Object.keys(aObj).sort();
let o1 = JSON.stringify(aObj, keys);
let o2 = JSON.stringify(aExpectedObj, keys);
if (aTodo) {
todo_is(o1, o2, `${aMessage} - Got ${o1}, expected ${o2}`);
} else {
is(o1, o2, aMessage);
}
}

Просмотреть файл

@ -28,7 +28,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
testAttrs("autocomplete", {"autocomplete": "true"}, true);
testAttrs("checkbox", {"checkable": "true"}, true);
testAttrs("checkedCheckbox", {"checkable": "true"}, true);
testAbsentAttrs("checkedMenuitem", {"checkable": "true"}, true);
testAbsentAttrs("checkedMenuitem", {"checkable": "true"});
testAttrs("checkedMenuitemCheckbox", {"checkable": "true"}, true);
testAttrs("checkedMenuitemRadio", {"checkable": "true"}, true);
testAttrs("checkedOption", {"checkable": "true"}, true);
@ -148,7 +148,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
testAttrs("th2", { "axis": "social" }, true);
// don't barf on an empty abbr element.
testAbsentAttrs("th3", { "abbr": "" }, true);
testAbsentAttrs("th3", { "abbr": "" });
// application accessible
if (WIN) {

Просмотреть файл

@ -28,7 +28,7 @@
testAbsentAttrs("main_footer", {"xml-roles": "contentinfo"});
testAbsentAttrs("section_footer", {"xml-roles": "contentinfo"});
testAttrs("aside", {"xml-roles": "complementary"}, true);
testAbsentAttrs("section", {"xml-roles": "region"}, true);
testAbsentAttrs("section", {"xml-roles": "region"});
testAttrs("main", {"xml-roles": "main"}, true); // // ARIA override
testAttrs("form", {"xml-roles": "form"}, true);
testAttrs("feed", {"xml-roles": "feed"}, true);