browser_dbg-xhr-breakpoints.js (6951B)
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 "use strict"; 6 7 const { asyncStore } = require("devtools/client/debugger/src/utils/prefs"); 8 9 add_task(async function () { 10 info("Test XHR requests done very early during page load"); 11 12 const dbg = await initDebugger("doc-xhr.html", "fetch.js"); 13 14 await addXHRBreakpoint(dbg, "doc", "GET"); 15 16 await SpecialPowers.spawn( 17 gBrowser.selectedBrowser, 18 [`${EXAMPLE_REMOTE_URL}doc-early-xhr.html`], 19 remoteUrl => { 20 const firstIframe = content.document.createElement("iframe"); 21 content.document.body.append(firstIframe); 22 firstIframe.src = remoteUrl; 23 } 24 ); 25 26 await waitForPaused(dbg); 27 await assertPausedAtSourceAndLine( 28 dbg, 29 findSource(dbg, "doc-early-xhr.html").id, 30 10 31 ); 32 33 const whyPaused = await waitFor( 34 () => dbg.win.document.querySelector(".why-paused")?.innerText 35 ); 36 is( 37 whyPaused, 38 `Paused on XMLHttpRequest\n(global) - doc-early-xhr.html:10:11` 39 ); 40 41 await resume(dbg); 42 43 await dbg.actions.removeXHRBreakpoint(0); 44 45 await SpecialPowers.spawn( 46 gBrowser.selectedBrowser, 47 [`${EXAMPLE_REMOTE_URL}doc-early-xhr.html`], 48 remoteUrl => { 49 const secondIframe = content.document.createElement("iframe"); 50 content.document.body.append(secondIframe); 51 secondIframe.src = remoteUrl; 52 } 53 ); 54 55 // Wait for some time, in order to wait for it to be paused 56 // in case we regress 57 await wait(1000); 58 59 assertNotPaused(dbg); 60 }); 61 62 add_task(async function () { 63 info("Test simple XHR breakpoints set before doing the request"); 64 65 const dbg = await initDebugger("doc-xhr.html", "fetch.js"); 66 67 await addXHRBreakpoint(dbg, "doc", "GET"); 68 69 invokeInTab("main", "doc-xhr.html"); 70 await waitForPaused(dbg); 71 await assertPausedAtSourceAndLine(dbg, findSource(dbg, "fetch.js").id, 4); 72 await resume(dbg); 73 74 await dbg.actions.removeXHRBreakpoint(0); 75 await invokeInTab("main", "doc-xhr.html"); 76 assertNotPaused(dbg); 77 78 info("Test that we do not pause on different method type"); 79 await addXHRBreakpoint(dbg, "doc", "POST"); 80 await invokeInTab("main", "doc-xhr.html"); 81 assertNotPaused(dbg); 82 }); 83 84 // Tests the "pause on any URL" checkbox works properly 85 add_task(async function () { 86 info("Test 'pause on any URL'"); 87 const dbg = await initDebugger("doc-xhr.html", "fetch.js"); 88 89 // Enable pause on any URL 90 await clickPauseOnAny(dbg, "SET_XHR_BREAKPOINT"); 91 92 invokeInTab("main", "doc-xhr.html"); 93 await waitForPaused(dbg); 94 await resume(dbg); 95 await assertDebuggerTabHighlight(dbg); 96 97 invokeInTab("main", "fetch.js"); 98 await waitForPaused(dbg); 99 await resume(dbg); 100 await assertDebuggerTabHighlight(dbg); 101 102 invokeInTab("main", "README.md"); 103 await waitForPaused(dbg); 104 await resume(dbg); 105 await assertDebuggerTabHighlight(dbg); 106 107 // Disable pause on any URL 108 await clickPauseOnAny(dbg, "DISABLE_XHR_BREAKPOINT"); 109 invokeInTab("main", "README.md"); 110 assertNotPaused(dbg); 111 112 // Turn off the checkbox 113 await dbg.actions.removeXHRBreakpoint(0); 114 }); 115 116 // Tests removal works properly 117 add_task(async function () { 118 info("Assert the frontend state when removing breakpoints"); 119 const dbg = await initDebugger("doc-xhr.html"); 120 121 const pauseOnAnyCheckbox = getXHRBreakpointCheckbox(dbg); 122 123 await clickPauseOnAny(dbg, "SET_XHR_BREAKPOINT"); 124 await addXHRBreakpoint(dbg, "1"); 125 await addXHRBreakpoint(dbg, "2"); 126 await addXHRBreakpoint(dbg, "3"); 127 await addXHRBreakpoint(dbg, "4"); 128 129 // Remove "2" 130 await removeXHRBreakpoint(dbg, 1); 131 132 const listItems = getXHRBreakpointsElements(dbg); 133 is(listItems.length, 3, "3 XHR breakpoints display in list"); 134 is(pauseOnAnyCheckbox.checked, true, "The pause on any is still checked"); 135 is( 136 getXHRBreakpointLabels(listItems).join(""), 137 "134", 138 "Only the desired breakpoint was removed" 139 ); 140 }); 141 142 add_task(async function () { 143 info("Assert that remove all the breakpoints work well"); 144 const dbg = await initDebugger("doc-xhr.html"); 145 146 await addXHRBreakpoint(dbg, "1"); 147 await addXHRBreakpoint(dbg, "2"); 148 await addXHRBreakpoint(dbg, "3"); 149 await addXHRBreakpoint(dbg, "4"); 150 151 is( 152 getXHRBreakpointsElements(dbg).length, 153 4, 154 "There a 4 items on the XHR breakpoints display list" 155 ); 156 157 let persistedXHRBreakpoints = await asyncStore.xhrBreakpoints; 158 is( 159 persistedXHRBreakpoints.length, 160 4, 161 "Check that the persisted XHR breakpoints have 4 items" 162 ); 163 164 await dbg.actions.removeAllXHRBreakpoints(); 165 166 is( 167 getXHRBreakpointsElements(dbg).length, 168 0, 169 "XHR breakpoints display list is empty" 170 ); 171 172 persistedXHRBreakpoints = await asyncStore.xhrBreakpoints; 173 is( 174 persistedXHRBreakpoints.length, 175 0, 176 "Check that there are no persisted XHR breakpoints" 177 ); 178 179 info("Trying adding a breakpoint with an empty path"); 180 const plusIcon = findElementWithSelector(dbg, ".xhr-breakpoints-pane .plus"); 181 if (plusIcon) { 182 plusIcon.click(); 183 } 184 findElementWithSelector(dbg, ".xhr-input-url").value = ""; 185 findElementWithSelector(dbg, ".xhr-input-method").value = "get"; 186 187 pressKey(dbg, "Enter"); 188 persistedXHRBreakpoints = await asyncStore.xhrBreakpoints; 189 is( 190 persistedXHRBreakpoints.length, 191 0, 192 "No breakpoint should be added when the path is empty" 193 ); 194 }); 195 196 async function addXHRBreakpoint(dbg, text, method) { 197 info(`Adding a XHR breakpoint for pattern ${text} and method ${method}`); 198 199 const plusIcon = findElementWithSelector(dbg, ".xhr-breakpoints-pane .plus"); 200 if (plusIcon) { 201 plusIcon.click(); 202 } 203 findElementWithSelector(dbg, ".xhr-input-url").focus(); 204 type(dbg, text); 205 206 if (method) { 207 findElementWithSelector(dbg, ".xhr-input-method").value = method; 208 } 209 210 pressKey(dbg, "Enter"); 211 212 await waitForDispatch(dbg.store, "SET_XHR_BREAKPOINT"); 213 } 214 215 async function removeXHRBreakpoint(dbg, index) { 216 info("Removing a XHR breakpoint"); 217 218 const closeButtons = dbg.win.document.querySelectorAll( 219 ".xhr-breakpoints-pane .close-btn" 220 ); 221 if (closeButtons[index]) { 222 closeButtons[index].click(); 223 } 224 225 await waitForDispatch(dbg.store, "REMOVE_XHR_BREAKPOINT"); 226 } 227 228 function getXHRBreakpointsElements(dbg) { 229 return [ 230 ...dbg.win.document.querySelectorAll( 231 ".xhr-breakpoints-pane .xhr-container" 232 ), 233 ]; 234 } 235 236 function getXHRBreakpointLabels(elements) { 237 return elements.map(element => element.title); 238 } 239 240 function getXHRBreakpointCheckbox(dbg) { 241 return findElementWithSelector( 242 dbg, 243 ".xhr-breakpoints-pane .breakpoints-exceptions input" 244 ); 245 } 246 247 async function clickPauseOnAny(dbg, expectedEvent) { 248 getXHRBreakpointCheckbox(dbg).click(); 249 await waitForDispatch(dbg.store, expectedEvent); 250 } 251 252 async function assertDebuggerTabHighlight(dbg) { 253 await waitUntil(() => !dbg.toolbox.isHighlighted("jsdebugger")); 254 ok(true, "Debugger is no longer highlighted after resume"); 255 }