/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Test if the context menu associated with each breakpoint does what it should. */ const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html"; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); let gTab, gDebuggee, gPanel, gDebugger; let gSources, gBreakpoints; initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { gTab = aTab; gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gSources = gDebugger.DebuggerView.Sources; gBreakpoints = gDebugger.DebuggerController.Breakpoints; waitForSourceShown(gPanel, "-01.js") .then(performTestWhileNotPaused) .then(performTestWhilePaused) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); }); function addBreakpoints() { return promise.resolve(null) .then(() => gPanel.addBreakpoint({ url: gSources.values[0], line: 5 })) .then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 6 })) .then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 7 })) .then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 8 })) .then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 9 })) .then(() => ensureThreadClientState(gPanel, "resumed")); } function performTestWhileNotPaused() { info("Performing test while not paused..."); return addBreakpoints() .then(initialChecks) .then(() => checkBreakpointToggleSelf(0)) .then(() => checkBreakpointToggleOthers(0)) .then(() => checkBreakpointToggleSelf(1)) .then(() => checkBreakpointToggleOthers(1)) .then(() => checkBreakpointToggleSelf(2)) .then(() => checkBreakpointToggleOthers(2)) .then(() => checkBreakpointToggleSelf(3)) .then(() => checkBreakpointToggleOthers(3)) .then(() => checkBreakpointToggleSelf(4)) .then(() => checkBreakpointToggleOthers(4)) .then(testDeleteAll); } function performTestWhilePaused() { info("Performing test while paused..."); return addBreakpoints() .then(initialChecks) .then(pauseAndCheck) .then(() => checkBreakpointToggleSelf(0)) .then(() => checkBreakpointToggleOthers(0)) .then(() => checkBreakpointToggleSelf(1)) .then(() => checkBreakpointToggleOthers(1)) .then(() => checkBreakpointToggleSelf(2)) .then(() => checkBreakpointToggleOthers(2)) .then(() => checkBreakpointToggleSelf(3)) .then(() => checkBreakpointToggleOthers(3)) .then(() => checkBreakpointToggleSelf(4)) .then(() => checkBreakpointToggleOthers(4)) .then(testDeleteAll); } function pauseAndCheck() { let finished = waitForSourceAndCaretAndScopes(gPanel, "-01.js", 5).then(() => { is(gSources.selectedValue, EXAMPLE_URL + "code_script-switching-01.js", "The currently selected source is incorrect (3)."); is(gSources.selectedIndex, 0, "The currently selected source is incorrect (4)."); ok(isCaretPos(gPanel, 5), "The editor location is correct after pausing."); }); is(gSources.selectedValue, EXAMPLE_URL + "code_script-switching-02.js", "The currently selected source is incorrect (1)."); is(gSources.selectedIndex, 1, "The currently selected source is incorrect (2)."); ok(isCaretPos(gPanel, 9), "The editor location is correct before pausing."); // Spin the event loop before causing the debuggee to pause, to allow // this function to return first. executeSoon(() => { EventUtils.sendMouseEvent({ type: "click" }, gDebuggee.document.querySelector("button"), gDebuggee); }); return finished; } function initialChecks() { for (let source of gSources) { for (let breakpoint of source) { ok(gBreakpoints._getAdded(breakpoint.attachment), "All breakpoint items should have corresponding promises (1)."); ok(!gBreakpoints._getRemoving(breakpoint.attachment), "All breakpoint items should have corresponding promises (2)."); ok(breakpoint.attachment.actor, "All breakpoint items should have corresponding promises (3)."); is(!!breakpoint.attachment.disabled, false, "All breakpoints should initially be enabled."); let prefix = "bp-cMenu-"; // "breakpoints context menu" let identifier = gBreakpoints.getIdentifier(breakpoint.attachment); let enableSelfId = prefix + "enableSelf-" + identifier + "-menuitem"; let disableSelfId = prefix + "disableSelf-" + identifier + "-menuitem"; is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true", "The 'Enable breakpoint' context menu item should initially be hidden'."); ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"), "The 'Disable breakpoint' context menu item should initially not be hidden'."); is(breakpoint.attachment.view.checkbox.getAttribute("checked"), "true", "All breakpoints should initially have a checked checkbox."); } } } function checkBreakpointToggleSelf(aIndex) { let deferred = promise.defer(); EventUtils.sendMouseEvent({ type: "click" }, gDebugger.document.querySelectorAll(".dbg-breakpoint")[aIndex], gDebugger); let selectedBreakpoint = gSources._selectedBreakpointItem; ok(gBreakpoints._getAdded(selectedBreakpoint.attachment), "There should be a breakpoint client available (1)."); ok(!gBreakpoints._getRemoving(selectedBreakpoint.attachment), "There should be a breakpoint client available (2)."); ok(selectedBreakpoint.attachment.actor, "There should be a breakpoint client available (3)."); is(!!selectedBreakpoint.attachment.disabled, false, "The breakpoint should not be disabled yet (" + aIndex + ")."); gBreakpoints._getAdded(selectedBreakpoint.attachment).then(aBreakpointClient => { ok(aBreakpointClient, "There should be a breakpoint client available as a promise."); }); let prefix = "bp-cMenu-"; // "breakpoints context menu" let identifier = gBreakpoints.getIdentifier(selectedBreakpoint.attachment); let enableSelfId = prefix + "enableSelf-" + identifier + "-menuitem"; let disableSelfId = prefix + "disableSelf-" + identifier + "-menuitem"; is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true", "The 'Enable breakpoint' context menu item should be hidden'."); ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"), "The 'Disable breakpoint' context menu item should not be hidden'."); ok(isCaretPos(gPanel, selectedBreakpoint.attachment.line), "The source editor caret position was incorrect (" + aIndex + ")."); waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED).then(() => { ok(!gBreakpoints._getAdded(selectedBreakpoint.attachment), "There should be no breakpoint client available (4)."); waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED).then(() => { ok(gBreakpoints._getAdded(selectedBreakpoint.attachment), "There should be a breakpoint client available (5)."); deferred.resolve(); }); // Test re-disabling this breakpoint. gSources._onEnableSelf(selectedBreakpoint.attachment); is(selectedBreakpoint.attachment.disabled, false, "The current breakpoint should now be enabled.") is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true", "The 'Enable breakpoint' context menu item should be hidden'."); ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"), "The 'Disable breakpoint' context menu item should not be hidden'."); ok(selectedBreakpoint.attachment.view.checkbox.hasAttribute("checked"), "The breakpoint should now be checked."); }); // Test disabling this breakpoint. gSources._onDisableSelf(selectedBreakpoint.attachment); is(selectedBreakpoint.attachment.disabled, true, "The current breakpoint should now be disabled.") ok(!gDebugger.document.getElementById(enableSelfId).hasAttribute("hidden"), "The 'Enable breakpoint' context menu item should not be hidden'."); is(gDebugger.document.getElementById(disableSelfId).getAttribute("hidden"), "true", "The 'Disable breakpoint' context menu item should be hidden'."); ok(!selectedBreakpoint.attachment.view.checkbox.hasAttribute("checked"), "The breakpoint should now be unchecked."); return deferred.promise; } function checkBreakpointToggleOthers(aIndex) { let deferred = promise.defer(); waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED, 4).then(() => { let selectedBreakpoint = gSources._selectedBreakpointItem; ok(gBreakpoints._getAdded(selectedBreakpoint.attachment), "There should be a breakpoint client available (6)."); ok(!gBreakpoints._getRemoving(selectedBreakpoint.attachment), "There should be a breakpoint client available (7)."); ok(selectedBreakpoint.attachment.actor, "There should be a breakpoint client available (8)."); is(!!selectedBreakpoint.attachment.disabled, false, "The targetted breakpoint should not have been disabled (" + aIndex + ")."); for (let source of gSources) { for (let otherBreakpoint of source) { if (otherBreakpoint != selectedBreakpoint) { ok(!gBreakpoints._getAdded(otherBreakpoint.attachment), "There should be no breakpoint client for a disabled breakpoint (9)."); is(otherBreakpoint.attachment.disabled, true, "Non-targetted breakpoints should have been disabled (10)."); } } } waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED, 4).then(() => { for (let source of gSources) { for (let someBreakpoint of source) { ok(gBreakpoints._getAdded(someBreakpoint.attachment), "There should be a breakpoint client for all enabled breakpoints (11)."); is(someBreakpoint.attachment.disabled, false, "All breakpoints should now have been enabled (12)."); } } waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED, 5).then(() => { for (let source of gSources) { for (let someBreakpoint of source) { ok(!gBreakpoints._getAdded(someBreakpoint.attachment), "There should be no breakpoint client for a disabled breakpoint (13)."); is(someBreakpoint.attachment.disabled, true, "All breakpoints should now have been disabled (14)."); } } waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED, 5).then(() => { for (let source of gSources) { for (let someBreakpoint of source) { ok(gBreakpoints._getAdded(someBreakpoint.attachment), "There should be a breakpoint client for all enabled breakpoints (15)."); is(someBreakpoint.attachment.disabled, false, "All breakpoints should now have been enabled (16)."); } } // Done. deferred.resolve(); }); // Test re-enabling all breakpoints. enableAll(); }); // Test disabling all breakpoints. disableAll(); }); // Test re-enabling other breakpoints. enableOthers(); }); // Test disabling other breakpoints. disableOthers(); return deferred.promise; } function testDeleteAll() { let deferred = promise.defer(); waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED, 5).then(() => { ok(!gSources._selectedBreakpointItem, "There should be no breakpoint available after removing all breakpoints."); for (let source of gSources) { for (let otherBreakpoint of source) { ok(false, "It's a trap!"); } } // Done. deferred.resolve() }); // Test deleting all breakpoints. deleteAll(); return deferred.promise; } function disableOthers() { gSources._onDisableOthers(gSources._selectedBreakpointItem.attachment); } function enableOthers() { gSources._onEnableOthers(gSources._selectedBreakpointItem.attachment); } function disableAll() { gSources._onDisableAll(); } function enableAll() { gSources._onEnableAll(); } function deleteAll() { gSources._onDeleteAll(); } }