1
0
Fork 0
firefox/devtools/client/debugger/test/mochitest/browser_dbg-editor-scroll.js
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

281 lines
9.3 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// Tests that the editor keeps proper scroll position per document
// while also moving to the correct location upon pause/breakpoint selection
"use strict";
// This test runs too slowly on linux debug. I'd like to figure out
// which is the slowest part of this and make it run faster, but to
// fix a frequent failure allow a longer timeout.
requestLongerTimeout(2);
/**
* Test some simple usecases where the editor should scroll to the paused location
* and remember the previously scrolled location when switching between two distinct sources.
*/
add_task(async function testScrollingOnPauseAndSourceSwitching() {
const dbg = await initDebugger(
"doc-editor-scroll.html",
"scroll.js",
"long.js"
);
// Set the initial breakpoint.
await selectSource(dbg, "scroll.js");
await addBreakpoint(dbg, "scroll.js", 26);
info("Open long file, scroll down to line below the fold");
await selectSource(dbg, "long.js");
// Make sure we have a real scroll event emitted.
// scrollEditorIntoView will bail out after 500ms but here we need to
// guarantee the scroll event was processed by CodeMirror, because this is
// when the viewport location gets saved.
const ensureScroll = waitForScrolling(dbg, { useTimeoutFallback: false });
await scrollEditorIntoView(dbg, 25, 0);
ok(isScrolledPositionVisible(dbg, 25), "Scroll position is visible");
info("Wait for the codemirror scroll event");
await ensureScroll;
info("Ensure vertical scroll is the same after switching documents");
let onScrolled = waitForScrolling(dbg);
await selectSource(dbg, "scroll.js");
// Wait for any codemirror editor scroll that can happen
await onScrolled;
ok(isScrolledPositionVisible(dbg, 1), "Scrolled to the top of the editor");
onScrolled = waitForScrolling(dbg);
await selectSource(dbg, "long.js");
await onScrolled;
ok(isScrolledPositionVisible(dbg, 25), "Scroll position is visible");
info("Trigger a pause, click on a frame, ensure the right line is selected");
onScrolled = waitForScrolling(dbg);
invokeInTab("line26");
await waitForPaused(dbg);
await onScrolled;
ok(
isScrolledPositionVisible(dbg, 26),
"Frame scrolled down to correct location"
);
info("Navigating while paused, goes to the correct location");
onScrolled = waitForScrolling(dbg);
await selectSource(dbg, "long.js");
await onScrolled;
ok(isScrolledPositionVisible(dbg, 25), "Scroll position is visible");
info("Open new source, ensure it's at 0 scroll");
onScrolled = waitForScrolling(dbg);
await selectSource(dbg, "frames.js");
await onScrolled;
ok(isScrolledPositionVisible(dbg, 1), "Scrolled to the top of the editor");
});
/**
* Some extensive test against Editor's isPositionVisible implementation.
*
* Assert precisely which lines are considered visible or hidden by this method,
* while ensuring that the editor scrolls to the pause location in some edgecases.
* For example, when the line is partially visible at the end of the viewport.
*/
add_task(async function testIsPositionVisible() {
// Ensure having the default fixed height, as it can impact the number of displayed lines
await pushPref("devtools.toolbox.footer.height", 250);
// Also set a precise size for side panels, as it can impact the number of displayed columns
await pushPref("devtools.debugger.start-panel-size", 300);
await pushPref("devtools.debugger.end-panel-size", 300);
// Strengthen the test by ensuring we always use the same Firefox window size.
// Note that the inner size is the important one as that's the final space available for DevTools.
// The outer size will be different based on OS/Environment.
const expectedWidth = 1280;
const expectedHeight = 1040;
if (
window.innerWidth != expectedWidth ||
window.innerHeight != expectedHeight
) {
info("Resize the top level window to match the expected size");
const onResize = once(window, "resize");
const deltaW = window.outerWidth - window.innerWidth;
const deltaH = window.outerHeight - window.innerHeight;
const originalWidth = window.outerWidth;
const originalHeight = window.outerHeight;
window.resizeTo(expectedWidth + deltaW, expectedHeight + deltaH);
await onResize;
registerCleanupFunction(() => {
window.resizeTo(originalWidth, originalHeight);
});
}
is(window.innerWidth, expectedWidth);
const dbg = await initDebugger(
"doc-editor-scroll.html",
"scroll.js",
"long.js"
);
await selectSource(dbg, "scroll.js");
const editor = getCMEditor(dbg);
// All the following methods lookup for first/last visible position in the current viewport.
// Also note that the element at the returned position may only be partially visible.
function getFirstVisibleLine() {
const { x, y } = editor.codeMirror.dom.getBoundingClientRect();
// Add a pixel as we may be on the edge of the previous line which is hidden
const pos = editor.codeMirror.posAtCoords({ x, y: y + 1 });
return editor.codeMirror.state.doc.lineAt(pos).number;
}
function getLastVisibleLine() {
const { x, y, height } = editor.codeMirror.dom.getBoundingClientRect();
const pos = editor.codeMirror.posAtCoords({ x, y: y + height });
return editor.codeMirror.state.doc.lineAt(pos).number;
}
const lastLine = getLastVisibleLine();
is(
lastLine,
11,
"The last line is the 11th. (it may change if you resize the default browser window height)"
);
ok(isScrolledPositionVisible(dbg, 1), "First line is visible");
ok(
isScrolledPositionVisible(dbg, lastLine - 1),
"The line before the last one is visible"
);
ok(
!isScrolledPositionVisible(dbg, lastLine),
"Last line is partially visible and considered hidden"
);
ok(
!isScrolledPositionVisible(dbg, lastLine + 1),
"The line after the last is hidden"
);
info(
"Set a breakpoint and pause on the last fully visible line, it should not scroll"
);
await addBreakpoint(dbg, "scroll.js", lastLine - 1);
invokeInTab("line" + (lastLine - 1));
await waitForPaused(dbg);
ok(
!isScrolledPositionVisible(dbg, lastLine),
"Last line, which is partially visible, is still hidden"
);
await resume(dbg);
info(
"Set a breakpoint on the last partially visible line, it should scroll that line in the middle of the viewport"
);
await addBreakpoint(dbg, "scroll.js", lastLine);
invokeInTab("line" + lastLine);
await waitForPaused(dbg);
const newLastLine = getLastVisibleLine();
is(newLastLine, 16, "The new last line is the 16th");
ok(
!isScrolledPositionVisible(dbg, newLastLine),
"The new Last line is still partially visible and considered hidden"
);
ok(
isScrolledPositionVisible(dbg, newLastLine - 1),
"The line before is reported as visible"
);
const firstLine = getFirstVisibleLine();
is(firstLine, 6);
ok(
isScrolledPositionVisible(dbg, firstLine),
"The new first line is visible"
);
ok(
!isScrolledPositionVisible(dbg, firstLine - 1),
"The line before the new first line is hidden"
);
await resume(dbg);
info(
"Set a breakpoint far from the current position, it should also scroll and display the paused line in the middle of the viewport"
);
await addBreakpoint(dbg, "scroll.js", 50);
invokeInTab("line50");
await waitForPaused(dbg);
const newLastLine2 = getLastVisibleLine();
is(newLastLine2, 55);
ok(
!isScrolledPositionVisible(dbg, newLastLine2),
"The new last line is partially visible and considered as hidden"
);
ok(
isScrolledPositionVisible(dbg, newLastLine2 - 1),
"The line before is visible"
);
const firstLine2 = getFirstVisibleLine();
is(firstLine2, 45);
ok(
isScrolledPositionVisible(dbg, firstLine2),
"The new first line is visible"
);
ok(
!isScrolledPositionVisible(dbg, firstLine2 - 1),
"The line before the new first line is hidden"
);
await resume(dbg);
});
add_task(async function testColumnBreakpointsLimitAfterVerticalScroll() {
// Keep the layout consistent
await pushPref("devtools.debugger.end-panel-size", 300);
await pushPref("devtools.debugger.ui.editor-wrapping", true);
const dbg = await initDebugger(
"doc-large-sources.html",
"codemirror-bundle.js"
);
info("Select the minified bundle and add a breakpoint");
await selectSource(dbg, "codemirror-bundle.js");
await addBreakpoint(dbg, "codemirror-bundle.js", 1);
let columnBreakpointMarkers = await waitForAllElements(
dbg,
"columnBreakpoints"
);
is(
columnBreakpointMarkers.length,
100,
"We have the expected limit of column breakpoint markers on the minified source"
);
info("Scroll to the bottom of the file");
await scrollEditorIntoView(dbg, 1);
columnBreakpointMarkers = findAllElements(dbg, "columnBreakpoints");
is(
columnBreakpointMarkers.length,
0,
"There are no column breakpoint markers as the source has vertically scrolled the viewport over the limit"
);
info("Scroll back to the top of the file");
await scrollEditorIntoView(dbg, 0);
columnBreakpointMarkers = await waitForAllElements(dbg, "columnBreakpoints");
is(
columnBreakpointMarkers.length,
100,
"We still have the expected limit of column breakpoint markers on the minified source"
);
});