Source code

Revision control

Copy as Markdown

Other Tools

function imageLoadedPromise(image) {
return new Promise(function(resolve, reject) {
if (image.complete)
resolve();
image.addEventListener("load", resolve, { once: true });
});
}
function videoLoadedPromise(video) {
return new Promise(function(resolve, reject) {
if (video.readyState == 4)
resolve();
else {
video.addEventListener("loadeddata", resolve, { once: true });
video.addEventListener("error", reject, { once: true });
}
});
}
function waitForNFrames(count) {
if (count <= 0)
return Promise.reject(new TypeError("count should be greater than 0!"));
return new Promise(resolve => {
function tick() {
(--count) ? requestAnimationFrame(tick) : resolve();
}
requestAnimationFrame(tick);
});
}
function seekTo(video, time) {
return new Promise(function(resolve, reject) {
video.addEventListener("seeked", async function() {
/* Work around flakiness in video players... */
await waitForNFrames(3);
resolve();
}, { once: true });
video.currentTime = time;
});
}
function checkBoundingBox(actual, expected, fuzziness) {
assert_equals(actual.constructor.name, "DOMRectReadOnly");
assert_approx_equals(actual.left, expected.left, fuzziness);
assert_approx_equals(actual.right, expected.right, fuzziness);
assert_approx_equals(actual.top, expected.top, fuzziness);
assert_approx_equals(actual.bottom, expected.bottom, fuzziness);
}
function checkPointsLieWithinBoundingBox(points, boundingBox) {
for (point of points) {
assert_between_inclusive(point.x, boundingBox.left, boundingBox.right);
assert_between_inclusive(point.y, boundingBox.top, boundingBox.bottom);
}
}
function checkPointIsNear(actual, expected, fuzzinessX, fuzzinessY) {
assert_approx_equals(actual.x, expected.x, fuzzinessX);
assert_approx_equals(actual.y, expected.y, fuzzinessY);
}
function checkPointsAreNear(actual, expected, fuzzinessX, fuzzinessY) {
for (point of actual)
checkPointIsNear(point, expected, fuzzinessX, fuzzinessY);
}