1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/tests/mochitest/attributes.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,382 @@ 1.4 +//////////////////////////////////////////////////////////////////////////////// 1.5 +// Object attributes. 1.6 + 1.7 +/** 1.8 + * Test object attributes. 1.9 + * 1.10 + * @param aAccOrElmOrID [in] the accessible identifier 1.11 + * @param aAttrs [in] the map of expected object attributes 1.12 + * (name/value pairs) 1.13 + * @param aSkipUnexpectedAttrs [in] points this function doesn't fail if 1.14 + * unexpected attribute is encountered 1.15 + */ 1.16 +function testAttrs(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs) 1.17 +{ 1.18 + testAttrsInternal(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs); 1.19 +} 1.20 + 1.21 +/** 1.22 + * Test object attributes that must not be present. 1.23 + * 1.24 + * @param aAccOrElmOrID [in] the accessible identifier 1.25 + * @param aAbsentAttrs [in] map of attributes that should not be 1.26 + * present (name/value pairs) 1.27 + */ 1.28 +function testAbsentAttrs(aAccOrElmOrID, aAbsentAttrs) 1.29 +{ 1.30 + testAttrsInternal(aAccOrElmOrID, {}, true, aAbsentAttrs); 1.31 +} 1.32 + 1.33 +/** 1.34 + * Test CSS based object attributes. 1.35 + */ 1.36 +function testCSSAttrs(aID) 1.37 +{ 1.38 + var node = document.getElementById(aID); 1.39 + var computedStyle = document.defaultView.getComputedStyle(node, ""); 1.40 + 1.41 + var attrs = { 1.42 + "display": computedStyle.display, 1.43 + "text-align": computedStyle.textAlign, 1.44 + "text-indent": computedStyle.textIndent, 1.45 + "margin-left": computedStyle.marginLeft, 1.46 + "margin-right": computedStyle.marginRight, 1.47 + "margin-top": computedStyle.marginTop, 1.48 + "margin-bottom": computedStyle.marginBottom 1.49 + }; 1.50 + testAttrs(aID, attrs, true); 1.51 +} 1.52 + 1.53 +/** 1.54 + * Test the accessible that it doesn't have CSS-based object attributes. 1.55 + */ 1.56 +function testAbsentCSSAttrs(aID) 1.57 +{ 1.58 + var attrs = { 1.59 + "display": "", 1.60 + "text-align": "", 1.61 + "text-indent": "", 1.62 + "margin-left": "", 1.63 + "margin-right": "", 1.64 + "margin-top": "", 1.65 + "margin-bottom": "" 1.66 + }; 1.67 + testAbsentAttrs(aID, attrs); 1.68 +} 1.69 + 1.70 +/** 1.71 + * Test group object attributes (posinset, setsize and level) and 1.72 + * nsIAccessible::groupPosition() method. 1.73 + * 1.74 + * @param aAccOrElmOrID [in] the ID, DOM node or accessible 1.75 + * @param aPosInSet [in] the value of 'posinset' attribute 1.76 + * @param aSetSize [in] the value of 'setsize' attribute 1.77 + * @param aLevel [in, optional] the value of 'level' attribute 1.78 + */ 1.79 +function testGroupAttrs(aAccOrElmOrID, aPosInSet, aSetSize, aLevel) 1.80 +{ 1.81 + var acc = getAccessible(aAccOrElmOrID); 1.82 + var levelObj = {}, posInSetObj = {}, setSizeObj = {}; 1.83 + acc.groupPosition(levelObj, setSizeObj, posInSetObj); 1.84 + 1.85 + if (aPosInSet && aSetSize) { 1.86 + is(posInSetObj.value, aPosInSet, 1.87 + "Wrong group position (posinset) for " + prettyName(aAccOrElmOrID)); 1.88 + is(setSizeObj.value, aSetSize, 1.89 + "Wrong size of the group (setsize) for " + prettyName(aAccOrElmOrID)); 1.90 + 1.91 + var attrs = { 1.92 + "posinset": String(aPosInSet), 1.93 + "setsize": String(aSetSize) 1.94 + }; 1.95 + testAttrs(aAccOrElmOrID, attrs, true); 1.96 + } 1.97 + 1.98 + if (aLevel) { 1.99 + is(levelObj.value, aLevel, 1.100 + "Wrong group level for " + prettyName(aAccOrElmOrID)); 1.101 + 1.102 + var attrs = { "level" : String(aLevel) }; 1.103 + testAttrs(aAccOrElmOrID, attrs, true); 1.104 + } 1.105 +} 1.106 + 1.107 +//////////////////////////////////////////////////////////////////////////////// 1.108 +// Text attributes. 1.109 + 1.110 +/** 1.111 + * Test text attributes. 1.112 + * 1.113 + * @param aID [in] the ID of DOM element having text 1.114 + * accessible 1.115 + * @param aOffset [in] the offset inside text accessible to fetch 1.116 + * text attributes 1.117 + * @param aAttrs [in] the map of expected text attributes 1.118 + * (name/value pairs) exposed at the offset 1.119 + * @param aDefAttrs [in] the map of expected text attributes 1.120 + * (name/value pairs) exposed on hyper text 1.121 + * accessible 1.122 + * @param aStartOffset [in] expected start offset where text attributes 1.123 + * are applied 1.124 + * @param aEndOffset [in] expected end offset where text attribute 1.125 + * are applied 1.126 + * @param aSkipUnexpectedAttrs [in] points the function doesn't fail if 1.127 + * unexpected attribute is encountered 1.128 + */ 1.129 +function testTextAttrs(aID, aOffset, aAttrs, aDefAttrs, 1.130 + aStartOffset, aEndOffset, aSkipUnexpectedAttrs) 1.131 +{ 1.132 + var accessible = getAccessible(aID, [nsIAccessibleText]); 1.133 + if (!accessible) 1.134 + return; 1.135 + 1.136 + var startOffset = { value: -1 }; 1.137 + var endOffset = { value: -1 }; 1.138 + 1.139 + // do not include attributes exposed on hyper text accessbile 1.140 + var attrs = getTextAttributes(aID, accessible, false, aOffset, 1.141 + startOffset, endOffset); 1.142 + 1.143 + if (!attrs) 1.144 + return; 1.145 + 1.146 + var errorMsg = " for " + aID + " at offset " + aOffset; 1.147 + 1.148 + is(startOffset.value, aStartOffset, "Wrong start offset" + errorMsg); 1.149 + is(endOffset.value, aEndOffset, "Wrong end offset" + errorMsg); 1.150 + 1.151 + compareAttrs(errorMsg, attrs, aAttrs, aSkipUnexpectedAttrs); 1.152 + 1.153 + // include attributes exposed on hyper text accessbile 1.154 + var expectedAttrs = {}; 1.155 + for (var name in aAttrs) 1.156 + expectedAttrs[name] = aAttrs[name]; 1.157 + 1.158 + for (var name in aDefAttrs) { 1.159 + if (!(name in expectedAttrs)) 1.160 + expectedAttrs[name] = aDefAttrs[name]; 1.161 + } 1.162 + 1.163 + attrs = getTextAttributes(aID, accessible, true, aOffset, 1.164 + startOffset, endOffset); 1.165 + 1.166 + if (!attrs) 1.167 + return; 1.168 + 1.169 + compareAttrs(errorMsg, attrs, expectedAttrs, aSkipUnexpectedAttrs); 1.170 +} 1.171 + 1.172 +/** 1.173 + * Test default text attributes. 1.174 + * 1.175 + * @param aID [in] the ID of DOM element having text 1.176 + * accessible 1.177 + * @param aDefAttrs [in] the map of expected text attributes 1.178 + * (name/value pairs) 1.179 + * @param aSkipUnexpectedAttrs [in] points the function doesn't fail if 1.180 + * unexpected attribute is encountered 1.181 + */ 1.182 +function testDefaultTextAttrs(aID, aDefAttrs, aSkipUnexpectedAttrs) 1.183 +{ 1.184 + var accessible = getAccessible(aID, [nsIAccessibleText]); 1.185 + if (!accessible) 1.186 + return; 1.187 + 1.188 + var defAttrs = null; 1.189 + try{ 1.190 + defAttrs = accessible.defaultTextAttributes; 1.191 + } catch (e) { 1.192 + } 1.193 + 1.194 + if (!defAttrs) { 1.195 + ok(false, "Can't get default text attributes for " + aID); 1.196 + return; 1.197 + } 1.198 + 1.199 + var errorMsg = ". Getting default text attributes for " + aID; 1.200 + compareAttrs(errorMsg, defAttrs, aDefAttrs, aSkipUnexpectedAttrs); 1.201 +} 1.202 + 1.203 +/** 1.204 + * Test text attributes for wrong offset. 1.205 + */ 1.206 +function testTextAttrsWrongOffset(aID, aOffset) 1.207 +{ 1.208 + var res = false; 1.209 + try { 1.210 + var s = {}, e = {}; 1.211 + var acc = getAccessible(ID, [nsIAccessibleText]); 1.212 + acc.getTextAttributes(false, 157, s, e); 1.213 + } catch (e) { 1.214 + res = true; 1.215 + } 1.216 + 1.217 + ok(res, 1.218 + "text attributes are calculated successfully at wrong offset " + aOffset + " for " + prettyName(aID)); 1.219 +} 1.220 + 1.221 +const kNormalFontWeight = 1.222 + function equalsToNormal(aWeight) { return aWeight <= 400 ; } 1.223 + 1.224 +const kBoldFontWeight = 1.225 + function equalsToBold(aWeight) { return aWeight > 400; } 1.226 + 1.227 +// The pt font size of the input element can vary by Linux distro. 1.228 +const kInputFontSize = WIN ? 1.229 + "10pt" : (MAC ? "8pt" : function() { return true; }); 1.230 + 1.231 +const kAbsentFontFamily = 1.232 + function(aFontFamily) { return aFontFamily != "sans-serif"; } 1.233 +const kInputFontFamily = 1.234 + function(aFontFamily) { return aFontFamily != "sans-serif"; } 1.235 + 1.236 +const kMonospaceFontFamily = 1.237 + function(aFontFamily) { return aFontFamily != "monospace"; } 1.238 +const kSansSerifFontFamily = 1.239 + function(aFontFamily) { return aFontFamily != "sans-serif"; } 1.240 +const kSerifFontFamily = 1.241 + function(aFontFamily) { return aFontFamily != "serif"; } 1.242 + 1.243 +const kCursiveFontFamily = LINUX ? "DejaVu Serif" : "Comic Sans MS"; 1.244 + 1.245 +/** 1.246 + * Return used font from the given computed style. 1.247 + */ 1.248 +function fontFamily(aComputedStyle) 1.249 +{ 1.250 + var name = aComputedStyle.fontFamily; 1.251 + switch (name) { 1.252 + case "monospace": 1.253 + return kMonospaceFontFamily; 1.254 + case "sans-serif": 1.255 + return kSansSerifFontFamily; 1.256 + case "serif": 1.257 + return kSerifFontFamily; 1.258 + default: 1.259 + return name; 1.260 + } 1.261 +} 1.262 + 1.263 +/** 1.264 + * Build an object of default text attributes expected for the given accessible. 1.265 + * 1.266 + * @param aID [in] identifier of accessible 1.267 + * @param aFontSize [in] font size 1.268 + * @param aFontWeight [in, optional] kBoldFontWeight or kNormalFontWeight, 1.269 + * default value is kNormalFontWeight 1.270 + */ 1.271 +function buildDefaultTextAttrs(aID, aFontSize, aFontWeight, aFontFamily) 1.272 +{ 1.273 + var elm = getNode(aID); 1.274 + var computedStyle = document.defaultView.getComputedStyle(elm, ""); 1.275 + var bgColor = computedStyle.backgroundColor == "transparent" ? 1.276 + "rgb(255, 255, 255)" : computedStyle.backgroundColor; 1.277 + 1.278 + var defAttrs = { 1.279 + "font-style": computedStyle.fontStyle, 1.280 + "font-size": aFontSize, 1.281 + "background-color": bgColor, 1.282 + "font-weight": aFontWeight ? aFontWeight : kNormalFontWeight, 1.283 + "color": computedStyle.color, 1.284 + "font-family": aFontFamily ? aFontFamily : fontFamily(computedStyle), 1.285 + "text-position": computedStyle.verticalAlign 1.286 + }; 1.287 + 1.288 + return defAttrs; 1.289 +} 1.290 + 1.291 +//////////////////////////////////////////////////////////////////////////////// 1.292 +// Private. 1.293 + 1.294 +function getTextAttributes(aID, aAccessible, aIncludeDefAttrs, aOffset, 1.295 + aStartOffset, aEndOffset) 1.296 +{ 1.297 + // This function expects the passed in accessible to already be queried for 1.298 + // nsIAccessibleText. 1.299 + var attrs = null; 1.300 + try { 1.301 + attrs = aAccessible.getTextAttributes(aIncludeDefAttrs, aOffset, 1.302 + aStartOffset, aEndOffset); 1.303 + } catch (e) { 1.304 + } 1.305 + 1.306 + if (attrs) 1.307 + return attrs; 1.308 + 1.309 + ok(false, "Can't get text attributes for " + aID); 1.310 + return null; 1.311 +} 1.312 + 1.313 +function testAttrsInternal(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs, 1.314 + aAbsentAttrs) 1.315 +{ 1.316 + var accessible = getAccessible(aAccOrElmOrID); 1.317 + if (!accessible) 1.318 + return; 1.319 + 1.320 + var attrs = null; 1.321 + try { 1.322 + attrs = accessible.attributes; 1.323 + } catch (e) { } 1.324 + 1.325 + if (!attrs) { 1.326 + ok(false, "Can't get object attributes for " + prettyName(aAccOrElmOrID)); 1.327 + return; 1.328 + } 1.329 + 1.330 + var errorMsg = " for " + prettyName(aAccOrElmOrID); 1.331 + compareAttrs(errorMsg, attrs, aAttrs, aSkipUnexpectedAttrs, aAbsentAttrs); 1.332 +} 1.333 + 1.334 +function compareAttrs(aErrorMsg, aAttrs, aExpectedAttrs, aSkipUnexpectedAttrs, 1.335 + aAbsentAttrs) 1.336 +{ 1.337 + // Check if all obtained attributes are expected and have expected value. 1.338 + var enumerate = aAttrs.enumerate(); 1.339 + while (enumerate.hasMoreElements()) { 1.340 + var prop = enumerate.getNext().QueryInterface(nsIPropertyElement); 1.341 + 1.342 + if (!(prop.key in aExpectedAttrs)) { 1.343 + if (!aSkipUnexpectedAttrs) 1.344 + ok(false, "Unexpected attribute '" + prop.key + "' having '" + 1.345 + prop.value + "'" + aErrorMsg); 1.346 + } else { 1.347 + var msg = "Attribute '" + prop.key + "' has wrong value" + aErrorMsg; 1.348 + var expectedValue = aExpectedAttrs[prop.key]; 1.349 + 1.350 + if (typeof expectedValue == "function") 1.351 + ok(expectedValue(prop.value), msg); 1.352 + else 1.353 + is(prop.value, expectedValue, msg); 1.354 + } 1.355 + } 1.356 + 1.357 + // Check if all expected attributes are presented. 1.358 + for (var name in aExpectedAttrs) { 1.359 + var value = ""; 1.360 + try { 1.361 + value = aAttrs.getStringProperty(name); 1.362 + } catch(e) { } 1.363 + 1.364 + if (!value) 1.365 + ok(false, 1.366 + "There is no expected attribute '" + name + "' " + aErrorMsg); 1.367 + } 1.368 + 1.369 + // Check if all unexpected attributes are absent. 1.370 + if (aAbsentAttrs) { 1.371 + for (var name in aAbsentAttrs) { 1.372 + var wasFound = false; 1.373 + 1.374 + var enumerate = aAttrs.enumerate(); 1.375 + while (enumerate.hasMoreElements()) { 1.376 + var prop = enumerate.getNext().QueryInterface(nsIPropertyElement); 1.377 + if (prop.key == name) 1.378 + wasFound = true; 1.379 + } 1.380 + } 1.381 + 1.382 + ok(!wasFound, 1.383 + "There is an unexpected attribute '" + name + "' " + aErrorMsg); 1.384 + } 1.385 +}