mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
Zero client JS, 165 static pages, self-hosted fonts, Otter Orange design system. Includes tool SEO data for all 157 tools, enterprise page, and updated e2e landing tests.
93 lines
3.1 KiB
TypeScript
93 lines
3.1 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
|
|
test.describe("Heading Hierarchy", () => {
|
|
const pages = [
|
|
{ path: "/", name: "Homepage" },
|
|
{ path: "/contact", name: "Contact" },
|
|
{ path: "/faq", name: "FAQ" },
|
|
{ path: "/privacy", name: "Privacy" },
|
|
{ path: "/terms", name: "Terms" },
|
|
{ path: "/enterprise", name: "Enterprise" },
|
|
];
|
|
|
|
for (const { path, name } of pages) {
|
|
test(`${name} page has exactly one h1`, async ({ page }) => {
|
|
await page.goto(path);
|
|
const h1Count = await page.locator("h1").count();
|
|
expect(h1Count).toBe(1);
|
|
});
|
|
}
|
|
});
|
|
|
|
test.describe("External Links", () => {
|
|
test("GitHub links open in new tab with noopener", async ({ page }) => {
|
|
await page.goto("/");
|
|
const ghLinks = page.locator('a[href*="github.com"]');
|
|
const count = await ghLinks.count();
|
|
expect(count).toBeGreaterThan(0);
|
|
for (let i = 0; i < count; i++) {
|
|
const link = ghLinks.nth(i);
|
|
await expect(link).toHaveAttribute("target", "_blank");
|
|
const rel = await link.getAttribute("rel");
|
|
expect(rel).toContain("noopener");
|
|
}
|
|
});
|
|
|
|
test("Docs link opens in new tab", async ({ page }) => {
|
|
await page.goto("/");
|
|
const docsLink = page.locator('a[href="https://docs.snapotter.com"]').first();
|
|
await expect(docsLink).toHaveAttribute("target", "_blank");
|
|
});
|
|
});
|
|
|
|
test.describe("Landmark Elements", () => {
|
|
test("homepage has nav, main, and footer landmarks", async ({ page }) => {
|
|
await page.goto("/");
|
|
await expect(page.locator("nav").first()).toBeVisible();
|
|
await expect(page.locator("main")).toBeVisible();
|
|
await expect(page.locator("footer")).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe("Skip Link", () => {
|
|
test("skip link targets main content", async ({ page }) => {
|
|
await page.goto("/");
|
|
const skipLink = page.locator('a.skip-link[href="#main"]');
|
|
await expect(skipLink).toHaveAttribute("href", "#main");
|
|
await expect(page.locator("main#main")).toBeAttached();
|
|
});
|
|
});
|
|
|
|
test.describe("Meta Tags", () => {
|
|
test("homepage has meta description", async ({ page }) => {
|
|
await page.goto("/");
|
|
const metaDesc = page.locator('meta[name="description"]');
|
|
const content = await metaDesc.getAttribute("content");
|
|
expect(content).toBeTruthy();
|
|
expect(content?.length).toBeGreaterThan(10);
|
|
});
|
|
|
|
test("homepage has Open Graph tags", async ({ page }) => {
|
|
await page.goto("/");
|
|
await expect(page.locator('meta[property="og:title"]')).toHaveAttribute("content", /.+/);
|
|
await expect(page.locator('meta[property="og:description"]')).toHaveAttribute("content", /.+/);
|
|
});
|
|
});
|
|
|
|
test.describe("Keyboard Navigation", () => {
|
|
test("Tab key moves focus through navbar links", async ({ page }) => {
|
|
await page.goto("/");
|
|
await page.keyboard.press("Tab");
|
|
const firstFocused = await page.evaluate(() => document.activeElement?.tagName);
|
|
expect(firstFocused).toBe("A");
|
|
});
|
|
});
|
|
|
|
test.describe("Image Accessibility", () => {
|
|
test("navbar logo has alt text", async ({ page }) => {
|
|
await page.goto("/");
|
|
const logo = page.locator('nav img[alt="SnapOtter"]');
|
|
await expect(logo).toBeVisible();
|
|
});
|
|
});
|