mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1517837 - Move web replay tests to their own directory, r=lsmyth.
--HG-- extra : rebase_source : f26c786e9f787a57faed62f54c59178a5067065f
This commit is contained in:
parent
491c3a9d73
commit
1290999d83
@ -106,6 +106,7 @@ devtools/client/shared/webpack/shims/test/test_clipboard.html
|
||||
devtools/shared/qrcode/tests/mochitest/test_decode.html
|
||||
devtools/shared/tests/mochitest/*.html
|
||||
devtools/shared/webconsole/test/test_*.html
|
||||
devtools/client/webreplay/mochitest/examples/*.html
|
||||
|
||||
# Soon to be removed, the new/ directory is explicitly excluded below due to
|
||||
# also being an imported repository.
|
||||
|
@ -656,11 +656,6 @@ support-files =
|
||||
examples/simple-worker.js
|
||||
examples/doc-event-handler.html
|
||||
examples/doc-eval-throw.html
|
||||
examples/doc_rr_basic.html
|
||||
examples/doc_rr_continuous.html
|
||||
examples/doc_rr_logs.html
|
||||
examples/doc_rr_recovery.html
|
||||
examples/doc_rr_error.html
|
||||
|
||||
[browser_dbg-asm.js]
|
||||
[browser_dbg-async-stepping.js]
|
||||
@ -775,36 +770,3 @@ skip-if = true
|
||||
[browser_dbg-windowless-workers.js]
|
||||
[browser_dbg-event-handler.js]
|
||||
[browser_dbg-eval-throw.js]
|
||||
[browser_dbg_rr_breakpoints-01.js]
|
||||
skip-if = true # bug 1513057 os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_breakpoints-02.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_breakpoints-03.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_breakpoints-04.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_breakpoints-05.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_record.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_stepping-01.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_stepping-02.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_stepping-03.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_stepping-04.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_recovery-01.js]
|
||||
skip-if = true # See bug 1481009
|
||||
[browser_dbg_rr_replay-01.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_replay-02.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_replay-03.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_console_warp-01.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
[browser_dbg_rr_console_warp-02.js]
|
||||
skip-if = true # os != "mac" || debug || !nightly_build
|
||||
|
||||
|
@ -5,7 +5,7 @@ add_task(async function() {
|
||||
await selectSource(dbg, "switching-01");
|
||||
|
||||
// open the console
|
||||
await getSplitConsole(dbg);
|
||||
await getDebuggerSplitConsole(dbg);
|
||||
ok(dbg.toolbox.splitConsole, "Split console is shown.");
|
||||
|
||||
// close the console
|
||||
|
@ -1,48 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
|
||||
// This functionality was copied from devtools/client/webconsole/test/mochitest/head.js,
|
||||
// since this test straddles both the web console and the debugger. I couldn't
|
||||
// figure out how to load that script directly here.
|
||||
function waitForThreadEvents(threadClient, eventName) {
|
||||
info(`Waiting for thread event '${eventName}' to fire.`);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
threadClient.addListener(eventName, function onEvent(eventName, ...args) {
|
||||
info(`Thread event '${eventName}' fired.`);
|
||||
threadClient.removeListener(eventName, onEvent);
|
||||
resolve.apply(resolve, args);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Test basic console time warping functionality in web replay.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
const dbg = await attachRecordingDebugger(
|
||||
"doc_rr_logs.html",
|
||||
{ waitForRecording: true }
|
||||
);
|
||||
|
||||
const {tab, toolbox, threadClient} = dbg;
|
||||
const console = await getSplitConsole(dbg);
|
||||
const hud = console.hud;
|
||||
|
||||
let message = await warpToMessage(hud, threadClient, "number: 1");
|
||||
ok(!message.classList.contains("paused-before"), "paused before message is not shown");
|
||||
|
||||
await stepOverToLine(threadClient, 18);
|
||||
await reverseStepOverToLine(threadClient, 17);
|
||||
|
||||
message = findMessage(hud, "number: 1")
|
||||
ok(message.classList.contains("paused-before"), "paused before message is shown");
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
@ -47,16 +47,6 @@ const EXAMPLE_URL =
|
||||
"http://example.com/browser/devtools/client/debugger/new/test/mochitest/examples/";
|
||||
|
||||
|
||||
async function waitUntilPredicate(predicate) {
|
||||
let result;
|
||||
await waitUntil(() => {
|
||||
result = predicate();
|
||||
return result;
|
||||
})
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: still experimental, the screenshots might not be exactly correct
|
||||
async function takeScreenshot(dbg) {
|
||||
let canvas = dbg.win.document.createElementNS(
|
||||
@ -70,193 +60,3 @@ async function takeScreenshot(dbg) {
|
||||
await waitForTime(1000);
|
||||
dump(`[SCREENSHOT] ${canvas.toDataURL()}\n`);
|
||||
}
|
||||
|
||||
// Attach a debugger to a tab, returning a promise that resolves with the
|
||||
// debugger's toolbox.
|
||||
async function attachDebugger(tab) {
|
||||
let target = await TargetFactory.forTab(tab);
|
||||
let toolbox = await gDevTools.showToolbox(target, "jsdebugger");
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
async function attachRecordingDebugger(url, { waitForRecording } = { waitForRecording: false }) {
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = tab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + url, "current");
|
||||
|
||||
if (waitForRecording) {
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
}
|
||||
const toolbox = await attachDebugger(tab);
|
||||
const dbg = createDebuggerContext(toolbox)
|
||||
const threadClient = dbg.toolbox.threadClient;
|
||||
|
||||
await threadClient.interrupt();
|
||||
return {...dbg, tab, threadClient};
|
||||
}
|
||||
|
||||
|
||||
// Return a promise with a reference to jsterm, opening the split
|
||||
// console if necessary. This cleans up the split console pref so
|
||||
// it won't pollute other tests.
|
||||
async function getSplitConsole(dbg) {
|
||||
const { toolbox, win } = dbg;
|
||||
|
||||
if (!win) {
|
||||
win = toolbox.win;
|
||||
}
|
||||
|
||||
if (!toolbox.splitConsole) {
|
||||
pressKey(dbg, "Escape");
|
||||
}
|
||||
|
||||
await toolbox.openSplitConsole();
|
||||
return toolbox.getPanel("webconsole");
|
||||
}
|
||||
|
||||
|
||||
// Return a promise that resolves when a breakpoint has been set.
|
||||
async function setBreakpoint(threadClient, expectedFile, lineno) {
|
||||
let {sources} = await threadClient.getSources();
|
||||
ok(sources.length == 1, "Got one source");
|
||||
ok(RegExp(expectedFile).test(sources[0].url), "Source is " + expectedFile);
|
||||
let sourceClient = threadClient.source(sources[0]);
|
||||
await sourceClient.setBreakpoint({ line: lineno });
|
||||
}
|
||||
|
||||
function resumeThenPauseAtLineFunctionFactory(method) {
|
||||
return async function(threadClient, lineno) {
|
||||
threadClient[method]();
|
||||
await threadClient.addOneTimeListener("paused", async function(event, packet) {
|
||||
let {frames} = await threadClient.getFrames(0, 1);
|
||||
let frameLine = frames[0] ? frames[0].where.line : undefined;
|
||||
ok(frameLine == lineno, "Paused at line " + frameLine + " expected " + lineno);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Define various methods that resume a thread in a specific way and ensure it
|
||||
// pauses at a specified line.
|
||||
var rewindToLine = resumeThenPauseAtLineFunctionFactory("rewind");
|
||||
var resumeToLine = resumeThenPauseAtLineFunctionFactory("resume");
|
||||
var reverseStepOverToLine = resumeThenPauseAtLineFunctionFactory("reverseStepOver");
|
||||
var stepOverToLine = resumeThenPauseAtLineFunctionFactory("stepOver");
|
||||
var reverseStepInToLine = resumeThenPauseAtLineFunctionFactory("reverseStepIn");
|
||||
var stepInToLine = resumeThenPauseAtLineFunctionFactory("stepIn");
|
||||
var reverseStepOutToLine = resumeThenPauseAtLineFunctionFactory("reverseStepOut");
|
||||
var stepOutToLine = resumeThenPauseAtLineFunctionFactory("stepOut");
|
||||
|
||||
// Return a promise that resolves with the result of a thread evaluating a
|
||||
// string in the topmost frame.
|
||||
async function evaluateInTopFrame(threadClient, text) {
|
||||
let {frames} = await threadClient.getFrames(0, 1);
|
||||
ok(frames.length == 1, "Got one frame");
|
||||
let response = await threadClient.eval(frames[0].actor, text);
|
||||
ok(response.type == "resumed", "Got resume response from eval");
|
||||
let rval;
|
||||
await threadClient.addOneTimeListener("paused", function(event, packet) {
|
||||
ok(packet.type == "paused" &&
|
||||
packet.why.type == "clientEvaluated" &&
|
||||
"return" in packet.why.frameFinished, "Eval returned a value");
|
||||
rval = packet.why.frameFinished["return"];
|
||||
});
|
||||
return (rval.type == "undefined") ? undefined : rval;
|
||||
}
|
||||
|
||||
// Return a promise that resolves when a thread evaluates a string in the
|
||||
// topmost frame, ensuring the result matches the expected value.
|
||||
async function checkEvaluateInTopFrame(threadClient, text, expected) {
|
||||
let rval = await evaluateInTopFrame(threadClient, text);
|
||||
ok(rval == expected, "Eval returned " + expected);
|
||||
}
|
||||
|
||||
// Return a promise that resolves when a thread evaluates a string in the
|
||||
// topmost frame, with the result throwing an exception.
|
||||
async function checkEvaluateInTopFrameThrows(threadClient, text) {
|
||||
let {frames} = await threadClient.getFrames(0, 1);
|
||||
ok(frames.length == 1, "Got one frame");
|
||||
let response = await threadClient.eval(frames[0].actor, text);
|
||||
ok(response.type == "resumed", "Got resume response from eval");
|
||||
await threadClient.addOneTimeListener("paused", function(event, packet) {
|
||||
ok(packet.type == "paused" &&
|
||||
packet.why.type == "clientEvaluated" &&
|
||||
"throw" in packet.why.frameFinished, "Eval threw an exception");
|
||||
});
|
||||
}
|
||||
|
||||
// Return a pathname that can be used for a new recording file.
|
||||
function newRecordingFile() {
|
||||
ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
|
||||
return OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
"MochitestRecording" + Math.round(Math.random() * 1000000000));
|
||||
}
|
||||
|
||||
|
||||
async function warpToMessage(hud, threadClient, text) {
|
||||
let messages = await waitForMessages(hud, text);
|
||||
ok(messages.length == 1, "Found one message");
|
||||
let message = messages.pop();
|
||||
|
||||
let menuPopup = await openConsoleContextMenu(hud, message);
|
||||
console.log(`.>> menu`, menuPopup);
|
||||
|
||||
|
||||
let timeWarpItem = menuPopup.querySelector("#console-menu-time-warp");
|
||||
ok(timeWarpItem, "Time warp menu item is available");
|
||||
|
||||
timeWarpItem.click();
|
||||
|
||||
await Promise.all([
|
||||
hideConsoleContextMenu(hud),
|
||||
once(Services.ppmm, "TimeWarpFinished"),
|
||||
waitForThreadEvents(threadClient, 'paused')
|
||||
]);
|
||||
|
||||
messages = findMessages(hud, "", ".paused");
|
||||
ok(messages.length == 1, "Found one paused message");
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
function findMessage(hud, text, selector = ".message") {
|
||||
return findMessages(hud, text, selector)[0]
|
||||
}
|
||||
|
||||
function findMessages(hud, text, selector = ".message") {
|
||||
const messages = hud.ui.outputNode.querySelectorAll(selector);
|
||||
const elements = Array.prototype.filter.call(
|
||||
messages,
|
||||
(el) => el.textContent.includes(text)
|
||||
);
|
||||
|
||||
if (elements.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
function waitForMessages(hud, text, selector = ".message") {
|
||||
return waitUntilPredicate(() => findMessages(hud, text, selector))
|
||||
}
|
||||
|
||||
async function openConsoleContextMenu(hud, element) {
|
||||
const onConsoleMenuOpened = hud.ui.consoleOutput.once("menu-open");
|
||||
synthesizeContextMenuEvent(element);
|
||||
await onConsoleMenuOpened;
|
||||
const doc = hud.ui.consoleOutput.owner.chromeWindow.document;
|
||||
return doc.getElementById("webconsole-menu");
|
||||
}
|
||||
|
||||
function hideConsoleContextMenu(hud) {
|
||||
const doc = hud.ui.consoleOutput.owner.chromeWindow.document;
|
||||
const popup = doc.getElementById("webconsole-menu");
|
||||
if (!popup) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const onPopupHidden = once(popup, "popuphidden");
|
||||
popup.hidePopup();
|
||||
return onPopupHidden;
|
||||
}
|
||||
|
@ -1462,3 +1462,75 @@ async function editExpression(dbg, input) {
|
||||
pressKey(dbg, "Enter");
|
||||
await evaluated;
|
||||
}
|
||||
|
||||
async function waitUntilPredicate(predicate) {
|
||||
let result;
|
||||
await waitUntil(() => {
|
||||
result = predicate();
|
||||
return result;
|
||||
})
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return a promise with a reference to jsterm, opening the split
|
||||
// console if necessary. This cleans up the split console pref so
|
||||
// it won't pollute other tests.
|
||||
async function getDebuggerSplitConsole(dbg) {
|
||||
const { toolbox, win } = dbg;
|
||||
|
||||
if (!win) {
|
||||
win = toolbox.win;
|
||||
}
|
||||
|
||||
if (!toolbox.splitConsole) {
|
||||
pressKey(dbg, "Escape");
|
||||
}
|
||||
|
||||
await toolbox.openSplitConsole();
|
||||
return toolbox.getPanel("webconsole");
|
||||
}
|
||||
|
||||
async function openConsoleContextMenu(hud, element) {
|
||||
const onConsoleMenuOpened = hud.ui.consoleOutput.once("menu-open");
|
||||
synthesizeContextMenuEvent(element);
|
||||
await onConsoleMenuOpened;
|
||||
const doc = hud.ui.consoleOutput.owner.chromeWindow.document;
|
||||
return doc.getElementById("webconsole-menu");
|
||||
}
|
||||
|
||||
function hideConsoleContextMenu(hud) {
|
||||
const doc = hud.ui.consoleOutput.owner.chromeWindow.document;
|
||||
const popup = doc.getElementById("webconsole-menu");
|
||||
if (!popup) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const onPopupHidden = once(popup, "popuphidden");
|
||||
popup.hidePopup();
|
||||
return onPopupHidden;
|
||||
}
|
||||
|
||||
// Return a promise that resolves with the result of a thread evaluating a
|
||||
// string in the topmost frame.
|
||||
async function evaluateInTopFrame(threadClient, text) {
|
||||
const {frames} = await threadClient.getFrames(0, 1);
|
||||
ok(frames.length == 1, "Got one frame");
|
||||
const response = await threadClient.eval(frames[0].actor, text);
|
||||
ok(response.type == "resumed", "Got resume response from eval");
|
||||
let rval;
|
||||
await threadClient.addOneTimeListener("paused", function(event, packet) {
|
||||
ok(packet.type == "paused" &&
|
||||
packet.why.type == "clientEvaluated" &&
|
||||
"return" in packet.why.frameFinished, "Eval returned a value");
|
||||
rval = packet.why.frameFinished.return;
|
||||
});
|
||||
return (rval.type == "undefined") ? undefined : rval;
|
||||
}
|
||||
|
||||
// Return a promise that resolves when a thread evaluates a string in the
|
||||
// topmost frame, ensuring the result matches the expected value.
|
||||
async function checkEvaluateInTopFrame(threadClient, text, expected) {
|
||||
const rval = await evaluateInTopFrame(threadClient, text);
|
||||
ok(rval == expected, "Eval returned " + expected);
|
||||
}
|
||||
|
38
devtools/client/webreplay/mochitest/browser.ini
Normal file
38
devtools/client/webreplay/mochitest/browser.ini
Normal file
@ -0,0 +1,38 @@
|
||||
[DEFAULT]
|
||||
tags = devtools
|
||||
subsuite = devtools
|
||||
|
||||
# Feel free to set this to true if an impending change breaks Web Replay and
|
||||
# fixing it would be annoying or difficult. This will avoid running all tests
|
||||
# that use Web Replay; we don't want this experimental feature to impede
|
||||
# development in the rest of Gecko.
|
||||
#
|
||||
# Please file a bug against the 'Core > Web Replay' component if you do so,
|
||||
# so that the problem can be fixed and tests reenabled.
|
||||
skip-if = os != "mac" || debug || !nightly_build
|
||||
|
||||
support-files =
|
||||
head.js
|
||||
examples/doc_rr_basic.html
|
||||
examples/doc_rr_continuous.html
|
||||
examples/doc_rr_logs.html
|
||||
examples/doc_rr_recovery.html
|
||||
examples/doc_rr_error.html
|
||||
|
||||
[browser_dbg_rr_breakpoints-01.js]
|
||||
[browser_dbg_rr_breakpoints-02.js]
|
||||
[browser_dbg_rr_breakpoints-03.js]
|
||||
[browser_dbg_rr_breakpoints-04.js]
|
||||
[browser_dbg_rr_breakpoints-05.js]
|
||||
[browser_dbg_rr_record.js]
|
||||
[browser_dbg_rr_stepping-01.js]
|
||||
[browser_dbg_rr_stepping-02.js]
|
||||
[browser_dbg_rr_stepping-03.js]
|
||||
[browser_dbg_rr_stepping-04.js]
|
||||
[browser_dbg_rr_recovery-01.js]
|
||||
skip-if = true # See bug 1481009
|
||||
[browser_dbg_rr_replay-01.js]
|
||||
[browser_dbg_rr_replay-02.js]
|
||||
[browser_dbg_rr_replay-03.js]
|
||||
[browser_dbg_rr_console_warp-01.js]
|
||||
[browser_dbg_rr_console_warp-02.js]
|
@ -2,11 +2,14 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test basic breakpoint functionality in web replay.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await attachRecordingDebugger(
|
||||
"doc_rr_basic.html",
|
||||
{ waitForRecording: true }
|
||||
@ -38,5 +41,4 @@ async function test() {
|
||||
|
||||
await toolbox.closeToolbox();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,12 +2,16 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test unhandled divergence while evaluating at a breakpoint with Web Replay.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
const dbg = await attachRecordingDebugger("doc_rr_basic.html", { waitForRecording: true });
|
||||
add_task(async function() {
|
||||
const dbg = await attachRecordingDebugger("doc_rr_basic.html",
|
||||
{ waitForRecording: true });
|
||||
const {threadClient, tab, toolbox} = dbg;
|
||||
|
||||
await setBreakpoint(threadClient, "doc_rr_basic.html", 21);
|
||||
@ -21,5 +25,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,11 +2,14 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test some issues when stepping around after hitting a breakpoint while recording.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await attachRecordingDebugger("doc_rr_continuous.html");
|
||||
const {threadClient, tab, toolbox} = dbg;
|
||||
|
||||
@ -14,7 +17,9 @@ async function test() {
|
||||
await setBreakpoint(threadClient, "doc_rr_continuous.html", 19);
|
||||
await resumeToLine(threadClient, 19);
|
||||
await reverseStepOverToLine(threadClient, 18);
|
||||
await checkEvaluateInTopFrame(threadClient, "SpecialPowers.Cu.recordReplayDirective(/* AlwaysTakeTemporarySnapshots */ 3)", undefined);
|
||||
await checkEvaluateInTopFrame(threadClient,
|
||||
"SpecialPowers.Cu.recordReplayDirective(/* AlwaysTakeTemporarySnapshots */ 3)",
|
||||
undefined);
|
||||
await stepInToLine(threadClient, 22);
|
||||
await setBreakpoint(threadClient, "doc_rr_continuous.html", 24);
|
||||
await resumeToLine(threadClient, 24);
|
||||
@ -23,5 +28,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,18 +2,21 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test navigating back to earlier breakpoints while recording, then resuming
|
||||
// recording.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await attachRecordingDebugger("doc_rr_continuous.html");
|
||||
const {threadClient, tab, toolbox} = dbg;
|
||||
|
||||
await setBreakpoint(threadClient, "doc_rr_continuous.html", 14);
|
||||
await resumeToLine(threadClient, 14);
|
||||
let value = await evaluateInTopFrame(threadClient, "number");
|
||||
const value = await evaluateInTopFrame(threadClient, "number");
|
||||
await resumeToLine(threadClient, 14);
|
||||
await checkEvaluateInTopFrame(threadClient, "number", value + 1);
|
||||
await rewindToLine(threadClient, 14);
|
||||
@ -29,5 +32,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,14 +2,17 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test hitting breakpoints when rewinding past the point where the breakpoint
|
||||
// script was created.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await attachRecordingDebugger(
|
||||
"doc_rr_basic.html",
|
||||
"doc_rr_basic.html",
|
||||
{ waitForRecording: true }
|
||||
);
|
||||
|
||||
@ -26,5 +29,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,37 +2,24 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
// This functionality was copied from devtools/client/webconsole/test/mochitest/head.js,
|
||||
// since this test straddles both the web console and the debugger. I couldn't
|
||||
// figure out how to load that script directly here.
|
||||
function waitForThreadEvents(threadClient, eventName) {
|
||||
info(`Waiting for thread event '${eventName}' to fire.`);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
threadClient.addListener(eventName, function onEvent(eventName, ...args) {
|
||||
info(`Thread event '${eventName}' fired.`);
|
||||
threadClient.removeListener(eventName, onEvent);
|
||||
resolve.apply(resolve, args);
|
||||
});
|
||||
});
|
||||
}
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test basic console time warping functionality in web replay.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await attachRecordingDebugger(
|
||||
"doc_rr_error.html",
|
||||
"doc_rr_error.html",
|
||||
{ waitForRecording: true }
|
||||
);
|
||||
|
||||
const {tab, toolbox, threadClient} = dbg;
|
||||
const console = await getSplitConsole(dbg);
|
||||
const console = await getDebuggerSplitConsole(dbg);
|
||||
const hud = console.hud;
|
||||
|
||||
await warpToMessage(hud, threadClient, "Number 5");
|
||||
await warpToMessage(hud, dbg, "Number 5");
|
||||
await threadClient.interrupt();
|
||||
|
||||
await checkEvaluateInTopFrame(threadClient, "number", 5);
|
||||
@ -49,5 +36,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -0,0 +1,33 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test basic console time warping functionality in web replay.
|
||||
add_task(async function() {
|
||||
const dbg = await attachRecordingDebugger(
|
||||
"doc_rr_logs.html",
|
||||
{ waitForRecording: true }
|
||||
);
|
||||
|
||||
const {tab, toolbox, threadClient} = dbg;
|
||||
const console = await getDebuggerSplitConsole(dbg);
|
||||
const hud = console.hud;
|
||||
|
||||
let message = await warpToMessage(hud, dbg, "number: 1");
|
||||
ok(!message.classList.contains("paused-before"), "paused before message is not shown");
|
||||
|
||||
await stepOverToLine(threadClient, 18);
|
||||
await reverseStepOverToLine(threadClient, 17);
|
||||
|
||||
message = findMessage(hud, "number: 1");
|
||||
ok(message.classList.contains("paused-before"), "paused before message is shown");
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
});
|
@ -2,12 +2,15 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test basic recording of a tab without any debugging.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var recordingTab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
add_task(async function() {
|
||||
const recordingTab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = recordingTab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
@ -15,5 +18,4 @@ async function test() {
|
||||
await gBrowser.removeTab(recordingTab);
|
||||
|
||||
ok(true, "Finished");
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,27 +2,32 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test basic recovery of crashed child processes in web replay.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
add_task(async function() {
|
||||
const tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = tab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_recovery.html", "current");
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
|
||||
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
const toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
await client.interrupt();
|
||||
await setBreakpoint(client, "doc_rr_recovery.html", 21);
|
||||
await rewindToLine(client, 21);
|
||||
await checkEvaluateInTopFrame(client, "SpecialPowers.Cu.recordReplayDirective(/* CrashSoon */ 1)", undefined);
|
||||
await checkEvaluateInTopFrame(client,
|
||||
"SpecialPowers.Cu.recordReplayDirective(/* CrashSoon */ 1)",
|
||||
undefined);
|
||||
await stepOverToLine(client, 22);
|
||||
await stepOverToLine(client, 23);
|
||||
await checkEvaluateInTopFrame(client, "SpecialPowers.Cu.recordReplayDirective(/* CrashSoon */ 1); " +
|
||||
"SpecialPowers.Cu.recordReplayDirective(/* MaybeCrash */ 2)", undefined);
|
||||
|
||||
await checkEvaluateInTopFrame(client,
|
||||
"SpecialPowers.Cu.recordReplayDirective(/* CrashSoon */ 1); " +
|
||||
"SpecialPowers.Cu.recordReplayDirective(/* MaybeCrash */ 2)",
|
||||
undefined);
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,27 +2,32 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Basic test for saving a recording and then replaying it in a new tab.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let recordingFile = newRecordingFile();
|
||||
let recordingTab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
add_task(async function() {
|
||||
const recordingFile = newRecordingFile();
|
||||
const recordingTab = BrowserTestUtils.addTab(gBrowser, null,
|
||||
{ recordExecution: "*" });
|
||||
gBrowser.selectedTab = recordingTab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
|
||||
let tabParent = recordingTab.linkedBrowser.frameLoader.tabParent;
|
||||
const tabParent = recordingTab.linkedBrowser.frameLoader.tabParent;
|
||||
ok(tabParent, "Found recording tab parent");
|
||||
ok(tabParent.saveRecording(recordingFile), "Saved recording");
|
||||
await once(Services.ppmm, "SaveRecordingFinished");
|
||||
|
||||
let replayingTab = BrowserTestUtils.addTab(gBrowser, null, { replayExecution: recordingFile });
|
||||
const replayingTab = BrowserTestUtils.addTab(gBrowser, null,
|
||||
{ replayExecution: recordingFile });
|
||||
gBrowser.selectedTab = replayingTab;
|
||||
await once(Services.ppmm, "HitRecordingEndpoint");
|
||||
|
||||
let toolbox = await attachDebugger(replayingTab), client = toolbox.threadClient;
|
||||
const toolbox = await attachDebugger(replayingTab), client = toolbox.threadClient;
|
||||
await client.interrupt();
|
||||
await setBreakpoint(client, "doc_rr_basic.html", 21);
|
||||
await rewindToLine(client, 21);
|
||||
@ -35,5 +40,4 @@ async function test() {
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(recordingTab);
|
||||
await gBrowser.removeTab(replayingTab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,13 +2,18 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test ending a recording at a breakpoint and then separately replaying to the end.
|
||||
async function test() {
|
||||
add_task(async function() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let recordingFile = newRecordingFile();
|
||||
let recordingTab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
const recordingFile = newRecordingFile();
|
||||
const recordingTab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = recordingTab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_continuous.html", "current");
|
||||
|
||||
@ -18,9 +23,9 @@ async function test() {
|
||||
await resumeToLine(client, 14);
|
||||
await resumeToLine(client, 14);
|
||||
await reverseStepOverToLine(client, 13);
|
||||
let lastNumberValue = await evaluateInTopFrame(client, "number");
|
||||
const lastNumberValue = await evaluateInTopFrame(client, "number");
|
||||
|
||||
let tabParent = recordingTab.linkedBrowser.frameLoader.tabParent;
|
||||
const tabParent = recordingTab.linkedBrowser.frameLoader.tabParent;
|
||||
ok(tabParent, "Found recording tab parent");
|
||||
ok(tabParent.saveRecording(recordingFile), "Saved recording");
|
||||
await once(Services.ppmm, "SaveRecordingFinished");
|
||||
@ -28,7 +33,8 @@ async function test() {
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(recordingTab);
|
||||
|
||||
let replayingTab = BrowserTestUtils.addTab(gBrowser, null, { replayExecution: recordingFile });
|
||||
const replayingTab = BrowserTestUtils.addTab(gBrowser, null,
|
||||
{ replayExecution: recordingFile });
|
||||
gBrowser.selectedTab = replayingTab;
|
||||
await once(Services.ppmm, "HitRecordingEndpoint");
|
||||
|
||||
@ -45,5 +51,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(replayingTab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,25 +2,30 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
// Test for saving a recording and then replaying it in a new tab, with rewinding disabled.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test for saving a recording and then replaying it in a new tab,
|
||||
// with rewinding disabled.
|
||||
add_task(async function() {
|
||||
await pushPref("devtools.recordreplay.enableRewinding", false);
|
||||
|
||||
let recordingFile = newRecordingFile();
|
||||
let recordingTab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
const recordingFile = newRecordingFile();
|
||||
const recordingTab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = recordingTab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
|
||||
let tabParent = recordingTab.linkedBrowser.frameLoader.tabParent;
|
||||
const tabParent = recordingTab.linkedBrowser.frameLoader.tabParent;
|
||||
ok(tabParent, "Found recording tab parent");
|
||||
ok(tabParent.saveRecording(recordingFile), "Saved recording");
|
||||
await once(Services.ppmm, "SaveRecordingFinished");
|
||||
|
||||
let replayingTab = BrowserTestUtils.addTab(gBrowser, null, { replayExecution: recordingFile });
|
||||
const replayingTab = BrowserTestUtils.addTab(gBrowser, null,
|
||||
{ replayExecution: recordingFile });
|
||||
gBrowser.selectedTab = replayingTab;
|
||||
await once(Services.ppmm, "HitRecordingEndpoint");
|
||||
|
||||
@ -28,5 +33,4 @@ async function test() {
|
||||
|
||||
await gBrowser.removeTab(recordingTab);
|
||||
await gBrowser.removeTab(replayingTab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,17 +2,20 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test basic step-over/back functionality in web replay.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
add_task(async function() {
|
||||
const tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = tab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
|
||||
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
const toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
await client.interrupt();
|
||||
await setBreakpoint(client, "doc_rr_basic.html", 21);
|
||||
await rewindToLine(client, 21);
|
||||
@ -25,5 +28,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,17 +2,20 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test fixes for some simple stepping bugs.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
add_task(async function() {
|
||||
const tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = tab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
|
||||
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
const toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
await client.interrupt();
|
||||
await setBreakpoint(client, "doc_rr_basic.html", 22);
|
||||
await rewindToLine(client, 22);
|
||||
@ -26,5 +29,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,20 +2,23 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Test stepping back while recording, then resuming recording.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
add_task(async function() {
|
||||
const tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = tab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_continuous.html", "current");
|
||||
|
||||
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
const toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
await client.interrupt();
|
||||
await setBreakpoint(client, "doc_rr_continuous.html", 13);
|
||||
await resumeToLine(client, 13);
|
||||
let value = await evaluateInTopFrame(client, "number");
|
||||
const value = await evaluateInTopFrame(client, "number");
|
||||
await reverseStepOverToLine(client, 12);
|
||||
await checkEvaluateInTopFrame(client, "number", value - 1);
|
||||
await resumeToLine(client, 13);
|
||||
@ -24,5 +27,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
@ -2,17 +2,20 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To disable all Web Replay tests, see browser.ini
|
||||
|
||||
// Stepping past the beginning or end of a frame should act like a step-out.
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
add_task(async function() {
|
||||
const tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = tab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
|
||||
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
const toolbox = await attachDebugger(tab), client = toolbox.threadClient;
|
||||
await client.interrupt();
|
||||
await setBreakpoint(client, "doc_rr_basic.html", 21);
|
||||
await rewindToLine(client, 21);
|
||||
@ -38,5 +41,4 @@ async function test() {
|
||||
|
||||
await toolbox.destroy();
|
||||
await gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
});
|
144
devtools/client/webreplay/mochitest/head.js
Normal file
144
devtools/client/webreplay/mochitest/head.js
Normal file
@ -0,0 +1,144 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
"use strict";
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
|
||||
this
|
||||
);
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/helpers.js",
|
||||
this
|
||||
);
|
||||
|
||||
const EXAMPLE_URL =
|
||||
"http://example.com/browser/devtools/client/webreplay/mochitest/examples/";
|
||||
|
||||
// Attach a debugger to a tab, returning a promise that resolves with the
|
||||
// debugger's toolbox.
|
||||
async function attachDebugger(tab) {
|
||||
const target = await TargetFactory.forTab(tab);
|
||||
const toolbox = await gDevTools.showToolbox(target, "jsdebugger");
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
async function attachRecordingDebugger(url,
|
||||
{ waitForRecording } = { waitForRecording: false }) {
|
||||
const tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
|
||||
gBrowser.selectedTab = tab;
|
||||
openTrustedLinkIn(EXAMPLE_URL + url, "current");
|
||||
|
||||
if (waitForRecording) {
|
||||
await once(Services.ppmm, "RecordingFinished");
|
||||
}
|
||||
const toolbox = await attachDebugger(tab);
|
||||
const dbg = createDebuggerContext(toolbox);
|
||||
const threadClient = dbg.toolbox.threadClient;
|
||||
|
||||
await threadClient.interrupt();
|
||||
return {...dbg, tab, threadClient};
|
||||
}
|
||||
|
||||
// Return a promise that resolves when a breakpoint has been set.
|
||||
async function setBreakpoint(threadClient, expectedFile, lineno) {
|
||||
const {sources} = await threadClient.getSources();
|
||||
ok(sources.length == 1, "Got one source");
|
||||
ok(RegExp(expectedFile).test(sources[0].url), "Source is " + expectedFile);
|
||||
const sourceClient = threadClient.source(sources[0]);
|
||||
await sourceClient.setBreakpoint({ line: lineno });
|
||||
}
|
||||
|
||||
function resumeThenPauseAtLineFunctionFactory(method) {
|
||||
return async function(threadClient, lineno) {
|
||||
threadClient[method]();
|
||||
await threadClient.addOneTimeListener("paused", async function(event, packet) {
|
||||
const {frames} = await threadClient.getFrames(0, 1);
|
||||
const frameLine = frames[0] ? frames[0].where.line : undefined;
|
||||
ok(frameLine == lineno, "Paused at line " + frameLine + " expected " + lineno);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Define various methods that resume a thread in a specific way and ensure it
|
||||
// pauses at a specified line.
|
||||
var rewindToLine = resumeThenPauseAtLineFunctionFactory("rewind");
|
||||
var resumeToLine = resumeThenPauseAtLineFunctionFactory("resume");
|
||||
var reverseStepOverToLine = resumeThenPauseAtLineFunctionFactory("reverseStepOver");
|
||||
var stepOverToLine = resumeThenPauseAtLineFunctionFactory("stepOver");
|
||||
var reverseStepInToLine = resumeThenPauseAtLineFunctionFactory("reverseStepIn");
|
||||
var stepInToLine = resumeThenPauseAtLineFunctionFactory("stepIn");
|
||||
var reverseStepOutToLine = resumeThenPauseAtLineFunctionFactory("reverseStepOut");
|
||||
var stepOutToLine = resumeThenPauseAtLineFunctionFactory("stepOut");
|
||||
|
||||
// Return a promise that resolves when a thread evaluates a string in the
|
||||
// topmost frame, with the result throwing an exception.
|
||||
async function checkEvaluateInTopFrameThrows(threadClient, text) {
|
||||
const {frames} = await threadClient.getFrames(0, 1);
|
||||
ok(frames.length == 1, "Got one frame");
|
||||
const response = await threadClient.eval(frames[0].actor, text);
|
||||
ok(response.type == "resumed", "Got resume response from eval");
|
||||
await threadClient.addOneTimeListener("paused", function(event, packet) {
|
||||
ok(packet.type == "paused" &&
|
||||
packet.why.type == "clientEvaluated" &&
|
||||
"throw" in packet.why.frameFinished, "Eval threw an exception");
|
||||
});
|
||||
}
|
||||
|
||||
// Return a pathname that can be used for a new recording file.
|
||||
function newRecordingFile() {
|
||||
ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
|
||||
return OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
"MochitestRecording" + Math.round(Math.random() * 1000000000));
|
||||
}
|
||||
|
||||
function findMessage(hud, text, selector = ".message") {
|
||||
return findMessages(hud, text, selector)[0];
|
||||
}
|
||||
|
||||
function findMessages(hud, text, selector = ".message") {
|
||||
const messages = hud.ui.outputNode.querySelectorAll(selector);
|
||||
const elements = Array.prototype.filter.call(
|
||||
messages,
|
||||
(el) => el.textContent.includes(text)
|
||||
);
|
||||
|
||||
if (elements.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
function waitForMessages(hud, text, selector = ".message") {
|
||||
return waitUntilPredicate(() => findMessages(hud, text, selector));
|
||||
}
|
||||
|
||||
async function warpToMessage(hud, threadClient, text) {
|
||||
let messages = await waitForMessages(hud, text);
|
||||
ok(messages.length == 1, "Found one message");
|
||||
const message = messages.pop();
|
||||
|
||||
const menuPopup = await openConsoleContextMenu(hud, message);
|
||||
console.log(`.>> menu`, menuPopup);
|
||||
|
||||
const timeWarpItem = menuPopup.querySelector("#console-menu-time-warp");
|
||||
ok(timeWarpItem, "Time warp menu item is available");
|
||||
|
||||
timeWarpItem.click();
|
||||
|
||||
await Promise.all([
|
||||
hideConsoleContextMenu(hud),
|
||||
once(Services.ppmm, "TimeWarpFinished"),
|
||||
waitForThreadEvents(threadClient, "paused"),
|
||||
]);
|
||||
|
||||
messages = findMessages(hud, "", ".paused");
|
||||
ok(messages.length == 1, "Found one paused message");
|
||||
|
||||
return message;
|
||||
}
|
@ -14,3 +14,5 @@ DevToolsModules(
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Core', 'Web Replay')
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [ 'mochitest/browser.ini' ]
|
||||
|
Loading…
Reference in New Issue
Block a user