1// Here's how waitForNotification works:
2//
3// - myTestFunction0()
4// - waitForNotification(myTestFunction1)
5// - requestAnimationFrame()
6// - Modify DOM in a way that should trigger an IntersectionObserver callback.
7// - BeginFrame
8// - requestAnimationFrame handler runs
9// - First step_timeout()
10// - Style, layout, paint
11// - IntersectionObserver generates new notifications
12// - Posts a task to deliver notifications
13// - First step_timeout handler runs
14// - Second step_timeout()
15// - Task to deliver IntersectionObserver notifications runs
16// - IntersectionObserver callbacks run
17// - Second step_timeout handler runs
18// - myTestFunction1()
19// - [optional] waitForNotification(myTestFunction2)
20// - requestAnimationFrame()
21// - Verify newly-arrived IntersectionObserver notifications
22// - [optional] Modify DOM to trigger new notifications
23function waitForNotification(t, f) {
24 requestAnimationFrame(function() {
25 t.step_timeout(function() { t.step_timeout(f); });
26 });
27}
28
29// The timing of when runTestCycle is called is important. It should be
30// called:
31//
32// - Before or during the window load event, or
33// - Inside of a prior runTestCycle callback, *before* any assert_* methods
34// are called.
35//
36// Following these rules will ensure that the test suite will not abort before
37// all test steps have run.
38function runTestCycle(f, description) {
39 async_test(function(t) {
40 waitForNotification(t, t.step_func_done(f));
41 }, description);
42}
43
44// Root bounds for a root with an overflow clip as defined by:
45// http://wicg.github.io/IntersectionObserver/#intersectionobserver-root-intersection-rectangle
46function contentBounds(root) {
47 var left = root.offsetLeft + root.clientLeft;
48 var right = left + root.clientWidth;
49 var top = root.offsetTop + root.clientTop;
50 var bottom = top + root.clientHeight;
51 return [left, right, top, bottom];
52}
53
54// Root bounds for a root without an overflow clip as defined by:
55// http://wicg.github.io/IntersectionObserver/#intersectionobserver-root-intersection-rectangle
56function borderBoxBounds(root) {
57 var left = root.offsetLeft;
58 var right = left + root.offsetWidth;
59 var top = root.offsetTop;
60 var bottom = top + root.offsetHeight;
61 return [left, right, top, bottom];
62}
63
64function clientBounds(element) {
65 var rect = element.getBoundingClientRect();
66 return [rect.left, rect.right, rect.top, rect.bottom];
67}
68
69function rectArea(rect) {
70 return (rect.left - rect.right) * (rect.bottom - rect.top);
71}
72
73function checkRect(actual, expected, description, all) {
74 if (!expected.length)
75 return;
76 assert_equals(actual.left | 0, expected[0] | 0, description + '.left');
77 assert_equals(actual.right | 0, expected[1] | 0, description + '.right');
78 assert_equals(actual.top | 0, expected[2] | 0, description + '.top');
79 assert_equals(actual.bottom | 0, expected[3] | 0, description + '.bottom');
80}
81
82function checkLastEntry(entries, i, expected) {
83 assert_equals(entries.length, i + 1, 'entries.length');
84 if (expected) {
85 checkRect(
86 entries[i].boundingClientRect, expected.slice(0, 4),
87 'entries[' + i + '].boundingClientRect', entries[i]);
88 checkRect(
89 entries[i].intersectionRect, expected.slice(4, 8),
90 'entries[' + i + '].intersectionRect', entries[i]);
91 checkRect(
92 entries[i].rootBounds, expected.slice(8, 12),
93 'entries[' + i + '].rootBounds', entries[i]);
94 if (expected.length > 12) {
95 assert_equals(
96 entries[i].isIntersecting, expected[12],
97 'entries[' + i + '].isIntersecting');
98 }
99 }
100}
101
102function checkJsonEntry(actual, expected) {
103 checkRect(
104 actual.boundingClientRect, expected.boundingClientRect,
105 'entry.boundingClientRect');
106 checkRect(
107 actual.intersectionRect, expected.intersectionRect,
108 'entry.intersectionRect');
109 if (actual.rootBounds == 'null')
110 assert_equals(expected.rootBounds, 'null', 'rootBounds is null');
111 else
112 checkRect(actual.rootBounds, expected.rootBounds, 'entry.rootBounds');
113 assert_equals(actual.target, expected.target);
114}
115
116function checkJsonEntries(actual, expected, description) {
117 test(function() {
118 assert_equals(actual.length, expected.length);
119 for (var i = 0; i < actual.length; i++)
120 checkJsonEntry(actual[i], expected[i]);
121 }, description);
122}
123
124function checkIsIntersecting(entries, i, expected) {
125 assert_equals(entries[i].isIntersecting, expected,
126 'entries[' + i + '].target.isIntersecting equals ' + expected);
127}