1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/tests/mochitest/events/test_coalescence.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,415 @@ 1.4 +<html> 1.5 + 1.6 +<head> 1.7 + <title>Accessible mutation events coalescence testing</title> 1.8 + 1.9 + <link rel="stylesheet" type="text/css" 1.10 + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> 1.11 + 1.12 + <script type="application/javascript" 1.13 + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 1.14 + <script type="application/javascript" 1.15 + src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> 1.16 + 1.17 + <script type="application/javascript" 1.18 + src="../common.js"></script> 1.19 + <script type="application/javascript" 1.20 + src="../events.js"></script> 1.21 + 1.22 + <script type="application/javascript"> 1.23 + 1.24 + //////////////////////////////////////////////////////////////////////////// 1.25 + // Invoker base classes 1.26 + 1.27 + const kRemoveElm = 1; 1.28 + const kHideElm = 2; 1.29 + const kAddElm = 3; 1.30 + const kShowElm = 4; 1.31 + 1.32 + const kToDo = true; 1.33 + 1.34 + /** 1.35 + * Base class to test of mutation events coalescence. 1.36 + */ 1.37 + function coalescenceBase(aChildAction, aParentAction, 1.38 + aPerformActionOnChildInTheFirstPlace, 1.39 + aIsChildsToDo) 1.40 + { 1.41 + // Invoker interface 1.42 + 1.43 + this.invoke = function coalescenceBase_invoke() 1.44 + { 1.45 + if (aPerformActionOnChildInTheFirstPlace) { 1.46 + this.invokeAction(this.childNode, aChildAction); 1.47 + this.invokeAction(this.parentNode, aParentAction); 1.48 + } else { 1.49 + this.invokeAction(this.parentNode, aParentAction); 1.50 + this.invokeAction(this.childNode, aChildAction); 1.51 + } 1.52 + } 1.53 + 1.54 + this.getID = function coalescenceBase_getID() 1.55 + { 1.56 + var childAction = this.getActionName(aChildAction) + " child"; 1.57 + var parentAction = this.getActionName(aParentAction) + " parent"; 1.58 + 1.59 + if (aPerformActionOnChildInTheFirstPlace) 1.60 + return childAction + " and then " + parentAction; 1.61 + 1.62 + return parentAction + " and then " + childAction; 1.63 + } 1.64 + 1.65 + this.finalCheck = function coalescenceBase_check() 1.66 + { 1.67 + if (!aIsChildsToDo) 1.68 + return; 1.69 + 1.70 + var eventType = eventTypeToString(this.getEventType(aChildAction)); 1.71 + todo(false, 1.72 + "Unexpected event " + eventType + 1.73 + " for child in the test '" + this.getID() + "'"); 1.74 + } 1.75 + 1.76 + // Implementation details 1.77 + 1.78 + this.invokeAction = function coalescenceBase_invokeAction(aNode, aAction) 1.79 + { 1.80 + switch (aAction) { 1.81 + case kRemoveElm: 1.82 + aNode.parentNode.removeChild(aNode); 1.83 + break; 1.84 + 1.85 + case kHideElm: 1.86 + aNode.style.display = "none"; 1.87 + break; 1.88 + 1.89 + case kAddElm: 1.90 + if (aNode == this.parentNode) 1.91 + this.hostNode.appendChild(this.parentNode); 1.92 + else 1.93 + this.parentNode.appendChild(this.childNode); 1.94 + break; 1.95 + 1.96 + case kShowElm: 1.97 + aNode.style.display = "block"; 1.98 + break; 1.99 + 1.100 + default: 1.101 + return INVOKER_ACTION_FAILED; 1.102 + } 1.103 + } 1.104 + 1.105 + this.getEventType = function coalescenceBase_getEventType(aAction) 1.106 + { 1.107 + switch (aAction) { 1.108 + case kRemoveElm: case kHideElm: 1.109 + return EVENT_HIDE; 1.110 + case kAddElm: case kShowElm: 1.111 + return EVENT_SHOW; 1.112 + } 1.113 + } 1.114 + 1.115 + this.getActionName = function coalescenceBase_getActionName(aAction) 1.116 + { 1.117 + switch (aAction) { 1.118 + case kRemoveElm: 1.119 + return "remove"; 1.120 + case kHideElm: 1.121 + return "hide"; 1.122 + case kAddElm: 1.123 + return "add"; 1.124 + case kShowElm: 1.125 + return "show"; 1.126 + default: 1.127 + return "??"; 1.128 + } 1.129 + } 1.130 + 1.131 + this.initSequence = function coalescenceBase_initSequence() 1.132 + { 1.133 + // expected events 1.134 + var eventType = this.getEventType(aParentAction); 1.135 + this.eventSeq = [ 1.136 + new invokerChecker(eventType, this.parentNode), 1.137 + new invokerChecker(EVENT_REORDER, this.hostNode) 1.138 + ]; 1.139 + 1.140 + // unexpected events 1.141 + this.unexpectedEventSeq = [ 1.142 + new invokerChecker(EVENT_REORDER, this.parentNode) 1.143 + ]; 1.144 + 1.145 + if (!aIsChildsToDo) { 1.146 + var eventType = this.getEventType(aChildAction); 1.147 + var checker = new invokerChecker(eventType, this.childNode); 1.148 + this.unexpectedEventSeq.unshift(checker); 1.149 + } 1.150 + } 1.151 + } 1.152 + 1.153 + /** 1.154 + * Remove or hide mutation events coalescence testing. 1.155 + */ 1.156 + function removeOrHideCoalescenceBase(aChildID, aParentID, 1.157 + aChildAction, aParentAction, 1.158 + aPerformActionOnChildInTheFirstPlace, 1.159 + aIsChildsToDo) 1.160 + { 1.161 + this.__proto__ = new coalescenceBase(aChildAction, aParentAction, 1.162 + aPerformActionOnChildInTheFirstPlace, 1.163 + aIsChildsToDo); 1.164 + 1.165 + this.init = function removeOrHideCoalescenceBase_init() 1.166 + { 1.167 + this.childNode = getNode(aChildID); 1.168 + this.parentNode = getNode(aParentID); 1.169 + this.hostNode = this.parentNode.parentNode; 1.170 + 1.171 + // ensure child accessible is created 1.172 + getAccessible(this.childNode); 1.173 + } 1.174 + 1.175 + // Initalization 1.176 + 1.177 + this.init(); 1.178 + this.initSequence(); 1.179 + } 1.180 + 1.181 + //////////////////////////////////////////////////////////////////////////// 1.182 + // Invokers 1.183 + 1.184 + /** 1.185 + * Remove child node and then its parent node from DOM tree. 1.186 + */ 1.187 + function removeChildNParent(aChildID, aParentID) 1.188 + { 1.189 + this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID, 1.190 + kRemoveElm, kRemoveElm, 1.191 + true, kToDo); 1.192 + } 1.193 + 1.194 + /** 1.195 + * Remove parent node and then its child node from DOM tree. 1.196 + */ 1.197 + function removeParentNChild(aChildID, aParentID) 1.198 + { 1.199 + this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID, 1.200 + kRemoveElm, kRemoveElm, 1.201 + false); 1.202 + } 1.203 + 1.204 + /** 1.205 + * Hide child node and then its parent node. 1.206 + */ 1.207 + function hideChildNParent(aChildID, aParentID) 1.208 + { 1.209 + this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID, 1.210 + kHideElm, kHideElm, 1.211 + true); 1.212 + } 1.213 + 1.214 + /** 1.215 + * Hide parent node and then its child node. 1.216 + */ 1.217 + function hideParentNChild(aChildID, aParentID) 1.218 + { 1.219 + this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID, 1.220 + kHideElm, kHideElm, 1.221 + false); 1.222 + } 1.223 + 1.224 + /** 1.225 + * Hide child node and then remove its parent node. 1.226 + */ 1.227 + function hideChildNRemoveParent(aChildID, aParentID) 1.228 + { 1.229 + this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID, 1.230 + kHideElm, kRemoveElm, 1.231 + true); 1.232 + } 1.233 + 1.234 + /** 1.235 + * Hide parent node and then remove its child node. 1.236 + */ 1.237 + function hideParentNRemoveChild(aChildID, aParentID) 1.238 + { 1.239 + // Because of async layout changes we handle remove child node change 1.240 + // before than hide parent node change even we hide parent before we 1.241 + // remove a child. Therefore mark this as todo until we have more smart 1.242 + // events coalescence. 1.243 + this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID, 1.244 + kRemoveElm, kHideElm, 1.245 + false, kToDo); 1.246 + } 1.247 + 1.248 + /** 1.249 + * Remove child node and then hide its parent node. 1.250 + */ 1.251 + function removeChildNHideParent(aChildID, aParentID) 1.252 + { 1.253 + this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID, 1.254 + kRemoveElm, kHideElm, 1.255 + true, kToDo); 1.256 + } 1.257 + 1.258 + /** 1.259 + * Remove parent node and then hide its child node. 1.260 + */ 1.261 + function removeParentNHideChild(aChildID, aParentID) 1.262 + { 1.263 + this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID, 1.264 + kHideElm, kRemoveElm, 1.265 + false); 1.266 + } 1.267 + 1.268 + /** 1.269 + * Create and append parent node and create and append child node to it. 1.270 + */ 1.271 + function addParentNChild(aHostID, aPerformActionOnChildInTheFirstPlace) 1.272 + { 1.273 + this.init = function addParentNChild_init() 1.274 + { 1.275 + this.hostNode = getNode(aHostID); 1.276 + this.parentNode = document.createElement("select"); 1.277 + this.childNode = document.createElement("option"); 1.278 + this.childNode.textContent = "testing"; 1.279 + } 1.280 + 1.281 + this.__proto__ = new coalescenceBase(kAddElm, kAddElm, 1.282 + aPerformActionOnChildInTheFirstPlace); 1.283 + 1.284 + this.init(); 1.285 + this.initSequence(); 1.286 + } 1.287 + 1.288 + /** 1.289 + * Show parent node and show child node to it. 1.290 + */ 1.291 + function showParentNChild(aParentID, aChildID, 1.292 + aPerformActionOnChildInTheFirstPlace) 1.293 + { 1.294 + this.init = function showParentNChild_init() 1.295 + { 1.296 + this.parentNode = getNode(aParentID); 1.297 + this.hostNode = this.parentNode.parentNode; 1.298 + this.childNode = getNode(aChildID); 1.299 + } 1.300 + 1.301 + this.__proto__ = new coalescenceBase(kShowElm, kShowElm, 1.302 + aPerformActionOnChildInTheFirstPlace); 1.303 + 1.304 + this.init(); 1.305 + this.initSequence(); 1.306 + } 1.307 + 1.308 + /** 1.309 + * Create and append child node to the DOM and then show parent node. 1.310 + */ 1.311 + function showParentNAddChild(aParentID, 1.312 + aPerformActionOnChildInTheFirstPlace) 1.313 + { 1.314 + this.init = function showParentNAddChild_init() 1.315 + { 1.316 + this.parentNode = getNode(aParentID); 1.317 + this.hostNode = this.parentNode.parentNode; 1.318 + this.childNode = document.createElement("option"); 1.319 + this.childNode.textContent = "testing"; 1.320 + } 1.321 + 1.322 + this.__proto__ = new coalescenceBase(kAddElm, kShowElm, 1.323 + aPerformActionOnChildInTheFirstPlace); 1.324 + 1.325 + this.init(); 1.326 + this.initSequence(); 1.327 + } 1.328 + 1.329 + //////////////////////////////////////////////////////////////////////////// 1.330 + // Do tests. 1.331 + 1.332 + var gQueue = null; 1.333 + //gA11yEventDumpToConsole = true; // debug stuff 1.334 + 1.335 + function doTests() 1.336 + { 1.337 + gQueue = new eventQueue(); 1.338 + 1.339 + gQueue.push(new removeChildNParent("option1", "select1")); 1.340 + gQueue.push(new removeParentNChild("option2", "select2")); 1.341 + gQueue.push(new hideChildNParent("option3", "select3")); 1.342 + gQueue.push(new hideParentNChild("option4", "select4")); 1.343 + gQueue.push(new hideChildNRemoveParent("option5", "select5")); 1.344 + gQueue.push(new hideParentNRemoveChild("option6", "select6")); 1.345 + gQueue.push(new removeChildNHideParent("option7", "select7")); 1.346 + gQueue.push(new removeParentNHideChild("option8", "select8")); 1.347 + 1.348 + gQueue.push(new addParentNChild("testContainer", false)); 1.349 + gQueue.push(new addParentNChild("testContainer", true)); 1.350 + gQueue.push(new showParentNChild("select9", "option9", false)); 1.351 + gQueue.push(new showParentNChild("select10", "option10", true)); 1.352 + gQueue.push(new showParentNAddChild("select11", false)); 1.353 + gQueue.push(new showParentNAddChild("select12", true)); 1.354 + 1.355 + gQueue.invoke(); // Will call SimpleTest.finish(); 1.356 + } 1.357 + 1.358 + SimpleTest.waitForExplicitFinish(); 1.359 + addA11yLoadEvent(doTests); 1.360 + </script> 1.361 +</head> 1.362 + 1.363 +<body> 1.364 + 1.365 + <a target="_blank" 1.366 + href="https://bugzilla.mozilla.org/show_bug.cgi?id=513213" 1.367 + title="coalesce events when new event is appended to the queue"> 1.368 + Mozilla Bug 513213 1.369 + </a><br> 1.370 + <a target="_blank" 1.371 + title="Rework accessible tree update code" 1.372 + href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275"> 1.373 + Mozilla Bug 570275 1.374 + </a> 1.375 + 1.376 + <p id="display"></p> 1.377 + <div id="content" style="display: none"></div> 1.378 + <pre id="test"> 1.379 + </pre> 1.380 + <div id="eventdump"></div> 1.381 + 1.382 + <div id="testContainer"> 1.383 + <select id="select1"> 1.384 + <option id="option1">option</option> 1.385 + </select> 1.386 + <select id="select2"> 1.387 + <option id="option2">option</option> 1.388 + </select> 1.389 + <select id="select3"> 1.390 + <option id="option3">option</option> 1.391 + </select> 1.392 + <select id="select4"> 1.393 + <option id="option4">option</option> 1.394 + </select> 1.395 + <select id="select5"> 1.396 + <option id="option5">option</option> 1.397 + </select> 1.398 + <select id="select6"> 1.399 + <option id="option6">option</option> 1.400 + </select> 1.401 + <select id="select7"> 1.402 + <option id="option7">option</option> 1.403 + </select> 1.404 + <select id="select8"> 1.405 + <option id="option8">option</option> 1.406 + </select> 1.407 + 1.408 + <select id="select9" style="display: none"> 1.409 + <option id="option9" style="display: none">testing</option> 1.410 + </select> 1.411 + <select id="select10" style="display: none"> 1.412 + <option id="option10" style="display: none">testing</option> 1.413 + </select> 1.414 + <select id="select11" style="display: none"></select> 1.415 + <select id="select12" style="display: none"></select> 1.416 + </div> 1.417 +</body> 1.418 +</html>