// E2E: prove /sama/skill is end-to-end editable. // // Walks the full user journey: // 1. Land on https://tdd.md/sama/skill (the SKILL.md viewer) // 2. Spot the "propose an edit →" link in the docs chrome // 3. Click it → navigate to /edit/sama/skill // 4. Confirm the editor login wall renders (server side returns 401 // with the GitHub sign-in button + ?to= preserving where to come // back to after auth) // 5. Confirm the raw source is reachable at /content/sama/skill.md // 6. Screenshot each step into test-results/ for visual evidence // // Authenticated submission isn't scripted here because admin write // requires a real GitHub OAuth round-trip — see the bottom of this // file for the storage-state-based test that runs when you've saved // a logged-in session via `bunx playwright codegen` or similar. import { test, expect } from "@playwright/test"; import * as fs from "fs"; import * as path from "path"; const SCREENSHOT_DIR = "test-results/sama-skill-editable"; test.beforeAll(() => { fs.mkdirSync(SCREENSHOT_DIR, { recursive: true }); }); test.describe("/sama/skill is editable end-to-end", () => { test("step 1: docs page renders with propose-an-edit link", async ({ page }) => { const res = await page.goto("/sama/skill"); expect(res?.status()).toBe(200); // Page identity — confirms we're on the SKILL.md viewer. The h1 // is the SAMA mnemonic "SAMA — Sorted, Architecture, Modeled, // Atomic" emitted from the markdown body. await expect(page.getByRole("heading", { name: /SAMA.*Sorted.*Architecture/i }).first()).toBeVisible(); // Edit link present and points at our self-hosted editor route // (NOT git.tdd.md). const editLink = page.locator('a[href="/edit/sama/skill"]', { hasText: /propose an edit/i }); await expect(editLink).toBeVisible(); // View-source goes to /content/sama/skill.md on the main domain. const sourceLink = page.locator('a[href="/content/sama/skill.md"]', { hasText: /view source/i }); await expect(sourceLink).toBeVisible(); // Hard guarantee: zero links on this page point at the git. // subdomain anymore. expect(await page.locator('a[href*="git.tdd.md"]').count()).toBe(0); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "1-sama-skill-page-with-edit-link.png"), fullPage: true, }); }); test("step 2: /content/sama/skill.md serves raw markdown from tdd.md", async ({ request }) => { const res = await request.get("/content/sama/skill.md"); expect(res.status()).toBe(200); expect(res.headers()["content-type"]).toMatch(/text\/plain/); const body = await res.text(); // SKILL.md frontmatter — confirms we got the actual file, not a // 200-with-html-error-page. expect(body).toMatch(/^---/m); expect(body).toMatch(/name:\s*sama/i); expect(body.length).toBeGreaterThan(500); }); test("step 3: clicking 'propose an edit' lands on the editor login wall", async ({ page }) => { await page.goto("/sama/skill"); const [navResponse] = await Promise.all([ page.waitForResponse((r) => r.url().endsWith("/edit/sama/skill")), page.locator('a[href="/edit/sama/skill"]').first().click(), ]); // 401 — login required. The page still renders content (login // wall HTML), it's the status that signals the gate. expect(navResponse.status()).toBe(401); await expect(page).toHaveURL(/\/edit\/sama\/skill$/); await expect(page.getByRole("heading", { name: /edit · SKILL/i })).toBeVisible(); // Sign-in button preserves return path so the user lands back on // the editor after GitHub OAuth. const signIn = page.getByRole("link", { name: /sign in with github/i }); await expect(signIn).toBeVisible(); const href = await signIn.getAttribute("href"); expect(href).toContain("/auth/github/start"); expect(href).toContain("to=%2Fedit%2Fsama%2Fskill"); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "2-edit-sama-skill-login-wall.png"), fullPage: true, }); }); test("step 4: /edit/sama/skill is the same form regardless of entry path", async ({ page }) => { // Direct hit on /edit/sama/skill — should render the same login // wall (proves the route resolves; nav-only pages are now // editable via the SITE_NAV fallback in c32_edit_resolve). const res = await page.goto("/edit/sama/skill"); expect(res?.status(), "before this fix it 404'd because 'skill' isn't in ALL_SAMA").toBe(401); await expect(page.getByRole("heading", { name: /edit · SKILL/i })).toBeVisible(); }); }); // Note: the admin-write happy-path test that used to live here was // retired — it asserted on a git.tdd.md commit link that no longer // exists (the applied-live page links to /GIT/... now), and the // admin-edit-lands-in-bare-repo flow is fully covered by // e2e/git-native-proof.spec.ts. Keeping a duplicate here would just // double-edit the same path and fight optimistic concurrency.