browser_dbg-editor-horizontal-scroll.js (8227B)
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 scrolls correctly when pausing on location that 6 // requires horizontal scrolling. 7 8 "use strict"; 9 10 add_task(async function testHorizontalScrolling() { 11 // Ensure having the default fixed height, as it can impact the number of displayed lines 12 await pushPref("devtools.toolbox.footer.height", 250); 13 14 // Also set a precise size for side panels, as it can impact the number of displayed columns 15 await pushPref("devtools.debugger.start-panel-size", 300); 16 await pushPref("devtools.debugger.end-panel-size", 300); 17 18 // Strengthen the test by ensuring we always use the same Firefox window size. 19 // Note that the inner size is the important one as that's the final space available for DevTools. 20 // The outer size will be different based on OS/Environment. 21 const expectedWidth = 1280; 22 const expectedHeight = 1040; 23 if ( 24 window.innerWidth != expectedWidth || 25 window.innerHeight != expectedHeight 26 ) { 27 info("Resize the top level window to match the expected size"); 28 const onResize = once(window, "resize"); 29 const deltaW = window.outerWidth - window.innerWidth; 30 const deltaH = window.outerHeight - window.innerHeight; 31 const originalWidth = window.outerWidth; 32 const originalHeight = window.outerHeight; 33 window.resizeTo(expectedWidth + deltaW, expectedHeight + deltaH); 34 await onResize; 35 registerCleanupFunction(() => { 36 window.resizeTo(originalWidth, originalHeight); 37 }); 38 } 39 is(window.innerWidth, expectedWidth); 40 41 const dbg = await initDebugger( 42 "doc-editor-scroll.html", 43 "scroll.js", 44 "long.js" 45 ); 46 47 await selectSource(dbg, "horizontal-scroll.js"); 48 const editor = getCMEditor(dbg); 49 50 const global = editor.codeMirror.contentDOM.ownerGlobal; 51 const font = new global.FontFace( 52 "Ahem", 53 "url(chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/examples/Ahem.ttf)" 54 ); 55 const loadedFont = await font.load(); 56 global.document.fonts.add(loadedFont); 57 58 is(global.devicePixelRatio, 1); 59 is(global.browsingContext.top.window.devicePixelRatio, 1); 60 global.browsingContext.top.overrideDPPX = 1; 61 is(global.browsingContext.fullZoom, 1); 62 is(global.browsingContext.textZoom, 1); 63 64 // /!\ Change the Codemirror font to use a fixed font across all OSes 65 // and always have the same number of characters displayed. 66 // Note that this devtools mono makes the "o" characters almost invisible. 67 editor.codeMirror.contentDOM.style.fontFamily = "Ahem"; 68 editor.codeMirror.contentDOM.style.fontSize = "10px"; 69 editor.codeMirror.contentDOM.style.lineHeight = "15px"; 70 editor.codeMirror.contentDOM.style.fontWeight = "normal"; 71 editor.codeMirror.contentDOM.style.fontStyle = "normal"; 72 editor.codeMirror.contentDOM.style.fontStretch = "normal"; 73 is(global.getComputedStyle(editor.codeMirror.contentDOM).fontFamily, "Ahem"); 74 75 await wait(1000); 76 77 is( 78 Math.round(editor.codeMirror.dom.getBoundingClientRect().width), 79 679, 80 "Sanity check to ensure we have a fixed editor width, so that we have the expected displayed columns" 81 ); 82 83 // All the following methods lookup for first/last visible position in the current viewport. 84 // Also note that the element at the returned position may only be partially visible. 85 function getFirstVisibleColumn() { 86 const { x, y } = editor.codeMirror.dom.getBoundingClientRect(); 87 const gutterWidth = 88 editor.codeMirror.dom.querySelector(".cm-gutters").clientWidth; 89 // This is hardcoded to match the second line, which is around 20px from the top. 90 // Also append the gutter width as it would pick hidden columns displayed behind it 91 const pos = editor.codeMirror.posAtCoords({ 92 x: x + gutterWidth + 2, 93 y: y + 20, 94 }); 95 // /!\ the column is 0-based while lines are 1-based 96 return pos - editor.codeMirror.state.doc.lineAt(pos).from; 97 } 98 function getLastVisibleColumn() { 99 const { x, y, width } = editor.codeMirror.dom.getBoundingClientRect(); 100 // This is hardcoded to match the second line, which is around 20px from the top 101 const pos = editor.codeMirror.posAtCoords({ x: x + width, y: y + 20 }); 102 // /!\ the column is 0-based while lines are 1-based 103 return pos - editor.codeMirror.state.doc.lineAt(pos).from; 104 } 105 106 info("Pause in middle of the screen, we should not scroll on pause"); 107 await addBreakpoint(dbg, "horizontal-scroll.js", 2, 25); 108 invokeInTab("horizontal"); 109 await waitForPaused(dbg); 110 111 const lastColumn = getLastVisibleColumn(); 112 is(lastColumn, 55); 113 ok( 114 isScrolledPositionVisible(dbg, 2, 1), 115 "The 2nd line, first column is visible" 116 ); 117 ok( 118 isScrolledPositionVisible(dbg, 2, lastColumn - 1), 119 "The 2nd line, column before the last is visible" 120 ); 121 ok( 122 !isScrolledPositionVisible(dbg, 2, lastColumn), 123 "The last column is hidden" 124 ); 125 126 info("Step to the last visible column, the editor shouldn't scroll"); 127 // There is one breakable position every two column. 128 // We can see the column breakpoint for the column after the last visible one. 129 // Setting a breakpoint on that column and pausing shouldn't cause to scroll the viewport. 130 await addBreakpoint(dbg, "horizontal-scroll.js", 2, lastColumn); 131 await resume(dbg); 132 await waitForPaused(dbg); 133 134 is(getLastVisibleColumn(), lastColumn, "We did not scroll horizontaly"); 135 ok( 136 isScrolledPositionVisible(dbg, 2, lastColumn - 1), 137 "The column before the last column is still visible" 138 ); 139 ok( 140 !isScrolledPositionVisible(dbg, 2, lastColumn), 141 "The last colunm is still hidden" 142 ); 143 144 info( 145 "Step to the next column, and the editor should scroll it into the center" 146 ); 147 148 info("Step into the next breakable column, the editor should now scroll"); 149 // Set a breakpoint on the first column that would cause a scroll 150 // (there is one breakable position every two column) 151 await addBreakpoint(dbg, "horizontal-scroll.js", 2, lastColumn + 2); 152 await resume(dbg); 153 await waitForPaused(dbg); 154 155 const lastColumn2 = getLastVisibleColumn(); 156 157 is(lastColumn2, 74); 158 ok( 159 isScrolledPositionVisible(dbg, 2, lastColumn2), 160 "The new last column is visible" 161 ); 162 ok( 163 !isScrolledPositionVisible(dbg, 2, lastColumn2 + 1), 164 "The column after the last is hidden" 165 ); 166 const firstColumn = getFirstVisibleColumn(); 167 is(firstColumn, 30); 168 ok( 169 !isScrolledPositionVisible(dbg, 2, firstColumn), 170 "The new first column is partially visible and considered hidden" 171 ); 172 ok( 173 isScrolledPositionVisible(dbg, 2, firstColumn + 1), 174 "The column after the first visible is visible" 175 ); 176 177 await resume(dbg); 178 }); 179 180 // Tests the limit of the no of column breakpoint markers in a minified source with a long line. 181 add_task(async function testColumnBreakpointsLimitAfterHorizontalScroll() { 182 // Keep the layout consistent 183 await pushPref("devtools.debugger.end-panel-size", 300); 184 185 const dbg = await initDebugger( 186 "doc-large-sources.html", 187 "codemirror-bundle.js" 188 ); 189 190 info("Select the minified bundle and add a breakpoint"); 191 await selectSource(dbg, "codemirror-bundle.js"); 192 await addBreakpoint(dbg, "codemirror-bundle.js", 1); 193 194 let columnBreakpointMarkers = await waitForAllElements( 195 dbg, 196 "columnBreakpoints" 197 ); 198 199 is( 200 columnBreakpointMarkers.length, 201 100, 202 "We have the expected limit of column breakpoint markers on the minified source" 203 ); 204 205 info("Scroll horizintally far to the right of the file"); 206 await scrollEditorIntoView(dbg, 0, 300000); 207 208 columnBreakpointMarkers = findAllElements(dbg, "columnBreakpoints"); 209 is( 210 columnBreakpointMarkers.length, 211 0, 212 "There are no column breakpoint marker as the source has horizontally scrolled the viewport over the limit" 213 ); 214 215 info("Scroll back to the start of the line"); 216 await scrollEditorIntoView(dbg, 0, 0); 217 218 columnBreakpointMarkers = await waitForAllElements(dbg, "columnBreakpoints"); 219 is( 220 columnBreakpointMarkers.length, 221 100, 222 "We still have the expected limit of column breakpoint markers on the minified source" 223 ); 224 });