diff --git a/e2e/playground.spec.ts b/e2e/playground.spec.ts new file mode 100644 index 00000000..31ccd04b --- /dev/null +++ b/e2e/playground.spec.ts @@ -0,0 +1,28 @@ +// Playground — the two-layer stack client-side: golden path runs a real +// authority system through the worker (no model download in CI). +import { expect, test } from "@playwright/test" + +test("playground runs a deterministic system end-to-end", async ({ page }) => { + await page.goto("/playground") + await expect(page.getByRole("heading", { name: "Playground" })).toBeVisible() + await page.fill("#input", "Антон Павлович Чехов") + await page.fill("#filter", "bgnpcgn-rus") + await page.selectOption("#system", { index: 0 }) + await page.click("#run") + const out = page.locator("#output") + await expect(out).not.toBeEmpty({ timeout: 30_000 }) + await expect(out).toContainText("Anton") + // shareable URL carries the state + await expect(page).toHaveURL(/sys=bgnpcgn-rus/) + // the snippet mirrors the selected system + await expect(page.locator("#snippet")).toContainText("transliterateAsync") +}) + +test("filter narrows the system list", async ({ page }) => { + await page.goto("/playground") + await page.fill("#filter", "Thai") + const first = await page.locator("#system option").first().textContent() + expect(first).toBeTruthy() + const count = await page.locator("#system option").count() + expect(count).toBeLessThan(50) +}) diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro index 8d6c6967..b88bb877 100644 --- a/src/layouts/Base.astro +++ b/src/layouts/Base.astro @@ -274,6 +274,7 @@ const slug = (label: string) => label.toLowerCase().replace(/\s+/g, "-")
  • Live transliteration
  • Map catalogue
  • Model catalogue
  • +
  • Playground
  • Neural demo
  • Authorities
  • Documentation
  • diff --git a/src/pages/playground.astro b/src/pages/playground.astro new file mode 100644 index 00000000..0323a1bd --- /dev/null +++ b/src/pages/playground.astro @@ -0,0 +1,231 @@ +--- +// Playground: the full two-layer stack in the browser — pick any of the +// 289 authority systems, optionally vocalize Arabic through the neural +// layer first, transliterate off-main-thread, share the state by URL, +// and copy the exact TS that does the same thing. +import Base from "../layouts/Base.astro" +import catalogue from "../data/maps-catalogue.json" + +const systems = Object.entries(catalogue as Record) + .map(([code, m]) => ({ code, name: m.data.name, lang: m.data.language })) + .sort((a, b) => a.name.localeCompare(b.name)) +--- + + +
    +

    Playground

    +

    + The whole stack runs in your browser: 289 authority systems, plus the + neural layer for the conversions no committee ever published. Nothing + leaves the page. +

    + +
    +
    + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + +
    +
    +
    + + + + +