128 lines
3.8 KiB
JavaScript
128 lines
3.8 KiB
JavaScript
let counter = 0;
|
|
const loadImage = size => {
|
|
return event => {
|
|
let zoom;
|
|
if (location.search.includes("replace")) {
|
|
zoom = document.getElementById("image");
|
|
} else {
|
|
zoom = new Image();
|
|
}
|
|
zoom.src=`/images/lcp-${size}.png`;
|
|
++counter;
|
|
zoom.elementTiming = "zoom" + counter;
|
|
document.body.appendChild(zoom);
|
|
}
|
|
};
|
|
const loadBackgroundImage = size => {
|
|
return event => {
|
|
const div = document.createElement("div");
|
|
const [width, height] = size.split("x");
|
|
++counter;
|
|
div.style = `background-image:
|
|
url(/images/lcp-${size}.png?${counter}); width: ${width}px; height: ${height}px`;
|
|
div.elementTiming = "zoom" + counter;
|
|
document.body.appendChild(div);
|
|
}
|
|
};
|
|
|
|
const registerMouseover = background => {
|
|
const image = document.getElementById("image");
|
|
const span = document.getElementById("span");
|
|
const func = background ? loadBackgroundImage : loadImage;
|
|
image.addEventListener("mouseover", func("100x50"));
|
|
span.addEventListener("mouseover", func("256x256"));
|
|
}
|
|
|
|
const dispatch_mouseover = () => {
|
|
span.dispatchEvent(new Event("mouseover"))
|
|
};
|
|
|
|
const wait_for_lcp_entries = async entries_expected => {
|
|
await new Promise(resolve => {
|
|
let entries_seen = 0;
|
|
const PO = new PerformanceObserver(list => {
|
|
const entries = list.getEntries();
|
|
for (let entry of entries) {
|
|
if (entry.url) {
|
|
entries_seen++;
|
|
}
|
|
}
|
|
if (entries_seen == entries_expected) {
|
|
PO.disconnect();
|
|
resolve()
|
|
} else if (entries_seen > entries_expected) {
|
|
PO.disconnect();
|
|
reject();
|
|
}
|
|
});
|
|
PO.observe({type: "largest-contentful-paint", buffered: true});
|
|
});
|
|
};
|
|
const wait_for_element_timing_entry = async identifier => {
|
|
await new Promise(resolve => {
|
|
const PO = new PerformanceObserver(list => {
|
|
const entries = list.getEntries();
|
|
for (let entry of entries) {
|
|
if (entry.identifier == identifier) {
|
|
PO.disconnect();
|
|
resolve()
|
|
}
|
|
}
|
|
});
|
|
PO.observe({type: "element", buffered: true});
|
|
});
|
|
};
|
|
const wait_for_resource_timing_entry = async name => {
|
|
await new Promise(resolve => {
|
|
const PO = new PerformanceObserver(list => {
|
|
const entries = list.getEntries();
|
|
for (let entry of entries) {
|
|
if (entry.name.includes(name)) {
|
|
PO.disconnect();
|
|
resolve()
|
|
}
|
|
}
|
|
});
|
|
PO.observe({type: "resource", buffered: true});
|
|
});
|
|
};
|
|
|
|
const run_mouseover_test = background => {
|
|
promise_test(async t => {
|
|
// await the first LCP entry
|
|
await wait_for_lcp_entries(1);
|
|
// Hover over the image
|
|
registerMouseover(background);
|
|
if (test_driver) {
|
|
await new test_driver.Actions().pointerMove(0, 0, {origin: image}).send();
|
|
}
|
|
if (!background) {
|
|
await wait_for_element_timing_entry("zoom1");
|
|
} else {
|
|
await wait_for_resource_timing_entry("png?1");
|
|
await new Promise(r => requestAnimationFrame(r));
|
|
}
|
|
// There's only a single LCP entry, because the zoom was skipped.
|
|
await wait_for_lcp_entries(1);
|
|
|
|
// Wait 600 ms as the heuristic is 500 ms.
|
|
// This will no longer be necessary once the heuristic relies on Task
|
|
// Attribution.
|
|
await new Promise(r => step_timeout(r, 600));
|
|
|
|
// Hover over the span.
|
|
if (test_driver) {
|
|
await new test_driver.Actions().pointerMove(0, 0, {origin: span}).send();
|
|
}
|
|
if (!background) {
|
|
await wait_for_element_timing_entry("zoom2");
|
|
} else {
|
|
await wait_for_resource_timing_entry("png?2");
|
|
await new Promise(r => requestAnimationFrame(r));
|
|
}
|
|
// There are 2 LCP entries, as the image loaded due to span hover is a
|
|
// valid LCP candidate.
|
|
await wait_for_lcp_entries(2);
|
|
}, `LCP mouseover heuristics ignore ${background ?
|
|
"background" : "element"}-based zoom widgets`);
|
|
}
|