summaryrefslogtreecommitdiffstats
path: root/layout/style/test/test_flexbox_reflow_counts.html
blob: f00983b317737e4c45b67e419e788f46bf609868 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1142686
-->
<head>
  <meta charset="utf-8">
  <title>Test for Bug 1142686</title>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
  <style>
    .flex {
      display: flex;
    }
    #outerFlex {
      border: 1px solid black;
    }
  </style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1142686">Mozilla Bug 1142686</a>
<div id="display">
  <div id="content">
    <div class="flex" id="outerFlex">
      <div class="flex" id="midFlex">
        <div id="innerBlock">
        </div>
      </div>
    </div>
  </div>
</div>
<pre id="test">
<script type="application/javascript;version=1.7">
"use strict";

/** Test for Bug 1142686 **/

/**
 * This test checks how many reflows are required, when we make a change inside
 * a set of two nested flex containers, with various styles applied to
 * the containers & innermost child.  Some flex layout operations require two
 * passes (which can cause exponential blowup). This test is intended to verify
 * that certain configurations do *not* require two-pass layout, by comparing
 * the reflow-count for a more-complex scenario against a less-complex scenario.
 *
 * We have two nested flex containers around an initially-empty block. For each
 * measurement, we put some text in the block, and we see how many frame-reflow
 * operations occur as a result.
 */

const gUtils = SpecialPowers.getDOMWindowUtils(window);

// The elements:
const gOuterFlex = document.getElementById("outerFlex");
const gMidFlex = document.getElementById("midFlex");
const gInnerBlock = document.getElementById("innerBlock");

// Remove contents of inner block, and remove manual styling:
function cleanup()
{
  outerFlex.style = midFlex.style = innerBlock.style = "";
  while (innerBlock.firstChild) {
    innerBlock.removeChild(innerBlock.firstChild);
  }
}

// Each testcase here has a label (used in test output), a function to set up
// the testcase, and (optionally) a function to set up the reference case.
let gTestcases = [
 {
    label : "border on flex items",
    addTestStyle : function() {
      midFlex.style.border = innerBlock.style.border = "3px solid black";
    },
 },
 {
    label : "padding on flex items",
    addTestStyle : function() {
      midFlex.style.padding = innerBlock.style.padding = "5px";
    },
 },
 {
    label : "margin on flex items",
    addTestStyle : function() {
      midFlex.style.margin = innerBlock.style.margin = "2px";
    },
 },
];

// Flush layout & return the global frame-reflow-count
function getReflowCount()
{
  let unusedVal = gOuterFlex.offsetHeight; // flush layout
  return gUtils.framesReflowed;
}

// This function adds some text inside of gInnerBlock, and returns the number
// of frames that need to be reflowed as a result.
function makeTweakAndCountReflows()
{
  let beforeCount = getReflowCount();
  gInnerBlock.appendChild(document.createTextNode("hello"));
  let afterCount = getReflowCount();

  let numReflows = afterCount - beforeCount;
  if (numReflows <= 0) {
    ok(false, "something's wrong -- we should've reflowed *something*");
  }
  return numReflows;
}

// Given a testcase (from gTestcases), this function verifies that the
// testcase scenario requires the same number of reflows as the reference
// scenario.
function runOneTest(aTestcase)
{
  aTestcase.addTestStyle();
  let numTestcaseReflows = makeTweakAndCountReflows();
  cleanup();

  if (aTestcase.addReferenceStyle) {
    aTestcase.addReferenceStyle();
  }
  let numReferenceReflows = makeTweakAndCountReflows();
  cleanup();

  is(numTestcaseReflows, numReferenceReflows,
     "Testcase & reference case should require same number of reflows" +
     " (testcase label: '" + aTestcase.label + "')");
}

gTestcases.forEach(runOneTest);

</script>
</pre>
</body>
</html>