browser_markup_dom_mutation_breakpoints.js (8338B)
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 Services.scriptloader.loadSubScript( 8 "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/shared-head.js", 9 this 10 ); 11 12 function toggleMutationBreakpoint(inspector) { 13 const allMenuItems = openContextMenuAndGetAllItems(inspector); 14 const attributeMenuItem = allMenuItems.find( 15 ({ id }) => id === "node-menu-mutation-breakpoint-attribute" 16 ); 17 attributeMenuItem.click(); 18 } 19 20 function getToolboxStoreMutationBreakpointsChanged(inspector) { 21 const toolboxStore = inspector.toolbox.store; 22 23 const breakpoints = getToolboxStoreDomMutationBreakpointsCount(toolboxStore); 24 return new Promise(resolve => { 25 const _unsubscribeFromToolboxStore = inspector.toolbox.store.subscribe( 26 () => { 27 if ( 28 getToolboxStoreDomMutationBreakpointsCount(toolboxStore) !== 29 breakpoints 30 ) { 31 resolve(); 32 _unsubscribeFromToolboxStore(); 33 } 34 } 35 ); 36 }); 37 } 38 39 function getToolboxStoreDomMutationBreakpointsCount(toolboxStore) { 40 return toolboxStore.getState().domMutationBreakpoints.breakpoints.length; 41 } 42 43 // Test inspector markup view handling DOM mutation breakpoints icons 44 // The icon should display when a breakpoint exists for a given node 45 add_task(async function () { 46 const { inspector } = await openInspectorForURL( 47 "data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>" 48 ); 49 50 await selectNode("span", inspector); 51 toggleMutationBreakpoint(inspector); 52 53 const span = await getContainerForSelector("span", inspector); 54 const mutationMarker = span.tagLine.querySelector( 55 ".markup-tag-mutation-marker" 56 ); 57 58 ok( 59 mutationMarker.classList.contains("has-mutations"), 60 "has-mutations class is present" 61 ); 62 63 toggleMutationBreakpoint(inspector); 64 await waitFor(() => !mutationMarker.classList.contains("has-mutations")); 65 66 ok(true, "has-mutations class is not present"); 67 }); 68 69 // Test that the inspector markup view dom mutation breakpoint icon behaves 70 // correctly when disabled 71 add_task(async function () { 72 await pushPref("devtools.debugger.dom-mutation-breakpoints-visible", true); 73 const { inspector, toolbox } = await openInspectorForURL( 74 "data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>" 75 ); 76 77 await selectNode("span", inspector); 78 toggleMutationBreakpoint(inspector); 79 80 const span = await getContainerForSelector("span", inspector); 81 const mutationMarker = span.tagLine.querySelector( 82 ".markup-tag-mutation-marker" 83 ); 84 85 ok( 86 mutationMarker.classList.contains("has-mutations"), 87 "has-mutations class is present" 88 ); 89 is( 90 mutationMarker.classList.contains("mutation-breakpoint-disabled"), 91 false, 92 "mutation-breakpoint-disabled class is not present" 93 ); 94 95 info("Switch over to the debugger pane"); 96 await toolbox.selectTool("jsdebugger"); 97 98 const dbg = createDebuggerContext(toolbox); 99 100 const mutationItem = await waitForElement(dbg, "domMutationItem"); 101 mutationItem.scrollIntoView(); 102 103 info("Disable the DOM mutation breakpoint"); 104 const checkbox = mutationItem.querySelector("input"); 105 checkbox.click(); 106 await waitFor(() => !checkbox.checked); 107 108 await waitFor( 109 () => 110 mutationMarker.classList.contains("has-mutations") && 111 mutationMarker.classList.contains("mutation-breakpoint-disabled") 112 ); 113 114 ok( 115 true, 116 "has-mutations and mutation-breakpoint-disabled classes are both present" 117 ); 118 119 info("Re-enable the DOM mutation breakpoint"); 120 checkbox.click(); 121 await waitFor(() => checkbox.checked); 122 123 await waitFor( 124 () => 125 mutationMarker.classList.contains("has-mutations") && 126 !mutationMarker.classList.contains("mutation-breakpoint-disabled") 127 ); 128 129 ok( 130 true, 131 "has-mutation class is present, mutation-breakpoint-disabled is not present" 132 ); 133 134 // Test re-enabling disabled dom mutation breakpoint from inspector 135 info("Disable the DOM mutation breakpoint"); 136 checkbox.click(); 137 await waitFor(() => !checkbox.checked); 138 139 await waitFor( 140 () => 141 mutationMarker.classList.contains("has-mutations") && 142 mutationMarker.classList.contains("mutation-breakpoint-disabled") 143 ); 144 145 ok( 146 true, 147 "has-mutations and mutation-breakpoint-disabled classes are both present" 148 ); 149 150 info("Switch over to the inspector pane"); 151 await toolbox.selectTool("inspector"); 152 153 toggleMutationBreakpoint(inspector); 154 await waitFor( 155 () => 156 mutationMarker.classList.contains("has-mutations") && 157 !mutationMarker.classList.contains("mutation-breakpoint-disabled") 158 ); 159 160 ok( 161 true, 162 "has-mutation class is present, mutation-breakpoint-disabled is not present" 163 ); 164 }); 165 166 // Test icon behavior with multiple breakpoints on the same node. 167 add_task(async function () { 168 await pushPref("devtools.debugger.dom-mutation-breakpoints-visible", true); 169 const { inspector, toolbox } = await openInspectorForURL( 170 "data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>" 171 ); 172 173 await selectNode("span", inspector); 174 const span = await getContainerForSelector("span", inspector); 175 const mutationMarker = span.tagLine.querySelector( 176 ".markup-tag-mutation-marker" 177 ); 178 179 info("Add 2 DOM mutation breakpoints"); 180 const allMenuItems = openContextMenuAndGetAllItems(inspector); 181 182 const attributeMenuItem = allMenuItems.find( 183 item => item.id === "node-menu-mutation-breakpoint-attribute" 184 ); 185 attributeMenuItem.click(); 186 187 const subtreeMenuItem = allMenuItems.find( 188 item => item.id === "node-menu-mutation-breakpoint-subtree" 189 ); 190 subtreeMenuItem.click(); 191 192 info("Switch over to the debugger pane"); 193 await toolbox.selectTool("jsdebugger"); 194 195 const dbg = createDebuggerContext(toolbox); 196 197 info("Confirm that DOM mutation breakpoints exists"); 198 await waitForAllElements(dbg, "domMutationItem", 2, true); 199 200 const mutationItem = await waitForElement(dbg, "domMutationItem"); 201 202 mutationItem.scrollIntoView(); 203 204 info("Disable 1 dom mutation breakpoint"); 205 const checkbox = mutationItem.querySelector("input"); 206 checkbox.click(); 207 await waitFor(() => !checkbox.checked); 208 209 await waitFor( 210 () => 211 mutationMarker.classList.contains("has-mutations") && 212 !mutationMarker.classList.contains("mutation-breakpoint-disabled") 213 ); 214 215 ok( 216 true, 217 "has-mutation class is present, mutation-breakpoint-disabled is not present" 218 ); 219 }); 220 221 // Test inspector markup view handling DOM mutation breakpoints after reload 222 add_task(async function () { 223 const { inspector } = await openInspectorForURL( 224 "data:text/html;charset=utf-8,<h1>foo</h1>" 225 ); 226 227 await selectNode("h1", inspector); 228 229 info("Add a mutation breakpoint on the h1"); 230 toggleMutationBreakpoint(inspector); 231 232 let h1 = await getContainerForSelector("h1", inspector); 233 let mutationMarker = h1.tagLine.querySelector(".markup-tag-mutation-marker"); 234 ok( 235 mutationMarker.classList.contains("has-mutations"), 236 "has-mutations class is present" 237 ); 238 239 info("Reload the page"); 240 const onBreakpointsListChanged = 241 getToolboxStoreMutationBreakpointsChanged(inspector); 242 await reload(); 243 await onBreakpointsListChanged; 244 ok(true, "Reloading impacted the number of DOM breakpoints"); 245 246 h1 = await getContainerForSelector("h1", inspector); 247 mutationMarker = h1.tagLine.querySelector(".markup-tag-mutation-marker"); 248 ok( 249 !mutationMarker.classList.contains("has-mutations"), 250 "has-mutations class is not present after reload" 251 ); 252 253 info("Add a mutation breakpoint on the h1, after reload"); 254 toggleMutationBreakpoint(inspector); 255 await waitFor(() => mutationMarker.classList.contains("has-mutations")); 256 ok(true, "has-mutations class was successfuly added"); 257 258 info("Remove the mutation breakpoint on the h1"); 259 // We need to wait until the mutation breakpoint was set on the nodeFront, otherwise 260 // the inspector code won't call the "remove" codepath. (waiting for the toolbox 261 // store change is not enough) 262 await waitFor( 263 () => inspector.selection.nodeFront.mutationBreakpoints.attribute 264 ); 265 toggleMutationBreakpoint(inspector); 266 await waitFor(() => !mutationMarker.classList.contains("has-mutations")); 267 ok(true, "has-mutations class was removed"); 268 });