test(web-next): add Playwright config + smoke specs (home, about, blog 404)

This commit is contained in:
2026-05-05 09:25:42 +02:00
parent 22bee5362f
commit 106e5c2737
8 changed files with 135 additions and 21 deletions

View File

@@ -0,0 +1,20 @@
import { test, expect } from "@playwright/test";
test("/blog/[slug] returns 404 for non-existent slug", async ({ page }) => {
const response = await page.goto("/blog/this-slug-does-not-exist", {
waitUntil: "domcontentloaded",
});
expect(response?.status()).toBe(404);
});
test("/blog/[slug] for a real slug renders the article", async ({ page }) => {
// The mock blog repository is empty by default — so this test currently
// expects 404. When seeded data exists in Payload, replace 404 with 200
// and check for article.title in the page body.
test.skip(
true,
"Pending: seed a published article in Payload before enabling this test",
);
await page.goto("/blog/example-slug");
await expect(page.locator("h1").first()).toBeVisible();
});

View File

@@ -0,0 +1,12 @@
import { test, expect } from "@playwright/test";
test("home page renders site name + nav + article list", async ({ page }) => {
await page.goto("/");
// Page renders and shows site name
await expect(page.locator("h1").first()).toBeVisible();
// Site name from siteSettings (mock seed: "My App")
await expect(page.locator("body")).toContainText(/My App/i);
// Nav element is present on the page
const nav = page.locator("nav");
await expect(nav).toHaveCount(1);
});

View File

@@ -0,0 +1,10 @@
import { test, expect } from "@playwright/test";
test("/about renders the about marketing page", async ({ page }) => {
await page.goto("/about");
// Either renders the seeded page (h1 = "About us") or "not yet published" message
// — both are HTTP 200, so the test only checks it doesn't 500.
const status = (await page.context().request.get("/about")).status();
expect(status).toBe(200);
await expect(page.locator("body")).toBeVisible();
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference path="./.next/types/routes.d.ts" />

View File

@@ -7,6 +7,8 @@
"build": "echo 'Next.js build requires full environment — use pnpm dev or docker'",
"dev": "next dev --port 3000",
"lint": "eslint .",
"test:e2e": "playwright test",
"test:e2e:install": "playwright install --with-deps chromium",
"typecheck": "tsc --noEmit"
},
"dependencies": {
@@ -29,6 +31,7 @@
"superjson": "^2.2.1"
},
"devDependencies": {
"@playwright/test": "^1.50.0",
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/node": "^22.0.0",

View File

@@ -0,0 +1,26 @@
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./e2e",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: "list",
use: {
baseURL: "http://localhost:3000",
trace: "on-first-retry",
},
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
webServer: {
command: "pnpm dev",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,
timeout: 60_000,
},
});

View File

@@ -0,0 +1,4 @@
{
"status": "passed",
"failedTests": []
}