var callbacks = [];
function callDelayed(fn) {
callbacks.push(fn);
}
requestAnimationFrame(function tick() { vari = 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: function (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: function (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 (vari = 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 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: function () { var callbacks = []; var fn = function () {
fn.callCount++;
fn.lastCall = { args: arguments };
if (callbacks.length) {
callbacks.shift()();
}
};
fn.callCount = 0;
fn.lastCall = { args: [] };
fn.waitForNotification = (fn) => {
callbacks.push(fn);
};
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;
afterEach(function() {
if (io && 'disconnect' in io) io.disconnect();
io = null;
window.onmessage = null;
removeStyles();
removeFixtures();
});
describe('constructor', function() {
it('move iframe and check reflow', function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
// Do a first change and wait for its intersection observer
// notification, to ensure one full reflow was completed.
function(done) {
targetEl1.style.top = '0px';
io.observe(targetEl1);
spy.waitForNotification(function() { var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(1);
expect(records[0].target).to.be(targetEl1);
done();
});
},
// Do another change, which may trigger an incremental reflow only.
function(done) {
targetEl4.style.top = '-20px';
targetEl4.style.left = '20px';
io.observe(targetEl4);
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(targetEl4);
// After the iframe is moved, reflow should include its parent,
// even if the iframe is a reflow root.
// If moved correctly (outside of rootEl), the intersection ratio
// should now be 0.
expect(records[0].intersectionRatio).to.be(0);
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);
/**
* 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';
/**
* 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();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.