test_tree.xhtml (10196B)
1 <?xml version="1.0"?> 2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?> 3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" 4 type="text/css"?> 5 6 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 7 title="DOM TreeRowCountChanged and a11y name change events."> 8 9 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> 10 11 <script type="application/javascript" 12 src="../treeview.js" /> 13 14 <script type="application/javascript" 15 src="../common.js" /> 16 <script type="application/javascript" 17 src="../events.js" /> 18 19 <script type="application/javascript"> 20 <![CDATA[ 21 var gView; 22 23 //////////////////////////////////////////////////////////////////////////// 24 // Invoker's checkers 25 26 /** 27 * Check TreeRowCountChanged event. 28 */ 29 function rowCountChangedChecker(aMsg, aIdx, aCount) 30 { 31 this.type = "TreeRowCountChanged"; 32 this.target = gTree; 33 this.check = function check(aEvent) 34 { 35 var propBag = aEvent.detail.QueryInterface(Ci.nsIPropertyBag2); 36 var index = propBag.getPropertyAsInt32("index"); 37 is(index, aIdx, "Wrong 'index' data of 'treeRowCountChanged' event."); 38 39 var count = propBag.getPropertyAsInt32("count"); 40 is(count, aCount, "Wrong 'count' data of 'treeRowCountChanged' event."); 41 } 42 this.getID = function getID() 43 { 44 return aMsg + "TreeRowCountChanged"; 45 } 46 } 47 48 /** 49 * Check TreeInvalidated event. 50 */ 51 function treeInvalidatedChecker(aMsg, aStartRow, aEndRow, aStartCol, aEndCol) 52 { 53 this.type = "TreeInvalidated"; 54 this.target = gTree; 55 this.check = function check(aEvent) 56 { 57 var propBag = aEvent.detail.QueryInterface(Ci.nsIPropertyBag2); 58 try { 59 var startRow = propBag.getPropertyAsInt32("startrow"); 60 } catch (e) { 61 if (e.name != 'NS_ERROR_NOT_AVAILABLE') { 62 throw e; 63 } 64 startRow = null; 65 } 66 is(startRow, aStartRow, 67 "Wrong 'startrow' of 'treeInvalidated' event on " + aMsg); 68 69 try { 70 var endRow = propBag.getPropertyAsInt32("endrow"); 71 } catch (e) { 72 if (e.name != 'NS_ERROR_NOT_AVAILABLE') { 73 throw e; 74 } 75 endRow = null; 76 } 77 is(endRow, aEndRow, 78 "Wrong 'endrow' of 'treeInvalidated' event on " + aMsg); 79 80 try { 81 var startCol = propBag.getPropertyAsInt32("startcolumn"); 82 } catch (e) { 83 if (e.name != 'NS_ERROR_NOT_AVAILABLE') { 84 throw e; 85 } 86 startCol = null; 87 } 88 is(startCol, aStartCol, 89 "Wrong 'startcolumn' of 'treeInvalidated' event on " + aMsg); 90 91 try { 92 var endCol = propBag.getPropertyAsInt32("endcolumn"); 93 } catch (e) { 94 if (e.name != 'NS_ERROR_NOT_AVAILABLE') { 95 throw e; 96 } 97 endCol = null; 98 } 99 is(endCol, aEndCol, 100 "Wrong 'endcolumn' of 'treeInvalidated' event on " + aMsg); 101 } 102 this.getID = function getID() 103 { 104 return "TreeInvalidated on " + aMsg; 105 } 106 } 107 108 /** 109 * Check name changed a11y event. 110 */ 111 function nameChangeChecker(aMsg, aRow, aCol) 112 { 113 this.type = EVENT_NAME_CHANGE; 114 115 function targetGetter() 116 { 117 var acc = getAccessible(gTree); 118 119 var tableAcc = getAccessible(acc, [nsIAccessibleTable]); 120 return tableAcc.getCellAt(aRow, aCol); 121 } 122 Object.defineProperty(this, "target", { get: targetGetter }); 123 124 this.getID = function getID() 125 { 126 return aMsg + "name changed"; 127 } 128 } 129 130 /** 131 * Check name changed a11y event for a row. 132 */ 133 function rowNameChangeChecker(aMsg, aRow) 134 { 135 this.type = EVENT_NAME_CHANGE; 136 137 function targetGetter() 138 { 139 var acc = getAccessible(gTree); 140 return acc.getChildAt(aRow + 1); 141 } 142 Object.defineProperty(this, "target", { get: targetGetter }); 143 144 this.getID = function getID() 145 { 146 return aMsg + "name changed"; 147 } 148 } 149 150 //////////////////////////////////////////////////////////////////////////// 151 // Invokers 152 153 /** 154 * Set tree view. 155 */ 156 function setTreeView() 157 { 158 this.invoke = function setTreeView_invoke() 159 { 160 gTree.view = gView; 161 } 162 163 this.getID = function setTreeView_getID() { return "set tree view"; } 164 165 this.eventSeq = [ 166 new invokerChecker(EVENT_REORDER, gTree) 167 ]; 168 }; 169 170 /** 171 * Insert row at 0 index and checks TreeRowCountChanged and TreeInvalidated 172 * event. 173 */ 174 function insertRow() 175 { 176 this.invoke = function insertRow_invoke() 177 { 178 gView.appendItem("last"); 179 gTree.rowCountChanged(0, 1); 180 } 181 182 this.eventSeq = 183 [ 184 new rowCountChangedChecker("insertRow: ", 0, 1), 185 new treeInvalidatedChecker("insertRow", 0, 5, null, null) 186 ]; 187 188 this.getID = function insertRow_getID() 189 { 190 return "insert row"; 191 } 192 } 193 194 /** 195 * Invalidates first column and checks six name changed events for each 196 * treeitem plus TreeInvalidated event. 197 */ 198 function invalidateColumn() 199 { 200 this.invoke = function invalidateColumn_invoke() 201 { 202 // Make sure accessible subtree of XUL tree is created otherwise no 203 // name change events for cell accessibles are emitted. 204 var tree = getAccessible(gTree); 205 var child = tree.firstChild; 206 var walkDown = true; 207 while (child != tree) { 208 if (walkDown) { 209 var grandChild = child.firstChild; 210 if (grandChild) { 211 child = grandChild; 212 continue; 213 } 214 } 215 216 var sibling = child.nextSibling; 217 if (sibling) { 218 child = sibling; 219 walkDown = true; 220 continue; 221 } 222 223 child = child.parent; 224 walkDown = false; 225 } 226 227 // Fire 'TreeInvalidated' event by InvalidateColumn() 228 var firstCol = gTree.columns.getFirstColumn(); 229 for (var i = 0; i < gView.rowCount; i++) 230 gView.setCellText(i, firstCol, "hey " + String(i) + "x0"); 231 232 gTree.invalidateColumn(firstCol); 233 } 234 235 this.eventSeq = 236 [ 237 new nameChangeChecker("invalidateColumn: ", 0, 0), 238 new nameChangeChecker("invalidateColumn: ", 1, 0), 239 new nameChangeChecker("invalidateColumn: ", 2, 0), 240 new nameChangeChecker("invalidateColumn: ", 3, 0), 241 new nameChangeChecker("invalidateColumn: ", 4, 0), 242 new nameChangeChecker("invalidateColumn: ", 5, 0), 243 new treeInvalidatedChecker("invalidateColumn", null, null, 0, 0) 244 ]; 245 246 this.getID = function invalidateColumn_getID() 247 { 248 return "invalidate column"; 249 } 250 } 251 252 /** 253 * Invalidates second row and checks name changed event for first treeitem 254 * (note, there are two name changed events on linux due to different 255 * accessible tree for xul:tree element) plus TreeInvalidated event. 256 */ 257 function invalidateRow() 258 { 259 this.invoke = function invalidateRow_invoke() 260 { 261 // Fire 'TreeInvalidated' event by InvalidateRow() 262 // eslint-disable-next-line no-unused-vars 263 var colCount = gTree.columns.count; 264 var column = gTree.columns.getFirstColumn(); 265 while (column) { 266 gView.setCellText(1, column, "aloha 1x" + String(column.index)); 267 column = column.getNext(); 268 } 269 270 gTree.invalidateRow(1); 271 } 272 273 this.eventSeq = 274 [ 275 new nameChangeChecker("invalidateRow: ", 1, 0), 276 new nameChangeChecker("invalidateRow: ", 1, 1), 277 new rowNameChangeChecker("invalidateRow: ", 1), 278 new treeInvalidatedChecker("invalidateRow", 1, 1, null, null) 279 ]; 280 281 this.getID = function invalidateRow_getID() 282 { 283 return "invalidate row"; 284 } 285 } 286 287 //////////////////////////////////////////////////////////////////////////// 288 // Test 289 290 var gTree = null; 291 var gTreeView = null; 292 var gQueue = null; 293 294 // gA11yEventDumpID = "debug"; 295 gA11yEventDumpToConsole = true; // debuggin 296 297 function doTest() 298 { 299 // Initialize the tree 300 gTree = document.getElementById("tree"); 301 gView = new nsTableTreeView(5); 302 303 // Perform actions 304 gQueue = new eventQueue(); 305 306 gQueue.push(new setTreeView()); 307 gQueue.push(new insertRow()); 308 gQueue.push(new invalidateColumn()); 309 gQueue.push(new invalidateRow()); 310 311 gQueue.invoke(); 312 } 313 314 SimpleTest.waitForExplicitFinish(); 315 addA11yLoadEvent(doTest); 316 ]]> 317 </script> 318 319 <hbox flex="1" style="overflow: auto;"> 320 <body xmlns="http://www.w3.org/1999/xhtml"> 321 <a target="_blank" 322 href="https://bugzilla.mozilla.org/show_bug.cgi?id=368835" 323 title="Fire TreeViewChanged/TreeRowCountChanged events."> 324 Mozilla Bug 368835 325 </a><br/> 326 <a target="_blank" 327 href="https://bugzilla.mozilla.org/show_bug.cgi?id=308564" 328 title="No accessibility events when data in a tree row changes."> 329 Mozilla Bug 308564 330 </a><br/> 331 <a target="_blank" 332 href="https://bugzilla.mozilla.org/show_bug.cgi?id=739524" 333 title="replace TreeViewChanged DOM event on direct call from XUL tree."> 334 Mozilla Bug 739524 335 </a><br/> 336 <a target="_blank" 337 href="https://bugzilla.mozilla.org/show_bug.cgi?id=743568" 338 title="Thunderbird message list tree emitting incorrect focus signals after message deleted."> 339 Mozilla Bug 743568 340 </a> 341 <p id="display"></p> 342 <div id="content" style="display: none"> 343 </div> 344 <pre id="test"> 345 </pre> 346 </body> 347 348 <vbox id="debug"/> 349 <tree id="tree" flex="1"> 350 <treecols> 351 <treecol id="col1" flex="1" primary="true" label="column"/> 352 <treecol id="col2" flex="1" label="column 2"/> 353 </treecols> 354 <treechildren id="treechildren"/> 355 </tree> 356 </hbox> 357 358 </window>