browser_inspector_highlighter-cssshape_06-scale.js (6988B)
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 // Test that shapes are updated correctly on mouse events in transform mode. 8 9 const TEST_URL = URL_ROOT + "doc_inspector_highlighter_cssshapes.html"; 10 const { TYPES } = ChromeUtils.importESModule( 11 "resource://devtools/shared/highlighters.mjs" 12 ); 13 const HIGHLIGHTER_TYPE = TYPES.SHAPES; 14 const SHAPE_SELECTORS = ["#polygon-transform", "#circle", "#ellipse", "#inset"]; 15 16 add_task(async function () { 17 const env = await openInspectorForURL(TEST_URL); 18 const helper = await getHighlighterHelperFor(HIGHLIGHTER_TYPE)(env); 19 const { highlighterTestFront, inspector } = env; 20 const view = selectRuleView(inspector); 21 const highlighters = view.highlighters; 22 const config = { 23 inspector, 24 view, 25 highlighters, 26 highlighterTestFront, 27 helper, 28 }; 29 30 await testScale(config); 31 }); 32 33 async function setup(config) { 34 const { inspector, view, selector, property, options } = config; 35 await selectNode(selector, inspector); 36 await toggleShapesHighlighter(view, selector, property, true, options); 37 } 38 39 async function teardown(config) { 40 const { view, selector, property } = config; 41 info(`Turn off shapes highlighter for ${selector}`); 42 await toggleShapesHighlighter(view, selector, property, false); 43 } 44 45 async function testScale(config) { 46 const { helper, highlighters } = config; 47 const options = { transformMode: true }; 48 const property = "clip-path"; 49 50 for (const selector of SHAPE_SELECTORS) { 51 await setup({ selector, property, options, ...config }); 52 const { mouse } = helper; 53 54 const { nw, width, height, center } = await getBoundingBoxInPx({ 55 selector, 56 ...config, 57 }); 58 59 // if the top or left edges are not visible, move the shape so it is. 60 if (nw[0] < 0 || nw[1] < 0) { 61 const [x, y] = center; 62 const dx = Math.max(0, -nw[0]); 63 const dy = Math.max(0, -nw[1]); 64 await mouse.down(x, y, selector); 65 await mouse.move(x + dx, y + dy, selector); 66 await mouse.up(x + dx, y + dy, selector); 67 await reflowContentPage(); 68 nw[0] += dx; 69 nw[1] += dy; 70 } 71 const dx = width / 10; 72 const dy = height / 10; 73 let onShapeChangeApplied; 74 75 info("Scaling from nw"); 76 onShapeChangeApplied = highlighters.once( 77 "shapes-highlighter-changes-applied" 78 ); 79 await mouse.down(nw[0], nw[1], selector); 80 await mouse.move(nw[0] + dx, nw[1] + dy, selector); 81 await mouse.up(nw[0] + dx, nw[1] + dy, selector); 82 await reflowContentPage(); 83 await onShapeChangeApplied; 84 85 const nwBB = await getBoundingBoxInPx({ selector, ...config }); 86 isnot(nwBB.nw[0], nw[0], `${selector} nw moved right after nw scale`); 87 isnot(nwBB.nw[1], nw[1], `${selector} nw moved down after nw scale`); 88 isnot(nwBB.width, width, `${selector} width reduced after nw scale`); 89 isnot(nwBB.height, height, `${selector} height reduced after nw scale`); 90 91 info("Scaling from ne"); 92 onShapeChangeApplied = highlighters.once( 93 "shapes-highlighter-changes-applied" 94 ); 95 await mouse.down(nwBB.ne[0], nwBB.ne[1], selector); 96 await mouse.move(nwBB.ne[0] - dx, nwBB.ne[1] + dy, selector); 97 await mouse.up(nwBB.ne[0] - dx, nwBB.ne[1] + dy, selector); 98 await reflowContentPage(); 99 await onShapeChangeApplied; 100 101 const neBB = await getBoundingBoxInPx({ selector, ...config }); 102 isnot(neBB.ne[0], nwBB.ne[0], `${selector} ne moved right after ne scale`); 103 isnot(neBB.ne[1], nwBB.ne[1], `${selector} ne moved down after ne scale`); 104 isnot(neBB.width, nwBB.width, `${selector} width reduced after ne scale`); 105 isnot( 106 neBB.height, 107 nwBB.height, 108 `${selector} height reduced after ne scale` 109 ); 110 111 info("Scaling from sw"); 112 onShapeChangeApplied = highlighters.once( 113 "shapes-highlighter-changes-applied" 114 ); 115 await mouse.down(neBB.sw[0], neBB.sw[1], selector); 116 await mouse.move(neBB.sw[0] + dx, neBB.sw[1] - dy, selector); 117 await mouse.up(neBB.sw[0] + dx, neBB.sw[1] - dy, selector); 118 await reflowContentPage(); 119 await onShapeChangeApplied; 120 121 const swBB = await getBoundingBoxInPx({ selector, ...config }); 122 isnot(swBB.sw[0], neBB.sw[0], `${selector} sw moved right after sw scale`); 123 isnot(swBB.sw[1], neBB.sw[1], `${selector} sw moved down after sw scale`); 124 isnot(swBB.width, neBB.width, `${selector} width reduced after sw scale`); 125 isnot( 126 swBB.height, 127 neBB.height, 128 `${selector} height reduced after sw scale` 129 ); 130 131 info("Scaling from se"); 132 onShapeChangeApplied = highlighters.once( 133 "shapes-highlighter-changes-applied" 134 ); 135 await mouse.down(swBB.se[0], swBB.se[1], selector); 136 await mouse.move(swBB.se[0] - dx, swBB.se[1] - dy, selector); 137 await mouse.up(swBB.se[0] - dx, swBB.se[1] - dy, selector); 138 await reflowContentPage(); 139 await onShapeChangeApplied; 140 141 const seBB = await getBoundingBoxInPx({ selector, ...config }); 142 isnot(seBB.se[0], swBB.se[0], `${selector} se moved right after se scale`); 143 isnot(seBB.se[1], swBB.se[1], `${selector} se moved down after se scale`); 144 isnot(seBB.width, swBB.width, `${selector} width reduced after se scale`); 145 isnot( 146 seBB.height, 147 swBB.height, 148 `${selector} height reduced after se scale` 149 ); 150 151 await teardown({ selector, property, ...config }); 152 } 153 } 154 155 async function getBoundingBoxInPx(config) { 156 const { highlighterTestFront, selector, inspector } = config; 157 const quads = await getAllAdjustedQuadsForContentPageElement(selector); 158 const { width, height } = quads.content[0].bounds; 159 const highlightedNode = await getNodeFront(selector, inspector); 160 const highlighterFront = 161 inspector.inspectorFront.getKnownHighlighter(HIGHLIGHTER_TYPE); 162 const computedStyle = 163 await highlightedNode.inspectorFront.pageStyle.getComputed(highlightedNode); 164 const paddingTop = parseFloat(computedStyle["padding-top"].value); 165 const paddingLeft = parseFloat(computedStyle["padding-left"].value); 166 // path is always of form "Mx y Lx y Lx y Lx y Z", where x/y are numbers 167 const path = await highlighterTestFront.getHighlighterNodeAttribute( 168 "shapes-bounding-box", 169 "d", 170 highlighterFront 171 ); 172 const coords = path 173 .replace(/[MLZ]/g, "") 174 .split(" ") 175 .map((n, i) => { 176 return i % 2 === 0 177 ? paddingLeft + (width * n) / 100 178 : paddingTop + (height * n) / 100; 179 }); 180 181 const nw = [coords[0], coords[1]]; 182 const ne = [coords[2], coords[3]]; 183 const se = [coords[4], coords[5]]; 184 const sw = [coords[6], coords[7]]; 185 const center = [(nw[0] + se[0]) / 2, (nw[1] + se[1]) / 2]; 186 const shapeWidth = Math.sqrt((ne[0] - nw[0]) ** 2 + (ne[1] - nw[1]) ** 2); 187 const shapeHeight = Math.sqrt((sw[0] - nw[0]) ** 2 + (sw[1] - nw[1]) ** 2); 188 189 return { nw, ne, se, sw, center, width: shapeWidth, height: shapeHeight }; 190 }