summaryrefslogtreecommitdiffstats
path: root/layout/style/test/test_visited_reftests.html
blob: 0353d948fc5ee0794e91acfed4fce43a59ee3672 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=147777
-->
<head>
  <title>Test for Bug 147777</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=147777">Mozilla Bug 147777</a>
<pre id="test">
<script type="application/javascript">

/** Test for Bug 147777 **/

// Because link-coloring for visited links is asynchronous, running
// reftests that involve link coloring requires that we poll for the
// correct result until all links are styled correctly.

// A requirement of these reftests is that the reference rendering is
// styled correctly when loaded.  We only poll for the tests.

var gTests = [
  // there's also an implicit "load visited-page.html" at the start,
  // thanks to the code below.

  // IMPORTANT NOTE: For these tests, the test and reference are not
  // snapshotted in the same way.  The REFERENCE (second file) is
  // assumed to be complete when loaded, but we poll for visited link
  // coloring on the TEST (first file) until the test passes.
  "== pseudo-classes-02.svg pseudo-classes-02-ref.svg",
  "needs-focus == caret-color-on-visited-1.html caret-color-on-visited-1-ref.html",
  "!= color-on-link-1-ref.html color-on-visited-1-ref.html",
  "== color-on-link-1.html color-on-link-1-ref.html",
  "== color-on-link-before-1.html color-on-link-1-ref.html",
  "== color-on-visited-1.html color-on-visited-1-ref.html",
  "== color-on-visited-before-1.html color-on-visited-1-ref.html",
  "== color-on-visited-text-1.html color-on-visited-text-1-ref.html",
  "!= content-color-on-link-before-1-ref.html content-color-on-visited-before-1-ref.html",
  "== content-color-on-link-before-1.html content-color-on-link-before-1-ref.html",
  "== content-color-on-visited-before-1.html content-color-on-visited-before-1-ref.html",
  "== content-on-link-before-1.html content-before-1-ref.html",
  "== content-on-visited-before-1.html content-before-1-ref.html",
  "== color-on-text-decoration-1.html color-on-text-decoration-1-ref.html",
  "== color-on-bullets-1.html color-on-bullets-1-ref.html",
  // NOTE: background-color is tested by all the selector tests (and
  // also color-choice-1) and therefore doesn't have its own tests.
  // FIXME: Maybe add a test for selection colors (foreground and
  // background), if possible.
  "== width-on-link-1.html width-1-ref.html",
  "== width-on-visited-1.html width-1-ref.html",
  "== border-1.html border-1-ref.html",
  "== border-2a.html border-2-ref.html",
  "== border-2b.html border-2-ref.html",
  // FIXME: Commented out because of dynamic change handling bugs in
  // border-collapse tables that mean we get an incorrect rendering when
  // the asynchronous restyle-from-history arrives.
  //"== border-collapse-1.html border-collapse-1-ref.html",
  "== outline-1.html outline-1-ref.html",
  "== column-rule-1.html column-rule-1-ref.html",
  "!= column-rule-1.html column-rule-1-notref.html",
  "== color-choice-1.html color-choice-1-ref.html",
  "== selector-descendant-1.html selector-descendant-1-ref.html",
  "== selector-descendant-2.xhtml selector-descendant-2-ref.xhtml",
  "== selector-child-1.html selector-child-1-ref.html",
  "== selector-child-2.xhtml selector-child-2-ref.xhtml",
  "== selector-adj-sibling-1.html selector-adj-sibling-1-ref.html",
  "== selector-adj-sibling-2.html selector-adj-sibling-2-ref.html",
  "== selector-adj-sibling-3.xhtml selector-adj-sibling-3-ref.xhtml",
  "== selector-any-sibling-1.html selector-any-sibling-1-ref.html",
  "== selector-any-sibling-2.html selector-any-sibling-2-ref.html",
  "== subject-of-selector-descendant-1.html subject-of-selector-1-ref.html",
  "== subject-of-selector-descendant-2.xhtml subject-of-selector-descendant-2-ref.xhtml",
  "== subject-of-selector-child-1.html subject-of-selector-1-ref.html",
  "== subject-of-selector-adj-sibling-1.html subject-of-selector-1-ref.html",
  "== subject-of-selector-any-sibling-1.html subject-of-selector-1-ref.html",
  "== inherit-keyword-1.xhtml inherit-keyword-1-ref.html",
  "== svg-image-visited-1a.html svg-image-visited-1-ref.html",
  "== svg-image-visited-1b.html svg-image-visited-1-ref.html",
  "== svg-image-visited-1c.html svg-image-visited-1-ref.html",
  "== svg-image-visited-1d.html svg-image-visited-1-ref.html",
  // FIXME: commented out because dynamic changes on the non-first-line
  // part of the test don't work right when the link becomes visited.
  //"== first-line-1.html first-line-1-ref.html",
  "== white-to-transparent-1.html white-to-transparent-1-ref.html",
  "== link-root-1.xhtml link-root-1-ref.xhtml",
  "== mathml-links.html mathml-links-ref.html",
  "== placeholder-1.html placeholder-1-ref.html",
  "== visited-inherit-1.html visited-inherit-1-ref.html",
  "== transition-on-visited.html transition-on-visited-ref.html",
  "== logical-box-border-color-visited-link-001.html logical-box-border-color-visited-link-ref.html",
  "== logical-box-border-color-visited-link-002.html logical-box-border-color-visited-link-ref.html",
  "== logical-box-border-color-visited-link-003.html logical-box-border-color-visited-link-ref.html",
  "== svg-paint-currentcolor-visited.svg svg-paint-currentcolor-visited-ref.svg",
  "== variables-visited.html variables-visited-ref.html",
];

// We record the maximum number of times we had to look at a test before
// it switched to the passing state (though we assume it's 10 to start
// rather than 0 so that we have a reasonable default).  Then we make a
// test "time out" if it takes more than gTimeoutFactor times that
// amount of time.  This allows us to report a test failure rather than
// making a test failure just show up as a timeout.
var gMaxPassingTries = 10;
var gTimeoutFactor = 10;

function startIframe(url) {
  return new Promise(resolve => {
    var element = document.createElement("iframe");
    element.addEventListener("load", () => {
      element.contentDocument.fonts.ready.then(() => {
        resolve(element.contentWindow);
      });
    }, {once: true});
    // smaller than normal reftests, but enough for these
    element.setAttribute("style", "width: 30em; height: 10em");
    element.src = "css-visited/" + url;
    document.body.appendChild(element);
  });
}

async function runTests() {
  SimpleTest.waitForExplicitFinish();
  SimpleTest.requestFlakyTimeout("async link coloring");
  // Set caret to a known size, for tests of :visited caret-color styling
  await SpecialPowers.pushPrefEnv({'set': [['ui.caretWidth', 16]]});
  info("opening visited page");
  let win = window.open("css-visited/visited-page.html", "_blank");
  await new Promise(resolve => {
    win.onload = resolve;
  });
  info("running tests");
  await Promise.all(gTests.map(runTest));
  win.close();
  SimpleTest.finish();
}

function passes(equal, shot1, shot2)
{
  let [correct] = compareSnapshots(shot1, shot2, equal);
  return correct;
}

function waitFor100msAndIdle() {
  return new Promise(resolve => setTimeout(function() {
    requestIdleCallback(resolve);
  }, 100));
}

async function runTest(testLine) {
  let splitData = testLine.split(" ");
  let isEqual;
  let needsFocus = false;
  while (true) {
    let op = splitData.shift();
    if (op == "needs-focus") {
      needsFocus = true;
    } else if (op == "==" || op == "!=") {
      isEqual = op == "==";
      break;
    } else {
      ok(false, "Unknown syntax");
      return;
    }
  }
  let [testFile, refFile] = splitData;

  let promiseTestWin = startIframe(testFile);
  let promiseRefWin = startIframe(refFile);
  let refSnapshot = snapshotWindow(await promiseRefWin);
  let testWindow = await promiseTestWin;
  // Always wait at least 100ms, so that any test that switches
  // from passing to failing when the asynchronous link coloring
  // happens should fail at least some of the time.
  await waitFor100msAndIdle();

  let tries;
  let testSnapshot;
  for (tries = 0; tries < gMaxPassingTries * gTimeoutFactor; ++tries) {
    if (needsFocus) {
      await SimpleTest.promiseFocus(testWindow, false);
    }
    testSnapshot = snapshotWindow(testWindow, true);
    if (passes(isEqual, testSnapshot, refSnapshot)) {
      if (tries > gMaxPassingTries) {
        gMaxPassingTries = tries;
      }
      break;
    }
    // Links might not have been colored yet. Try again in 100ms.
    await waitFor100msAndIdle();
  }

  let result = assertSnapshots(testSnapshot, refSnapshot,
                               isEqual, null, testFile, refFile);
  if (!result) {
    info(`Gave up after ${tries} tries, ` +
         `maxp=${gMaxPassingTries}, fact=${gTimeoutFactor}`);
  }
}

runTests();

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