tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_dbg-editor-scroll.js (9714B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
      4 
      5 // Tests that the editor keeps proper scroll position per document
      6 // while also moving to the correct location upon pause/breakpoint selection
      7 
      8 "use strict";
      9 
     10 // This test runs too slowly on linux debug. I'd like to figure out
     11 // which is the slowest part of this and make it run faster, but to
     12 // fix a frequent failure allow a longer timeout.
     13 requestLongerTimeout(2);
     14 
     15 /**
     16 * Test some simple usecases where the editor should scroll to the paused location
     17 * and remember the previously scrolled location when switching between two distinct sources.
     18 */
     19 add_task(async function testScrollingOnPauseAndSourceSwitching() {
     20  const dbg = await initDebugger(
     21    "doc-editor-scroll.html",
     22    "scroll.js",
     23    "long.js"
     24  );
     25 
     26  // Set the initial breakpoint.
     27  await selectSource(dbg, "scroll.js");
     28  await addBreakpoint(dbg, "scroll.js", 26);
     29 
     30  info("Open long file, scroll down to line below the fold");
     31  await selectSource(dbg, "long.js");
     32 
     33  // Make sure we have a real scroll event emitted.
     34  // scrollEditorIntoView will bail out after 500ms but here we need to
     35  // guarantee the scroll event was processed by CodeMirror, because this is
     36  // when the viewport location gets saved.
     37  const ensureScroll = waitForScrolling(dbg, { useTimeoutFallback: false });
     38 
     39  await scrollEditorIntoView(dbg, 25, 0);
     40  ok(isScrolledPositionVisible(dbg, 25), "Scroll position is visible");
     41 
     42  info("Wait for the codemirror scroll event");
     43  await ensureScroll;
     44 
     45  info("Ensure vertical scroll is the same after switching documents");
     46  let onScrolled = waitForScrolling(dbg);
     47  await selectSource(dbg, "scroll.js");
     48  // Wait for any codemirror editor scroll that can happen
     49  await onScrolled;
     50  ok(isScrolledPositionVisible(dbg, 1), "Scrolled to the top of the editor");
     51 
     52  onScrolled = waitForScrolling(dbg);
     53  await selectSource(dbg, "long.js");
     54  await onScrolled;
     55  ok(isScrolledPositionVisible(dbg, 25), "Scroll position is visible");
     56 
     57  info("Trigger a pause, click on a frame, ensure the right line is selected");
     58  onScrolled = waitForScrolling(dbg);
     59  invokeInTab("line26");
     60  await waitForPaused(dbg);
     61  await onScrolled;
     62 
     63  ok(
     64    isScrolledPositionVisible(dbg, 26),
     65    "Frame scrolled down to correct location"
     66  );
     67 
     68  info("Navigating while paused, goes to the correct location");
     69  onScrolled = waitForScrolling(dbg);
     70  await selectSource(dbg, "long.js");
     71  await onScrolled;
     72  ok(isScrolledPositionVisible(dbg, 25), "Scroll position is visible");
     73 
     74  info("Open new source, ensure it's at 0 scroll");
     75  onScrolled = waitForScrolling(dbg);
     76  await selectSource(dbg, "frames.js");
     77  await onScrolled;
     78  ok(isScrolledPositionVisible(dbg, 1), "Scrolled to the top of the editor");
     79 });
     80 
     81 /**
     82 * Some extensive test against Editor's isPositionVisible implementation.
     83 *
     84 * Assert precisely which lines are considered visible or hidden by this method,
     85 * while ensuring that the editor scrolls to the pause location in some edgecases.
     86 * For example, when the line is partially visible at the end of the viewport.
     87 */
     88 add_task(async function testIsPositionVisible() {
     89  // Ensure having the default fixed height, as it can impact the number of displayed lines
     90  await pushPref("devtools.toolbox.footer.height", 250);
     91 
     92  // Also set a precise size for side panels, as it can impact the number of displayed columns
     93  await pushPref("devtools.debugger.start-panel-size", 300);
     94  await pushPref("devtools.debugger.end-panel-size", 300);
     95 
     96  // Strengthen the test by ensuring we always use the same Firefox window size.
     97  // Note that the inner size is the important one as that's the final space available for DevTools.
     98  // The outer size will be different based on OS/Environment.
     99  const expectedWidth = 1280;
    100  const expectedHeight = 1040;
    101  if (
    102    window.innerWidth != expectedWidth ||
    103    window.innerHeight != expectedHeight
    104  ) {
    105    info("Resize the top level window to match the expected size");
    106    const onResize = once(window, "resize");
    107    const deltaW = window.outerWidth - window.innerWidth;
    108    const deltaH = window.outerHeight - window.innerHeight;
    109    const originalWidth = window.outerWidth;
    110    const originalHeight = window.outerHeight;
    111    window.resizeTo(expectedWidth + deltaW, expectedHeight + deltaH);
    112    await onResize;
    113    registerCleanupFunction(() => {
    114      window.resizeTo(originalWidth, originalHeight);
    115    });
    116  }
    117  is(window.innerWidth, expectedWidth);
    118 
    119  const dbg = await initDebugger(
    120    "doc-editor-scroll.html",
    121    "scroll.js",
    122    "long.js"
    123  );
    124 
    125  await selectSource(dbg, "scroll.js");
    126  const editor = getCMEditor(dbg);
    127 
    128  // All the following methods lookup for first/last visible position in the current viewport.
    129  // Also note that the element at the returned position may only be partially visible.
    130  function getFirstVisibleLine() {
    131    const { x, y } = editor.codeMirror.dom.getBoundingClientRect();
    132    // Add a pixel as we may be on the edge of the previous line which is hidden
    133    const pos = editor.codeMirror.posAtCoords({ x, y: y + 1 });
    134    return editor.codeMirror.state.doc.lineAt(pos).number;
    135  }
    136  function getLastVisibleLine() {
    137    const { x, y, height } = editor.codeMirror.dom.getBoundingClientRect();
    138    const pos = editor.codeMirror.posAtCoords({ x, y: y + height });
    139    return editor.codeMirror.state.doc.lineAt(pos).number;
    140  }
    141  const lastLine = getLastVisibleLine();
    142 
    143  is(
    144    lastLine,
    145    11,
    146    "The last line is the 11th. (it may change if you resize the default browser window height)"
    147  );
    148  ok(isScrolledPositionVisible(dbg, 1), "First line is visible");
    149  ok(
    150    isScrolledPositionVisible(dbg, lastLine - 1),
    151    "The line before the last one is visible"
    152  );
    153  ok(
    154    !isScrolledPositionVisible(dbg, lastLine),
    155    "Last line is partially visible and considered hidden"
    156  );
    157  ok(
    158    !isScrolledPositionVisible(dbg, lastLine + 1),
    159    "The line after the last is hidden"
    160  );
    161 
    162  info(
    163    "Set a breakpoint and pause on the last fully visible line, it should not scroll"
    164  );
    165  await addBreakpoint(dbg, "scroll.js", lastLine - 1);
    166  invokeInTab("line" + (lastLine - 1));
    167  await waitForPaused(dbg);
    168 
    169  ok(
    170    !isScrolledPositionVisible(dbg, lastLine),
    171    "Last line, which is partially visible, is still hidden"
    172  );
    173 
    174  await resume(dbg);
    175 
    176  info(
    177    "Set a breakpoint on the last partially visible line, it should scroll that line in the middle of the viewport"
    178  );
    179  await addBreakpoint(dbg, "scroll.js", lastLine);
    180  invokeInTab("line" + lastLine);
    181  await waitForPaused(dbg);
    182 
    183  const newLastLine = getLastVisibleLine();
    184  is(newLastLine, 16, "The new last line is the 16th");
    185  ok(
    186    !isScrolledPositionVisible(dbg, newLastLine),
    187    "The new Last line is still partially visible and considered hidden"
    188  );
    189  ok(
    190    isScrolledPositionVisible(dbg, newLastLine - 1),
    191    "The line before is reported as visible"
    192  );
    193  const firstLine = getFirstVisibleLine();
    194  is(firstLine, 6);
    195  ok(
    196    isScrolledPositionVisible(dbg, firstLine + 1),
    197    "The next line of the new first line is visible"
    198  );
    199  ok(
    200    !isScrolledPositionVisible(dbg, firstLine - 1),
    201    "The line before the new first line is hidden"
    202  );
    203 
    204  await resume(dbg);
    205 
    206  info(
    207    "Set a breakpoint far from the current position, it should also scroll and display the paused line in the middle of the viewport"
    208  );
    209  await addBreakpoint(dbg, "scroll.js", 50);
    210  invokeInTab("line50");
    211  await waitForPaused(dbg);
    212 
    213  info("Wait for the paused line marker to be visible");
    214  await waitForElementWithSelector(dbg, ".cm-content .paused-line");
    215 
    216  const newLastLine2 = getLastVisibleLine();
    217  is(newLastLine2, 55);
    218  /*ok(
    219    !isScrolledPositionVisible(dbg, newLastLine2),
    220    "The new last line is partially visible and considered as hidden"
    221  );*/
    222  ok(
    223    isScrolledPositionVisible(dbg, newLastLine2 - 1),
    224    "The line before is visible"
    225  );
    226  const firstLine2 = getFirstVisibleLine();
    227  is(firstLine2, 45);
    228  ok(
    229    isScrolledPositionVisible(dbg, firstLine2 + 1),
    230    "The next line of the new first line is visible"
    231  );
    232  ok(
    233    !isScrolledPositionVisible(dbg, firstLine2 - 1),
    234    "The line before the new first line is hidden"
    235  );
    236 
    237  await resume(dbg);
    238 });
    239 
    240 add_task(async function testColumnBreakpointsLimitAfterVerticalScroll() {
    241  // Keep the layout consistent
    242  await pushPref("devtools.debugger.end-panel-size", 300);
    243  await pushPref("devtools.debugger.ui.editor-wrapping", true);
    244 
    245  const dbg = await initDebugger(
    246    "doc-large-sources.html",
    247    "codemirror-bundle.js"
    248  );
    249 
    250  info("Select the minified bundle and add a breakpoint");
    251  await selectSource(dbg, "codemirror-bundle.js");
    252  await addBreakpoint(dbg, "codemirror-bundle.js", 1);
    253 
    254  let columnBreakpointMarkers = await waitForAllElements(
    255    dbg,
    256    "columnBreakpoints"
    257  );
    258 
    259  is(
    260    columnBreakpointMarkers.length,
    261    100,
    262    "We have the expected limit of column breakpoint markers on the minified source"
    263  );
    264 
    265  info("Scroll to the bottom of the file");
    266  await scrollEditorIntoView(dbg, 1);
    267 
    268  columnBreakpointMarkers = findAllElements(dbg, "columnBreakpoints");
    269  is(
    270    columnBreakpointMarkers.length,
    271    0,
    272    "There are no column breakpoint markers as the source has vertically scrolled the viewport over the limit"
    273  );
    274 
    275  info("Scroll back to the top of the file");
    276  await scrollEditorIntoView(dbg, 0);
    277 
    278  columnBreakpointMarkers = await waitForAllElements(dbg, "columnBreakpoints");
    279  is(
    280    columnBreakpointMarkers.length,
    281    100,
    282    "We still have the expected limit of column breakpoint markers on the minified source"
    283  );
    284 });