browser_inspector_highlighter-geometry_07.js (4438B)
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 the original position of a relative positioned node is correct 8 // even when zooming. 9 10 const TEST_URL = URL_ROOT + "doc_inspector_highlighter-geometry_01.html"; 11 const ID = "geometry-editor-"; 12 const { TYPES } = ChromeUtils.importESModule( 13 "resource://devtools/shared/highlighters.mjs" 14 ); 15 const HIGHLIGHTER_TYPE = TYPES.GEOMETRY; 16 17 const TESTS = { 18 ".absolute-all-4": { 19 desc: "Check absolute positioned element's parentOffset highlight", 20 sides: ["top", "right", "bottom", "left"], 21 }, 22 ".relative": { 23 desc: "Check relative positioned element original offset highlight", 24 sides: ["top", "left"], 25 }, 26 }; 27 28 add_task(async function () { 29 const inspector = await openInspectorForURL(TEST_URL); 30 const helper = await getHighlighterHelperFor(HIGHLIGHTER_TYPE)(inspector); 31 32 helper.prefix = ID; 33 34 const { finalize } = helper; 35 36 for (const selector in TESTS) { 37 await executeTest(inspector, helper, selector, TESTS[selector]); 38 } 39 40 await finalize(); 41 }); 42 43 async function executeTest(inspector, helper, selector, data) { 44 const { show, hide } = helper; 45 46 info("Showing the highlighter"); 47 await show(selector); 48 info(data.desc); 49 50 await checkOffsetParentSame(helper, selector, data.sides); 51 52 setContentPageZoomLevel(1.2); 53 await reflowContentPage(); 54 55 await checkOffsetParentSame(helper, selector, data.sides); 56 57 info("Hiding the highlighter and resetting zoom"); 58 setContentPageZoomLevel(1); 59 await hide(); 60 } 61 62 // Check that the offsetParent element does not move around, 63 // when the target element itself is being moved. 64 async function checkOffsetParentSame({ getElementAttribute }, selector, sides) { 65 const expectedOffsetParent = splitPointsIntoCoordinates( 66 await getElementAttribute("offset-parent", "points") 67 ); 68 const expectedArrowStartPos = await checkArrowStartingPos( 69 getElementAttribute, 70 expectedOffsetParent, 71 sides 72 ); 73 74 // Setting both to 0px would disable the offsetParent highlighter and not update points. 75 await setContentPageElementAttribute(selector, "style", "top:1px; left:1px;"); 76 await reflowContentPage(); 77 78 const actualOffsetParent = splitPointsIntoCoordinates( 79 await getElementAttribute("offset-parent", "points") 80 ); 81 const actualArrowStartPos = await checkArrowStartingPos( 82 getElementAttribute, 83 actualOffsetParent, 84 sides 85 ); 86 87 await removeContentPageElementAttribute(selector, "style"); 88 89 for (let i = 0; i < 4; i++) { 90 for (let j = 0; j < 2; j++) { 91 is( 92 actualOffsetParent[i][j], 93 expectedOffsetParent[i][j], 94 `Coordinate ${j + 1}/2 of point ${ 95 i + 1 96 }/4 is the same after repositioning.` 97 ); 98 } 99 } 100 101 for (let i = 0; i < expectedArrowStartPos.length; i++) { 102 is( 103 actualArrowStartPos[i], 104 expectedArrowStartPos[i], 105 `Start position of arrow-${sides[i]} is the same after repositioning.` 106 ); 107 } 108 } 109 110 // Check that the arrow starts at the boundary of the offsetParent. 111 // This also returns the start coordinate along the relevant axis. 112 async function checkArrowStartingPos( 113 getElementAttribute, 114 offsetParentPoints, 115 sides 116 ) { 117 // offsetParentPoints is a number[][]. 118 offsetParentPoints = offsetParentPoints.flat(); 119 const result = []; 120 121 for (const side of sides) { 122 // The only attribute that must not change is the start position of the arrow. 123 // Cross-axis and end position could change when the target element is moved. 124 const axis = side === "top" || side === "bottom" ? "y" : "x"; 125 // We have to round because floating point arithmetics are not consistent. 126 // (They are consistent enough, they just vary in their 10^(-5)) 127 const arrowPos = Math.round( 128 parseFloat(await getElementAttribute("arrow-" + side, axis + "1")) 129 ); 130 ok( 131 offsetParentPoints.includes(arrowPos), 132 `arrow-${side} starts at offset parent` 133 ); 134 result.push(arrowPos); 135 } 136 137 return result; 138 } 139 140 // Splits the value of the points attribute into coordinates. 141 function splitPointsIntoCoordinates(points) { 142 const result = []; 143 for (const coord of points.split(" ")) { 144 // We have to round (see above). 145 result.push(coord.split(",").map(s => Math.round(parseFloat(s)))); 146 } 147 148 return result; 149 }