Files
KoalaSync/tests/e2e/fixtures/pages/ready.js
T
KoalaDev 36e1291d2c feat: rank player candidates by ordered signals, add browser E2E suite
The weighted score summed incomparable units, so size could outvote traits
that disqualify an element outright. Measured on a real page: a display:none
preload reports its full 1080p intrinsic size and scored 2073600, beating a
visible unmuted player at 509920.

Selection now compares an ordered list of signals, highest priority first:
has a source, is rendered, is not a silent background loop, rendered size
bucket, is playing, has controls, duration. Rendered size replaces intrinsic
resolution, and mute state is gone from the ranking entirely: it is a viewer
preference, not evidence about which element is the player.

It stays a ranking rather than a filter, so a page of only bad candidates
still yields one and findVideo never returns null where a video exists.

The new tests/e2e suite runs the shipped finder against real fixture pages
and drives the packed extension for injection, reinjection and remote
play/pause/seek into a first-party frame. All five scoring scenarios fail
against the previous implementation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 07:23:12 +02:00

52 lines
1.8 KiB
JavaScript

/**
* Fixture helper. Marks the page ready once every <video> that is supposed to
* carry metadata has it, and once every video marked data-autoplay is actually
* playing. Tests wait for window.__fixtureReady instead of sleeping, so the
* scoring signals (videoWidth, duration, paused) are settled before we look.
*/
(function () {
window.__fixtureReady = false;
function collectVideos(doc, out) {
for (const video of doc.querySelectorAll('video')) out.push(video);
for (const frame of doc.querySelectorAll('iframe')) {
let frameDoc = null;
try { frameDoc = frame.contentDocument; } catch (_e) { frameDoc = null; }
if (frameDoc) collectVideos(frameDoc, out);
}
for (const host of doc.querySelectorAll('*')) {
if (host.shadowRoot) collectVideos(host.shadowRoot, out);
}
return out;
}
function metadataReady(video) {
if (video.dataset.sourceless !== undefined) return true;
return video.readyState >= 1;
}
function playbackReady(video) {
if (video.dataset.autoplay === undefined) return true;
return !video.paused;
}
function check() {
const videos = collectVideos(document, []);
if (!videos.length) return false;
if (!videos.every(v => metadataReady(v) && playbackReady(v))) return false;
window.__fixtureReady = true;
return true;
}
function start() {
for (const video of collectVideos(document, [])) {
if (video.dataset.autoplay !== undefined) video.play().catch(() => {});
}
if (check()) return;
const timer = setInterval(() => { if (check()) clearInterval(timer); }, 50);
}
if (document.readyState === 'complete') start();
else window.addEventListener('load', start);
})();