mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-18 18:05:28 -04:00
update tests
This commit is contained in:
2 files changed
+223
No files matched your search
@@ -0,0 +1,219 @@
|
||||
<!DOCTYPE html>
|
||||
<script src="../../testing.js"></script>
|
||||
<body></body>
|
||||
|
||||
<!--
|
||||
These run with load_resources = .{ .image = true } (see Image.zig's test
|
||||
decl). Every route here has a real body, so a `load` event is only
|
||||
reachable if the transfer really did stop after the headers and still
|
||||
complete successfully — that's what makes these a test of the fetch path
|
||||
and not just of the event plumbing.
|
||||
|
||||
/images/ok.png is over Request.HEADERS_ONLY_DRAIN_MAX (abort branch),
|
||||
/images/small.png is under it (drain branch).
|
||||
-->
|
||||
|
||||
<script id="img-200-fires-load" type=module>
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
|
||||
const evt = await new Promise(resolve => {
|
||||
img.addEventListener("load", () => resolve("load"));
|
||||
img.addEventListener("error", () => resolve("error"));
|
||||
img.src = "/images/ok.png";
|
||||
});
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual("load", evt);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-404-fires-error" type=module>
|
||||
// The whole point of the flag: without a request there is no status to
|
||||
// branch on, and this fired `load` like everything else.
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
|
||||
const evt = await new Promise(resolve => {
|
||||
img.addEventListener("load", () => resolve("load"));
|
||||
img.addEventListener("error", () => resolve("error"));
|
||||
img.src = "/images/404.png";
|
||||
});
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual("error", evt);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-small-body-drains-and-loads" type=module>
|
||||
// Under the drain threshold: the body is read and discarded rather than
|
||||
// aborted, so the connection stays poolable. Observably identical to the
|
||||
// abort branch above.
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
|
||||
const evt = await new Promise(resolve => {
|
||||
img.addEventListener("load", () => resolve("load"));
|
||||
img.addEventListener("error", () => resolve("error"));
|
||||
img.src = "/images/small.png";
|
||||
});
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual("load", evt);
|
||||
// Drained, not decoded: still no dimensions.
|
||||
testing.expectEqual(0, img.naturalWidth);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-many-share-one-connection" type=module>
|
||||
// A page's worth of small images. They queue at low priority behind
|
||||
// anything else, and each drained body returns its connection to the
|
||||
// pool, so this must settle without starving or stalling.
|
||||
const state = await testing.async();
|
||||
const results = await Promise.all(
|
||||
Array.from({ length: 12 }, (_, i) => new Promise(resolve => {
|
||||
const img = document.createElement("img");
|
||||
img.addEventListener("load", () => resolve("load"));
|
||||
img.addEventListener("error", () => resolve("error"));
|
||||
img.src = "/images/small.png?n=" + i;
|
||||
}))
|
||||
);
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual(12, results.length);
|
||||
testing.expectEqual(true, results.every(r => r === "load"));
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-500-fires-error" type=module>
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
|
||||
const evt = await new Promise(resolve => {
|
||||
img.addEventListener("load", () => resolve("load"));
|
||||
img.addEventListener("error", () => resolve("error"));
|
||||
img.src = "/images/500.png";
|
||||
});
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual("error", evt);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-redirect-fires-load" type=module>
|
||||
// Redirect hops never reach the header callback, so the status the
|
||||
// load/error decision is made from is the final 200, not the 302.
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
|
||||
const evt = await new Promise(resolve => {
|
||||
img.addEventListener("load", () => resolve("load"));
|
||||
img.addEventListener("error", () => resolve("error"));
|
||||
img.src = "/images/redirect.png";
|
||||
});
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual("load", evt);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-complete-tracks-the-fetch" type=module>
|
||||
// complete is false only while a request is in flight. naturalWidth stays
|
||||
// 0 either way: we fetch images, we don't decode them.
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
|
||||
testing.expectEqual(true, img.complete);
|
||||
img.src = "/images/ok.png";
|
||||
const during = img.complete;
|
||||
|
||||
await new Promise(resolve => {
|
||||
img.addEventListener("load", resolve);
|
||||
img.addEventListener("error", resolve);
|
||||
});
|
||||
const after = img.complete;
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual(false, during);
|
||||
testing.expectEqual(true, after);
|
||||
testing.expectEqual(0, img.naturalWidth);
|
||||
testing.expectEqual(0, img.naturalHeight);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-unresolvable-src-fires-error" type=module>
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
|
||||
const evt = await new Promise(resolve => {
|
||||
img.addEventListener("load", () => resolve("load"));
|
||||
img.addEventListener("error", () => resolve("error"));
|
||||
img.src = "http://";
|
||||
});
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual("error", evt);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-empty-src-does-nothing" type=module>
|
||||
// No src, no request, no event — in any mode.
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
let fired = null;
|
||||
img.addEventListener("load", () => fired = "load");
|
||||
img.addEventListener("error", () => fired = "error");
|
||||
img.src = "";
|
||||
document.body.appendChild(img);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual(null, fired);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-src-reassignment-supersedes" type=module>
|
||||
// Reassigning src while a fetch is in flight: the element must end up
|
||||
// reflecting the LAST src, not whichever response happens to land first.
|
||||
const state = await testing.async();
|
||||
const img = document.createElement("img");
|
||||
|
||||
const events = [];
|
||||
img.addEventListener("load", () => events.push("load"));
|
||||
img.addEventListener("error", () => events.push("error"));
|
||||
|
||||
img.src = "/images/404.png";
|
||||
img.src = "/images/ok.png";
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
// The superseded 404 is dropped; only the winning fetch reports.
|
||||
testing.expectEqual(1, events.length);
|
||||
testing.expectEqual("load", events[0]);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script id="img-fragment-parse-does-not-fetch">
|
||||
{
|
||||
// Images parsed via innerHTML / DOMParser must not hit the network, for
|
||||
// the same reason stylesheet links in a fragment don't: the subtree may
|
||||
// never be attached, or belongs to another Document.
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = '<img src="/images/404.png">';
|
||||
const img = div.querySelector('img');
|
||||
// No fetch was issued, so it never entered the in-flight state.
|
||||
testing.expectEqual(true, img.complete);
|
||||
}
|
||||
</script>
|
||||
@@ -193,3 +193,7 @@ const testing = @import("../../../../testing.zig");
|
||||
test "WebApi: HTML.Image" {
|
||||
try testing.htmlRunner("element/html/image.html", .{});
|
||||
}
|
||||
|
||||
test "WebApi: HTML.Image fetch" {
|
||||
try testing.htmlRunner("element/html/image_fetch.html", .{ .load_resources = .{ .image = true } });
|
||||
}
|
||||
Reference in new issue
Block a user