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: * Tests that the break-on-dom-events request works. michael@0: */ michael@0: michael@0: const TAB_URL = EXAMPLE_URL + "doc_event-listeners.html"; michael@0: michael@0: let gClient, gThreadClient, gInput, gButton; michael@0: michael@0: function test() { michael@0: if (!DebuggerServer.initialized) { michael@0: DebuggerServer.init(() => true); michael@0: DebuggerServer.addBrowserActors(); michael@0: } michael@0: michael@0: let transport = DebuggerServer.connectPipe(); michael@0: gClient = new DebuggerClient(transport); michael@0: gClient.connect((aType, aTraits) => { michael@0: is(aType, "browser", michael@0: "Root actor should identify itself as a browser."); michael@0: michael@0: addTab(TAB_URL) michael@0: .then(() => attachThreadActorForUrl(gClient, TAB_URL)) michael@0: .then(setupGlobals) michael@0: .then(pauseDebuggee) michael@0: .then(testBreakOnAll) michael@0: .then(testBreakOnDisabled) michael@0: .then(testBreakOnNone) michael@0: .then(testBreakOnClick) michael@0: .then(closeConnection) michael@0: .then(finish) michael@0: .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 setupGlobals(aThreadClient) { michael@0: gThreadClient = aThreadClient; michael@0: gInput = content.document.querySelector("input"); michael@0: gButton = content.document.querySelector("button"); michael@0: } michael@0: michael@0: function pauseDebuggee() { michael@0: let deferred = promise.defer(); michael@0: michael@0: gClient.addOneTimeListener("paused", (aEvent, aPacket) => { michael@0: is(aPacket.type, "paused", michael@0: "We should now be paused."); michael@0: is(aPacket.why.type, "debuggerStatement", michael@0: "The debugger statement was hit."); michael@0: michael@0: deferred.resolve(); michael@0: }); michael@0: michael@0: // Spin the event loop before causing the debuggee to pause, to allow michael@0: // this function to return first. michael@0: executeSoon(triggerButtonClick); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: // Test pause on all events. michael@0: function testBreakOnAll() { michael@0: let deferred = promise.defer(); michael@0: michael@0: // Test calling pauseOnDOMEvents from a paused state. michael@0: gThreadClient.pauseOnDOMEvents("*", (aPacket) => { michael@0: is(aPacket.error, undefined, michael@0: "The pause-on-any-event request completed successfully."); michael@0: michael@0: gClient.addOneTimeListener("paused", (aEvent, aPacket) => { michael@0: is(aPacket.why.type, "pauseOnDOMEvents", michael@0: "A hidden breakpoint was hit."); michael@0: is(aPacket.frame.callee.name, "keyupHandler", michael@0: "The keyupHandler is entered."); michael@0: michael@0: gClient.addOneTimeListener("paused", (aEvent, aPacket) => { michael@0: is(aPacket.why.type, "pauseOnDOMEvents", michael@0: "A hidden breakpoint was hit."); michael@0: is(aPacket.frame.callee.name, "clickHandler", michael@0: "The clickHandler is entered."); michael@0: michael@0: gClient.addOneTimeListener("paused", (aEvent, aPacket) => { michael@0: is(aPacket.why.type, "pauseOnDOMEvents", michael@0: "A hidden breakpoint was hit."); michael@0: is(aPacket.frame.callee.name, "onchange", michael@0: "The onchange handler is entered."); michael@0: michael@0: gThreadClient.resume(deferred.resolve); michael@0: }); michael@0: michael@0: gThreadClient.resume(triggerInputChange); michael@0: }); michael@0: michael@0: gThreadClient.resume(triggerButtonClick); michael@0: }); michael@0: michael@0: gThreadClient.resume(triggerInputKeyup); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: // Test that removing events from the array disables them. michael@0: function testBreakOnDisabled() { michael@0: let deferred = promise.defer(); michael@0: michael@0: // Test calling pauseOnDOMEvents from a running state. michael@0: gThreadClient.pauseOnDOMEvents(["click"], (aPacket) => { michael@0: is(aPacket.error, undefined, michael@0: "The pause-on-click-only request completed successfully."); michael@0: michael@0: gClient.addListener("paused", unexpectedListener); michael@0: michael@0: // This non-capturing event listener is guaranteed to run after the page's michael@0: // capturing one had a chance to execute and modify window.foobar. michael@0: once(gInput, "keyup").then(() => { michael@0: is(content.wrappedJSObject.foobar, "keyupHandler", michael@0: "No hidden breakpoint was hit."); michael@0: michael@0: gClient.removeListener("paused", unexpectedListener); michael@0: deferred.resolve(); michael@0: }); michael@0: michael@0: triggerInputKeyup(); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: // Test that specifying an empty event array clears all hidden breakpoints. michael@0: function testBreakOnNone() { michael@0: let deferred = promise.defer(); michael@0: michael@0: // Test calling pauseOnDOMEvents from a running state. michael@0: gThreadClient.pauseOnDOMEvents([], (aPacket) => { michael@0: is(aPacket.error, undefined, michael@0: "The pause-on-none request completed successfully."); michael@0: michael@0: gClient.addListener("paused", unexpectedListener); michael@0: michael@0: // This non-capturing event listener is guaranteed to run after the page's michael@0: // capturing one had a chance to execute and modify window.foobar. michael@0: once(gInput, "keyup").then(() => { michael@0: is(content.wrappedJSObject.foobar, "keyupHandler", michael@0: "No hidden breakpoint was hit."); michael@0: michael@0: gClient.removeListener("paused", unexpectedListener); michael@0: deferred.resolve(); michael@0: }); michael@0: michael@0: triggerInputKeyup(); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: // Test pause on a single event. michael@0: function testBreakOnClick() { michael@0: let deferred = promise.defer(); michael@0: michael@0: // Test calling pauseOnDOMEvents from a running state. michael@0: gThreadClient.pauseOnDOMEvents(["click"], (aPacket) => { michael@0: is(aPacket.error, undefined, michael@0: "The pause-on-click request completed successfully."); michael@0: michael@0: gClient.addOneTimeListener("paused", (aEvent, aPacket) => { michael@0: is(aPacket.why.type, "pauseOnDOMEvents", michael@0: "A hidden breakpoint was hit."); michael@0: is(aPacket.frame.callee.name, "clickHandler", michael@0: "The clickHandler is entered."); michael@0: michael@0: gThreadClient.resume(deferred.resolve); michael@0: }); michael@0: michael@0: triggerButtonClick(); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function closeConnection() { michael@0: let deferred = promise.defer(); michael@0: gClient.close(deferred.resolve); michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function unexpectedListener() { michael@0: gClient.removeListener("paused", unexpectedListener); michael@0: ok(false, "An unexpected hidden breakpoint was hit."); michael@0: gThreadClient.resume(testBreakOnClick); michael@0: } michael@0: michael@0: function triggerInputKeyup() { michael@0: // Make sure that the focus is not on the input box so that a focus event michael@0: // will be triggered. michael@0: window.focus(); michael@0: gBrowser.selectedBrowser.focus(); michael@0: gButton.focus(); michael@0: michael@0: // Focus the element and wait for focus event. michael@0: once(gInput, "focus").then(() => { michael@0: executeSoon(() => { michael@0: EventUtils.synthesizeKey("e", { shiftKey: 1 }, content); michael@0: }); michael@0: }); michael@0: michael@0: gInput.focus(); michael@0: } michael@0: michael@0: function triggerButtonClick() { michael@0: EventUtils.sendMouseEvent({ type: "click" }, gButton); michael@0: } michael@0: michael@0: function triggerInputChange() { michael@0: gInput.focus(); michael@0: gInput.value = "foo"; michael@0: gInput.blur(); michael@0: } michael@0: michael@0: registerCleanupFunction(function() { michael@0: removeTab(gBrowser.selectedTab); michael@0: gClient = null; michael@0: gThreadClient = null; michael@0: gInput = null; michael@0: gButton = null; michael@0: });