253 lines
7.3 KiB
HTML
253 lines
7.3 KiB
HTML
<!doctype html>
|
|
<title>ResizeObserver notification event loop tests</title>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="./resources/resizeTestHelper.js"></script>
|
|
<div id="log"></div>
|
|
<script>
|
|
'use strict';
|
|
|
|
// allow uncaught exception because ResizeObserver posts exceptions
|
|
// to window error handler when limit is exceeded.
|
|
// This codepath is tested in this file.
|
|
|
|
setup({allow_uncaught_exception: true});
|
|
|
|
function template() {
|
|
let helper = new ResizeTestHelper(
|
|
"test0: title",
|
|
[
|
|
{
|
|
setup: observer => {
|
|
},
|
|
notify: (entries, observer) => {
|
|
return true; // Delay next step
|
|
}
|
|
}
|
|
]);
|
|
return helper.start();
|
|
}
|
|
|
|
var onErrorCalled = false;
|
|
|
|
window.onerror = err => {
|
|
onErrorCalled = true;
|
|
}
|
|
|
|
function test0() {
|
|
let t1 = createAndAppendElement("div");
|
|
let t2 = createAndAppendElement("div", t1);
|
|
let t3 = createAndAppendElement("div", t2);
|
|
|
|
let divs = [t1, t2, t3];
|
|
let rAF = 0;
|
|
let helper = new ResizeTestHelper(
|
|
"test0: multiple notifications inside same event loop",
|
|
[
|
|
{
|
|
setup: observer => {
|
|
onErrorCalled = false;
|
|
observer.observe(t1);
|
|
observer.observe(t2);
|
|
observer.observe(t3);
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 3, "3 notifications");
|
|
}
|
|
},
|
|
{
|
|
setup: observer => {
|
|
helper.startCountingRaf();
|
|
divs.forEach( el => { el.style.width = "101px";});
|
|
},
|
|
notify: (entries, observer) => {
|
|
// t1 is not delivered
|
|
assert_equals(entries.length, 2, "2 notifications");
|
|
assert_equals(helper.rafCount, 0, "still in same loop");
|
|
}
|
|
},
|
|
{
|
|
setup: observer => {
|
|
divs.forEach( el => { el.style.width = "102px";});
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 1, "1 notifications");
|
|
assert_equals(helper.rafCount, 0, "same loop");
|
|
}
|
|
},
|
|
{ // t1 and t2 get notified
|
|
setup: observer => {
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 2, "2 notifications");
|
|
assert_equals(helper.rafCount, 1, "new loop");
|
|
assert_equals(onErrorCalled, true, "error was fired");
|
|
observer.disconnect();
|
|
}
|
|
}
|
|
]);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
// This test uses requestAnimationFrame() to check the count of event loop,
|
|
// but on some browsers, the FrameRequestCallback may be throttled (i.e.
|
|
// simply fired after some extra time) in cases where this test is running
|
|
// in an iframe that hasn't yet been painted (i.e. we're not visible).
|
|
// This may result in some intermittent failures if this test didn't get a
|
|
// first paint (and hence may not have started firing FrameRequestCallbacks)
|
|
// by the time the test starts expecting helper.rafCount to have changed.
|
|
//
|
|
// Therefore, we don't start the test logic until body.onload has fired.
|
|
// This increases the likelihood that this testcase will have gotten a
|
|
// chance to paint when we start invoking requestAnimationFrame, and that
|
|
// its rAF callbacks will fire when the test logic expects them to.
|
|
document.body.onload = () => resolve();
|
|
}).then(() => {
|
|
return helper.start(() => t1.remove());
|
|
});
|
|
}
|
|
|
|
function test1() {
|
|
let t1 = createAndAppendElement("div");
|
|
t1.style.width = '100px';
|
|
let t2 = createAndAppendElement("div", t1);
|
|
let t3 = createAndAppendElement("div", t2);
|
|
let shadow = t3.attachShadow({ mode: "open" });
|
|
let t4 = createAndAppendElement("div", shadow);
|
|
let t5 = createAndAppendElement("div", t4);
|
|
|
|
let resizers = [t1, t2, t3, t4, t5];
|
|
|
|
// Testing depths of shadow roots
|
|
// DOM: t1 <- t2 <- t3 <-shadow- t4 <- t5
|
|
let helper = new ResizeTestHelper(
|
|
"test1: depths of shadow roots",
|
|
[
|
|
{
|
|
setup: observer => {
|
|
onErrorCalled = false;
|
|
resizers.forEach( el => observer.observe(el) );
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 5, "all entries resized");
|
|
}
|
|
},
|
|
{
|
|
setup: observer => {
|
|
resizers.forEach( el => el.style.width = "111px" );
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 4, "depth limited");
|
|
}
|
|
},
|
|
{
|
|
setup: observer => {
|
|
resizers.forEach( el => el.style.width = "112px" );
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 3, "depth limited");
|
|
}
|
|
},
|
|
{
|
|
setup: observer => {
|
|
resizers.forEach( el => el.style.width = "113px" );
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 2, "depth limited");
|
|
}
|
|
},
|
|
{
|
|
setup: observer => {
|
|
resizers.forEach( el => el.style.width = "114px" );
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 1, "depth limited");
|
|
}
|
|
},
|
|
{
|
|
setup: observer => {
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 4, "limit notifications");
|
|
assert_equals(onErrorCalled, true, "breached limit");
|
|
observer.disconnect();
|
|
}
|
|
},
|
|
]);
|
|
return helper.start(() => t1.remove());
|
|
}
|
|
|
|
function test2() {
|
|
// <div id="container">
|
|
// <div id="a1" style="width:100px;height:100px">
|
|
// <div id="a2" style="width:100px;height:100px"></div>
|
|
// </div>
|
|
// <div id="b1" style="width:100px;height:100px">
|
|
// <div id="b2" style="width:100px;height:100px"></div>
|
|
// </div>
|
|
// </div>
|
|
let container = createAndAppendElement("div");
|
|
let a1 = createAndAppendElement("div", container);
|
|
let a2 = createAndAppendElement("div", a1);
|
|
let b1 = createAndAppendElement("div", container);
|
|
let b2 = createAndAppendElement("div", b1);
|
|
let targets = [a1, a2, b1, b2];
|
|
|
|
let helper = new ResizeTestHelper(
|
|
"test2: move target in dom while inside event loop",
|
|
[
|
|
{
|
|
setup: observer => {
|
|
for (let t of targets)
|
|
observer.observe(t);
|
|
},
|
|
notify: (entries, observer) => {
|
|
return true; // delay next observation
|
|
}
|
|
},
|
|
{ // resize them all
|
|
setup: observer => {
|
|
for (let t of targets)
|
|
t.style.width = "110px";
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, targets.length, "all targets observed");
|
|
}
|
|
},
|
|
{ // resize all, move dom upwards
|
|
setup: observer => {
|
|
for (let t of targets)
|
|
t.style.width = "130px";
|
|
container.appendChild(b2);
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 1, "b2 moved upwards");
|
|
assert_equals(entries[0].target, a2);
|
|
}
|
|
},
|
|
{ // resize all, move dom downwards
|
|
setup: observer => {
|
|
for (let t of targets)
|
|
t.style.width = "130px";
|
|
a2.appendChild(b2);
|
|
},
|
|
notify: (entries, observer) => {
|
|
assert_equals(entries.length, 1, "b2 moved downwards");
|
|
assert_equals(entries[0].target, b2);
|
|
}
|
|
},
|
|
]);
|
|
return helper.start(() => container.remove());
|
|
}
|
|
|
|
let guard;
|
|
test(_ => {
|
|
assert_own_property(window, "ResizeObserver");
|
|
guard = async_test('guard');
|
|
}, "ResizeObserver implemented")
|
|
|
|
test0()
|
|
.then(() => test1())
|
|
.then(() => test2())
|
|
.then(() => guard.done());
|
|
|
|
</script>
|