products/Sources/formale Sprachen/C/Firefox/dom/base/test/test_intersectionobservers.html
<!
DOCTYPE HTML >
<
html >
<!--
https : / / bugzilla . mozilla . org / show_bug . cgi ? id = 1243846
Some tests ported from IntersectionObserver / polyfill / intersection - observer - test . html
Original license header :
Copyright 2016 Google Inc . All Rights Reserved .
Licensed under the Apache License , Version 2 . 0 ( the " License " ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : / / www . apache . org / licenses / LICENSE - 2 . 0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an " AS IS " BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
-->
<
head >
<
meta charset=
"utf-8" >
<
title >Test for Bug
1243846 </
title >
<
script src=
"/tests/SimpleTest/SimpleTest.js" ></
script >
<
link rel=
"stylesheet" type=
"text/css" href=
"/tests/SimpleTest/test.css" />
</
head >
<
body onload=
"onLoad()" >
<
a target=
"_blank" href=
"https://bugzilla.mozilla.org/show_bug.cgi?id=1243846 " >Mozil
la Bug 1243846 </a >
<p id="display" ></p >
<pre id="test" >
<script type="application/javascript" >
/* eslint "no-shadow" : ["error" , {"allow" : ["done" , "next" ]}] */
var tests = [];
var curDescribeMsg = '' ;
var curItMsg = '' ;
function beforeEach_fn() { };
function afterEach_fn() { };
function before(fn) {
fn();
}
function beforeEach(fn) {
beforeEach_fn = fn;
}
function afterEach(fn) {
afterEach_fn = fn;
}
function it(msg, fn) {
tests.push({
msg: `${msg} [${curDescribeMsg}]`,
fn
});
}
var callbacks = [];
function callDelayed(fn) {
callbacks.push(fn);
}
requestAnimationFrame(function tick() {
var i = callbacks.length;
while (i --) {
var cb = callbacks[i ];
SimpleTest.executeSoon(function() { SimpleTest.executeSoon(cb) });
callbacks.splice(i , 1 );
}
requestAnimationFrame(tick);
});
function expect(val) {
return {
to: {
throwException (regexp) {
try {
val();
ok(false, `${curItMsg} - an exception should have beeen thrown`);
} catch (e) {
ok(regexp.test(e), `${curItMsg} - supplied regexp should match thrown exception`);
}
},
get be() {
var fn = function (expected) {
is(val, expected, curItMsg);
};
fn.ok = function () {
ok(val, curItMsg);
};
fn.greaterThan = function (other) {
ok(val > other, `${curItMsg} - ${val} should be greater than ${other}`);
};
fn.lessThan = function (other) {
ok(val < other, `${curItMsg} - ${val} should be less than ${other}`);
};
return fn;
},
eql (expected) {
if (Array.isArray(expected)) {
if (!Array.isArray(val)) {
ok(false, curItMsg, `${curItMsg} - should be an array,`);
return;
}
is(val.length, expected.length, curItMsg, `${curItMsg} - arrays should be the same length`);
if (expected.length != val.length) {
return;
}
for (var i = 0 ; i < expected.length; i ++) {
is(val[i ], expected[i ], `${curItMsg} - array elements at position ${i } should be equal`);
if (expected[i ] != val[i ]) {
return;
}
}
ok(true);
}
},
}
}
}
function describe(msg, fn) {
curDescribeMsg = msg;
fn();
curDescribeMsg = '' ;
}
function next() {
var test = tests.shift();
if (test) {
console.log(test.msg);
curItMsg = test.msg;
var fn = test.fn;
beforeEach_fn();
if (fn.length) {
fn(function () {
afterEach_fn();
next();
});
} else {
fn();
afterEach_fn();
next();
}
} else {
SimpleTest.finish();
}
}
var sinon = {
spy () {
var cbs = [];
var fn = function () {
fn.callCount++;
fn.lastCall = { args: arguments };
if (cbs.length) {
cbs.shift()();
}
};
fn.callCount = 0 ;
fn.lastCall = { args: [] };
fn.waitForNotification = (fn1) => {
cbs.push(fn1);
};
return fn;
}
};
var ASYNC_TIMEOUT = 300 ;
var io;
var noop = function() {};
// References to DOM elements, which are accessible to any test
// and reset prior to each test so state isn't shared.
var rootEl;
var grandParentEl;
var parentEl;
var targetEl1;
var targetEl2;
var targetEl3;
var targetEl4;
var targetEl5;
describe('IntersectionObserver' , function() {
before(function() {
});
beforeEach(function() {
addStyles();
addFixtures();
});
afterEach(function() {
if (io && 'disconnect' in io) io.disconnect();
io = null;
window.onmessage = null;
removeStyles();
removeFixtures();
});
describe('constructor' , function() {
it('throws when callback is not a function' , function() {
expect(function() {
io = new IntersectionObserver(null);
}).to.throwException(/.*/i );
});
it('instantiates root correctly' , function() {
io = new IntersectionObserver(noop);
expect(io.root).to.be(null);
io = new IntersectionObserver(noop, {root: rootEl});
expect(io.root).to.be(rootEl);
});
it('throws when root is not an Element' , function() {
expect(function() {
io = new IntersectionObserver(noop, {root: 'foo' });
}).to.throwException(/.*/i );
});
it('instantiates rootMargin correctly' , function() {
io = new IntersectionObserver(noop, {rootMargin: '10px' });
expect(io.rootMargin).to.be('10px 10px 10px 10px' );
io = new IntersectionObserver(noop, {rootMargin: '10px -5%' });
expect(io.rootMargin).to.be('10px -5% 10px -5%' );
io = new IntersectionObserver(noop, {rootMargin: '10px 20% 0px' });
expect(io.rootMargin).to.be('10px 20% 0px 20%' );
io = new IntersectionObserver(noop, {rootMargin: '0px 0px -5% 5px' });
expect(io.rootMargin).to.be('0px 0px -5% 5px' );
});
it('throws when rootMargin is not in pixels or percent' , function() {
expect(function() {
io = new IntersectionObserver(noop, {rootMargin: 'auto' });
}).to.throwException(/pixels.*percent/i );
});
it('instantiates thresholds correctly' , function() {
io = new IntersectionObserver(noop);
expect(io.thresholds).to.eql([0 ]);
io = new IntersectionObserver(noop, {threshold: 0 .5 });
expect(io.thresholds).to.eql([0 .5 ]);
io = new IntersectionObserver(noop, {threshold: [0 .25 , 0 .5 , 0 .75 ]});
expect(io.thresholds).to.eql([0 .25 , 0 .5 , 0 .75 ]);
io = new IntersectionObserver(noop, {threshold: [1 , .5 , 0 ]});
expect(io.thresholds).to.eql([0 , .5 , 1 ]);
});
it('throws when a threshold value is not between 0 and 1' , function() {
expect(function() {
io = new IntersectionObserver(noop, {threshold: [0 , -1 ]});
}).to.throwException(/threshold/i );
});
it('throws when a threshold value is not a number' , function() {
expect(function() {
io = new IntersectionObserver(noop, {threshold: "foo" });
}).to.throwException(/.*/i );
});
});
describe('observe' , function() {
it('throws when target is not an Element' , function() {
expect(function() {
io = new IntersectionObserver(noop);
io.observe(null);
}).to.throwException(/.*/i );
});
it('triggers if target intersects when observing begins' , function(done) {
io = new IntersectionObserver(function(records) {
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
done();
}, {root: rootEl});
io.observe(targetEl1);
});
it('triggers with the correct arguments' , function(done) {
io = new IntersectionObserver(function(records, observer) {
expect(records.length).to.be(1 );
expect(records[0 ] instanceof IntersectionObserverEntry).to.be.ok();
expect(observer).to.be(io);
expect(this).to.be(io);
done();
}, {root: rootEl});
io.observe(targetEl1);
});
it('does trigger if target does not intersect when observing begins' ,
function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
targetEl2.style .top = '-40px' ;
io.observe(targetEl2);
callDelayed(function() {
expect(spy.callCount).to.be(1 );
done();
});
});
it('triggers if target or root becomes invisible' ,
function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
function(done) {
io.observe(targetEl1);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
done();
});
},
function(done) {
targetEl1.style .display = 'none' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(2 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(0 );
done();
});
},
function(done) {
targetEl1.style .display = 'block' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(3 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
done();
});
},
function(done) {
rootEl.style .display = 'none' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(4 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(0 );
done();
});
},
function(done) {
rootEl.style .display = 'block' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(5 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
done();
});
},
], done);
});
it('handles container elements with non-visible overflow' ,
function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
function(done) {
io.observe(targetEl1);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
done();
});
},
function(done) {
targetEl1.style .left = '-40px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(2 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(0 );
done();
});
},
function(done) {
parentEl.style .overflow = 'visible' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(3 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
done();
});
}
], done);
});
it('observes one target at a single threshold correctly' , function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl, threshold: 0 .5 });
runSequence([
function(done) {
targetEl1.style .left = '-5px' ;
io.observe(targetEl1);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be.greaterThan(0 .5 );
done();
});
},
function(done) {
targetEl1.style .left = '-15px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(2 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be.lessThan(0 .5 );
done();
});
},
function(done) {
targetEl1.style .left = '-25px' ;
callDelayed(function() {
expect(spy.callCount).to.be(2 );
done();
});
},
function(done) {
targetEl1.style .left = '-10px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(3 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(0 .5 );
done();
});
}
], done);
});
it('observes multiple targets at multiple thresholds correctly' ,
function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {
root: rootEl,
threshold: [1 , 0 .5 , 0 ]
});
runSequence([
function(done) {
targetEl1.style .top = '0px' ;
targetEl1.style .left = '-15px' ;
targetEl2.style .top = '-5px' ;
targetEl2.style .left = '0px' ;
targetEl3.style .top = '0px' ;
targetEl3.style .left = '205px' ;
io.observe(targetEl1);
io.observe(targetEl2);
io.observe(targetEl3);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(3 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(0 .25 );
expect(records[1 ].target).to.be(targetEl2);
expect(records[1 ].intersectionRatio).to.be(0 .75 );
done();
});
},
function(done) {
targetEl1.style .top = '0px' ;
targetEl1.style .left = '-5px' ;
targetEl2.style .top = '-15px' ;
targetEl2.style .left = '0px' ;
targetEl3.style .top = '0px' ;
targetEl3.style .left = '195px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(2 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(3 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(0 .75 );
expect(records[1 ].target).to.be(targetEl2);
expect(records[1 ].intersectionRatio).to.be(0 .25 );
expect(records[2 ].target).to.be(targetEl3);
expect(records[2 ].intersectionRatio).to.be(0 .25 );
done();
});
},
function(done) {
targetEl1.style .top = '0px' ;
targetEl1.style .left = '5px' ;
targetEl2.style .top = '-25px' ;
targetEl2.style .left = '0px' ;
targetEl3.style .top = '0px' ;
targetEl3.style .left = '185px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(3 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(3 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(1 );
expect(records[1 ].target).to.be(targetEl2);
expect(records[1 ].intersectionRatio).to.be(0 );
expect(records[2 ].target).to.be(targetEl3);
expect(records[2 ].intersectionRatio).to.be(0 .75 );
done();
});
},
function(done) {
targetEl1.style .top = '0px' ;
targetEl1.style .left = '15px' ;
targetEl2.style .top = '-35px' ;
targetEl2.style .left = '0px' ;
targetEl3.style .top = '0px' ;
targetEl3.style .left = '175px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(4 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].target).to.be(targetEl3);
expect(records[0 ].intersectionRatio).to.be(1 );
done();
});
}
], done);
});
it('handles rootMargin properly' , function(done) {
parentEl.style .overflow = 'visible' ;
targetEl1.style .top = '0px' ;
targetEl1.style .left = '-20px' ;
targetEl2.style .top = '-20px' ;
targetEl2.style .left = '0px' ;
targetEl3.style .top = '0px' ;
targetEl3.style .left = '200px' ;
targetEl4.style .top = '180px' ;
targetEl4.style .left = '180px' ;
runSequence([
function(done) {
io = new IntersectionObserver(function(records) {
records = sortRecords(records);
expect(records.length).to.be(4 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(1 );
expect(records[1 ].target).to.be(targetEl2);
expect(records[1 ].intersectionRatio).to.be(.5 );
expect(records[2 ].target).to.be(targetEl3);
expect(records[2 ].intersectionRatio).to.be(.5 );
expect(records[3 ].target).to.be(targetEl4);
expect(records[3 ].intersectionRatio).to.be(1 );
io.disconnect();
done();
}, {root: rootEl, rootMargin: '10px' });
io.observe(targetEl1);
io.observe(targetEl2);
io.observe(targetEl3);
io.observe(targetEl4);
},
function(done) {
io = new IntersectionObserver(function(records) {
records = sortRecords(records);
expect(records.length).to.be(4 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(0 .5 );
expect(records[2 ].target).to.be(targetEl3);
expect(records[2 ].intersectionRatio).to.be(0 .5 );
expect(records[3 ].target).to.be(targetEl4);
expect(records[3 ].intersectionRatio).to.be(0 .5 );
io.disconnect();
done();
}, {root: rootEl, rootMargin: '-10px 10%' });
io.observe(targetEl1);
io.observe(targetEl2);
io.observe(targetEl3);
io.observe(targetEl4);
},
function(done) {
io = new IntersectionObserver(function(records) {
records = sortRecords(records);
expect(records.length).to.be(4 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(0 .5 );
expect(records[3 ].target).to.be(targetEl4);
expect(records[3 ].intersectionRatio).to.be(0 .5 );
io.disconnect();
done();
}, {root: rootEl, rootMargin: '-5% -2.5% 0px' });
io.observe(targetEl1);
io.observe(targetEl2);
io.observe(targetEl3);
io.observe(targetEl4);
},
function(done) {
io = new IntersectionObserver(function(records) {
records = sortRecords(records);
expect(records.length).to.be(4 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(0 .5 );
expect(records[1 ].target).to.be(targetEl2);
expect(records[1 ].intersectionRatio).to.be(0 .5 );
expect(records[3 ].target).to.be(targetEl4);
expect(records[3 ].intersectionRatio).to.be(0 .25 );
io.disconnect();
done();
}, {root: rootEl, rootMargin: '5% -2.5% -10px -190px' });
io.observe(targetEl1);
io.observe(targetEl2);
io.observe(targetEl3);
io.observe(targetEl4);
}
], done);
});
it('handles targets on the boundary of root' , function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
function(done) {
targetEl1.style .top = '0px' ;
targetEl1.style .left = '-21px' ;
targetEl2.style .top = '-20px' ;
targetEl2.style .left = '0px' ;
io.observe(targetEl1);
io.observe(targetEl2);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(2 );
expect(records[1 ].intersectionRatio).to.be(0 );
expect(records[1 ].target).to.be(targetEl2);
done();
});
},
function(done) {
targetEl1.style .top = '0px' ;
targetEl1.style .left = '-20px' ;
targetEl2.style .top = '-21px' ;
targetEl2.style .left = '0px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(2 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(2 );
expect(records[0 ].intersectionRatio).to.be(0 );
expect(records[0 ].isIntersecting).to.be.ok();
expect(records[0 ].target).to.be(targetEl1);
expect(records[1 ].intersectionRatio).to.be(0 );
expect(records[1 ].target).to.be(targetEl2);
done();
});
},
function(done) {
targetEl1.style .top = '-20px' ;
targetEl1.style .left = '200px' ;
targetEl2.style .top = '200px' ;
targetEl2.style .left = '200px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(3 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(0 );
expect(records[0 ].target).to.be(targetEl2);
done();
});
},
function(done) {
targetEl3.style .top = '20px' ;
targetEl3.style .left = '-20px' ;
targetEl4.style .top = '-20px' ;
targetEl4.style .left = '20px' ;
io.observe(targetEl3);
io.observe(targetEl4);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(4 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(2 );
expect(records[0 ].intersectionRatio).to.be(0 );
expect(records[0 ].isIntersecting).to.be.ok();
expect(records[0 ].target).to.be(targetEl3);
expect(records[1 ].intersectionRatio).to.be(0 );
expect(records[1 ].target).to.be(targetEl4);
done();
});
}
], done);
});
it('handles zero-size targets within the root coordinate space' ,
function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
function(done) {
targetEl1.style .top = '0px' ;
targetEl1.style .left = '0px' ;
targetEl1.style .width = '0px' ;
targetEl1.style .height = '0px' ;
io.observe(targetEl1);
spy.waitForNotification(function() {
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
expect(records[0 ].isIntersecting).to.be.ok();
done();
});
},
function(done) {
targetEl1.style .top = '-1px' ;
spy.waitForNotification(function() {
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(0 );
expect(records[0 ].isIntersecting).to.be(false);
done();
});
}
], done);
});
it('handles root/target elements not yet in the DOM' , function(done) {
rootEl.remove();
targetEl1.remove();
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
function(done) {
io.observe(targetEl1);
callDelayed(done);
},
function(done) {
document.getElementById('fixtures' ).appendChild(rootEl);
callDelayed(function() {
expect(spy.callCount).to.be(1 );
done();
});
},
function(done) {
parentEl.insertBefore(targetEl1, targetEl2);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(2 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
expect(records[0 ].target).to.be(targetEl1);
done();
});
},
function(done) {
grandParentEl.remove();
spy.waitForNotification(function() {
expect(spy.callCount).to.be(3 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(0 );
expect(records[0 ].target).to.be(targetEl1);
done();
});
},
function(done) {
rootEl.appendChild(targetEl1);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(4 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
expect(records[0 ].target).to.be(targetEl1);
done();
});
},
function(done) {
rootEl.remove();
spy.waitForNotification(function() {
expect(spy.callCount).to.be(5 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(0 );
expect(records[0 ].target).to.be(targetEl1);
done();
});
}
], done);
});
it('handles sub-root element scrolling' , function(done) {
io = new IntersectionObserver(function(records) {
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
done();
}, {root: rootEl});
io.observe(targetEl3);
callDelayed(function() {
parentEl.scrollLeft = 40 ;
});
});
it('supports CSS transitions and transforms' , function(done) {
targetEl1.style .top = '220px' ;
targetEl1.style .left = '220px' ;
var callCount = 0 ;
io = new IntersectionObserver(function(records) {
callCount++;
if (callCount <= 1 ) {
return;
}
expect(records.length).to.be(1 );
expect(records[0 ].intersectionRatio).to.be(1 );
done();
}, {root: rootEl, threshold: [1 ]});
io.observe(targetEl1);
callDelayed(function() {
targetEl1.style .transform = 'translateX(-40px) translateY(-40px)' ;
});
});
it('uses the viewport when no root is specified' , function(done) {
window.onmessage = function (e) {
expect(e.data).to.be.ok();
win.close();
done();
};
var win = window.open("intersectionobserver_window.html" );
});
it('triggers only once if observed multiple times (and does not crash when collected)' , function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
io.observe(targetEl1);
io.observe(targetEl1);
io.observe(targetEl1);
spy.waitForNotification(function() {
callDelayed(function () {
expect(spy.callCount).to.be(1 );
done();
});
});
});
});
describe('observe subframe' , function () {
it('boundingClientRect matches target.getBoundingClientRect() for an element inside an iframe' ,
function(done) {
io = new IntersectionObserver(function(records) {
expect(records.length).to.be(1 );
expect(records[0 ].boundingClientRect.top, targetEl5.getBoundingClientRect().top);
expect(records[0 ].boundingClientRect.left, targetEl5.getBoundingClientRect().left);
expect(records[0 ].boundingClientRect.width, targetEl5.getBoundingClientRect().width);
expect(records[0 ].boundingClientRect.height, targetEl5.getBoundingClientRect().height);
done();
}, {threshold: [1 ]});
targetEl4.onload = function () {
targetEl5 = targetEl4.contentDocument.getElementById('target5' );
io.observe(targetEl5);
}
targetEl4.src = "intersectionobserver_iframe.html" ;
});
it('rootBounds is set to null for cross-origin observations' , function(done) {
window.onmessage = function (e) {
expect(e.data).to.be(true);
done();
};
targetEl4.src = "http://example.org/tests/dom/base/test/intersectionobserver_cross_domain_iframe.html " ;
});
});
describe('takeRecords' , function() {
it('supports getting records before the callback is invoked' , function(done) {
var lastestRecords = [];
io = new IntersectionObserver(function(records) {
lastestRecords = lastestRecords.concat(records);
}, {root: rootEl});
io.observe(targetEl1);
window.requestAnimationFrame && requestAnimationFrame(function wait() {
lastestRecords = lastestRecords.concat(io.takeRecords());
if (!lastestRecords.length) {
requestAnimationFrame(wait);
return;
}
callDelayed(function() {
expect(lastestRecords.length).to.be(1 );
expect(lastestRecords[0 ].intersectionRatio).to.be(1 );
done();
});
});
});
});
describe('unobserve' , function() {
it('removes targets from the internal store' , function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
function(done) {
targetEl1.style .top = targetEl2.style .top = '0px' ;
targetEl1.style .left = targetEl2.style .left = '0px' ;
io.observe(targetEl1);
io.observe(targetEl2);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(2 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(1 );
expect(records[1 ].target).to.be(targetEl2);
expect(records[1 ].intersectionRatio).to.be(1 );
done();
});
},
function(done) {
io.unobserve(targetEl1);
targetEl1.style .top = targetEl2.style .top = '0px' ;
targetEl1.style .left = targetEl2.style .left = '-40px' ;
spy.waitForNotification(function() {
expect(spy.callCount).to.be(2 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(1 );
expect(records[0 ].target).to.be(targetEl2);
expect(records[0 ].intersectionRatio).to.be(0 );
done();
});
},
function(done) {
io.unobserve(targetEl2);
targetEl1.style .top = targetEl2.style .top = '0px' ;
targetEl1.style .left = targetEl2.style .left = '0px' ;
callDelayed(function() {
expect(spy.callCount).to.be(2 );
done();
});
}
], done);
});
});
describe('disconnect' , function() {
it('removes all targets and stops listening for changes' , function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
function(done) {
targetEl1.style .top = targetEl2.style .top = '0px' ;
targetEl1.style .left = targetEl2.style .left = '0px' ;
io.observe(targetEl1);
io.observe(targetEl2);
spy.waitForNotification(function() {
expect(spy.callCount).to.be(1 );
var records = sortRecords(spy.lastCall.args[0 ]);
expect(records.length).to.be(2 );
expect(records[0 ].target).to.be(targetEl1);
expect(records[0 ].intersectionRatio).to.be(1 );
expect(records[1 ].target).to.be(targetEl2);
expect(records[1 ].intersectionRatio).to.be(1 );
done();
});
},
function(done) {
io.disconnect();
targetEl1.style .top = targetEl2.style .top = '0px' ;
targetEl1.style .left = targetEl2.style .left = '-40px' ;
callDelayed(function() {
expect(spy.callCount).to.be(1 );
done();
});
}
], done);
});
});
});
/**
* Runs a sequence of function and when finished invokes the done callback.
* Each function in the sequence is invoked with its own done function and
* it should call that function once it's complete.
*
* @param {Array<Function>} functions An array of async functions.
* @param {Function} done A final callback to be invoked once all function
* have run.
*/
function runSequence(functions, done) {
var next = functions.shift();
if (next) {
next(function() {
runSequence(functions, done);
});
} else {
done && done();
}
}
/**
* Sorts an array of records alphebetically by ascending ID. Since the current
* native implementation doesn't sort change entries by `observe` order, we do
* that ourselves for the non-polyfill case. Since all tests call observe
* on targets in sequential order, this should always match.
* https://crbug.com/ 613679
*
* @param {Array<IntersectionObserverEntry>} entries The entries to sort.
* @return {Array<IntersectionObserverEntry>} The sorted array.
*/
function sortRecords(entries) {
entries = entries.sort(function(a , b ) {
return a .target.id < b .target.id ? -1 : 1 ;
});
return entries;
}
/**
* Adds the common styles used by all tests to the page.
*/
function addStyles() {
var styles = document.createElement('style' );
styles.id = 'styles' ;
document.documentElement.appendChild(styles);
var cssText =
'#root {' +
' position: relative;' +
' width: 400px;' +
' height: 200px;' +
' background: #eee' +
'}' +
'#grand-parent {' +
' position: relative;' +
' width: 200px;' +
' height: 200px;' +
'}' +
'#parent {' +
' position: absolute;' +
' top: 0px;' +
' left: 200px;' +
' overflow: hidden;' +
' width: 200px;' +
' height: 200px;' +
' background: #ddd;' +
'}' +
'#target1, #target2, #target3, #target4 {' +
' position: absolute;' +
' top: 0px;' +
' left: 0px;' +
' width: 20px;' +
' height: 20px;' +
' transform: translateX(0px) translateY(0px);' +
' transition: transform .5s;' +
' background: #f00;' +
' border: none;' +
'}' ;
styles.innerHTML = cssText;
}
/**
* Adds the DOM fixtures used by all tests to the page and assigns them to
* global variables so they can be referenced within the tests.
*/
function addFixtures() {
var fixtures = document.createElement('div' );
fixtures.id = 'fixtures' ;
fixtures.innerHTML =
'<div id="root">' +
' <div id="grand-parent">' +
' <div id="parent">' +
' <div id="target1"></div>' +
' <div id="target2"></div>' +
' <div id="target3"></div>' +
' <iframe id="target4"></iframe>' +
' </div>' +
' </div>' +
'</div>' ;
document.body .appendChild(fixtures);
rootEl = document.getElementById('root' );
grandParentEl = document.getElementById('grand-parent' );
parentEl = document.getElementById('parent' );
targetEl1 = document.getElementById('target1' );
targetEl2 = document.getElementById('target2' );
targetEl3 = document.getElementById('target3' );
targetEl4 = document.getElementById('target4' );
}
/**
* Removes the common styles from the page.
*/
function removeStyles() {
var styles = document.getElementById('styles' );
styles.remove();
}
/**
* Removes the DOM fixtures from the page and resets the global references.
*/
function removeFixtures() {
var fixtures = document.getElementById('fixtures' );
fixtures.remove();
rootEl = null;
grandParentEl = null;
parentEl = null;
targetEl1 = null;
targetEl2 = null;
targetEl3 = null;
targetEl4 = null;
}
function onLoad() {
next();
}
SimpleTest.waitForExplicitFinish();
</script >
</pre >
<div id="log" >
</div >
</body >
</html >
Messung V0.5 in Prozent C=94 H=99 G=96
¤ Dauer der Verarbeitung: 0.19 Sekunden
¤
*© Formatika GbR, Deutschland