diff --git a/tests/e2e-landing/interactions.spec.ts b/tests/e2e-landing/interactions.spec.ts new file mode 100644 index 00000000..86e198e8 --- /dev/null +++ b/tests/e2e-landing/interactions.spec.ts @@ -0,0 +1,109 @@ +import { expect, test } from "@playwright/test"; + +test.describe("BentoGrid Interactions", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/"); + }); + + test("search filters tools by name", async ({ page }) => { + const input = page.getByPlaceholder("Search tools..."); + await input.fill("resize"); + await expect(page.getByText("Resize", { exact: true }).first()).toBeVisible(); + await expect(page.getByText(/Showing \d+ of 47 tools/)).toBeVisible(); + }); + + test("category pill filters tools", async ({ page }) => { + await page.getByText(/AI Tools/).click(); + await expect(page.getByText(/Showing 14 of 47 tools/)).toBeVisible(); + await expect(page.getByText("Remove Background")).toBeVisible(); + }); + + test("clicking All resets category filter", async ({ page }) => { + await page.getByText(/AI Tools/).click(); + await expect(page.getByText(/Showing 14 of 47 tools/)).toBeVisible(); + + await page.getByText(/All \(47\)/).click(); + await expect(page.getByText(/Showing 47 of 47 tools/)).toBeVisible(); + }); + + test("search with no results shows empty state", async ({ page }) => { + const input = page.getByPlaceholder("Search tools..."); + await input.fill("xyznonexistent"); + await expect(page.getByText("No tools found. Try a different search.")).toBeVisible(); + await expect(page.getByText(/Showing 0 of 47 tools/)).toBeVisible(); + }); + + test("combined search and category filter works", async ({ page }) => { + await page.getByText(/AI Tools/).click(); + const input = page.getByPlaceholder("Search tools..."); + await input.fill("background"); + await expect(page.getByText("Remove Background")).toBeVisible(); + }); +}); + +test.describe("HowItWorks Copy Button", () => { + test("copy button shows Copied! feedback", async ({ page }) => { + await page.goto("/"); + const copyButton = page.locator("button").filter({ hasText: "docker run" }); + await copyButton.click(); + await expect(page.getByText("Copied!")).toBeVisible(); + }); +}); + +test.describe("FAQ Page Accordion", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/faq"); + }); + + test("renders all FAQ questions", async ({ page }) => { + await expect(page.getByText("Frequently Asked Questions")).toBeVisible(); + await expect(page.getByText("Are my files safe and private?")).toBeVisible(); + await expect(page.getByText("Is SnapOtter really free?")).toBeVisible(); + await expect(page.getByText("Do I need an internet connection?")).toBeVisible(); + }); + + test("answers are hidden by default", async ({ page }) => { + await expect(page.getByText(/All processing happens on your own server/)).not.toBeVisible(); + }); + + test("clicking a question expands the answer", async ({ page }) => { + await page.getByText("Are my files safe and private?").click(); + await expect( + page.getByText(/All processing happens on your own server/), + ).toBeVisible(); + }); + + test("clicking again collapses the answer", async ({ page }) => { + const question = page.getByText("Are my files safe and private?"); + await question.click(); + await expect( + page.getByText(/All processing happens on your own server/), + ).toBeVisible(); + await question.click(); + await expect( + page.getByText(/All processing happens on your own server/), + ).not.toBeVisible(); + }); + + test("multiple FAQs can be open simultaneously", async ({ page }) => { + await page.getByText("Are my files safe and private?").click(); + await page.getByText("Is SnapOtter really free?").click(); + await expect( + page.getByText(/All processing happens on your own server/), + ).toBeVisible(); + await expect(page.getByText(/open source under AGPL-3.0/)).toBeVisible(); + }); +}); + +test.describe("Mobile Navigation", () => { + test("hamburger menu opens and shows links", async ({ page }) => { + await page.setViewportSize({ width: 375, height: 812 }); + await page.goto("/"); + const toggle = page.getByLabel("Toggle menu"); + await toggle.click(); + await expect(page.getByRole("link", { name: "Features" }).last()).toBeVisible(); + await expect(page.getByRole("link", { name: "Pricing" }).last()).toBeVisible(); + await expect(page.getByRole("link", { name: "Docs" }).last()).toBeVisible(); + await expect(page.getByRole("link", { name: "Contact" }).last()).toBeVisible(); + }); +});