diff --git a/packages/kilo-ui/src/stories/avatar.stories.tsx b/packages/kilo-ui/src/stories/avatar.stories.tsx index 6ee6edb411c..9cc53007a4e 100644 --- a/packages/kilo-ui/src/stories/avatar.stories.tsx +++ b/packages/kilo-ui/src/stories/avatar.stories.tsx @@ -33,10 +33,15 @@ export const WithCustomColors: Story = { args: { fallback: "KL", background: "#1a4d8f", foreground: "#ffffff" }, } +// Inline data URI so the visual regression test never depends on network. +// 1×1 teal PNG — small enough to embed, large enough to prove rendering. +const AVATAR_DATA_URI = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAADZJREFUWIW2xzERACAQBLA7/pWACxrsgfFhJpmtsrMn0N2S2RNIZk+gu2X2BLpbZk8gmT0B4AWJGwMhBjARKwAAAABJRU5ErkJggg==" + export const WithImage: Story = { args: { fallback: "OC", - src: "https://avatars.githubusercontent.com/u/154330673?s=48", + src: AVATAR_DATA_URI, }, } diff --git a/packages/kilo-ui/tests/visual-regression.spec.ts b/packages/kilo-ui/tests/visual-regression.spec.ts index 553ce269027..24662af93fe 100644 --- a/packages/kilo-ui/tests/visual-regression.spec.ts +++ b/packages/kilo-ui/tests/visual-regression.spec.ts @@ -45,6 +45,24 @@ async function disableAnimations(page: Page) { }) } +// Wait for every inside the story root to finish loading so screenshots +// never capture an intermediate state with missing / half-loaded images. +async function waitForImages(page: Page) { + await page.evaluate(() => { + const imgs = document.querySelectorAll("#storybook-root img") + return Promise.all( + Array.from(imgs).map( + (img) => + img.complete || + new Promise((resolve) => { + img.addEventListener("load", () => resolve(), { once: true }) + img.addEventListener("error", () => resolve(), { once: true }) + }), + ), + ) + }) +} + // Stories to skip from visual regression: // - Font/Favicon: inject into , no visible content in #storybook-root // - Typewriter: uses JS setTimeout + Math.random(), inherently non-deterministic @@ -72,6 +90,7 @@ for (const story of stories) { await disableAnimations(page) // Wait for Kobalte/SolidJS to finish hydrating interactive components await page.waitForSelector("#storybook-root *", { state: "attached" }) + await waitForImages(page) // Screenshot just the story content, not the full 1280x720 canvas. // Use [component, variant] path so snapshots are grouped per component dir. diff --git a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-avatar/with-image-chromium-linux.png b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-avatar/with-image-chromium-linux.png deleted file mode 100644 index 0e23ee9a5f4..00000000000 --- a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-avatar/with-image-chromium-linux.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:79b80c13a1fa198f1602c85728a48467ac9b47c6430dadd6ff698f9c4d39980e -size 809