Visual regression tests refined

This commit is contained in:
adilallo
2025-08-29 13:42:25 -06:00
parent e8691efac4
commit f7621d2086
6 changed files with 1421 additions and 7 deletions
+184 -2
View File
@@ -7,9 +7,17 @@ export default {
parameters: {
// Chromatic configuration for responsive testing
chromatic: {
viewports: [360, 640, 768, 1024, 1280],
viewports: [320, 360, 480, 640, 768, 1024, 1280, 1440, 1920],
// Capture screenshots at each breakpoint
delay: 100, // Small delay to ensure layout is stable
delay: 200, // Increased delay to ensure layout is stable
// Capture both light and dark themes if available
modes: {
light: {},
dark: {
// This will be used if dark mode is implemented
colorScheme: "dark",
},
},
},
// Storybook viewport configuration
viewport: {
@@ -49,6 +57,20 @@ export default {
height: "700px",
},
},
xxl: {
name: "2XL (xxl)",
styles: {
width: "1440px",
height: "700px",
},
},
full: {
name: "Full HD (full)",
styles: {
width: "1920px",
height: "700px",
},
},
},
},
},
@@ -198,3 +220,163 @@ export const Interactive = {
});
},
};
// Story for testing hover states
export const HoverStates = {
args: {
onToggle: () => console.log("Navigation toggled"),
},
parameters: {
docs: {
description: {
story:
"Header with hover states visible. This story captures the visual appearance when elements are hovered.",
},
},
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
await step("Hover over navigation items", async () => {
const useCasesLink = canvas.getByRole("link", { name: /use cases/i });
await userEvent.hover(useCasesLink);
// Wait for hover state to be visible
await new Promise((resolve) => setTimeout(resolve, 100));
const learnLink = canvas.getByRole("link", { name: /learn/i });
await userEvent.hover(learnLink);
await new Promise((resolve) => setTimeout(resolve, 100));
const aboutLink = canvas.getByRole("link", { name: /about/i });
await userEvent.hover(aboutLink);
await new Promise((resolve) => setTimeout(resolve, 100));
});
await step("Hover over authentication elements", async () => {
const loginLink = canvas.getByRole("link", {
name: /log in to your account/i,
});
await userEvent.hover(loginLink);
await new Promise((resolve) => setTimeout(resolve, 100));
const createRuleButton = canvas.getByRole("button", {
name: /create a new rule with avatar decoration/i,
});
await userEvent.hover(createRuleButton);
await new Promise((resolve) => setTimeout(resolve, 100));
});
},
};
// Story for testing focus states
export const FocusStates = {
args: {
onToggle: () => console.log("Navigation toggled"),
},
parameters: {
docs: {
description: {
story:
"Header with focus states visible. This story captures the visual appearance when elements are focused.",
},
},
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
await step("Focus on navigation items", async () => {
const useCasesLink = canvas.getByRole("link", { name: /use cases/i });
useCasesLink.focus();
await new Promise((resolve) => setTimeout(resolve, 100));
const learnLink = canvas.getByRole("link", { name: /learn/i });
learnLink.focus();
await new Promise((resolve) => setTimeout(resolve, 100));
const aboutLink = canvas.getByRole("link", { name: /about/i });
aboutLink.focus();
await new Promise((resolve) => setTimeout(resolve, 100));
});
await step("Focus on authentication elements", async () => {
const loginLink = canvas.getByRole("link", {
name: /log in to your account/i,
});
loginLink.focus();
await new Promise((resolve) => setTimeout(resolve, 100));
const createRuleButton = canvas.getByRole("button", {
name: /create a new rule with avatar decoration/i,
});
createRuleButton.focus();
await new Promise((resolve) => setTimeout(resolve, 100));
});
},
};
// Story for testing with long content
export const WithLongContent = {
args: {
onToggle: () => console.log("Navigation toggled"),
},
render: () => (
<div className="min-h-screen bg-[var(--color-surface-default-primary)]">
<Header onToggle={() => console.log("Navigation toggled")} />
<main className="p-8">
<div className="max-w-4xl mx-auto">
<h1 className="text-2xl font-bold text-white mb-4">
Header with Long Content
</h1>
<p className="text-white mb-4">
This story tests how the header looks with a lot of content below
it. This helps ensure the header maintains its visual integrity in
real-world scenarios.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{Array.from({ length: 12 }, (_, i) => (
<div
key={i}
className="bg-[var(--color-surface-default-secondary)] p-4 rounded-lg"
>
<h3 className="text-white font-semibold mb-2">
Content Block {i + 1}
</h3>
<p className="text-[var(--color-content-default-secondary)] text-sm">
This is example content to show how the header integrates with
page content. This block contains enough text to test layout
behavior.
</p>
</div>
))}
</div>
</div>
</main>
</div>
),
parameters: {
docs: {
description: {
story:
"Header with long content below to test visual integration and layout stability.",
},
},
},
};
// Story for testing edge cases
export const EdgeCases = {
args: {
onToggle: () => console.log("Navigation toggled"),
},
parameters: {
viewport: {
defaultViewport: "xs",
},
docs: {
description: {
story:
"Header at the smallest breakpoint to test edge case behavior and ensure no layout issues.",
},
},
},
};