Fixes from the cropin.com / ooni.com audit reviews:
- walker: preserve whitespace-only text in inline elements ("ofthe" bug);
capture ::placeholder styles for inputs
- css: emit visibility (hidden-at-rest wordmark artifact); exempt list
markers from inherited elision (lost bullets); ::placeholder rules
- seo: sanitize og:type to Next's enum (render crash -> dev badge leak);
generated next.config disables devIndicators
- capture/stabilize: promote lazy-loader data attrs before snapshots
(collapsed sections, viewport-inconsistent captures); settle autoplay
carousels to home slide before every snapshot; force-reveal hidden
videos for poster shots + log failures
- generate: ship downloaded video files as local <video src>; keep
picture>source through IR prune with srcset rewrite (mobile-crop-on-
desktop heroes); pin Tailwind named screens to computeBands boundaries
- capture/graft: capture cross-origin iframe subtrees (Klaviyo signup
forms) with element-screenshot fallback; asset download retry +
visual-assets-missing reporting
Checkpoint commit: wave 4 (reveal settling, 206 range-response fix,
hidden-geometry banding, bare-zero utility gating) is mid-implementation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
38 lines
1.7 KiB
TypeScript
38 lines
1.7 KiB
TypeScript
import { describe, it } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { isRetryableAssetFailure, ASSET_RETRY_DELAY_MS } from "../src/capture/capture.js";
|
|
|
|
describe("asset download retry decision", () => {
|
|
it("retries visual/font assets on network error (no response)", () => {
|
|
for (const type of ["image", "svg", "video", "font"]) {
|
|
assert.equal(isRetryableAssetFailure(type, null), true, `${type} + network error retries`);
|
|
}
|
|
});
|
|
|
|
it("retries visual/font assets on transient server states (5xx, 429)", () => {
|
|
assert.equal(isRetryableAssetFailure("image", 500), true);
|
|
assert.equal(isRetryableAssetFailure("image", 503), true);
|
|
assert.equal(isRetryableAssetFailure("video", 502), true);
|
|
assert.equal(isRetryableAssetFailure("font", 429), true);
|
|
});
|
|
|
|
it("does NOT retry authoritative 4xx failures (404/403/410)", () => {
|
|
assert.equal(isRetryableAssetFailure("image", 404), false);
|
|
assert.equal(isRetryableAssetFailure("image", 403), false);
|
|
assert.equal(isRetryableAssetFailure("video", 410), false);
|
|
assert.equal(isRetryableAssetFailure("font", 401), false);
|
|
});
|
|
|
|
it("does NOT retry non-visual asset types at all", () => {
|
|
assert.equal(isRetryableAssetFailure("css", null), false);
|
|
assert.equal(isRetryableAssetFailure("manifest", 500), false);
|
|
assert.equal(isRetryableAssetFailure("lottie", 503), false);
|
|
assert.equal(isRetryableAssetFailure("other", null), false);
|
|
});
|
|
|
|
it("uses a fixed, bounded retry delay (deterministic — no jitter)", () => {
|
|
assert.equal(typeof ASSET_RETRY_DELAY_MS, "number");
|
|
assert.ok(ASSET_RETRY_DELAY_MS > 0 && ASSET_RETRY_DELAY_MS <= 2000);
|
|
});
|
|
});
|