// E2E: Fase 2b block-editor surface. This is the SAMA-ported CMS UI at // /admin/edit/:type/:slug — distinct from the legacy textarea editor at // /edit/:section/:slug. The legacy editor is covered by // git-native-proof.spec; this file proves the new block-editor // infrastructure is alive on live: // // 1. /admin is auth-gated (anonymous → 401) // 2. /admin/assets/blockeditor.js bundles + serves the client TS as // JavaScript with an ETag (and 304s on re-request) // 3. With the admin storage state, /admin renders the list page // (no 401, contains the "+ New" button or admin chrome) // // We deliberately do NOT exercise create/edit/save here — those // roundtrip sxdoc → SQLite → commit and need fixtures + cleanup. // git-native-proof.spec already proves the commit-pipeline shape via // the legacy editor; what this file proves is that the *new* surface // also exists, is gated correctly, and ships its bundle. import { test, expect } from "@playwright/test"; import * as fs from "fs"; const ADMIN_AUTH_FILE = ".auth/admin.json"; test.describe("admin block-editor infrastructure", () => { test("anonymous /admin is 401 (auth-gate intact)", async ({ request }) => { const res = await request.get("/admin", { failOnStatusCode: false }); expect(res.status()).toBe(401); }); test("blockeditor bundle serves with ETag + 304 on re-request", async ({ request }) => { const first = await request.get("/admin/assets/blockeditor.js"); expect(first.status()).toBe(200); expect(first.headers()["content-type"]).toMatch(/javascript/); const body = await first.text(); // It's an ES-module bundle compiled from src/client/blockeditor.ts + // src/client/blocks.ts + src/client/slashmenu.ts — the slash-menu // ID is a stable marker that survives minification. expect(body.length).toBeGreaterThan(2000); const etag = first.headers()["etag"]; expect(etag).toBeTruthy(); const second = await request.get("/admin/assets/blockeditor.js", { headers: { "If-None-Match": etag! }, }); expect(second.status()).toBe(304); }); }); test.describe("admin block-editor (authenticated)", () => { test.skip(!fs.existsSync(ADMIN_AUTH_FILE), `no ${ADMIN_AUTH_FILE} found`); test.use({ storageState: ADMIN_AUTH_FILE }); test("authenticated /admin renders the list page", async ({ page }) => { const res = await page.goto("/admin"); expect(res?.status()).toBe(200); // The list page links to /admin/new — that anchor is the canonical // marker that the block-editor surface (not the legacy editor) is // serving this request. await expect(page.locator('a[href="/admin/new"]')).toBeVisible(); }); });