toolkit/content/tests/widgets/tree_shared.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 var columns_simpletree =
michael@0 2 [
michael@0 3 { name: "name", label: "Name", key: true, properties: "one two" },
michael@0 4 { name: "address", label: "Address" }
michael@0 5 ];
michael@0 6
michael@0 7 var columns_hiertree =
michael@0 8 [
michael@0 9 { name: "name", label: "Name", primary: true, key: true, properties: "one two" },
michael@0 10 { name: "address", label: "Address" },
michael@0 11 { name: "planet", label: "Planet" },
michael@0 12 { name: "gender", label: "Gender", cycler: true }
michael@0 13 ];
michael@0 14
michael@0 15 // XXXndeakin still to add some tests for:
michael@0 16 // cycler columns, checkbox cells, progressmeter cells
michael@0 17
michael@0 18 // this test function expects a tree to have 8 rows in it when it isn't
michael@0 19 // expanded. The tree should only display four rows at a time. If editable,
michael@0 20 // the cell at row 1 and column 0 must be editable, and the cell at row 2 and
michael@0 21 // column 1 must not be editable.
michael@0 22 function testtag_tree(treeid, treerowinfoid, seltype, columnstype, testid)
michael@0 23 {
michael@0 24 // Stop keystrokes that aren't handled by the tree from leaking out and
michael@0 25 // scrolling the main Mochitests window!
michael@0 26 function preventDefault(event) {
michael@0 27 event.preventDefault();
michael@0 28 }
michael@0 29 document.addEventListener("keypress", preventDefault, false);
michael@0 30
michael@0 31 var multiple = (seltype == "multiple");
michael@0 32
michael@0 33 var tree = document.getElementById(treeid);
michael@0 34 var treerowinfo = document.getElementById(treerowinfoid);
michael@0 35 var rowInfo;
michael@0 36 if (testid =="tree view")
michael@0 37 rowInfo = getCustomTreeViewCellInfo();
michael@0 38 else
michael@0 39 rowInfo = convertDOMtoTreeRowInfo(treerowinfo, 0, { value: -1 });
michael@0 40 var columnInfo = (columnstype == "simple") ? columns_simpletree : columns_hiertree;
michael@0 41
michael@0 42 is(tree.view.selection.currentColumn, null, testid + " initial currentColumn");
michael@0 43 is(tree.selType, seltype == "multiple" ? "" : seltype, testid + " seltype");
michael@0 44
michael@0 45 // note: the functions below should be in this order due to changes made in later tests
michael@0 46
michael@0 47 // select the first column in cell selection mode so that the selection
michael@0 48 // functions can be tested
michael@0 49 if (seltype == "cell")
michael@0 50 tree.view.selection.currentColumn = tree.columns[0];
michael@0 51
michael@0 52 testtag_tree_columns(tree, columnInfo, testid);
michael@0 53 testtag_tree_TreeSelection(tree, testid, multiple);
michael@0 54 testtag_tree_TreeSelection_UI(tree, testid, multiple);
michael@0 55 if (seltype == "cell")
michael@0 56 testtag_tree_TreeSelection_UI_cell(tree, testid, rowInfo);
michael@0 57
michael@0 58 testtag_tree_TreeView(tree, testid, rowInfo);
michael@0 59
michael@0 60 is(tree.editable, false, "tree should not be editable");
michael@0 61 // currently, the editable flag means that tree editing cannot be invoked
michael@0 62 // by the user. However, editing can still be started with a script.
michael@0 63 is(tree.editingRow, -1, testid + " initial editingRow");
michael@0 64 is(tree.editingColumn, null, testid + " initial editingColumn");
michael@0 65
michael@0 66 testtag_tree_UI_editing(tree, testid, rowInfo);
michael@0 67
michael@0 68 is(tree.editable, false, "tree should not be editable after testtag_tree_UI_editing");
michael@0 69 // currently, the editable flag means that tree editing cannot be invoked
michael@0 70 // by the user. However, editing can still be started with a script.
michael@0 71 is(tree.editingRow, -1, testid + " initial editingRow (continued)");
michael@0 72 is(tree.editingColumn, null, testid + " initial editingColumn (continued)");
michael@0 73
michael@0 74 var ecolumn = tree.columns[0];
michael@0 75 ok(!tree.startEditing(1, ecolumn), "non-editable trees shouldn't start editing");
michael@0 76 is(tree.editingRow, -1, testid + " failed startEditing shouldn't set editingRow");
michael@0 77 is(tree.editingColumn, null, testid + " failed startEditing shouldn't set editingColumn");
michael@0 78
michael@0 79 tree.editable = true;
michael@0 80
michael@0 81 ok(tree.startEditing(1, ecolumn), "startEditing should have returned true");
michael@0 82 is(tree.editingRow, 1, testid + " startEditing editingRow");
michael@0 83 is(tree.editingColumn, ecolumn, testid + " startEditing editingColumn");
michael@0 84 is(tree.getAttribute("editing"), "true", testid + " startEditing editing attribute");
michael@0 85
michael@0 86 tree.stopEditing(true);
michael@0 87 is(tree.editingRow, -1, testid + " stopEditing editingRow");
michael@0 88 is(tree.editingColumn, null, testid + " stopEditing editingColumn");
michael@0 89 is(tree.hasAttribute("editing"), false, testid + " stopEditing editing attribute");
michael@0 90
michael@0 91 tree.startEditing(-1, ecolumn);
michael@0 92 is(tree.editingRow == -1 && tree.editingColumn == null, true, testid + " startEditing -1 editingRow");
michael@0 93 tree.startEditing(15, ecolumn);
michael@0 94 is(tree.editingRow == -1 && tree.editingColumn == null, true, testid + " startEditing 15 editingRow");
michael@0 95 tree.startEditing(1, null);
michael@0 96 is(tree.editingRow == -1 && tree.editingColumn == null, true, testid + " startEditing null column editingRow");
michael@0 97 tree.startEditing(2, tree.columns[1]);
michael@0 98 is(tree.editingRow == -1 && tree.editingColumn == null, true, testid + " startEditing non editable cell editingRow");
michael@0 99
michael@0 100 tree.startEditing(1, ecolumn);
michael@0 101 var inputField = tree.inputField;
michael@0 102 is(inputField instanceof Components.interfaces.nsIDOMXULTextBoxElement, true, testid + "inputField");
michael@0 103 inputField.value = "Changed Value";
michael@0 104 tree.stopEditing(true);
michael@0 105 is(tree.view.getCellText(1, ecolumn), "Changed Value", testid + "edit cell accept");
michael@0 106
michael@0 107 // this cell can be edited, but stopEditing(false) means don't accept the change.
michael@0 108 tree.startEditing(1, ecolumn);
michael@0 109 inputField.value = "Second Value";
michael@0 110 tree.stopEditing(false);
michael@0 111 is(tree.view.getCellText(1, ecolumn), "Changed Value", testid + "edit cell no accept");
michael@0 112
michael@0 113 tree.editable = false;
michael@0 114
michael@0 115 // do the sorting tests last as it will cause the rows to rearrange
michael@0 116 // skip them for the custom tree view
michael@0 117 if (testid !="tree view")
michael@0 118 testtag_tree_TreeView_rows_sort(tree, testid, rowInfo);
michael@0 119
michael@0 120 testtag_tree_wheel(tree);
michael@0 121
michael@0 122 document.removeEventListener("keypress", preventDefault, false);
michael@0 123
michael@0 124 SimpleTest.finish();
michael@0 125 }
michael@0 126
michael@0 127 function testtag_tree_columns(tree, expectedColumns, testid)
michael@0 128 {
michael@0 129 testid += " ";
michael@0 130
michael@0 131 var columns = tree.columns;
michael@0 132
michael@0 133 is(columns instanceof TreeColumns, true, testid + "columns is a TreeColumns");
michael@0 134 is(columns.count, expectedColumns.length, testid + "TreeColumns count");
michael@0 135 is(columns.length, expectedColumns.length, testid + "TreeColumns length");
michael@0 136
michael@0 137 var treecols = tree.getElementsByTagName("treecols")[0];
michael@0 138 var treecol = treecols.getElementsByTagName("treecol");
michael@0 139
michael@0 140 var x = 0;
michael@0 141 var primary = null, sorted = null, key = null;
michael@0 142 for (var c = 0; c < expectedColumns.length; c++) {
michael@0 143 var adjtestid = testid + " column " + c + " ";
michael@0 144 var column = columns[c];
michael@0 145 var expectedColumn = expectedColumns[c];
michael@0 146 is(columns.getColumnAt(c), column, adjtestid + "getColumnAt");
michael@0 147 is(columns.getNamedColumn(expectedColumn.name), column, adjtestid + "getNamedColumn");
michael@0 148 is(columns.getColumnFor(treecol[c]), column, adjtestid + "getColumnFor");
michael@0 149 if (expectedColumn.primary)
michael@0 150 primary = column;
michael@0 151 if (expectedColumn.sorted)
michael@0 152 sorted = column;
michael@0 153 if (expectedColumn.key)
michael@0 154 key = column;
michael@0 155
michael@0 156 // XXXndeakin on Windows and Linux, some columns are one pixel to the
michael@0 157 // left of where they should be. Could just be a rounding issue.
michael@0 158 var adj = 1;
michael@0 159 is(column.x + adj >= x, true, adjtestid + "position is after last column " +
michael@0 160 column.x + "," + column.width + "," + x);
michael@0 161 is(column.width > 0, true, adjtestid + "width is greater than 0");
michael@0 162 x = column.x + column.width;
michael@0 163
michael@0 164 // now check the TreeColumn properties
michael@0 165 is(column instanceof TreeColumn, true, adjtestid + "is a TreeColumn");
michael@0 166 is(column.element, treecol[c], adjtestid + "element is treecol");
michael@0 167 is(column.columns, columns, adjtestid + "columns is TreeColumns");
michael@0 168 is(column.id, expectedColumn.name, adjtestid + "name");
michael@0 169 is(column.index, c, adjtestid + "index");
michael@0 170 is(column.primary, primary == column, adjtestid + "column is primary");
michael@0 171
michael@0 172 is(column.cycler, "cycler" in expectedColumn && expectedColumn.cycler,
michael@0 173 adjtestid + "column is cycler");
michael@0 174 is(column.selectable, true, adjtestid + "column is selectable");
michael@0 175 is(column.editable, "editable" in expectedColumn && expectedColumn.editable,
michael@0 176 adjtestid + "column is editable");
michael@0 177
michael@0 178 is(column.type, "type" in expectedColumn ? expectedColumn.type : 1, adjtestid + "type");
michael@0 179
michael@0 180 is(column.getPrevious(), c > 0 ? columns[c - 1] : null, adjtestid + "getPrevious");
michael@0 181 is(column.getNext(), c < columns.length - 1 ? columns[c + 1] : null, adjtestid + "getNext");
michael@0 182
michael@0 183 // check the view's getColumnProperties method
michael@0 184 var properties = tree.view.getColumnProperties(column);
michael@0 185 var expectedProperties = expectedColumn.properties;
michael@0 186 is(properties, expectedProperties ? expectedProperties : "", adjtestid + "getColumnProperties");
michael@0 187 }
michael@0 188
michael@0 189 is(columns.getFirstColumn(), columns[0], testid + "getFirstColumn");
michael@0 190 is(columns.getLastColumn(), columns[columns.length - 1], testid + "getLastColumn");
michael@0 191 is(columns.getPrimaryColumn(), primary, testid + "getPrimaryColumn");
michael@0 192 is(columns.getSortedColumn(), sorted, testid + "getSortedColumn");
michael@0 193 is(columns.getKeyColumn(), key, testid + "getKeyColumn");
michael@0 194
michael@0 195 is(columns.getColumnAt(-1), null, testid + "getColumnAt under");
michael@0 196 is(columns.getColumnAt(columns.length), null, testid + "getColumnAt over");
michael@0 197 is(columns.getNamedColumn(""), null, testid + "getNamedColumn null");
michael@0 198 is(columns.getNamedColumn("unknown"), null, testid + "getNamedColumn unknown");
michael@0 199 is(columns.getColumnFor(null), null, testid + "getColumnFor null");
michael@0 200 is(columns.getColumnFor(tree), null, testid + "getColumnFor other");
michael@0 201 }
michael@0 202
michael@0 203 function testtag_tree_TreeSelection(tree, testid, multiple)
michael@0 204 {
michael@0 205 testid += " selection ";
michael@0 206
michael@0 207 var selection = tree.view.selection;
michael@0 208 is(selection instanceof Components.interfaces.nsITreeSelection, true,
michael@0 209 testid + "selection is a TreeSelection");
michael@0 210 is(selection.single, !multiple, testid + "single");
michael@0 211
michael@0 212 testtag_tree_TreeSelection_State(tree, testid + "initial", -1, []);
michael@0 213 is(selection.shiftSelectPivot, -1, testid + "initial shiftSelectPivot");
michael@0 214
michael@0 215 selection.currentIndex = 2;
michael@0 216 testtag_tree_TreeSelection_State(tree, testid + "set currentIndex", 2, []);
michael@0 217 tree.currentIndex = 3;
michael@0 218 testtag_tree_TreeSelection_State(tree, testid + "set tree.currentIndex", 3, []);
michael@0 219
michael@0 220 // test the select() method, which should deselect all rows and select
michael@0 221 // a single row
michael@0 222 selection.select(1);
michael@0 223 testtag_tree_TreeSelection_State(tree, testid + "select 1", 1, [1]);
michael@0 224 selection.select(3);
michael@0 225 testtag_tree_TreeSelection_State(tree, testid + "select 2", 3, [3]);
michael@0 226 selection.select(3);
michael@0 227 testtag_tree_TreeSelection_State(tree, testid + "select same", 3, [3]);
michael@0 228
michael@0 229 selection.currentIndex = 1;
michael@0 230 testtag_tree_TreeSelection_State(tree, testid + "set currentIndex with single selection", 1, [3]);
michael@0 231
michael@0 232 tree.currentIndex = 2;
michael@0 233 testtag_tree_TreeSelection_State(tree, testid + "set tree.currentIndex with single selection", 2, [3]);
michael@0 234
michael@0 235 // check the toggleSelect method. In single selection mode, it only toggles on when
michael@0 236 // there isn't currently a selection.
michael@0 237 selection.toggleSelect(2);
michael@0 238 testtag_tree_TreeSelection_State(tree, testid + "toggleSelect 1", 2, multiple ? [2, 3] : [3]);
michael@0 239 selection.toggleSelect(2);
michael@0 240 selection.toggleSelect(3);
michael@0 241 testtag_tree_TreeSelection_State(tree, testid + "toggleSelect 2", 3, []);
michael@0 242
michael@0 243 // the current index doesn't change after a selectAll, so it should still be set to 1
michael@0 244 // selectAll has no effect on single selection trees
michael@0 245 selection.currentIndex = 1;
michael@0 246 selection.selectAll();
michael@0 247 testtag_tree_TreeSelection_State(tree, testid + "selectAll 1", 1, multiple ? [0, 1, 2, 3, 4, 5, 6 , 7] : []);
michael@0 248 selection.toggleSelect(2);
michael@0 249 testtag_tree_TreeSelection_State(tree, testid + "toggleSelect after selectAll", 2,
michael@0 250 multiple ? [0, 1, 3, 4, 5, 6, 7] : [2]);
michael@0 251 selection.clearSelection();
michael@0 252 testtag_tree_TreeSelection_State(tree, testid + "clearSelection", 2, []);
michael@0 253 selection.toggleSelect(3);
michael@0 254 selection.toggleSelect(1);
michael@0 255 if (multiple) {
michael@0 256 selection.selectAll();
michael@0 257 testtag_tree_TreeSelection_State(tree, testid + "selectAll 2", 1, [0, 1, 2, 3, 4, 5, 6, 7]);
michael@0 258 }
michael@0 259 selection.currentIndex = 2;
michael@0 260 selection.clearSelection();
michael@0 261 testtag_tree_TreeSelection_State(tree, testid + "clearSelection after selectAll", 2, []);
michael@0 262
michael@0 263 // XXXndeakin invertSelection isn't implemented
michael@0 264 // selection.invertSelection();
michael@0 265
michael@0 266 is(selection.shiftSelectPivot, -1, testid + "shiftSelectPivot set to -1");
michael@0 267
michael@0 268 // rangedSelect and clearRange set the currentIndex to the endIndex. The
michael@0 269 // shiftSelectPivot property will be set to startIndex.
michael@0 270 selection.rangedSelect(1, 3, false);
michael@0 271 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect no augment",
michael@0 272 multiple ? 3 : 2, multiple ? [1, 2, 3] : []);
michael@0 273 is(selection.shiftSelectPivot, multiple ? 1 : -1,
michael@0 274 testid + "shiftSelectPivot after rangedSelect no augment");
michael@0 275 if (multiple) {
michael@0 276 selection.select(1);
michael@0 277 selection.rangedSelect(0, 2, true);
michael@0 278 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect augment", 2, [0, 1, 2]);
michael@0 279 is(selection.shiftSelectPivot, 0, testid + "shiftSelectPivot after rangedSelect augment");
michael@0 280
michael@0 281 selection.clearRange(1, 3);
michael@0 282 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect augment", 3, [0]);
michael@0 283
michael@0 284 // check that rangedSelect can take a start value higher than end
michael@0 285 selection.rangedSelect(3, 1, false);
michael@0 286 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect reverse", 1, [1, 2, 3]);
michael@0 287 is(selection.shiftSelectPivot, 3, testid + "shiftSelectPivot after rangedSelect reverse");
michael@0 288
michael@0 289 // check that setting the current index doesn't change the selection
michael@0 290 selection.currentIndex = 0;
michael@0 291 testtag_tree_TreeSelection_State(tree, testid + "currentIndex with range selection", 0, [1, 2, 3]);
michael@0 292 }
michael@0 293
michael@0 294 // both values of rangedSelect may be the same
michael@0 295 selection.rangedSelect(2, 2, false);
michael@0 296 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect one row", 2, [2]);
michael@0 297 is(selection.shiftSelectPivot, 2, testid + "shiftSelectPivot after selecting one row");
michael@0 298
michael@0 299 if (multiple) {
michael@0 300 selection.rangedSelect(2, 3, true);
michael@0 301
michael@0 302 // a start index of -1 means from the last point
michael@0 303 selection.rangedSelect(-1, 0, true);
michael@0 304 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect -1 existing selection", 0, [0, 1, 2, 3]);
michael@0 305 is(selection.shiftSelectPivot, 2, testid + "shiftSelectPivot after -1 existing selection");
michael@0 306
michael@0 307 selection.currentIndex = 2;
michael@0 308 selection.rangedSelect(-1, 0, false);
michael@0 309 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect -1 from currentIndex", 0, [0, 1, 2]);
michael@0 310 is(selection.shiftSelectPivot, 2, testid + "shiftSelectPivot -1 from currentIndex");
michael@0 311 }
michael@0 312
michael@0 313 // XXXndeakin need to test out of range values but these don't work properly
michael@0 314 /*
michael@0 315 selection.select(-1);
michael@0 316 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect augment -1", -1, []);
michael@0 317
michael@0 318 selection.select(8);
michael@0 319 testtag_tree_TreeSelection_State(tree, testid + "rangedSelect augment 8", 3, [0]);
michael@0 320 */
michael@0 321 }
michael@0 322
michael@0 323 function testtag_tree_TreeSelection_UI(tree, testid, multiple)
michael@0 324 {
michael@0 325 testid += " selection UI ";
michael@0 326
michael@0 327 var selection = tree.view.selection;
michael@0 328 selection.clearSelection();
michael@0 329 selection.currentIndex = 0;
michael@0 330 tree.focus();
michael@0 331
michael@0 332 var keydownFired = 0;
michael@0 333 var keypressFired = 0;
michael@0 334 function keydownListener(event)
michael@0 335 {
michael@0 336 keydownFired++;
michael@0 337 }
michael@0 338 function keypressListener(event) {
michael@0 339 keypressFired++;
michael@0 340 }
michael@0 341
michael@0 342 // check that cursor up and down keys navigate up and down
michael@0 343 // select event fires after a delay so don't expect it. The reason it fires after a delay
michael@0 344 // is so that cursor navigation allows quicking skimming over a set of items without
michael@0 345 // actually firing events in-between, improving performance. The select event will only
michael@0 346 // be fired on the row where the cursor stops.
michael@0 347 window.addEventListener("keydown", keydownListener, false);
michael@0 348 window.addEventListener("keypress", keypressListener, false);
michael@0 349
michael@0 350 synthesizeKeyExpectEvent("VK_DOWN", {}, tree, "!select", "key down");
michael@0 351 testtag_tree_TreeSelection_State(tree, testid + "key down", 1, [1], 0);
michael@0 352
michael@0 353 synthesizeKeyExpectEvent("VK_UP", {}, tree, "!select", "key up");
michael@0 354 testtag_tree_TreeSelection_State(tree, testid + "key up", 0, [0], 0);
michael@0 355
michael@0 356 synthesizeKeyExpectEvent("VK_UP", {}, tree, "!select", "key up at start");
michael@0 357 testtag_tree_TreeSelection_State(tree, testid + "key up at start", 0, [0], 0);
michael@0 358
michael@0 359 // pressing down while the last row is selected should not fire a select event,
michael@0 360 // as the selection won't have changed. Also the view is not scrolled in this case.
michael@0 361 selection.select(7);
michael@0 362 synthesizeKeyExpectEvent("VK_DOWN", {}, tree, "!select", "key down at end");
michael@0 363 testtag_tree_TreeSelection_State(tree, testid + "key down at end", 7, [7], 0);
michael@0 364
michael@0 365 // pressing keys while at the edge of the visible rows should scroll the list
michael@0 366 tree.treeBoxObject.scrollToRow(4);
michael@0 367 selection.select(4);
michael@0 368 synthesizeKeyExpectEvent("VK_UP", {}, tree, "!select", "key up with scroll");
michael@0 369 is(tree.treeBoxObject.getFirstVisibleRow(), 3, testid + "key up with scroll");
michael@0 370
michael@0 371 tree.treeBoxObject.scrollToRow(0);
michael@0 372 selection.select(3);
michael@0 373 synthesizeKeyExpectEvent("VK_DOWN", {}, tree, "!select", "key down with scroll");
michael@0 374 is(tree.treeBoxObject.getFirstVisibleRow(), 1, testid + "key down with scroll");
michael@0 375
michael@0 376 // accel key and cursor movement adjust currentIndex but should not change
michael@0 377 // the selection. In single selection mode, the selection will not change,
michael@0 378 // but instead will just scroll up or down a line
michael@0 379 tree.treeBoxObject.scrollToRow(0);
michael@0 380 selection.select(1);
michael@0 381 synthesizeKeyExpectEvent("VK_DOWN", { accelKey: true }, tree, "!select", "key down with accel");
michael@0 382 testtag_tree_TreeSelection_State(tree, testid + "key down with accel", multiple ? 2 : 1, [1]);
michael@0 383 if (!multiple)
michael@0 384 is(tree.treeBoxObject.getFirstVisibleRow(), 1, testid + "key down with accel and scroll");
michael@0 385
michael@0 386 tree.treeBoxObject.scrollToRow(4);
michael@0 387 selection.select(4);
michael@0 388 synthesizeKeyExpectEvent("VK_UP", { accelKey: true }, tree, "!select", "key up with accel");
michael@0 389 testtag_tree_TreeSelection_State(tree, testid + "key up with accel", multiple ? 3 : 4, [4]);
michael@0 390 if (!multiple)
michael@0 391 is(tree.treeBoxObject.getFirstVisibleRow(), 3, testid + "key up with accel and scroll");
michael@0 392
michael@0 393 // do this three times, one for each state of pageUpOrDownMovesSelection,
michael@0 394 // and then once with the accel key pressed
michael@0 395 for (var t = 0; t < 3; t++) {
michael@0 396 var testidmod = (t == 2) ? " with accel" : (t == 1) ? " rev" : "";
michael@0 397 var keymod = (t == 2) ? { accelKey: true } : { };
michael@0 398
michael@0 399 var moveselection = tree.pageUpOrDownMovesSelection;
michael@0 400 if (t == 2)
michael@0 401 moveselection = !moveselection;
michael@0 402
michael@0 403 tree.treeBoxObject.scrollToRow(4);
michael@0 404 selection.currentIndex = 6;
michael@0 405 selection.select(6);
michael@0 406 var expected = moveselection ? 4 : 6;
michael@0 407 synthesizeKeyExpectEvent("VK_PAGE_UP", keymod, tree, "!select", "key page up");
michael@0 408 testtag_tree_TreeSelection_State(tree, testid + "key page up" + testidmod,
michael@0 409 expected, [expected], moveselection ? 4 : 0);
michael@0 410
michael@0 411 expected = moveselection ? 0 : 6;
michael@0 412 synthesizeKeyExpectEvent("VK_PAGE_UP", keymod, tree, "!select", "key page up again");
michael@0 413 testtag_tree_TreeSelection_State(tree, testid + "key page up again" + testidmod,
michael@0 414 expected, [expected], 0);
michael@0 415
michael@0 416 expected = moveselection ? 0 : 6;
michael@0 417 synthesizeKeyExpectEvent("VK_PAGE_UP", keymod, tree, "!select", "key page up at start");
michael@0 418 testtag_tree_TreeSelection_State(tree, testid + "key page up at start" + testidmod,
michael@0 419 expected, [expected], 0);
michael@0 420
michael@0 421 tree.treeBoxObject.scrollToRow(0);
michael@0 422 selection.currentIndex = 1;
michael@0 423 selection.select(1);
michael@0 424 expected = moveselection ? 3 : 1;
michael@0 425 synthesizeKeyExpectEvent("VK_PAGE_DOWN", keymod, tree, "!select", "key page down");
michael@0 426 testtag_tree_TreeSelection_State(tree, testid + "key page down" + testidmod,
michael@0 427 expected, [expected], moveselection ? 0 : 4);
michael@0 428
michael@0 429 expected = moveselection ? 7 : 1;
michael@0 430 synthesizeKeyExpectEvent("VK_PAGE_DOWN", keymod, tree, "!select", "key page down again");
michael@0 431 testtag_tree_TreeSelection_State(tree, testid + "key page down again" + testidmod,
michael@0 432 expected, [expected], 4);
michael@0 433
michael@0 434 expected = moveselection ? 7 : 1;
michael@0 435 synthesizeKeyExpectEvent("VK_PAGE_DOWN", keymod, tree, "!select", "key page down at start");
michael@0 436 testtag_tree_TreeSelection_State(tree, testid + "key page down at start" + testidmod,
michael@0 437 expected, [expected], 4);
michael@0 438
michael@0 439 if (t < 2)
michael@0 440 tree.pageUpOrDownMovesSelection = !tree.pageUpOrDownMovesSelection;
michael@0 441 }
michael@0 442
michael@0 443 tree.treeBoxObject.scrollToRow(4);
michael@0 444 selection.select(6);
michael@0 445 synthesizeKeyExpectEvent("VK_HOME", {}, tree, "!select", "key home");
michael@0 446 testtag_tree_TreeSelection_State(tree, testid + "key home", 0, [0], 0);
michael@0 447
michael@0 448 tree.treeBoxObject.scrollToRow(0);
michael@0 449 selection.select(1);
michael@0 450 synthesizeKeyExpectEvent("VK_END", {}, tree, "!select", "key end");
michael@0 451 testtag_tree_TreeSelection_State(tree, testid + "key end", 7, [7], 4);
michael@0 452
michael@0 453 // in single selection mode, the selection doesn't change in this case
michael@0 454 tree.treeBoxObject.scrollToRow(4);
michael@0 455 selection.select(6);
michael@0 456 synthesizeKeyExpectEvent("VK_HOME", { accelKey: true }, tree, "!select", "key home with accel");
michael@0 457 testtag_tree_TreeSelection_State(tree, testid + "key home with accel", multiple ? 0 : 6, [6], 0);
michael@0 458
michael@0 459 tree.treeBoxObject.scrollToRow(0);
michael@0 460 selection.select(1);
michael@0 461 synthesizeKeyExpectEvent("VK_END", { accelKey: true }, tree, "!select", "key end with accel");
michael@0 462 testtag_tree_TreeSelection_State(tree, testid + "key end with accel", multiple ? 7 : 1, [1], 4);
michael@0 463
michael@0 464 // next, test cursor navigation with selection. Here the select event will be fired
michael@0 465 selection.select(1);
michael@0 466 var eventExpected = multiple ? "select" : "!select";
michael@0 467 synthesizeKeyExpectEvent("VK_DOWN", { shiftKey: true }, tree, eventExpected, "key shift down to select");
michael@0 468 testtag_tree_TreeSelection_State(tree, testid + "key shift down to select",
michael@0 469 multiple ? 2 : 1, multiple ? [1, 2] : [1]);
michael@0 470 is(selection.shiftSelectPivot, multiple ? 1 : -1,
michael@0 471 testid + "key shift down to select shiftSelectPivot");
michael@0 472 synthesizeKeyExpectEvent("VK_UP", { shiftKey: true }, tree, eventExpected, "key shift up to unselect");
michael@0 473 testtag_tree_TreeSelection_State(tree, testid + "key shift up to unselect", 1, [1]);
michael@0 474 is(selection.shiftSelectPivot, multiple ? 1 : -1,
michael@0 475 testid + "key shift up to unselect shiftSelectPivot");
michael@0 476 if (multiple) {
michael@0 477 synthesizeKeyExpectEvent("VK_UP", { shiftKey: true }, tree, "select", "key shift up to select");
michael@0 478 testtag_tree_TreeSelection_State(tree, testid + "key shift up to select", 0, [0, 1]);
michael@0 479 is(selection.shiftSelectPivot, 1, testid + "key shift up to select shiftSelectPivot");
michael@0 480 synthesizeKeyExpectEvent("VK_DOWN", { shiftKey: true }, tree, "select", "key shift down to unselect");
michael@0 481 testtag_tree_TreeSelection_State(tree, testid + "key shift down to unselect", 1, [1]);
michael@0 482 is(selection.shiftSelectPivot, 1, testid + "key shift down to unselect shiftSelectPivot");
michael@0 483 }
michael@0 484
michael@0 485 // do this twice, one for each state of pageUpOrDownMovesSelection, however
michael@0 486 // when selecting with the shift key, pageUpOrDownMovesSelection is ignored
michael@0 487 // and the selection always changes
michael@0 488 var lastidx = tree.view.rowCount - 1;
michael@0 489 for (var t = 0; t < 2; t++) {
michael@0 490 var testidmod = (t == 0) ? "" : " rev";
michael@0 491
michael@0 492 // If the top or bottom visible row is the current row, pressing shift and
michael@0 493 // page down / page up selects one page up or one page down. Otherwise, the
michael@0 494 // selection is made to the top or bottom of the visible area.
michael@0 495 tree.treeBoxObject.scrollToRow(lastidx - 3);
michael@0 496 selection.currentIndex = 6;
michael@0 497 selection.select(6);
michael@0 498 synthesizeKeyExpectEvent("VK_PAGE_UP", { shiftKey: true }, tree, eventExpected, "key shift page up");
michael@0 499 testtag_tree_TreeSelection_State(tree, testid + "key shift page up" + testidmod,
michael@0 500 multiple ? 4 : 6, multiple ? [4, 5, 6] : [6]);
michael@0 501 if (multiple) {
michael@0 502 synthesizeKeyExpectEvent("VK_PAGE_UP", { shiftKey: true }, tree, "select", "key shift page up again");
michael@0 503 testtag_tree_TreeSelection_State(tree, testid + "key shift page up again" + testidmod,
michael@0 504 0, [0, 1, 2, 3, 4, 5, 6]);
michael@0 505 // no change in the selection, so no select event should be fired
michael@0 506 synthesizeKeyExpectEvent("VK_PAGE_UP", { shiftKey: true }, tree, "!select", "key shift page up at start");
michael@0 507 testtag_tree_TreeSelection_State(tree, testid + "key shift page up at start" + testidmod,
michael@0 508 0, [0, 1, 2, 3, 4, 5, 6]);
michael@0 509 // deselect by paging down again
michael@0 510 synthesizeKeyExpectEvent("VK_PAGE_DOWN", { shiftKey: true }, tree, "select", "key shift page down deselect");
michael@0 511 testtag_tree_TreeSelection_State(tree, testid + "key shift page down deselect" + testidmod,
michael@0 512 3, [3, 4, 5, 6]);
michael@0 513 }
michael@0 514
michael@0 515 tree.treeBoxObject.scrollToRow(1);
michael@0 516 selection.currentIndex = 2;
michael@0 517 selection.select(2);
michael@0 518 synthesizeKeyExpectEvent("VK_PAGE_DOWN", { shiftKey: true }, tree, eventExpected, "key shift page down");
michael@0 519 testtag_tree_TreeSelection_State(tree, testid + "key shift page down" + testidmod,
michael@0 520 multiple ? 4 : 2, multiple ? [2, 3, 4] : [2]);
michael@0 521 if (multiple) {
michael@0 522 synthesizeKeyExpectEvent("VK_PAGE_DOWN", { shiftKey: true }, tree, "select", "key shift page down again");
michael@0 523 testtag_tree_TreeSelection_State(tree, testid + "key shift page down again" + testidmod,
michael@0 524 7, [2, 3, 4, 5, 6, 7]);
michael@0 525 synthesizeKeyExpectEvent("VK_PAGE_DOWN", { shiftKey: true }, tree, "!select", "key shift page down at start");
michael@0 526 testtag_tree_TreeSelection_State(tree, testid + "key shift page down at start" + testidmod,
michael@0 527 7, [2, 3, 4, 5, 6, 7]);
michael@0 528 synthesizeKeyExpectEvent("VK_PAGE_UP", { shiftKey: true }, tree, "select", "key shift page up deselect");
michael@0 529 testtag_tree_TreeSelection_State(tree, testid + "key shift page up deselect" + testidmod,
michael@0 530 4, [2, 3, 4]);
michael@0 531 }
michael@0 532
michael@0 533 // test when page down / page up is pressed when the view is scrolled such
michael@0 534 // that the selection is not visible
michael@0 535 if (multiple) {
michael@0 536 tree.treeBoxObject.scrollToRow(3);
michael@0 537 selection.currentIndex = 1;
michael@0 538 selection.select(1);
michael@0 539 synthesizeKeyExpectEvent("VK_PAGE_DOWN", { shiftKey: true }, tree, eventExpected,
michael@0 540 "key shift page down with view scrolled down");
michael@0 541 testtag_tree_TreeSelection_State(tree, testid + "key shift page down with view scrolled down" + testidmod,
michael@0 542 6, [1, 2, 3, 4, 5, 6], 3);
michael@0 543
michael@0 544 tree.treeBoxObject.scrollToRow(2);
michael@0 545 selection.currentIndex = 6;
michael@0 546 selection.select(6);
michael@0 547 synthesizeKeyExpectEvent("VK_PAGE_UP", { shiftKey: true }, tree, eventExpected,
michael@0 548 "key shift page up with view scrolled up");
michael@0 549 testtag_tree_TreeSelection_State(tree, testid + "key shift page up with view scrolled up" + testidmod,
michael@0 550 2, [2, 3, 4, 5, 6], 2);
michael@0 551
michael@0 552 tree.treeBoxObject.scrollToRow(2);
michael@0 553 selection.currentIndex = 0;
michael@0 554 selection.select(0);
michael@0 555 // don't expect the select event, as the selection won't have changed
michael@0 556 synthesizeKeyExpectEvent("VK_PAGE_UP", { shiftKey: true }, tree, "!select",
michael@0 557 "key shift page up at start with view scrolled down");
michael@0 558 testtag_tree_TreeSelection_State(tree, testid + "key shift page up at start with view scrolled down" + testidmod,
michael@0 559 0, [0], 0);
michael@0 560
michael@0 561 tree.treeBoxObject.scrollToRow(0);
michael@0 562 selection.currentIndex = 7;
michael@0 563 selection.select(7);
michael@0 564 // don't expect the select event, as the selection won't have changed
michael@0 565 synthesizeKeyExpectEvent("VK_PAGE_DOWN", { shiftKey: true }, tree, "!select",
michael@0 566 "key shift page down at end with view scrolled up");
michael@0 567 testtag_tree_TreeSelection_State(tree, testid + "key shift page down at end with view scrolled up" + testidmod,
michael@0 568 7, [7], 4);
michael@0 569 }
michael@0 570
michael@0 571 tree.pageUpOrDownMovesSelection = !tree.pageUpOrDownMovesSelection;
michael@0 572 }
michael@0 573
michael@0 574 tree.treeBoxObject.scrollToRow(4);
michael@0 575 selection.select(5);
michael@0 576 synthesizeKeyExpectEvent("VK_HOME", { shiftKey: true }, tree, eventExpected, "key shift home");
michael@0 577 testtag_tree_TreeSelection_State(tree, testid + "key shift home",
michael@0 578 multiple ? 0 : 5, multiple ? [0, 1, 2, 3, 4, 5] : [5], multiple ? 0 : 4);
michael@0 579
michael@0 580 tree.treeBoxObject.scrollToRow(0);
michael@0 581 selection.select(3);
michael@0 582 synthesizeKeyExpectEvent("VK_END", { shiftKey: true }, tree, eventExpected, "key shift end");
michael@0 583 testtag_tree_TreeSelection_State(tree, testid + "key shift end",
michael@0 584 multiple ? 7 : 3, multiple ? [3, 4, 5, 6, 7] : [3], multiple ? 4 : 0);
michael@0 585
michael@0 586 // pressing space selects a row, pressing accel + space unselects a row
michael@0 587 selection.select(2);
michael@0 588 selection.currentIndex = 4;
michael@0 589 synthesizeKeyExpectEvent(" ", {}, tree, "select", "key space on");
michael@0 590 // in single selection mode, space shouldn't do anything
michael@0 591 testtag_tree_TreeSelection_State(tree, testid + "key space on", 4, multiple ? [2, 4] : [2]);
michael@0 592
michael@0 593 if (multiple) {
michael@0 594 synthesizeKeyExpectEvent(" ", { accelKey: true }, tree, "select", "key space off");
michael@0 595 testtag_tree_TreeSelection_State(tree, testid + "key space off", 4, [2]);
michael@0 596 }
michael@0 597
michael@0 598 // check that clicking on a row selects it
michael@0 599 tree.treeBoxObject.scrollToRow(0);
michael@0 600 selection.select(2);
michael@0 601 selection.currentIndex = 2;
michael@0 602 if (0) { // XXXndeakin disable these tests for now
michael@0 603 mouseOnCell(tree, 1, tree.columns[1], "mouse on row");
michael@0 604 testtag_tree_TreeSelection_State(tree, testid + "mouse on row", 1, [1], 0,
michael@0 605 tree.selType == "cell" ? tree.columns[1] : null);
michael@0 606 }
michael@0 607
michael@0 608 // restore the scroll position to the start of the page
michael@0 609 sendKey("HOME");
michael@0 610
michael@0 611 window.removeEventListener("keydown", keydownListener, false);
michael@0 612 window.removeEventListener("keypress", keypressListener, false);
michael@0 613 is(keydownFired, multiple ? 63 : 40, "keydown event wasn't fired properly");
michael@0 614 is(keypressFired, multiple ? 2 : 1, "keypress event wasn't fired properly");
michael@0 615 }
michael@0 616
michael@0 617 function testtag_tree_UI_editing(tree, testid, rowInfo)
michael@0 618 {
michael@0 619 testid += " editing UI ";
michael@0 620
michael@0 621 // check editing UI
michael@0 622 var ecolumn = tree.columns[0];
michael@0 623 var rowIndex = 2;
michael@0 624 var inputField = tree.inputField;
michael@0 625
michael@0 626 // temporary make the tree editable to test mouse double click
michael@0 627 var wasEditable = tree.editable;
michael@0 628 if (!wasEditable)
michael@0 629 tree.editable = true;
michael@0 630
michael@0 631 // if this is a container save its current open status
michael@0 632 var row = rowInfo.rows[rowIndex];
michael@0 633 var wasOpen = null;
michael@0 634 if (tree.view.isContainer(row))
michael@0 635 wasOpen = tree.view.isContainerOpen(row);
michael@0 636
michael@0 637 // Test whether a keystroke can enter text entry, and another can exit.
michael@0 638 if (tree.selType == "cell")
michael@0 639 {
michael@0 640 tree.stopEditing(false);
michael@0 641 ok(!tree.editingColumn, "Should not be editing tree cell now");
michael@0 642 tree.view.selection.currentColumn = ecolumn;
michael@0 643 tree.currentIndex = rowIndex;
michael@0 644
michael@0 645 const isMac = (navigator.platform.indexOf("Mac") >= 0);
michael@0 646 const StartEditingKey = isMac ? "RETURN" : "F2";
michael@0 647 sendKey(StartEditingKey);
michael@0 648 is(tree.editingColumn, ecolumn, "Should be editing tree cell now");
michael@0 649 sendKey("ESCAPE");
michael@0 650 ok(!tree.editingColumn, "Should not be editing tree cell now");
michael@0 651 is(tree.currentIndex, rowIndex, "Current index should not have changed");
michael@0 652 is(tree.view.selection.currentColumn, ecolumn, "Current column should not have changed");
michael@0 653 }
michael@0 654
michael@0 655 mouseDblClickOnCell(tree, rowIndex, ecolumn, testid + "edit on double click");
michael@0 656 is(tree.editingColumn, ecolumn, testid + "editing column");
michael@0 657 is(tree.editingRow, rowIndex, testid + "editing row");
michael@0 658
michael@0 659 // ensure that we don't expand an expandable container on edit
michael@0 660 if (wasOpen != null)
michael@0 661 is(tree.view.isContainerOpen(row), wasOpen, testid + "opened container node on edit");
michael@0 662
michael@0 663 // ensure to restore editable attribute
michael@0 664 if (!wasEditable)
michael@0 665 tree.editable = false;
michael@0 666
michael@0 667 var ci = tree.currentIndex;
michael@0 668
michael@0 669 // cursor navigation should not change the selection while editing
michael@0 670 var testKey = function(key) {
michael@0 671 synthesizeKeyExpectEvent(key, {}, tree, "!select", "key " + key + " with editing");
michael@0 672 is(tree.editingRow == rowIndex && tree.editingColumn == ecolumn && tree.currentIndex == ci,
michael@0 673 true, testid + "key " + key + " while editing");
michael@0 674 }
michael@0 675
michael@0 676 testKey("VK_DOWN");
michael@0 677 testKey("VK_UP");
michael@0 678 testKey("VK_PAGE_DOWN");
michael@0 679 testKey("VK_PAGE_UP");
michael@0 680 testKey("VK_HOME");
michael@0 681 testKey("VK_END");
michael@0 682
michael@0 683 // XXXndeakin figure out how to send characters to the textbox
michael@0 684 // inputField.inputField.focus()
michael@0 685 // synthesizeKeyExpectEvent(inputField.inputField, "b", null, "");
michael@0 686 // tree.stopEditing(true);
michael@0 687 // is(tree.view.getCellText(0, ecolumn), "b", testid + "edit cell");
michael@0 688
michael@0 689 // Restore initial state.
michael@0 690 tree.stopEditing(false);
michael@0 691 }
michael@0 692
michael@0 693 function testtag_tree_TreeSelection_UI_cell(tree, testid, rowInfo)
michael@0 694 {
michael@0 695 testid += " selection UI cell ";
michael@0 696
michael@0 697 var columns = tree.columns;
michael@0 698 var firstcolumn = columns[0];
michael@0 699 var secondcolumn = columns[1];
michael@0 700 var lastcolumn = columns[columns.length - 1];
michael@0 701 var secondlastcolumn = columns[columns.length - 2];
michael@0 702 var selection = tree.view.selection;
michael@0 703
michael@0 704 selection.clearSelection();
michael@0 705 selection.currentIndex = -1;
michael@0 706 selection.currentColumn = firstcolumn;
michael@0 707 is(selection.currentColumn, firstcolumn, testid + " first currentColumn");
michael@0 708
michael@0 709 // no selection yet so nothing should happen when the left and right cursor keys are pressed
michael@0 710 synthesizeKeyExpectEvent("VK_RIGHT", {}, tree, "!select", "key right no selection");
michael@0 711 testtag_tree_TreeSelection_State(tree, testid + "key right no selection", -1, [], null, firstcolumn);
michael@0 712
michael@0 713 selection.currentColumn = secondcolumn;
michael@0 714 synthesizeKeyExpectEvent("VK_LEFT", {}, tree, "!select", "key left no selection");
michael@0 715 testtag_tree_TreeSelection_State(tree, testid + "key left no selection", -1, [], null, secondcolumn);
michael@0 716
michael@0 717 selection.select(2);
michael@0 718 selection.currentIndex = 2;
michael@0 719 if (0) { // XXXndeakin disable these tests for now
michael@0 720 mouseOnCell(tree, 1, secondlastcolumn, "mouse on cell");
michael@0 721 testtag_tree_TreeSelection_State(tree, testid + "mouse on cell", 1, [1], null, secondlastcolumn);
michael@0 722 }
michael@0 723
michael@0 724 tree.focus();
michael@0 725
michael@0 726 // selection is set, so it should move when the left and right cursor keys are pressed
michael@0 727 tree.treeBoxObject.scrollToRow(0);
michael@0 728 selection.select(1);
michael@0 729 selection.currentIndex = 1;
michael@0 730 selection.currentColumn = secondcolumn;
michael@0 731 synthesizeKeyExpectEvent("VK_LEFT", {}, tree, "!select", "key left in second column");
michael@0 732 testtag_tree_TreeSelection_State(tree, testid + "key left in second column", 1, [1], 0, firstcolumn);
michael@0 733
michael@0 734 synthesizeKeyExpectEvent("VK_LEFT", {}, tree, "!select", "key left in first column");
michael@0 735 testtag_tree_TreeSelection_State(tree, testid + "key left in first column", 1, [1], 0, firstcolumn);
michael@0 736
michael@0 737 selection.currentColumn = secondlastcolumn;
michael@0 738 synthesizeKeyExpectEvent("VK_RIGHT", {}, tree, "!select", "key right in second last column");
michael@0 739 testtag_tree_TreeSelection_State(tree, testid + "key right in second last column", 1, [1], 0, lastcolumn);
michael@0 740
michael@0 741 synthesizeKeyExpectEvent("VK_RIGHT", {}, tree, "!select", "key right in last column");
michael@0 742 testtag_tree_TreeSelection_State(tree, testid + "key right in last column", 1, [1], 0, lastcolumn);
michael@0 743
michael@0 744 synthesizeKeyExpectEvent("VK_UP", {}, tree, "!select", "key up in second row");
michael@0 745 testtag_tree_TreeSelection_State(tree, testid + "key up in second row", 0, [0], 0, lastcolumn);
michael@0 746
michael@0 747 synthesizeKeyExpectEvent("VK_UP", {}, tree, "!select", "key up in first row");
michael@0 748 testtag_tree_TreeSelection_State(tree, testid + "key up in first row", 0, [0], 0, lastcolumn);
michael@0 749
michael@0 750 synthesizeKeyExpectEvent("VK_DOWN", {}, tree, "!select", "key down in first row");
michael@0 751 testtag_tree_TreeSelection_State(tree, testid + "key down in first row", 1, [1], 0, lastcolumn);
michael@0 752
michael@0 753 var lastidx = tree.view.rowCount - 1;
michael@0 754 tree.treeBoxObject.scrollToRow(lastidx - 3);
michael@0 755 selection.select(lastidx);
michael@0 756 selection.currentIndex = lastidx;
michael@0 757 synthesizeKeyExpectEvent("VK_DOWN", {}, tree, "!select", "key down in last row");
michael@0 758 testtag_tree_TreeSelection_State(tree, testid + "key down in last row", lastidx, [lastidx], lastidx - 3, lastcolumn);
michael@0 759
michael@0 760 synthesizeKeyExpectEvent("VK_HOME", {}, tree, "!select", "key home");
michael@0 761 testtag_tree_TreeSelection_State(tree, testid + "key home", 0, [0], 0, lastcolumn);
michael@0 762
michael@0 763 synthesizeKeyExpectEvent("VK_END", {}, tree, "!select", "key end");
michael@0 764 testtag_tree_TreeSelection_State(tree, testid + "key end", lastidx, [lastidx], lastidx - 3, lastcolumn);
michael@0 765
michael@0 766 for (var t = 0; t < 2; t++) {
michael@0 767 var testidmod = (t == 0) ? "" : " rev";
michael@0 768
michael@0 769 // scroll to the end, subtract 3 because we want lastidx to appear
michael@0 770 // at the end of view
michael@0 771 tree.treeBoxObject.scrollToRow(lastidx - 3);
michael@0 772 selection.select(lastidx);
michael@0 773 selection.currentIndex = lastidx;
michael@0 774 var expectedrow = tree.pageUpOrDownMovesSelection ? lastidx - 3 : lastidx;
michael@0 775 synthesizeKeyExpectEvent("VK_PAGE_UP", {}, tree, "!select", "key page up");
michael@0 776 testtag_tree_TreeSelection_State(tree, testid + "key page up" + testidmod,
michael@0 777 expectedrow, [expectedrow],
michael@0 778 tree.pageUpOrDownMovesSelection ? lastidx - 3 : 0, lastcolumn);
michael@0 779
michael@0 780 tree.treeBoxObject.scrollToRow(1);
michael@0 781 selection.select(1);
michael@0 782 selection.currentIndex = 1;
michael@0 783 var expectedrow = tree.pageUpOrDownMovesSelection ? 4 : 1;
michael@0 784 synthesizeKeyExpectEvent("VK_PAGE_DOWN", {}, tree, "!select", "key page down");
michael@0 785 testtag_tree_TreeSelection_State(tree, testid + "key page down" + testidmod,
michael@0 786 expectedrow, [expectedrow],
michael@0 787 tree.pageUpOrDownMovesSelection ? 1 : lastidx - 3, lastcolumn);
michael@0 788
michael@0 789 tree.pageUpOrDownMovesSelection = !tree.pageUpOrDownMovesSelection;
michael@0 790 }
michael@0 791
michael@0 792 // now check navigation when there is unselctable column
michael@0 793 secondcolumn.element.setAttribute("selectable", "false");
michael@0 794 secondcolumn.invalidate();
michael@0 795 is(secondcolumn.selectable, false, testid + "set selectable attribute");
michael@0 796
michael@0 797 if (columns.length >= 3) {
michael@0 798 selection.select(3);
michael@0 799 selection.currentIndex = 3;
michael@0 800 // check whether unselectable columns are skipped over
michael@0 801 selection.currentColumn = firstcolumn;
michael@0 802 synthesizeKeyExpectEvent("VK_RIGHT", {}, tree, "!select", "key right unselectable column");
michael@0 803 testtag_tree_TreeSelection_State(tree, testid + "key right unselectable column",
michael@0 804 3, [3], null, secondcolumn.getNext());
michael@0 805
michael@0 806 synthesizeKeyExpectEvent("VK_LEFT", {}, tree, "!select", "key left unselectable column");
michael@0 807 testtag_tree_TreeSelection_State(tree, testid + "key left unselectable column",
michael@0 808 3, [3], null, firstcolumn);
michael@0 809 }
michael@0 810
michael@0 811 secondcolumn.element.removeAttribute("selectable");
michael@0 812 secondcolumn.invalidate();
michael@0 813 is(secondcolumn.selectable, true, testid + "clear selectable attribute");
michael@0 814
michael@0 815 // check to ensure that navigation isn't allowed if the first column is not selectable
michael@0 816 selection.currentColumn = secondcolumn;
michael@0 817 firstcolumn.element.setAttribute("selectable", "false");
michael@0 818 firstcolumn.invalidate();
michael@0 819 synthesizeKeyExpectEvent("VK_LEFT", {}, tree, "!select", "key left unselectable first column");
michael@0 820 testtag_tree_TreeSelection_State(tree, testid + "key left unselectable first column",
michael@0 821 3, [3], null, secondcolumn);
michael@0 822 firstcolumn.element.removeAttribute("selectable");
michael@0 823 firstcolumn.invalidate();
michael@0 824
michael@0 825 // check to ensure that navigation isn't allowed if the last column is not selectable
michael@0 826 selection.currentColumn = secondlastcolumn;
michael@0 827 lastcolumn.element.setAttribute("selectable", "false");
michael@0 828 lastcolumn.invalidate();
michael@0 829 synthesizeKeyExpectEvent("VK_RIGHT", {}, tree, "!select", "key right unselectable last column");
michael@0 830 testtag_tree_TreeSelection_State(tree, testid + "key right unselectable last column",
michael@0 831 3, [3], null, secondlastcolumn);
michael@0 832 lastcolumn.element.removeAttribute("selectable");
michael@0 833 lastcolumn.invalidate();
michael@0 834
michael@0 835 // now check for cells with selectable false
michael@0 836 if (!rowInfo.rows[4].cells[1].selectable && columns.length >= 3) {
michael@0 837 // check whether unselectable cells are skipped over
michael@0 838 selection.select(4);
michael@0 839 selection.currentIndex = 4;
michael@0 840
michael@0 841 selection.currentColumn = firstcolumn;
michael@0 842 synthesizeKeyExpectEvent("VK_RIGHT", {}, tree, "!select", "key right unselectable cell");
michael@0 843 testtag_tree_TreeSelection_State(tree, testid + "key right unselectable cell",
michael@0 844 4, [4], null, secondcolumn.getNext());
michael@0 845
michael@0 846 synthesizeKeyExpectEvent("VK_LEFT", {}, tree, "!select", "key left unselectable cell");
michael@0 847 testtag_tree_TreeSelection_State(tree, testid + "key left unselectable cell",
michael@0 848 4, [4], null, firstcolumn);
michael@0 849
michael@0 850 tree.treeBoxObject.scrollToRow(1);
michael@0 851 selection.select(3);
michael@0 852 selection.currentIndex = 3;
michael@0 853 selection.currentColumn = secondcolumn;
michael@0 854
michael@0 855 synthesizeKeyExpectEvent("VK_DOWN", {}, tree, "!select", "key down unselectable cell");
michael@0 856 testtag_tree_TreeSelection_State(tree, testid + "key down unselectable cell",
michael@0 857 5, [5], 2, secondcolumn);
michael@0 858
michael@0 859 tree.treeBoxObject.scrollToRow(4);
michael@0 860 synthesizeKeyExpectEvent("VK_UP", {}, tree, "!select", "key up unselectable cell");
michael@0 861 testtag_tree_TreeSelection_State(tree, testid + "key up unselectable cell",
michael@0 862 3, [3], 3, secondcolumn);
michael@0 863 }
michael@0 864
michael@0 865 // restore the scroll position to the start of the page
michael@0 866 sendKey("HOME");
michael@0 867 }
michael@0 868
michael@0 869 function testtag_tree_TreeView(tree, testid, rowInfo)
michael@0 870 {
michael@0 871 testid += " view ";
michael@0 872
michael@0 873 var columns = tree.columns;
michael@0 874 var view = tree.view;
michael@0 875
michael@0 876 is(view instanceof Components.interfaces.nsITreeView, true, testid + "view is a TreeView");
michael@0 877 is(view.rowCount, rowInfo.rows.length, testid + "rowCount");
michael@0 878
michael@0 879 testtag_tree_TreeView_rows(tree, testid, rowInfo, 0);
michael@0 880
michael@0 881 // note that this will only work for content trees currently
michael@0 882 view.setCellText(0, columns[1], "Changed Value");
michael@0 883 is(view.getCellText(0, columns[1]), "Changed Value", "setCellText");
michael@0 884
michael@0 885 view.setCellValue(1, columns[0], "Another Changed Value");
michael@0 886 is(view.getCellValue(1, columns[0]), "Another Changed Value", "setCellText");
michael@0 887 }
michael@0 888
michael@0 889 function testtag_tree_TreeView_rows(tree, testid, rowInfo, startRow)
michael@0 890 {
michael@0 891 var r;
michael@0 892 var columns = tree.columns;
michael@0 893 var view = tree.view;
michael@0 894 var length = rowInfo.rows.length;
michael@0 895
michael@0 896 // methods to test along with the functions which determine the expected value
michael@0 897 var checkRowMethods =
michael@0 898 {
michael@0 899 isContainer: function(row) { return row.container },
michael@0 900 isContainerOpen: function(row) { return false },
michael@0 901 isContainerEmpty: function(row) { return (row.children != null && row.children.rows.length == 0) },
michael@0 902 isSeparator: function(row) { return row.separator },
michael@0 903 getRowProperties: function(row) { return row.properties },
michael@0 904 getLevel: function(row) { return row.level },
michael@0 905 getParentIndex: function(row) { return row.parent },
michael@0 906 hasNextSibling: function(row) { return r < startRow + length - 1; }
michael@0 907 };
michael@0 908
michael@0 909 var checkCellMethods =
michael@0 910 {
michael@0 911 getCellText: function(row, cell) { return cell.label },
michael@0 912 getCellValue: function(row, cell) { return cell.value },
michael@0 913 getCellProperties: function(row, cell) { return cell.properties },
michael@0 914 isEditable: function(row, cell) { return cell.editable },
michael@0 915 isSelectable: function(row, cell) { return cell.selectable },
michael@0 916 getImageSrc: function(row, cell) { return cell.image },
michael@0 917 getProgressMode: function(row, cell) { return cell.mode }
michael@0 918 };
michael@0 919
michael@0 920 var failedMethods = { };
michael@0 921 var checkMethod, actual, expected;
michael@0 922 var containerInfo = null;
michael@0 923 var toggleOpenStateOK = true;
michael@0 924
michael@0 925 for (r = startRow; r < length; r++) {
michael@0 926 var row = rowInfo.rows[r];
michael@0 927 for (var c = 0; c < row.cells.length; c++) {
michael@0 928 var cell = row.cells[c];
michael@0 929
michael@0 930 for (checkMethod in checkCellMethods) {
michael@0 931 expected = checkCellMethods[checkMethod](row, cell);
michael@0 932 actual = view[checkMethod](r, columns[c]);
michael@0 933 if (actual !== expected) {
michael@0 934 failedMethods[checkMethod] = true;
michael@0 935 is(actual, expected, testid + "row " + r + " column " + c + " " + checkMethod + " is incorrect");
michael@0 936 }
michael@0 937 }
michael@0 938 }
michael@0 939
michael@0 940 // compare row properties
michael@0 941 for (checkMethod in checkRowMethods) {
michael@0 942 expected = checkRowMethods[checkMethod](row, r);
michael@0 943 if (checkMethod == "hasNextSibling") {
michael@0 944 actual = view[checkMethod](r, r);
michael@0 945 }
michael@0 946 else {
michael@0 947 actual = view[checkMethod](r);
michael@0 948 }
michael@0 949 if (actual !== expected) {
michael@0 950 failedMethods[checkMethod] = true;
michael@0 951 is(actual, expected, testid + "row " + r + " " + checkMethod + " is incorrect");
michael@0 952 }
michael@0 953 }
michael@0 954 /*
michael@0 955 // open and recurse into containers
michael@0 956 if (row.container) {
michael@0 957 view.toggleOpenState(r);
michael@0 958 if (!view.isContainerOpen(r)) {
michael@0 959 toggleOpenStateOK = false;
michael@0 960 is(view.isContainerOpen(r), true, testid + "row " + r + " toggleOpenState open");
michael@0 961 }
michael@0 962 testtag_tree_TreeView_rows(tree, testid + "container " + r + " ", row.children, r + 1);
michael@0 963 view.toggleOpenState(r);
michael@0 964 if (view.isContainerOpen(r)) {
michael@0 965 toggleOpenStateOK = false;
michael@0 966 is(view.isContainerOpen(r), false, testid + "row " + r + " toggleOpenState close");
michael@0 967 }
michael@0 968 }
michael@0 969 */
michael@0 970 }
michael@0 971
michael@0 972 for (var failedMethod in failedMethods) {
michael@0 973 if (failedMethod in checkRowMethods)
michael@0 974 delete checkRowMethods[failedMethod];
michael@0 975 if (failedMethod in checkCellMethods)
michael@0 976 delete checkCellMethods[failedMethod];
michael@0 977 }
michael@0 978
michael@0 979 for (checkMethod in checkRowMethods)
michael@0 980 is(checkMethod + " ok", checkMethod + " ok", testid + checkMethod);
michael@0 981 for (checkMethod in checkCellMethods)
michael@0 982 is(checkMethod + " ok", checkMethod + " ok", testid + checkMethod);
michael@0 983 if (toggleOpenStateOK)
michael@0 984 is("toggleOpenState ok", "toggleOpenState ok", testid + "toggleOpenState");
michael@0 985 }
michael@0 986
michael@0 987 function testtag_tree_TreeView_rows_sort(tree, testid, rowInfo)
michael@0 988 {
michael@0 989 // check if cycleHeader sorts the columns
michael@0 990 var columnIndex = 0;
michael@0 991 var view = tree.view;
michael@0 992 var column = tree.columns[columnIndex];
michael@0 993 var columnElement = column.element;
michael@0 994 var sortkey = columnElement.getAttribute("sort");
michael@0 995 if (sortkey) {
michael@0 996 view.cycleHeader(column);
michael@0 997 is(tree.getAttribute("sort"), sortkey, "cycleHeader sort");
michael@0 998 is(tree.getAttribute("sortDirection"), "ascending", "cycleHeader sortDirection ascending");
michael@0 999 is(columnElement.getAttribute("sortDirection"), "ascending", "cycleHeader column sortDirection");
michael@0 1000 is(columnElement.getAttribute("sortActive"), "true", "cycleHeader column sortActive");
michael@0 1001 view.cycleHeader(column);
michael@0 1002 is(tree.getAttribute("sortDirection"), "descending", "cycleHeader sortDirection descending");
michael@0 1003 is(columnElement.getAttribute("sortDirection"), "descending", "cycleHeader column sortDirection descending");
michael@0 1004 view.cycleHeader(column);
michael@0 1005 is(tree.getAttribute("sortDirection"), "", "cycleHeader sortDirection natural");
michael@0 1006 is(columnElement.getAttribute("sortDirection"), "", "cycleHeader column sortDirection natural");
michael@0 1007 // XXXndeakin content view isSorted needs to be tested
michael@0 1008 }
michael@0 1009
michael@0 1010 // Check that clicking on column header sorts the column.
michael@0 1011 var columns = getSortedColumnArray(tree);
michael@0 1012 is(columnElement.getAttribute("sortDirection"), "",
michael@0 1013 "cycleHeader column sortDirection");
michael@0 1014
michael@0 1015 // Click once on column header and check sorting has cycled once.
michael@0 1016 mouseClickOnColumnHeader(columns, columnIndex, 0, 1);
michael@0 1017 is(columnElement.getAttribute("sortDirection"), "ascending",
michael@0 1018 "single click cycleHeader column sortDirection ascending");
michael@0 1019
michael@0 1020 // Now simulate a double click.
michael@0 1021 mouseClickOnColumnHeader(columns, columnIndex, 0, 2);
michael@0 1022 if (navigator.platform.indexOf("Win") == 0) {
michael@0 1023 // Windows cycles only once on double click.
michael@0 1024 is(columnElement.getAttribute("sortDirection"), "descending",
michael@0 1025 "double click cycleHeader column sortDirection descending");
michael@0 1026 // 1 single clicks should restore natural sorting.
michael@0 1027 mouseClickOnColumnHeader(columns, columnIndex, 0, 1);
michael@0 1028 }
michael@0 1029
michael@0 1030 // Check we have gone back to natural sorting.
michael@0 1031 is(columnElement.getAttribute("sortDirection"), "",
michael@0 1032 "cycleHeader column sortDirection");
michael@0 1033
michael@0 1034 columnElement.setAttribute("sorthints", "twostate");
michael@0 1035 view.cycleHeader(column);
michael@0 1036 is(tree.getAttribute("sortDirection"), "ascending", "cycleHeader sortDirection ascending twostate");
michael@0 1037 view.cycleHeader(column);
michael@0 1038 is(tree.getAttribute("sortDirection"), "descending", "cycleHeader sortDirection ascending twostate");
michael@0 1039 view.cycleHeader(column);
michael@0 1040 is(tree.getAttribute("sortDirection"), "ascending", "cycleHeader sortDirection ascending twostate again");
michael@0 1041 columnElement.removeAttribute("sorthints");
michael@0 1042 view.cycleHeader(column);
michael@0 1043 view.cycleHeader(column);
michael@0 1044
michael@0 1045 is(columnElement.getAttribute("sortDirection"), "",
michael@0 1046 "cycleHeader column sortDirection reset");
michael@0 1047 }
michael@0 1048
michael@0 1049 // checks if the current and selected rows are correct
michael@0 1050 // current is the index of the current row
michael@0 1051 // selected is an array of the indicies of the selected rows
michael@0 1052 // column is the selected column
michael@0 1053 // viewidx is the row that should be visible at the top of the tree
michael@0 1054 function testtag_tree_TreeSelection_State(tree, testid, current, selected, viewidx, column)
michael@0 1055 {
michael@0 1056 var selection = tree.view.selection;
michael@0 1057
michael@0 1058 if (!column)
michael@0 1059 column = (tree.selType == "cell") ? tree.columns[0] : null;
michael@0 1060
michael@0 1061 is(selection.count, selected.length, testid + " count");
michael@0 1062 is(tree.currentIndex, current, testid + " currentIndex");
michael@0 1063 is(selection.currentIndex, current, testid + " TreeSelection currentIndex");
michael@0 1064 is(selection.currentColumn, column, testid + " currentColumn");
michael@0 1065 if (viewidx !== null && viewidx !== undefined)
michael@0 1066 is(tree.treeBoxObject.getFirstVisibleRow(), viewidx, testid + " first visible row");
michael@0 1067
michael@0 1068 var actualSelected = [];
michael@0 1069 var count = tree.view.rowCount;
michael@0 1070 for (var s = 0; s < count; s++) {
michael@0 1071 if (selection.isSelected(s))
michael@0 1072 actualSelected.push(s);
michael@0 1073 }
michael@0 1074
michael@0 1075 is(compareArrays(selected, actualSelected), true, testid + " selection [" + selected + "]");
michael@0 1076
michael@0 1077 actualSelected = [];
michael@0 1078 var rangecount = selection.getRangeCount();
michael@0 1079 for (var r = 0; r < rangecount; r++) {
michael@0 1080 var start = {}, end = {};
michael@0 1081 selection.getRangeAt(r, start, end);
michael@0 1082 for (var rs = start.value; rs <= end.value; rs++)
michael@0 1083 actualSelected.push(rs);
michael@0 1084 }
michael@0 1085
michael@0 1086 is(compareArrays(selected, actualSelected), true, testid + " range selection [" + selected + "]");
michael@0 1087 }
michael@0 1088
michael@0 1089 function testtag_tree_column_reorder()
michael@0 1090 {
michael@0 1091 // Make sure the tree is scrolled into the view, otherwise the test will
michael@0 1092 // fail
michael@0 1093 var testframe = window.parent.document.getElementById("testframe");
michael@0 1094 if (testframe) {
michael@0 1095 testframe.scrollIntoView();
michael@0 1096 }
michael@0 1097
michael@0 1098 var tree = document.getElementById("tree-column-reorder");
michael@0 1099 var numColumns = tree.columns.count;
michael@0 1100
michael@0 1101 var reference = [];
michael@0 1102 for (var i = 0; i < numColumns; i++) {
michael@0 1103 reference.push("col_" + i);
michael@0 1104 }
michael@0 1105
michael@0 1106 // Drag the first column to each position
michael@0 1107 for (var i = 0; i < numColumns - 1; i++) {
michael@0 1108 synthesizeColumnDrag(tree, i, i + 1, true);
michael@0 1109 arrayMove(reference, i, i + 1, true);
michael@0 1110 checkColumns(tree, reference, "drag first column right");
michael@0 1111 }
michael@0 1112
michael@0 1113 // And back
michael@0 1114 for (var i = numColumns - 1; i >= 1; i--) {
michael@0 1115 synthesizeColumnDrag(tree, i, i - 1, false);
michael@0 1116 arrayMove(reference, i, i - 1, false);
michael@0 1117 checkColumns(tree, reference, "drag last column left");
michael@0 1118 }
michael@0 1119
michael@0 1120 // Drag each column one column left
michael@0 1121 for (var i = 1; i < numColumns; i++) {
michael@0 1122 synthesizeColumnDrag(tree, i, i - 1, false);
michael@0 1123 arrayMove(reference, i, i - 1, false);
michael@0 1124 checkColumns(tree, reference, "drag each column left");
michael@0 1125 }
michael@0 1126
michael@0 1127 // And back
michael@0 1128 for (var i = numColumns - 2; i >= 0; i--) {
michael@0 1129 synthesizeColumnDrag(tree, i, i + 1, true);
michael@0 1130 arrayMove(reference, i, i + 1, true);
michael@0 1131 checkColumns(tree, reference, "drag each column right");
michael@0 1132 }
michael@0 1133
michael@0 1134 // Drag each column 5 to the right
michael@0 1135 for (var i = 0; i < numColumns - 5; i++) {
michael@0 1136 synthesizeColumnDrag(tree, i, i + 5, true);
michael@0 1137 arrayMove(reference, i, i + 5, true);
michael@0 1138 checkColumns(tree, reference, "drag each column 5 to the right");
michael@0 1139 }
michael@0 1140
michael@0 1141 // And to the left
michael@0 1142 for (var i = numColumns - 6; i >= 5; i--) {
michael@0 1143 synthesizeColumnDrag(tree, i, i - 5, false);
michael@0 1144 arrayMove(reference, i, i - 5, false);
michael@0 1145 checkColumns(tree, reference, "drag each column 5 to the left");
michael@0 1146 }
michael@0 1147
michael@0 1148 // Test that moving a column after itself does not move anything
michael@0 1149 synthesizeColumnDrag(tree, 0, 0, true);
michael@0 1150 checkColumns(tree, reference, "drag to itself");
michael@0 1151 is(document.treecolDragging, null, "drag to itself completed");
michael@0 1152
michael@0 1153 // XXX roc should this be here???
michael@0 1154 SimpleTest.finish();
michael@0 1155 }
michael@0 1156
michael@0 1157 function testtag_tree_wheel(aTree)
michael@0 1158 {
michael@0 1159 const deltaModes = [
michael@0 1160 WheelEvent.DOM_DELTA_PIXEL, // 0
michael@0 1161 WheelEvent.DOM_DELTA_LINE, // 1
michael@0 1162 WheelEvent.DOM_DELTA_PAGE // 2
michael@0 1163 ];
michael@0 1164 function helper(aStart, aDelta, aIntDelta, aDeltaMode)
michael@0 1165 {
michael@0 1166 aTree.treeBoxObject.scrollToRow(aStart);
michael@0 1167 var expected = !aIntDelta ? aStart :
michael@0 1168 aDeltaMode != WheelEvent.DOM_DELTA_PAGE ? aStart + aIntDelta :
michael@0 1169 aIntDelta > 0 ? aStart + aTree.treeBoxObject.getPageLength() :
michael@0 1170 aStart - aTree.treeBoxObject.getPageLength();
michael@0 1171 if (expected < 0) {
michael@0 1172 expected = 0;
michael@0 1173 }
michael@0 1174 if (expected > aTree.view.rowCount - aTree.treeBoxObject.getPageLength()) {
michael@0 1175 expected = aTree.view.rowCount - aTree.treeBoxObject.getPageLength();
michael@0 1176 }
michael@0 1177 synthesizeWheel(aTree.body, 1, 1,
michael@0 1178 { deltaMode: aDeltaMode, deltaY: aDelta,
michael@0 1179 lineOrPageDeltaY: aIntDelta });
michael@0 1180 is(aTree.treeBoxObject.getFirstVisibleRow(), expected,
michael@0 1181 "testtag_tree_wheel: vertical, starting " + aStart +
michael@0 1182 " delta " + aDelta + " lineOrPageDelta " + aIntDelta +
michael@0 1183 " aDeltaMode " + aDeltaMode);
michael@0 1184
michael@0 1185 aTree.treeBoxObject.scrollToRow(aStart);
michael@0 1186 // Check that horizontal scrolling has no effect
michael@0 1187 synthesizeWheel(aTree.body, 1, 1,
michael@0 1188 { deltaMode: aDeltaMode, deltaX: aDelta,
michael@0 1189 lineOrPageDeltaX: aIntDelta });
michael@0 1190 is(aTree.treeBoxObject.getFirstVisibleRow(), aStart,
michael@0 1191 "testtag_tree_wheel: horizontal, starting " + aStart +
michael@0 1192 " delta " + aDelta + " lineOrPageDelta " + aIntDelta +
michael@0 1193 " aDeltaMode " + aDeltaMode);
michael@0 1194 }
michael@0 1195
michael@0 1196 var defaultPrevented = 0;
michael@0 1197
michael@0 1198 function wheelListener(event) {
michael@0 1199 defaultPrevented++;
michael@0 1200 }
michael@0 1201 window.addEventListener("wheel", wheelListener, false);
michael@0 1202
michael@0 1203 deltaModes.forEach(function(aDeltaMode) {
michael@0 1204 var delta = (aDeltaMode == WheelEvent.DOM_DELTA_PIXEL) ? 5.0 : 0.3;
michael@0 1205 helper(2, -delta, 0, aDeltaMode);
michael@0 1206 helper(2, -delta, -1, aDeltaMode);
michael@0 1207 helper(2, delta, 0, aDeltaMode);
michael@0 1208 helper(2, delta, 1, aDeltaMode);
michael@0 1209 helper(2, -2 * delta, 0, aDeltaMode);
michael@0 1210 helper(2, -2 * delta, -1, aDeltaMode);
michael@0 1211 helper(2, 2 * delta, 0, aDeltaMode);
michael@0 1212 helper(2, 2 * delta, 1, aDeltaMode);
michael@0 1213 });
michael@0 1214
michael@0 1215 window.removeEventListener("wheel", wheelListener, false);
michael@0 1216 is(defaultPrevented, 48, "wheel event default prevented");
michael@0 1217 }
michael@0 1218
michael@0 1219 function synthesizeColumnDrag(aTree, aMouseDownColumnNumber, aMouseUpColumnNumber, aAfter)
michael@0 1220 {
michael@0 1221 var columns = getSortedColumnArray(aTree);
michael@0 1222
michael@0 1223 var down = columns[aMouseDownColumnNumber].element;
michael@0 1224 var up = columns[aMouseUpColumnNumber].element;
michael@0 1225
michael@0 1226 // Target the initial mousedown in the middle of the column header so we
michael@0 1227 // avoid the extra hit test space given to the splitter
michael@0 1228 var columnWidth = down.boxObject.width;
michael@0 1229 var splitterHitWidth = columnWidth / 2;
michael@0 1230 synthesizeMouse(down, splitterHitWidth, 3, { type: "mousedown"});
michael@0 1231
michael@0 1232 var offsetX = 0;
michael@0 1233 if (aAfter) {
michael@0 1234 offsetX = columnWidth;
michael@0 1235 }
michael@0 1236
michael@0 1237 if (aMouseUpColumnNumber > aMouseDownColumnNumber) {
michael@0 1238 for (var i = aMouseDownColumnNumber; i <= aMouseUpColumnNumber; i++) {
michael@0 1239 var move = columns[i].element;
michael@0 1240 synthesizeMouse(move, offsetX, 3, { type: "mousemove"});
michael@0 1241 }
michael@0 1242 }
michael@0 1243 else {
michael@0 1244 for (var i = aMouseDownColumnNumber; i >= aMouseUpColumnNumber; i--) {
michael@0 1245 var move = columns[i].element;
michael@0 1246 synthesizeMouse(move, offsetX, 3, { type: "mousemove"});
michael@0 1247 }
michael@0 1248 }
michael@0 1249
michael@0 1250 synthesizeMouse(up, offsetX, 3, { type: "mouseup"});
michael@0 1251 }
michael@0 1252
michael@0 1253 function arrayMove(aArray, aFrom, aTo, aAfter)
michael@0 1254 {
michael@0 1255 var o = aArray.splice(aFrom, 1)[0];
michael@0 1256 if (aTo > aFrom) {
michael@0 1257 aTo--;
michael@0 1258 }
michael@0 1259
michael@0 1260 if (aAfter) {
michael@0 1261 aTo++;
michael@0 1262 }
michael@0 1263
michael@0 1264 aArray.splice(aTo, 0, o);
michael@0 1265 }
michael@0 1266
michael@0 1267 function getSortedColumnArray(aTree)
michael@0 1268 {
michael@0 1269 var columns = aTree.columns;
michael@0 1270 var a = [];
michael@0 1271 for (var i = 0; i < columns.length; i++) {
michael@0 1272 a.push(columns.getColumnAt(i));
michael@0 1273 }
michael@0 1274
michael@0 1275 a.sort(function(a, b) {
michael@0 1276 var o1 = parseInt(a.element.getAttribute("ordinal"));
michael@0 1277 var o2 = parseInt(b.element.getAttribute("ordinal"));
michael@0 1278 return o1 - o2;
michael@0 1279 });
michael@0 1280 return a;
michael@0 1281 }
michael@0 1282
michael@0 1283 function checkColumns(aTree, aReference, aMessage)
michael@0 1284 {
michael@0 1285 var columns = getSortedColumnArray(aTree);
michael@0 1286 var ids = [];
michael@0 1287 columns.forEach(function(e) {
michael@0 1288 ids.push(e.element.id);
michael@0 1289 });
michael@0 1290 is(compareArrays(ids, aReference), true, aMessage);
michael@0 1291 }
michael@0 1292
michael@0 1293 function mouseOnCell(tree, row, column, testname)
michael@0 1294 {
michael@0 1295 var x = {}, y = {}, width = {}, height = {};
michael@0 1296 tree.boxObject.getCoordsForCellItem(row, column, "text", x, y, width, height);
michael@0 1297
michael@0 1298 synthesizeMouseExpectEvent(tree.body, x.value, y.value, {}, tree, "select", testname);
michael@0 1299 }
michael@0 1300
michael@0 1301 function mouseClickOnColumnHeader(aColumns, aColumnIndex, aButton, aClickCount)
michael@0 1302 {
michael@0 1303 var columnHeader = aColumns[aColumnIndex].element;
michael@0 1304 var columnHeaderRect = columnHeader.getBoundingClientRect();
michael@0 1305 var columnWidth = columnHeaderRect.right - columnHeaderRect.left;
michael@0 1306 // For multiple click we send separate click events, with increasing
michael@0 1307 // clickCount. This simulates the common behavior of multiple clicks.
michael@0 1308 for (var i = 1; i <= aClickCount; i++) {
michael@0 1309 // Target the middle of the column header.
michael@0 1310 synthesizeMouse(columnHeader, columnWidth / 2, 3,
michael@0 1311 { button: aButton,
michael@0 1312 clickCount: i }, null);
michael@0 1313 }
michael@0 1314 }
michael@0 1315
michael@0 1316 function mouseDblClickOnCell(tree, row, column, testname)
michael@0 1317 {
michael@0 1318 // select the row we will edit
michael@0 1319 var selection = tree.view.selection;
michael@0 1320 selection.select(row);
michael@0 1321 tree.treeBoxObject.ensureRowIsVisible(row);
michael@0 1322
michael@0 1323 // get cell coordinates
michael@0 1324 var x = {}, y = {}, width = {}, height = {};
michael@0 1325 tree.treeBoxObject.getCoordsForCellItem(row, column, "text", x, y, width, height);
michael@0 1326
michael@0 1327 synthesizeMouse(tree.body, x.value, y.value, { clickCount: 2 }, null);
michael@0 1328 }
michael@0 1329
michael@0 1330 function compareArrays(arr1, arr2)
michael@0 1331 {
michael@0 1332 if (arr1.length != arr2.length)
michael@0 1333 return false;
michael@0 1334
michael@0 1335 for (var i = 0; i < arr1.length; i++) {
michael@0 1336 if (arr1[i] != arr2[i])
michael@0 1337 return false;
michael@0 1338 }
michael@0 1339
michael@0 1340 return true;
michael@0 1341 }
michael@0 1342
michael@0 1343 function convertProperties(arr)
michael@0 1344 {
michael@0 1345 var results = [];
michael@0 1346 var count = arr.Count();
michael@0 1347 for (var i = 0; i < count; i++)
michael@0 1348 results.push(arr.GetElementAt(i).QueryInterface(Components.interfaces.nsIAtom).toString());
michael@0 1349
michael@0 1350 results.sort();
michael@0 1351 return results.join(" ");
michael@0 1352 }
michael@0 1353
michael@0 1354 function convertDOMtoTreeRowInfo(treechildren, level, rowidx)
michael@0 1355 {
michael@0 1356 var obj = { rows: [] };
michael@0 1357
michael@0 1358 var parentidx = rowidx.value;
michael@0 1359
michael@0 1360 treechildren = treechildren.childNodes;
michael@0 1361 for (var r = 0; r < treechildren.length; r++) {
michael@0 1362 rowidx.value++;
michael@0 1363
michael@0 1364 var treeitem = treechildren[r];
michael@0 1365 if (treeitem.hasChildNodes()) {
michael@0 1366 var treerow = treeitem.firstChild;
michael@0 1367 var cellInfo = [];
michael@0 1368 for (var c = 0; c < treerow.childNodes.length; c++) {
michael@0 1369 var cell = treerow.childNodes[c];
michael@0 1370 cellInfo.push({ label: "" + cell.getAttribute("label"),
michael@0 1371 value: cell.getAttribute("value"),
michael@0 1372 properties: cell.getAttribute("properties"),
michael@0 1373 editable: cell.getAttribute("editable") != "false",
michael@0 1374 selectable: cell.getAttribute("selectable") != "false",
michael@0 1375 image: cell.getAttribute("src"),
michael@0 1376 mode: cell.hasAttribute("mode") ? parseInt(cell.getAttribute("mode")) : 3 });
michael@0 1377 }
michael@0 1378
michael@0 1379 var descendants = treeitem.lastChild;
michael@0 1380 var children = (treerow == descendants) ? null :
michael@0 1381 convertDOMtoTreeRowInfo(descendants, level + 1, rowidx);
michael@0 1382 obj.rows.push({ cells: cellInfo,
michael@0 1383 properties: treerow.getAttribute("properties"),
michael@0 1384 container: treeitem.getAttribute("container") == "true",
michael@0 1385 separator: treeitem.localName == "treeseparator",
michael@0 1386 children: children,
michael@0 1387 level: level,
michael@0 1388 parent: parentidx });
michael@0 1389 }
michael@0 1390 }
michael@0 1391
michael@0 1392 return obj;
michael@0 1393 }

mercurial