michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: /** michael@0: * Make sure that the variables view is keyboard accessible. michael@0: */ michael@0: michael@0: let gTab, gDebuggee, gPanel, gDebugger; michael@0: let gVariablesView; michael@0: michael@0: function test() { michael@0: initDebugger("about:blank").then(([aTab, aDebuggee, aPanel]) => { michael@0: gTab = aTab; michael@0: gDebuggee = aDebuggee; michael@0: gPanel = aPanel; michael@0: gDebugger = gPanel.panelWin; michael@0: gVariablesView = gDebugger.DebuggerView.Variables; michael@0: michael@0: performTest().then(null, aError => { michael@0: ok(false, "Got an error: " + aError.message + "\n" + aError.stack); michael@0: }); michael@0: }); michael@0: } michael@0: michael@0: function performTest() { michael@0: let arr = [ michael@0: 42, michael@0: true, michael@0: "nasu", michael@0: undefined, michael@0: null, michael@0: [0, 1, 2], michael@0: { prop1: 9, prop2: 8 } michael@0: ]; michael@0: michael@0: let obj = { michael@0: p0: 42, michael@0: p1: true, michael@0: p2: "nasu", michael@0: p3: undefined, michael@0: p4: null, michael@0: p5: [3, 4, 5], michael@0: p6: { prop1: 7, prop2: 6 }, michael@0: get p7() { return arr; }, michael@0: set p8(value) { arr[0] = value } michael@0: }; michael@0: michael@0: let test = { michael@0: someProp0: 42, michael@0: someProp1: true, michael@0: someProp2: "nasu", michael@0: someProp3: undefined, michael@0: someProp4: null, michael@0: someProp5: arr, michael@0: someProp6: obj, michael@0: get someProp7() { return arr; }, michael@0: set someProp7(value) { arr[0] = value } michael@0: }; michael@0: michael@0: gVariablesView.eval = function() {}; michael@0: gVariablesView.switch = function() {}; michael@0: gVariablesView.delete = function() {}; michael@0: gVariablesView.rawObject = test; michael@0: gVariablesView.scrollPageSize = 5; michael@0: michael@0: return Task.spawn(function() { michael@0: yield waitForTick(); michael@0: michael@0: // Part 0: Test generic focus methods on the variables view. michael@0: michael@0: gVariablesView.focusFirstVisibleItem(); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: gVariablesView.focusNextItem(); michael@0: is(gVariablesView.getFocusedItem().name, "someProp1", michael@0: "The 'someProp1' item should be focused."); michael@0: michael@0: gVariablesView.focusPrevItem(); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: // Part 1: Make sure that UP/DOWN keys don't scroll the variables view. michael@0: michael@0: yield synthesizeKeyAndWaitForTick("VK_DOWN", {}); michael@0: is(gVariablesView._parent.scrollTop, 0, michael@0: "The 'variables' view shouldn't scroll when pressing the DOWN key."); michael@0: michael@0: yield synthesizeKeyAndWaitForTick("VK_UP", {}); michael@0: is(gVariablesView._parent.scrollTop, 0, michael@0: "The 'variables' view shouldn't scroll when pressing the UP key."); michael@0: michael@0: // Part 2: Make sure that RETURN/ESCAPE toggle input elements. michael@0: michael@0: yield synthesizeKeyAndWaitForElement("VK_RETURN", {}, ".element-value-input", true); michael@0: yield synthesizeKeyAndWaitForElement("VK_ESCAPE", {}, ".element-value-input", false); michael@0: yield synthesizeKeyAndWaitForElement("VK_RETURN", { shiftKey: true }, ".element-name-input", true); michael@0: yield synthesizeKeyAndWaitForElement("VK_ESCAPE", {}, ".element-name-input", false); michael@0: michael@0: // Part 3: Test simple navigation. michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp1", michael@0: "The 'someProp1' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("END", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("HOME", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: // Part 4: Test if pressing the same navigation key twice works as expected. michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp1", michael@0: "The 'someProp1' item should be focused."); michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp2", michael@0: "The 'someProp2' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp1", michael@0: "The 'someProp1' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: // Part 5: Test that HOME/PAGE_UP/PAGE_DOWN are symmetrical. michael@0: michael@0: EventUtils.sendKey("HOME", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("HOME", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("HOME", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("END", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("END", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("END", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: // Part 6: Test that focus doesn't leave the variables view. michael@0: michael@0: EventUtils.sendKey("PAGE_UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: // Part 7: Test that random offsets don't occur in tandem with HOME/END. michael@0: michael@0: EventUtils.sendKey("HOME", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp1", michael@0: "The 'someProp1' item should be focused."); michael@0: michael@0: EventUtils.sendKey("END", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: // Part 8: Test that the RIGHT key expands elements as intended. michael@0: michael@0: EventUtils.sendKey("PAGE_UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, false, michael@0: "The 'someProp5' item should not be expanded yet."); michael@0: michael@0: yield synthesizeKeyAndWaitForTick("VK_RIGHT", {}); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, true, michael@0: "The 'someProp5' item should now be expanded."); michael@0: is(gVariablesView.getFocusedItem()._store.size, 9, michael@0: "There should be 9 properties in the selected variable."); michael@0: is(gVariablesView.getFocusedItem()._enumItems.length, 7, michael@0: "There should be 7 enumerable properties in the selected variable."); michael@0: is(gVariablesView.getFocusedItem()._nonEnumItems.length, 2, michael@0: "There should be 2 non-enumerable properties in the selected variable."); michael@0: michael@0: yield waitForChildNodes(gVariablesView.getFocusedItem()._enum, 7); michael@0: yield waitForChildNodes(gVariablesView.getFocusedItem()._nonenum, 2); michael@0: michael@0: EventUtils.sendKey("RIGHT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "0", michael@0: "The '0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("RIGHT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "0", michael@0: "The '0' item should still be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "5", michael@0: "The '5' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, false, michael@0: "The '5' item should not be expanded yet."); michael@0: michael@0: yield synthesizeKeyAndWaitForTick("VK_RIGHT", {}); michael@0: is(gVariablesView.getFocusedItem().name, "5", michael@0: "The '5' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, true, michael@0: "The '5' item should now be expanded."); michael@0: is(gVariablesView.getFocusedItem()._store.size, 5, michael@0: "There should be 5 properties in the selected variable."); michael@0: is(gVariablesView.getFocusedItem()._enumItems.length, 3, michael@0: "There should be 3 enumerable properties in the selected variable."); michael@0: is(gVariablesView.getFocusedItem()._nonEnumItems.length, 2, michael@0: "There should be 2 non-enumerable properties in the selected variable."); michael@0: michael@0: yield waitForChildNodes(gVariablesView.getFocusedItem()._enum, 3); michael@0: yield waitForChildNodes(gVariablesView.getFocusedItem()._nonenum, 2); michael@0: michael@0: EventUtils.sendKey("RIGHT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "0", michael@0: "The '0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("RIGHT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "0", michael@0: "The '0' item should still be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "6", michael@0: "The '6' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, false, michael@0: "The '6' item should not be expanded yet."); michael@0: michael@0: yield synthesizeKeyAndWaitForTick("VK_RIGHT", {}); michael@0: is(gVariablesView.getFocusedItem().name, "6", michael@0: "The '6' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, true, michael@0: "The '6' item should now be expanded."); michael@0: is(gVariablesView.getFocusedItem()._store.size, 3, michael@0: "There should be 3 properties in the selected variable."); michael@0: is(gVariablesView.getFocusedItem()._enumItems.length, 2, michael@0: "There should be 2 enumerable properties in the selected variable."); michael@0: is(gVariablesView.getFocusedItem()._nonEnumItems.length, 1, michael@0: "There should be 1 non-enumerable properties in the selected variable."); michael@0: michael@0: yield waitForChildNodes(gVariablesView.getFocusedItem()._enum, 2); michael@0: yield waitForChildNodes(gVariablesView.getFocusedItem()._nonenum, 1); michael@0: michael@0: EventUtils.sendKey("RIGHT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "prop1", michael@0: "The 'prop1' item should be focused."); michael@0: michael@0: EventUtils.sendKey("RIGHT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "prop1", michael@0: "The 'prop1' item should still be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp6", michael@0: "The 'someProp6' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, false, michael@0: "The 'someProp6' item should not be expanded yet."); michael@0: michael@0: // Part 9: Test that the RIGHT key collapses elements as intended. michael@0: michael@0: EventUtils.sendKey("LEFT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp6", michael@0: "The 'someProp6' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: EventUtils.sendKey("LEFT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, true, michael@0: "The '6' item should still be expanded."); michael@0: michael@0: EventUtils.sendKey("LEFT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should still be focused."); michael@0: is(gVariablesView.getFocusedItem().expanded, false, michael@0: "The '6' item should still not be expanded anymore."); michael@0: michael@0: EventUtils.sendKey("LEFT", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should still be focused."); michael@0: michael@0: // Part 9: Test continuous navigation. michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp4", michael@0: "The 'someProp4' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp3", michael@0: "The 'someProp3' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp2", michael@0: "The 'someProp2' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp1", michael@0: "The 'someProp1' item should be focused."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp0", michael@0: "The 'someProp0' item should be focused."); michael@0: michael@0: EventUtils.sendKey("PAGE_DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp5", michael@0: "The 'someProp5' item should be focused."); michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp6", michael@0: "The 'someProp6' item should be focused."); michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp7", michael@0: "The 'someProp7' item should be focused."); michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "get", michael@0: "The 'get' item should be focused."); michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "set", michael@0: "The 'set' item should be focused."); michael@0: michael@0: EventUtils.sendKey("DOWN", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' item should be focused."); michael@0: michael@0: // Part 10: Test that BACKSPACE deletes items in the variables view. michael@0: michael@0: EventUtils.sendKey("BACK_SPACE", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "__proto__", michael@0: "The '__proto__' variable should still be focused."); michael@0: is(gVariablesView.getFocusedItem().value, "[object Object]", michael@0: "The '__proto__' variable should not have an empty value."); michael@0: is(gVariablesView.getFocusedItem().visible, false, michael@0: "The '__proto__' variable should be hidden."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "set", michael@0: "The 'set' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().value, "[object Object]", michael@0: "The 'set' item should not have an empty value."); michael@0: is(gVariablesView.getFocusedItem().visible, true, michael@0: "The 'set' item should be visible."); michael@0: michael@0: EventUtils.sendKey("BACK_SPACE", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "set", michael@0: "The 'set' item should still be focused."); michael@0: is(gVariablesView.getFocusedItem().value, "[object Object]", michael@0: "The 'set' item should not have an empty value."); michael@0: is(gVariablesView.getFocusedItem().visible, true, michael@0: "The 'set' item should be visible."); michael@0: is(gVariablesView.getFocusedItem().twisty, false, michael@0: "The 'set' item should be disabled and have a hidden twisty."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "get", michael@0: "The 'get' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().value, "[object Object]", michael@0: "The 'get' item should not have an empty value."); michael@0: is(gVariablesView.getFocusedItem().visible, true, michael@0: "The 'get' item should be visible."); michael@0: michael@0: EventUtils.sendKey("BACK_SPACE", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "get", michael@0: "The 'get' item should still be focused."); michael@0: is(gVariablesView.getFocusedItem().value, "[object Object]", michael@0: "The 'get' item should not have an empty value."); michael@0: is(gVariablesView.getFocusedItem().visible, true, michael@0: "The 'get' item should be visible."); michael@0: is(gVariablesView.getFocusedItem().twisty, false, michael@0: "The 'get' item should be disabled and have a hidden twisty."); michael@0: michael@0: EventUtils.sendKey("UP", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp7", michael@0: "The 'someProp7' item should be focused."); michael@0: is(gVariablesView.getFocusedItem().value, undefined, michael@0: "The 'someProp7' variable should have an empty value."); michael@0: is(gVariablesView.getFocusedItem().visible, true, michael@0: "The 'someProp7' variable should be visible."); michael@0: michael@0: EventUtils.sendKey("BACK_SPACE", gDebugger); michael@0: is(gVariablesView.getFocusedItem().name, "someProp7", michael@0: "The 'someProp7' variable should still be focused."); michael@0: is(gVariablesView.getFocusedItem().value, undefined, michael@0: "The 'someProp7' variable should have an empty value."); michael@0: is(gVariablesView.getFocusedItem().visible, false, michael@0: "The 'someProp7' variable should be hidden."); michael@0: michael@0: // Part 11: Test that Ctrl-C copies the current item to the system clipboard michael@0: michael@0: gVariablesView.focusFirstVisibleItem(); michael@0: let copied = promise.defer(); michael@0: let expectedValue = gVariablesView.getFocusedItem().name michael@0: + gVariablesView.getFocusedItem().separatorStr michael@0: + gVariablesView.getFocusedItem().value; michael@0: michael@0: waitForClipboard(expectedValue, function setup() { michael@0: EventUtils.synthesizeKey("C", { metaKey: true }, gDebugger); michael@0: }, copied.resolve, copied.reject michael@0: ); michael@0: michael@0: try { michael@0: yield copied.promise; michael@0: ok(true, michael@0: "Ctrl-C copied the selected item to the clipboard."); michael@0: } catch (e) { michael@0: ok(false, michael@0: "Ctrl-C didn't copy the selected item to the clipboard."); michael@0: } michael@0: michael@0: yield closeDebuggerAndFinish(gPanel); michael@0: }); michael@0: } michael@0: michael@0: registerCleanupFunction(function() { michael@0: gTab = null; michael@0: gDebuggee = null; michael@0: gPanel = null; michael@0: gDebugger = null; michael@0: gVariablesView = null; michael@0: }); michael@0: michael@0: function synthesizeKeyAndWaitForElement(aKey, aModifiers, aSelector, aExistence) { michael@0: EventUtils.synthesizeKey(aKey, aModifiers, gDebugger); michael@0: return waitForElement(aSelector, aExistence); michael@0: } michael@0: michael@0: function synthesizeKeyAndWaitForTick(aKey, aModifiers) { michael@0: EventUtils.synthesizeKey(aKey, aModifiers, gDebugger); michael@0: return waitForTick(); michael@0: } michael@0: michael@0: function waitForElement(aSelector, aExistence) { michael@0: return waitForPredicate(() => { michael@0: return !!gVariablesView._list.querySelector(aSelector) == aExistence; michael@0: }); michael@0: } michael@0: michael@0: function waitForChildNodes(aTarget, aCount) { michael@0: return waitForPredicate(() => { michael@0: return aTarget.childNodes.length == aCount; michael@0: }); michael@0: } michael@0: michael@0: function waitForPredicate(aPredicate, aInterval = 10) { michael@0: let deferred = promise.defer(); michael@0: michael@0: // Poll every few milliseconds until the element is retrieved. michael@0: let count = 0; michael@0: let intervalID = window.setInterval(() => { michael@0: // Make sure we don't wait for too long. michael@0: if (++count > 1000) { michael@0: deferred.reject("Timed out while polling for the element."); michael@0: window.clearInterval(intervalID); michael@0: return; michael@0: } michael@0: // Check if the predicate condition is fulfilled. michael@0: if (!aPredicate()) { michael@0: return; michael@0: } michael@0: // We got the element, it's safe to callback. michael@0: window.clearInterval(intervalID); michael@0: deferred.resolve(); michael@0: }, aInterval); michael@0: michael@0: return deferred.promise; michael@0: }