mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 1897755 - [devtools] Update DAMP tests to support Codemirror 6 r=perftest-reviewers,devtools-reviewers,nchevobbe,sparky
This patch adds support for running debugger DAMP tests with CM6. Currently switch off by default. Set the `devtools.debugger.features.codemirror-next` pref in the custom.js to `true` to run. Differential Revision: https://phabricator.services.mozilla.com/D210909
This commit is contained in:
parent
7e58206c82
commit
c41b562cdd
@ -625,7 +625,13 @@ class Editor extends EventEmitter {
|
||||
codemirrorView: { EditorView, lineNumbers },
|
||||
codemirrorState: { EditorState, Compartment },
|
||||
codemirrorSearch: { highlightSelectionMatches },
|
||||
codemirrorLanguage,
|
||||
codemirrorLanguage: {
|
||||
syntaxTreeAvailable,
|
||||
indentUnit,
|
||||
codeFolding,
|
||||
syntaxHighlighting,
|
||||
bracketMatching,
|
||||
},
|
||||
codemirrorLangJavascript,
|
||||
lezerHighlight,
|
||||
} = this.#CodeMirror6;
|
||||
@ -663,21 +669,30 @@ class Editor extends EventEmitter {
|
||||
);
|
||||
|
||||
const extensions = [
|
||||
codemirrorLanguage.bracketMatching(),
|
||||
indentCompartment.of(codemirrorLanguage.indentUnit.of(indentStr)),
|
||||
bracketMatching(),
|
||||
indentCompartment.of(indentUnit.of(indentStr)),
|
||||
tabSizeCompartment.of(EditorState.tabSize.of(this.config.tabSize)),
|
||||
lineWrapCompartment.of(
|
||||
this.config.lineWrapping ? EditorView.lineWrapping : []
|
||||
),
|
||||
EditorState.readOnly.of(this.config.readOnly),
|
||||
lineNumberCompartment.of(this.config.lineNumbers ? lineNumbers() : []),
|
||||
codemirrorLanguage.codeFolding({
|
||||
codeFolding({
|
||||
placeholderText: "↔",
|
||||
}),
|
||||
foldGutterCompartment.of([]),
|
||||
codemirrorLanguage.syntaxHighlighting(lezerHighlight.classHighlighter),
|
||||
syntaxHighlighting(lezerHighlight.classHighlighter),
|
||||
EditorView.updateListener.of(v => {
|
||||
if (!cm.isDocumentLoadComplete) {
|
||||
// Check that the full syntax tree is available the current viewport
|
||||
if (syntaxTreeAvailable(v.state, v.view.viewState.viewport.to)) {
|
||||
cm.isDocumentLoadComplete = true;
|
||||
}
|
||||
}
|
||||
if (v.viewportChanged || v.docChanged) {
|
||||
if (v.docChanged) {
|
||||
cm.isDocumentLoadComplete = false;
|
||||
}
|
||||
// reset line gutter markers for the new visible ranges
|
||||
// when the viewport changes(e.g when the page is scrolled).
|
||||
if (this.#lineGutterMarkers.size > 0) {
|
||||
@ -708,6 +723,8 @@ class Editor extends EventEmitter {
|
||||
extensions,
|
||||
});
|
||||
|
||||
cm.isDocumentLoadComplete = false;
|
||||
this.#ownerDoc.sourceEditor = { editor: this, cm };
|
||||
editors.set(this, cm);
|
||||
}
|
||||
|
||||
|
@ -49,9 +49,13 @@ const TEST_URL = PAGES_BASE_URL + "custom/debugger/app-build/index.html";
|
||||
const MINIFIED_URL = `${IFRAME_BASE_URL}custom/debugger/app-build/static/js/minified.js`;
|
||||
|
||||
module.exports = async function () {
|
||||
const isCm6Enabled = Services.prefs.getBoolPref(
|
||||
"devtools.debugger.features.codemirror-next"
|
||||
);
|
||||
|
||||
const tab = await testSetup(TEST_URL, { disableCache: true });
|
||||
|
||||
const toolbox = await openDebuggerAndLog("custom", EXPECTED);
|
||||
const toolbox = await openDebuggerAndLog("custom", EXPECTED, isCm6Enabled);
|
||||
|
||||
dump("Waiting for debugger panel\n");
|
||||
const panel = await toolbox.getPanelWhenReady("jsdebugger");
|
||||
@ -62,16 +66,16 @@ module.exports = async function () {
|
||||
// Reselect App.js as that's the source expected to be selected after page reload
|
||||
await selectSource(dbg, EXPECTED.file);
|
||||
|
||||
await reloadDebuggerAndLog("custom", toolbox, EXPECTED);
|
||||
await reloadDebuggerAndLog("custom", toolbox, EXPECTED, isCm6Enabled);
|
||||
|
||||
// these tests are only run on custom.jsdebugger
|
||||
await pauseDebuggerAndLog(dbg, tab, EXPECTED_FUNCTION);
|
||||
await stepDebuggerAndLog(dbg, tab, EXPECTED_FUNCTION);
|
||||
|
||||
await testProjectSearch(dbg, tab);
|
||||
await testPreview(dbg, tab, EXPECTED_FUNCTION);
|
||||
await testOpeningLargeMinifiedFile(dbg, tab);
|
||||
await testPrettyPrint(dbg, toolbox);
|
||||
await testPreview(dbg, tab, EXPECTED_FUNCTION, isCm6Enabled);
|
||||
await testOpeningLargeMinifiedFile(dbg, isCm6Enabled);
|
||||
await testPrettyPrint(dbg, toolbox, isCm6Enabled);
|
||||
|
||||
await closeToolboxAndLog("custom.jsdebugger", toolbox);
|
||||
|
||||
@ -198,12 +202,13 @@ async function testProjectSearch(dbg) {
|
||||
await garbageCollect();
|
||||
}
|
||||
|
||||
async function testPreview(dbg, tab, testFunction) {
|
||||
async function testPreview(dbg, tab, testFunction, isCm6Enabled) {
|
||||
dump("Executing preview test ...\n");
|
||||
const pauseLocation = { line: 22, file: "App.js" };
|
||||
|
||||
let test = runTest("custom.jsdebugger.preview.DAMP");
|
||||
await pauseDebugger(dbg, tab, testFunction, pauseLocation);
|
||||
await hoverOnToken(dbg, "window.hitBreakpoint", "window");
|
||||
await hoverOnToken(dbg, "window.hitBreakpoint", "window", isCm6Enabled);
|
||||
test.done();
|
||||
|
||||
await removeBreakpoints(dbg);
|
||||
@ -211,7 +216,8 @@ async function testPreview(dbg, tab, testFunction) {
|
||||
await garbageCollect();
|
||||
}
|
||||
|
||||
async function testOpeningLargeMinifiedFile(dbg) {
|
||||
async function testOpeningLargeMinifiedFile(dbg, isCm6Enabled) {
|
||||
dump("Executing opening large minified test ...\n");
|
||||
const fileFirstMinifiedChars = `(()=>{var e,t,n,r,o={82603`;
|
||||
|
||||
dump("Open minified.js (large minified file)\n");
|
||||
@ -220,7 +226,7 @@ async function testOpeningLargeMinifiedFile(dbg) {
|
||||
);
|
||||
const test = runTest("custom.jsdebugger.open-large-minified-file.DAMP");
|
||||
const onSelected = selectSource(dbg, MINIFIED_URL);
|
||||
await waitForText(dbg, fileFirstMinifiedChars);
|
||||
await waitForText(dbg, fileFirstMinifiedChars, isCm6Enabled);
|
||||
test.done();
|
||||
await onSelected;
|
||||
fullTest.done();
|
||||
@ -233,7 +239,7 @@ async function testOpeningLargeMinifiedFile(dbg) {
|
||||
await garbageCollect();
|
||||
}
|
||||
|
||||
async function testPrettyPrint(dbg, toolbox) {
|
||||
async function testPrettyPrint(dbg, toolbox, isCm6Enabled) {
|
||||
const formattedFileUrl = `${MINIFIED_URL}:formatted`;
|
||||
const filePrettyChars = "82603: (e, t, n) => {\n";
|
||||
|
||||
@ -241,12 +247,16 @@ async function testPrettyPrint(dbg, toolbox) {
|
||||
await selectSource(dbg, MINIFIED_URL);
|
||||
|
||||
dump("Wait until CodeMirror highlighting is done\n");
|
||||
const cm = getCM(dbg);
|
||||
// highlightFrontier is not documented but is an internal variable indicating the current
|
||||
// line that was just highlighted. This document has only 2 lines, so wait until both
|
||||
// are highlighted. Since there was an other document opened before, we need to do an
|
||||
// exact check to properly wait.
|
||||
await waitUntil(() => cm.doc.highlightFrontier === 2);
|
||||
const cm = getCM(dbg, isCm6Enabled);
|
||||
await waitUntil(() => {
|
||||
return isCm6Enabled
|
||||
? cm.isDocumentLoadComplete
|
||||
: // For CM5 highlightFrontier is not documented but is an internal variable indicating the current
|
||||
// line that was just highlighted. This document has only 2 lines, so wait until both
|
||||
// are highlighted. Since there was an other document opened before, we need to do an
|
||||
// exact check to properly wait.
|
||||
cm.doc.highlightFrontier === 2;
|
||||
});
|
||||
|
||||
const prettyPrintButton = await waitUntil(() => {
|
||||
return dbg.win.document.querySelector(".source-footer .prettyPrint.active");
|
||||
@ -256,7 +266,7 @@ async function testPrettyPrint(dbg, toolbox) {
|
||||
const test = runTest("custom.jsdebugger.pretty-print.DAMP");
|
||||
prettyPrintButton.click();
|
||||
await waitForSource(dbg, formattedFileUrl);
|
||||
await waitForText(dbg, filePrettyChars);
|
||||
await waitForText(dbg, filePrettyChars, isCm6Enabled);
|
||||
test.done();
|
||||
|
||||
await addBreakpoint(dbg, 776, formattedFileUrl);
|
||||
@ -265,12 +275,17 @@ async function testPrettyPrint(dbg, toolbox) {
|
||||
const reloadAndPauseInPrettyPrintedFileTest = runTest(
|
||||
"custom.jsdebugger.pretty-print.reload-and-pause.DAMP"
|
||||
);
|
||||
await reloadDebuggerAndLog("custom.pretty-print", toolbox, {
|
||||
sources: 1105,
|
||||
sourceURL: formattedFileUrl,
|
||||
text: filePrettyChars,
|
||||
threadsCount: EXPECTED.threadsCount,
|
||||
});
|
||||
await reloadDebuggerAndLog(
|
||||
"custom.pretty-print",
|
||||
toolbox,
|
||||
{
|
||||
sources: 1105,
|
||||
sourceURL: formattedFileUrl,
|
||||
text: filePrettyChars,
|
||||
threadsCount: EXPECTED.threadsCount,
|
||||
},
|
||||
isCm6Enabled
|
||||
);
|
||||
await onPaused;
|
||||
|
||||
// When reloading, the `togglePrettyPrint` action is called to pretty print the minified source.
|
||||
|
@ -102,21 +102,31 @@ function findSource(dbg, url) {
|
||||
}
|
||||
exports.findSource = findSource;
|
||||
|
||||
function getCM(dbg) {
|
||||
function getCM(dbg, isCm6Enabled) {
|
||||
if (isCm6Enabled) {
|
||||
return dbg.win.document.sourceEditor.cm;
|
||||
}
|
||||
const el = dbg.win.document.querySelector(".CodeMirror");
|
||||
return el.CodeMirror;
|
||||
}
|
||||
exports.getCM = getCM;
|
||||
|
||||
function waitForText(dbg, text) {
|
||||
function waitForText(dbg, text, isCm6Enabled = false) {
|
||||
return waitUntil(() => {
|
||||
// the welcome box is removed once text is displayed
|
||||
const welcomebox = dbg.win.document.querySelector(".welcomebox");
|
||||
if (welcomebox) {
|
||||
return false;
|
||||
}
|
||||
const cm = getCM(dbg);
|
||||
const editorText = cm.doc.getValue();
|
||||
const cm = getCM(dbg, isCm6Enabled);
|
||||
let editorText = "";
|
||||
if (isCm6Enabled) {
|
||||
if (cm) {
|
||||
editorText = cm.state.doc.toString();
|
||||
}
|
||||
} else {
|
||||
editorText = cm.doc.getValue();
|
||||
}
|
||||
return editorText.includes(text);
|
||||
}, "text is visible");
|
||||
}
|
||||
@ -286,13 +296,13 @@ function evalInFrame(tab, testFunction) {
|
||||
}
|
||||
exports.evalInFrame = evalInFrame;
|
||||
|
||||
async function openDebuggerAndLog(label, expected) {
|
||||
async function openDebuggerAndLog(label, expected, isCm6Enabled) {
|
||||
const onLoad = async (toolbox, panel) => {
|
||||
const dbg = await createContext(panel);
|
||||
await waitForThreadCount(dbg, expected.threadsCount);
|
||||
await waitForSource(dbg, expected.sourceURL);
|
||||
await selectSource(dbg, expected.file);
|
||||
await waitForText(dbg, expected.text);
|
||||
await waitForText(dbg, expected.text, isCm6Enabled);
|
||||
await waitForSymbols(dbg);
|
||||
};
|
||||
|
||||
@ -305,7 +315,7 @@ async function openDebuggerAndLog(label, expected) {
|
||||
}
|
||||
exports.openDebuggerAndLog = openDebuggerAndLog;
|
||||
|
||||
async function reloadDebuggerAndLog(label, toolbox, expected) {
|
||||
async function reloadDebuggerAndLog(label, toolbox, expected, isCm6Enabled) {
|
||||
const onReload = async () => {
|
||||
const panel = await toolbox.getPanelWhenReady("jsdebugger");
|
||||
const dbg = await createContext(panel);
|
||||
@ -318,7 +328,7 @@ async function reloadDebuggerAndLog(label, toolbox, expected) {
|
||||
|
||||
await waitForSources(dbg, expected.sources);
|
||||
await waitForSource(dbg, expected.sourceURL);
|
||||
await waitForText(dbg, expected.text);
|
||||
await waitForText(dbg, expected.text, isCm6Enabled);
|
||||
await waitForSymbols(dbg);
|
||||
};
|
||||
await reloadPageAndLog(`${label}.jsdebugger`, toolbox, onReload);
|
||||
@ -392,11 +402,12 @@ async function step(dbg, stepType) {
|
||||
}
|
||||
exports.step = step;
|
||||
|
||||
async function hoverOnToken(dbg, textToWaitFor, textToHover) {
|
||||
await waitForText(dbg, textToWaitFor);
|
||||
const tokenElement = [
|
||||
...dbg.win.document.querySelectorAll(".CodeMirror span"),
|
||||
].find(el => el.textContent === textToHover);
|
||||
async function hoverOnToken(dbg, textToWaitFor, textToHover, isCm6Enabled) {
|
||||
await waitForText(dbg, textToWaitFor, isCm6Enabled);
|
||||
const selector = isCm6Enabled ? ".cm-editor span" : ".CodeMirror span";
|
||||
const tokenElement = [...dbg.win.document.querySelectorAll(selector)].find(
|
||||
el => el.textContent === textToHover
|
||||
);
|
||||
|
||||
const mouseOverEvent = new dbg.win.MouseEvent("mouseover", {
|
||||
bubbles: true,
|
||||
|
Loading…
Reference in New Issue
Block a user