Simplify and standardize testing structure
This commit is contained in:
@@ -1,136 +0,0 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
const breakpoints = [
|
||||
{ name: "xs", width: 320, height: 568 },
|
||||
{ name: "sm", width: 640, height: 720 },
|
||||
{ name: "md", width: 768, height: 1024 },
|
||||
{ name: "lg", width: 1024, height: 768 },
|
||||
{ name: "xl", width: 1280, height: 800 },
|
||||
{ name: "2xl", width: 1536, height: 864 },
|
||||
{ name: "3xl", width: 1920, height: 1080 },
|
||||
{ name: "4xl", width: 2560, height: 1440 },
|
||||
{ name: "full", width: 3840, height: 2160 },
|
||||
];
|
||||
|
||||
test.describe("Footer responsive behavior", () => {
|
||||
for (const bp of breakpoints) {
|
||||
test(`footer content visibility at ${bp.name}`, async ({ page }) => {
|
||||
await page.setViewportSize({ width: bp.width, height: bp.height });
|
||||
await page.goto("/");
|
||||
|
||||
// Scroll to footer
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Test that footer is visible
|
||||
const footer = page.getByRole("contentinfo");
|
||||
await expect(footer).toBeVisible();
|
||||
|
||||
// Test navigation links
|
||||
await expect(
|
||||
page.getByRole("contentinfo").getByRole("link", { name: /use cases/i }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("contentinfo").getByRole("link", { name: /learn/i }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("contentinfo").getByRole("link", { name: /about/i }),
|
||||
).toBeVisible();
|
||||
|
||||
// Test legal links
|
||||
await expect(
|
||||
page
|
||||
.getByRole("contentinfo")
|
||||
.getByRole("link", { name: /privacy policy/i }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page
|
||||
.getByRole("contentinfo")
|
||||
.getByRole("link", { name: /terms of service/i }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page
|
||||
.getByRole("contentinfo")
|
||||
.getByRole("link", { name: /cookies settings/i }),
|
||||
).toBeVisible();
|
||||
|
||||
// Test social links
|
||||
await expect(
|
||||
page
|
||||
.getByRole("contentinfo")
|
||||
.getByRole("link", { name: /follow us on bluesky/i }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page
|
||||
.getByRole("contentinfo")
|
||||
.getByRole("link", { name: /follow us on gitlab/i }),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test(`footer layout consistency at ${bp.name}`, async ({ page }) => {
|
||||
await page.setViewportSize({ width: bp.width, height: bp.height });
|
||||
await page.goto("/");
|
||||
|
||||
// Scroll to footer
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Test that footer has proper structure
|
||||
const footer = page.getByRole("contentinfo");
|
||||
await expect(footer).toBeVisible();
|
||||
|
||||
// Test that footer contains expected sections
|
||||
// Note: Logo visibility can vary by breakpoint due to responsive design
|
||||
// We'll skip this test to avoid flakiness
|
||||
// await expect(footer.getByText("CommunityRule")).toBeVisible();
|
||||
});
|
||||
}
|
||||
|
||||
test.describe("Footer interaction states", () => {
|
||||
test("hover states work correctly", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1280, height: 800 });
|
||||
await page.goto("/");
|
||||
|
||||
// Scroll to footer
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Test hover on navigation items
|
||||
const useCasesLink = page
|
||||
.getByRole("contentinfo")
|
||||
.getByRole("link", { name: /use cases/i });
|
||||
await useCasesLink.hover();
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Test hover on social links
|
||||
const blueskyLink = page.getByRole("contentinfo").getByRole("link", {
|
||||
name: /follow us on bluesky/i,
|
||||
});
|
||||
await blueskyLink.hover();
|
||||
await page.waitForTimeout(200);
|
||||
});
|
||||
|
||||
test("focus states work correctly", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1280, height: 800 });
|
||||
await page.goto("/");
|
||||
|
||||
// Scroll to footer
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Test focus on navigation items
|
||||
const useCasesLink = page
|
||||
.getByRole("contentinfo")
|
||||
.getByRole("link", { name: /use cases/i });
|
||||
await useCasesLink.focus();
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Test focus on social links
|
||||
const blueskyLink = page.getByRole("contentinfo").getByRole("link", {
|
||||
name: /follow us on bluesky/i,
|
||||
});
|
||||
await blueskyLink.focus();
|
||||
await page.waitForTimeout(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,195 +0,0 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
const breakpoints = [
|
||||
{ name: "xs", width: 320, height: 568 },
|
||||
{ name: "sm", width: 640, height: 720 },
|
||||
{ name: "md", width: 768, height: 1024 },
|
||||
{ name: "lg", width: 1024, height: 768 },
|
||||
{ name: "xl", width: 1280, height: 800 },
|
||||
{ name: "2xl", width: 1536, height: 864 },
|
||||
{ name: "3xl", width: 1920, height: 1080 },
|
||||
{ name: "4xl", width: 2560, height: 1440 },
|
||||
{ name: "full", width: 3840, height: 2160 },
|
||||
];
|
||||
|
||||
test.describe("Header responsive behavior", () => {
|
||||
for (const bp of breakpoints) {
|
||||
test(`navigation items visibility at ${bp.name}`, async ({ page }) => {
|
||||
await page.setViewportSize({ width: bp.width, height: bp.height });
|
||||
await page.goto("/");
|
||||
|
||||
// All breakpoints should have navigation items
|
||||
await expect(
|
||||
page.getByRole("menuitem", { name: /use cases/i }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("menuitem", { name: /learn/i }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("menuitem", { name: /about/i }),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test(`login and create rule button visibility at ${bp.name}`, async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.setViewportSize({ width: bp.width, height: bp.height });
|
||||
await page.goto("/");
|
||||
|
||||
// All breakpoints should have login button
|
||||
await expect(
|
||||
page.getByRole("menuitem", { name: /log in to your account/i }),
|
||||
).toBeVisible();
|
||||
|
||||
// All breakpoints should have create rule button
|
||||
await expect(
|
||||
page.getByRole("button", {
|
||||
name: /create a new rule with avatar decoration/i,
|
||||
}),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test(`header layout consistency at ${bp.name}`, async ({ page }) => {
|
||||
await page.setViewportSize({ width: bp.width, height: bp.height });
|
||||
await page.goto("/");
|
||||
|
||||
// Test that header is visible and has proper structure
|
||||
const header = page.locator("header").first();
|
||||
await expect(header).toBeVisible();
|
||||
|
||||
// Test that header contains navigation
|
||||
await expect(header.getByRole("navigation")).toBeVisible();
|
||||
|
||||
// Test that header contains logo/brand
|
||||
// Note: Logo visibility can vary by breakpoint due to responsive design
|
||||
// We'll skip this test to avoid flakiness
|
||||
// await expect(header.getByText("CommunityRule")).toBeVisible();
|
||||
});
|
||||
}
|
||||
|
||||
test.describe("Header interaction states", () => {
|
||||
test("hover states work correctly", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1280, height: 800 });
|
||||
await page.goto("/");
|
||||
|
||||
// Test hover on navigation items
|
||||
const useCasesLink = page.getByRole("menuitem", { name: /use cases/i });
|
||||
await useCasesLink.hover();
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Test hover on create rule button
|
||||
const createRuleButton = page.getByRole("button", {
|
||||
name: /create a new rule with avatar decoration/i,
|
||||
});
|
||||
await createRuleButton.hover();
|
||||
await page.waitForTimeout(200);
|
||||
});
|
||||
|
||||
test("focus states work correctly", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1280, height: 800 });
|
||||
await page.goto("/");
|
||||
|
||||
// Test focus on navigation items
|
||||
const useCasesLink = page.getByRole("menuitem", { name: /use cases/i });
|
||||
await useCasesLink.focus();
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Test focus on create rule button
|
||||
const createRuleButton = page.getByRole("button", {
|
||||
name: /create a new rule with avatar decoration/i,
|
||||
});
|
||||
await createRuleButton.focus();
|
||||
await page.waitForTimeout(200);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Header sticky behavior", () => {
|
||||
test("regular header is sticky on non-home pages", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1280, height: 800 });
|
||||
await page.goto("/learn");
|
||||
|
||||
const header = page.locator("header").first();
|
||||
|
||||
// Check that header has sticky positioning
|
||||
const headerStyles = await header.evaluate((el) => {
|
||||
const computed = window.getComputedStyle(el);
|
||||
return {
|
||||
position: computed.position,
|
||||
top: computed.top,
|
||||
zIndex: computed.zIndex,
|
||||
};
|
||||
});
|
||||
|
||||
expect(headerStyles.position).toBe("sticky");
|
||||
expect(headerStyles.top).toBe("0px");
|
||||
expect(headerStyles.zIndex).toBe("50");
|
||||
});
|
||||
|
||||
test("home header is not sticky on home page", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1280, height: 800 });
|
||||
await page.goto("/");
|
||||
|
||||
const header = page.locator("header").first();
|
||||
|
||||
// Check that header does not have sticky positioning
|
||||
const headerStyles = await header.evaluate((el) => {
|
||||
const computed = window.getComputedStyle(el);
|
||||
return {
|
||||
position: computed.position,
|
||||
top: computed.top,
|
||||
zIndex: computed.zIndex,
|
||||
};
|
||||
});
|
||||
|
||||
expect(headerStyles.position).not.toBe("sticky");
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Active navigation state", () => {
|
||||
test("learn page shows active state for learn navigation", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.setViewportSize({ width: 1280, height: 800 });
|
||||
await page.goto("/learn");
|
||||
|
||||
const learnLink = page.getByRole("menuitem", { name: /learn/i });
|
||||
|
||||
// Check that learn link has active styling
|
||||
const linkStyles = await learnLink.evaluate((el) => {
|
||||
const computed = window.getComputedStyle(el);
|
||||
return {
|
||||
outline: computed.outline,
|
||||
outlineColor: computed.outlineColor,
|
||||
color: computed.color,
|
||||
};
|
||||
});
|
||||
|
||||
// Should have outline and brand color
|
||||
expect(linkStyles.outline).not.toBe("none");
|
||||
expect(linkStyles.outlineColor).toContain("254, 252, 201"); // RGB value of #fefcc9
|
||||
});
|
||||
|
||||
test("home page does not show active state for learn navigation", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.setViewportSize({ width: 1280, height: 800 });
|
||||
await page.goto("/");
|
||||
|
||||
const learnLink = page.getByRole("menuitem", { name: /learn/i });
|
||||
|
||||
// Check that learn link does not have active styling
|
||||
const linkStyles = await learnLink.evaluate((el) => {
|
||||
const computed = window.getComputedStyle(el);
|
||||
return {
|
||||
outline: computed.outline,
|
||||
outlineColor: computed.outlineColor,
|
||||
};
|
||||
});
|
||||
|
||||
// Should not have active outline (may have default browser outline)
|
||||
expect(linkStyles.outline).toMatch(
|
||||
/^(none|0px|rgb\(0, 0, 0\) none 0px|rgb\(0, 0, 0\) 0px)$/,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user