test_flexbox_layout.html (6161B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=666041 5 --> 6 <head> 7 <meta charset="utf-8"> 8 <title>Test for Bug 666041</title> 9 <script src="/tests/SimpleTest/SimpleTest.js"></script> 10 <script type="text/javascript" src="flexbox_layout_testcases.js"></script> 11 <script type="text/javascript" src="property_database.js"></script> 12 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 13 </head> 14 <body> 15 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666041">Mozilla Bug 666041</a> 16 <div id="display"> 17 <div id="content"> 18 </div> 19 </div> 20 <pre id="test"> 21 <script type="application/javascript"> 22 "use strict"; 23 24 /** Test for Bug 666041 */ 25 26 /* Flexbox Layout Tests 27 * -------------------- 28 * This mochitest exercises our implementation of the flexbox layout algorithm 29 * by creating a flex container, inserting some flexible children, and then 30 * verifying that the computed width of those children is what we expect. 31 * 32 * See flexbox_layout_testcases.js for the actual testcases & testcase format. 33 */ 34 35 function getComputedStyleWrapper(elem, prop) 36 { 37 return window.getComputedStyle(elem).getPropertyValue(prop); 38 } 39 40 function setPossiblyAliasedProperty(aElem, aPropertyName, aPropertyValue, 41 aPropertyMapping) 42 { 43 let actualPropertyName = (aPropertyName in aPropertyMapping ? 44 aPropertyMapping[aPropertyName] : aPropertyName); 45 46 if (!gCSSProperties[actualPropertyName]) { 47 ok(false, "Bug in test: property '" + actualPropertyName + 48 "' doesn't exist in gCSSProperties"); 49 } else { 50 let domPropertyName = gCSSProperties[actualPropertyName].domProp; 51 aElem.style[domPropertyName] = aPropertyValue; 52 } 53 } 54 55 // Helper function to strip "px" off the end of a string 56 // (so that we can compare two lengths using "isfuzzy()" with an epsilon) 57 function stripPx(aLengthInPx) 58 { 59 let pxOffset = aLengthInPx.length - 2; // subtract off length of "px" 60 61 // Sanity-check the arg: 62 ok(pxOffset > 0 && aLengthInPx.substr(pxOffset) == "px", 63 "expecting value with 'px' units"); 64 65 return aLengthInPx.substr(0, pxOffset); 66 } 67 68 // The main test function. 69 // aFlexboxTestcase is an entry from the list in flexbox_layout_testcases.js 70 function testFlexboxTestcase(aFlexboxTestcase, aFlexDirection, aPropertyMapping) 71 { 72 let content = document.getElementById("content"); 73 74 // Create flex container 75 let flexContainer = document.createElement("div"); 76 flexContainer.style.display = "flex"; 77 flexContainer.style.flexDirection = aFlexDirection; 78 setPossiblyAliasedProperty(flexContainer, "_main-size", 79 gDefaultFlexContainerSize, 80 aPropertyMapping); 81 82 // Apply testcase's customizations for flex container (if any). 83 if (aFlexboxTestcase.container_properties) { 84 for (let propName in aFlexboxTestcase.container_properties) { 85 let propValue = aFlexboxTestcase.container_properties[propName]; 86 setPossiblyAliasedProperty(flexContainer, propName, propValue, 87 aPropertyMapping); 88 } 89 } 90 91 // Create & append flex items 92 aFlexboxTestcase.items.forEach(function(aChildSpec) { 93 // Create an element for our item 94 let child = document.createElement("div"); 95 96 // Set all the specified properties on our item 97 for (let propName in aChildSpec) { 98 // aChildSpec[propName] is either a specified value, 99 // or an array of [specifiedValue, computedValue] 100 let specifiedValue = Array.isArray(aChildSpec[propName]) ? 101 aChildSpec[propName][0] : 102 aChildSpec[propName]; 103 104 // SANITY CHECK: 105 if (Array.isArray(aChildSpec[propName])) { 106 ok(aChildSpec[propName].length >= 2 && 107 aChildSpec[propName].length <= 3, 108 "unexpected number of elements in array within child spec"); 109 } 110 111 if (specifiedValue !== null) { 112 setPossiblyAliasedProperty(child, propName, specifiedValue, 113 aPropertyMapping); 114 } 115 } 116 117 // Append the item to the flex container 118 flexContainer.appendChild(child); 119 }); 120 121 // Append the flex container 122 content.appendChild(flexContainer); 123 124 // NOW: Test the computed style on the flex items 125 let child = flexContainer.firstChild; 126 for (let i = 0; i < aFlexboxTestcase.items.length; i++) { 127 if (!child) { // sanity 128 ok(false, "should have created a child for each child-spec"); 129 } 130 131 let childSpec = aFlexboxTestcase.items[i]; 132 for (let propName in childSpec) { 133 if (Array.isArray(childSpec[propName])) { 134 let expectedVal = childSpec[propName][1]; 135 let actualPropName = (propName in aPropertyMapping ? 136 aPropertyMapping[propName] : propName); 137 let actualVal = getComputedStyleWrapper(child, actualPropName); 138 let message = "computed value of '" + actualPropName + 139 "' should match expected"; 140 141 if (childSpec[propName].length > 2) { 142 // 3rd entry in array is epsilon 143 // Need to strip off "px" units in order to use epsilon: 144 let actualValNoPx = stripPx(actualVal); 145 let expectedValNoPx = stripPx(expectedVal); 146 isfuzzy(actualValNoPx, expectedValNoPx, 147 childSpec[propName][2], message); 148 } else { 149 is(actualVal, expectedVal, message); 150 } 151 } 152 } 153 154 child = child.nextSibling; 155 } 156 157 // Clean up: drop the flex container. 158 content.removeChild(flexContainer); 159 } 160 161 function main() 162 { 163 gFlexboxTestcases.forEach( 164 function(aTestcase) { 165 testFlexboxTestcase(aTestcase, "", 166 gRowPropertyMapping); 167 testFlexboxTestcase(aTestcase, "row", 168 gRowPropertyMapping); 169 testFlexboxTestcase(aTestcase, "row-reverse", 170 gRowReversePropertyMapping); 171 testFlexboxTestcase(aTestcase, "column", 172 gColumnPropertyMapping); 173 testFlexboxTestcase(aTestcase, "column-reverse", 174 gColumnReversePropertyMapping); 175 } 176 ); 177 } 178 179 main(); 180 181 </script> 182 </pre> 183 </body> 184 </html>