Use cases, aktivity a testy cloud UI
Tato stránka je plán pokrytí cloud UI (/, /app, /admin, /docs/): z use cases vycházejí aktivity, z aktivit úkoly (tasky) a ke každému úkolu je uvedeno, jakým testem se ověří.
Stav
Use cases a aktivity jsou odvozené z reálného kódu stránek (app.html, admin.html, landing.html) a z tras serveru. Sloupec Test říká, kde se má aktivita ověřit. Stávající testy (ui-tests/, jsdom s mockovaným fetch) pokrývají jen chování stránek, ne server a prohlížeč; e2e testy proti skutečnému serveru přidává Plán realizace.
Úrovně testů
| Kód |
Co to je |
Co dokazuje |
Kde běží |
| JSDOM |
stávající ui-tests/*.js (skutečný DOM, fetch je mock) |
logika stránky, vazby ovládacích prvků, XSS/CSP allowlist |
lokálně, bez serveru |
| API |
Rust testy proti skutečnému Postgresu (route_status) |
oprávnění, stavové kódy, DB |
cargo test -p glass-cloud |
| E2E |
Playwright v prohlížeči proti běžícímu glass-cloud + Postgres |
celý řetěz: server → HTML → JS → API → DB → zobrazení |
ui-tests/e2e/ |
Pravidlo: co lze ověřit levněji (JSDOM/API), se nezdvojuje v E2E; E2E drží cesty napříč vrstvami a to, co jen skutečný prohlížeč umí (CSP, přesměrování, localStorage, chyby v konzoli, responsivita).
Uživatel (tester / hráč)
U1 — Zjistit, co je Scryglass, a stáhnout aplikaci
Aktér: návštěvník. Stránka: /.
| Aktivita |
Tasky |
Test |
| U1.1 Zobrazit úvodní stránku |
stránka vrací 200, nadpis a navigace (Features, Download, Docs, Dashboard) jsou vidět |
E2E |
| U1.2 Přejít na Dashboard / Docs |
Dashboard vede na /app, Docs na /docs/ (200, ne 401) |
E2E |
| U1.3 Stáhnout aplikaci jako alpha uživatel |
po přihlášení /me vrátí alpha, tlačítka stažení se ukážou; GET /download/{platform} vrací soubor |
E2E + API |
| U1.4 Stažení bez alpha je odepřeno |
uživatel bez role alpha dostane 403 z /download/… a tlačítka nevidí |
API + E2E |
U2 — Přihlásit se
Stránka: /app, /auth/*.
| Aktivita |
Tasky |
Test |
| U2.1 Přihlášení e-mailovým kódem |
e-mail → krok 2 → správný 6místný kód → dashboard; špatný kód → chybová hláška, zůstat na kroku 2 |
E2E |
| U2.2 Změnit e-mail v kroku 2 |
tlačítko Change vrátí na krok 1 |
JSDOM (stávající) |
| U2.3 Přihlášení heslem |
Use a password instead → formulář → přihlášení; špatné heslo → hláška |
E2E |
| U2.4 Přihlášení passkey |
tlačítko je vidět; bez podpory WebAuthn hláška místo pádu |
JSDOM + E2E (virtuální authenticator) |
| U2.5 Magic link |
GET odkazu ukáže stránku s tlačítkem (nespotřebuje token), tlačítko vytvoří session |
E2E + API |
| U2.6 Session přežije reload |
token v localStorage; po obnovení zůstane přihlášen |
E2E |
| U2.7 Odhlášení |
Sign out smaže token, server ho zneplatní (/auth/logout), reload ukáže přihlašovací kartu |
E2E + API |
| U2.8 Výpadek sítě není odhlášení |
při selhání načtení dat se ukáže Couldn't reach Scryglass + Retry, ne přihlašovací formulář |
JSDOM (stávající) |
| U2.9 Neplatný / vypršelý token |
401 z /me vede na přihlašovací kartu |
E2E |
U3 — Přehled (Overview)
| Aktivita |
Tasky |
Test |
| U3.1 První spuštění (prázdný účet) |
ukáže se Welcome to Scryglass se třemi kroky a poznámkou o kreditu; ne tabulka zápasů |
JSDOM (stávající) + E2E |
| U3.2 Dlaždice statistik |
Total Matches, Win rate, Training Events, AI Guide budget odpovídají datům účtu |
E2E (seed) |
| U3.3 Poslední zápasy |
tabulka Recent Matches (When / Deck / Opponent / Result); prázdný stav No recent matches |
E2E (seed) |
| U3.4 Cizí data se nezobrazí |
uživatel A nikdy nevidí zápasy uživatele B |
API |
| U3.5 Bezpečné vykreslení |
název balíčku nebo soupeře s <script>/HTML se zobrazí jako text |
JSDOM (stávající) + E2E |
U4 — Balíčky a AI průvodce (Decks)
| Aktivita |
Tasky |
Test |
| U4.1 Seznam balíčků synchronizovaných z aplikace |
tabulka Deck / Colors / Archetype / AI Guide; prázdný stav No decks synced yet |
E2E (seed přes PUT /me/decks) |
| U4.2 Vygenerovat průvodce |
tlačítko založí úlohu (POST /guide/jobs), stav se zobrazí |
E2E (LLM vypnuté → očekávaný stav) + API |
| U4.3 Bez alpha / bez kreditu |
odepřeno s jasnou hláškou, kredit se nestrhne |
API + E2E |
| U4.4 Zobrazit průvodce |
markdown se vykreslí bez spuštění skriptu, odkazy mají noopener |
JSDOM (stávající, 160 payloadů) |
| U4.5 Vybrat model (Fast/Standard) |
PUT /me/model-tier; volba přežije reload |
API + E2E |
| U4.6 Verze balíčku ACTIVE / STALE |
odznak odpovídá tomu, zda pravidla patří k nejnovější verzi |
JSDOM |
U5 — Zabezpečení účtu (Security)
| Aktivita |
Tasky |
Test |
| U5.1 Nastavit heslo |
min. 10 znaků; shoda obou polí; po uložení hláška o úspěchu a přihlášení heslem funguje |
E2E |
| U5.2 Přidat passkey |
WebAuthn registrace s virtuálním authenticatorem; passkey se objeví v seznamu |
E2E |
| U5.3 Smazat passkey |
zmizí ze seznamu a přestane fungovat |
E2E + API |
| U5.4 Přehled zařízení / session |
/me/sessions; odvolání jedné session ji zneplatní |
API + E2E |
| U5.5 Odvolat ostatní session |
/me/revoke-others ponechá aktuální |
API |
U6 — Statistiky (Stats)
| Aktivita |
Tasky |
Test |
| U6.1 Filtry (balíček, rozsah, min. her) |
změna přepočítá KPI a grafy; prázdný rozsah ukáže vysvětlení |
E2E (seed) |
| U6.2 Grafy podle hodiny a soupeře |
SVG se vykreslí; Table view přepne na tabulku se stejnými čísly |
JSDOM + E2E |
| U6.3 Info dialogy |
ⓘ otevře dialog; Esc, klik na pozadí i × ho zavřou |
E2E |
U7 — Ovládání a přístupnost
| Aktivita |
Tasky |
Test |
| U7.1 Karty (tabs) klávesnicí |
šipky přepínají, právě jedna karta je v tab pořadí |
JSDOM (stávající) |
| U7.2 Bez inline handlerů (CSP) |
odpověď /app má script-src bez unsafe-inline; konzole bez CSP chyb; všech 11 vazeb funguje |
JSDOM + Rust (stávající) + E2E (konzole) |
| U7.3 Mobilní šířka |
žádné vodorovné posouvání při 375 px |
E2E |
U8 — Dokumentace
| Aktivita |
Tasky |
Test |
U8.1 Otevřít /docs/ a projít stránky |
všechny stránky vrací 200, navigace funguje |
E2E |
| U8.2 Odkazy na docs z UI |
landing, dashboard i admin mají odkaz Docs |
E2E |
| U8.3 Docs neprozradí cizí soubory |
/docs/../…, neexistující cesta → 404 (ne 200/500) |
API (stávající) + E2E |
Administrátor
A1 — Vstoupit do administrace
Stránka: /admin.
| Aktivita |
Tasky |
Test |
| A1.1 Admin uvidí odkaz Admin v dashboardu |
/me má is_admin, odkaz se odkryje; běžný uživatel ho nevidí |
E2E |
A1.2 Běžný uživatel na /admin |
datová volání vrátí 403 a UI ukáže odepření (ne prázdná data) |
E2E + API |
| A1.3 Token zařízení nestačí |
admin se sync tokenem dostane na privilegovaných trasách 403 (jen web session) |
API (stávající) |
| A1.4 Vypršelá session |
401 vede na přihlášení, ne na tichý prázdný přehled |
E2E |
A2 — Přehled provozu (Overview)
| Aktivita |
Tasky |
Test |
| A2.1 Souhrnné dlaždice |
Matches / Clients / Reactive Decisions odpovídají /stats |
E2E (seed) |
| A2.2 Top archetypy soupeřů |
tabulka seřazená sestupně; prázdný stav No archetype data |
JSDOM + E2E |
| A2.3 Automatické obnovení (30 s) |
přehled se překreslí, aniž by se ztratil vybraný uživatel |
JSDOM |
A3 — Uživatelé a přístup (Users & Access)
| Aktivita |
Tasky |
Test |
| A3.1 Tabulka uživatelů |
sloupce Account / Created / Matches / Last event / Build / Schema / Engine / Alpha |
E2E (seed) |
| A3.2 Verze klienta a schéma |
Build ukazuje last_app_version; Schema ukazuje nejnovější replay schéma a je žlutá, je-li nižší než serverové; STALE · version unknown pro klienta bez verze |
E2E + API (stávající DB test) |
| A3.3 Filtr Real accounts / All |
anonymní účty se skryjí / ukážou |
JSDOM |
| A3.4 Detail účtu |
klik na řádek otevře detail: profil, role, poslední build a replay schema, aktivita, balíčky, zápasy |
E2E |
| A3.5 Alpha pozvánka |
e-mail → POST /admin/alpha → řádek v allowlistu; neplatný e-mail → hláška |
E2E + API |
| A3.6 Odvolat alpha |
první klik vyžádá potvrzení (Really revoke?), druhý odešle právě jeden požadavek |
JSDOM (stávající) |
| A3.7 Přidělit / odebrat roli |
admin a corpus_reader přes /admin/roles/grant|revoke; seznam rolí se obnoví; jen RoleAdmin |
API + E2E |
| A3.8 Sloučit anonymní účet |
POST /admin/merge-anon přesune historii; nelze sloučit sám se sebou |
API |
A4 — Ekonomika (Economy)
| Aktivita |
Tasky |
Test |
| A4.1 Přehled spotřeby LLM |
tabulka uživatelů: úlohy, tokeny, použito, zůstatek (záporný zůstatek je vidět) |
JSDOM (stávající) + E2E |
| A4.2 Přidat kredit / nastavit zůstatek |
POST /admin/guide/credit s důvodem; kniha zůstává append-only; jen Billing (owner) |
API |
| A4.3 Nastavit model uživateli |
POST /admin/users/{id}/model-tier |
API |
| A4.4 Celkové součty sedí |
součet použitého = součet řádků |
JSDOM (stávající) |
A5 — Data (Data)
| Aktivita |
Tasky |
Test |
| A5.1 Artefakty |
tabulka distribuovaných verzí bundlů (Kind/Version/Created) |
E2E |
| A5.2 Spustit obnovu meta |
POST /refresh (operátor/admin); výsledek v /jobs |
API |
| A5.3 Druhy událostí uživatele |
/admin/users/{id}/event-kinds |
API |
A6 — Označená rozhodnutí (Flags)
| Aktivita |
Tasky |
Test |
| A6.1 Seznam flagged decisions |
nejnovější první; obsahuje build (engine_git_sha) |
API + E2E |
| A6.2 Prázdný stav |
srozumitelná hláška, ne rozbitá tabulka |
JSDOM |
A7 — Audit (Audit)
| Aktivita |
Tasky |
Test |
| A7.1 Změny rolí, kreditu a alpha |
každá akce z A3/A4 vytvoří řádek (kdo, co, komu) |
API + E2E |
| A7.2 Čtení korpusu |
každé čtení /admin/replays čtenářem zapíše corpus_read s počtem a kurzorem |
API (stávající) |
| A7.3 Stránkování |
kurzor (ts,id) je stabilní při souběžných zápisech |
API |
A8 — Korpus her (mimo UI, součást produktu)
| Aktivita |
Tasky |
Test |
| A8.1 Čtenář stáhne hry |
token corpus_reader → GET /admin/replays 200 bez e-mailů; ostatní admin trasy 403 |
API (stávající) |
| A8.2 Vydání tokenu |
POST /admin/corpus-token jen pro RoleAdmin a jen pro účet s rolí |
API (stávající) |
| A8.3 Neplatný kurzor |
odmítnut 400, ne návrat na první stránku |
API |
A9 — Dokumentace a navigace
| Aktivita |
Tasky |
Test |
| A9.1 Odkazy v hlavičce admina |
Dashboard, Docs, ← Public Site vedou správně |
E2E |
| A9.2 Bezpečnostní hlavičky |
admin má CSP s nonce; /docs/ má vlastní CSP a nosniff |
Rust (stávající) + E2E (response.headers) |
Průřezové kontroly (každý E2E běh)
- Žádná chyba v konzoli (
console.error, neodchycená výjimka, CSP violation) na žádné stránce.
- Žádný požadavek na cizí doménu, který CSP nepovoluje.
- Žádný
5xx z API během scénáře.
- Screenshot a trace při selhání.
Plán realizace
Doporučené pořadí — od nejvyššího rizika:
- Infrastruktura E2E (jednou):
ui-tests/e2e/ s Playwrightem (@playwright/test, Chromium),
global-setup: throwaway Postgres (postup v Provoz) → spustit binárku glass-cloud na volném portu s DATABASE_URL, CLOUD_TOKEN, OWNER_EMAILS, DOCS_DIR → čekat na /health,
- seed přes API/SQL (ne přes UI): uživatelé s rolemi a tokeny všech druhů (
session, sync), zápasy, replay záznamy různých schémat, balíčky; přihlášení v testu = vložení tokenu do localStorage (scry-web-token),
- e-mailový kód: server v testu nemá poštu → kód se čte z DB / testovacího hooku, nikdy ne z produkčního e-mailu.
- Kouřový sloupec (U1.1, U2.1, U2.6, U2.7, U3.1, A1.1, A1.2, U8.1): dokazuje, že server + stránky + přihlášení drží pohromadě.
- Nová funkce tohoto týdne (A3.2, A3.4, U8.2, A9.1): sloupec Schema, odkazy na docs.
- Oprávnění na úrovni UI (A1.2, A3.7, A4.2, U4.3): že UI ukáže odepření, ne prázdná data.
- Passkey (U2.4, U5.2, U5.3) s virtuálním authenticatorem — nejvíc práce, nejnižší priorita.
Pravidla kvality testů
- Každý E2E test musí selhat na rozbité verzi — před slučováním ho spustit proti záměrně rozbitému UI/serveru (např. odstranit sloupec Schema, vrátit
unsafe-inline do CSP) a ověřit červenou. Test, který nikdy nemůže selhat, je horší než žádný.
- Seed je deterministický a každý test si vytváří vlastní účty (e-maily s náhodnou příponou), takže jde spouštět opakovaně i paralelně.
- E2E netestuje LLM ani skutečnou poštu; ty jsou vypnuté a jejich hranice se ověřuje v API testech.
- Trace a screenshot se ukládají jen při selhání.
Stav pokrytí E2E (2026-09-30)
79 testů (1 volitelný E2E_ONLINE), každý prošel fail-first (75 mutací, ui-tests/e2e/mutate_e2e.py).
Všechny use cases výše jsou pokryté: E2E v prohlížeči, API kontraktem proti skutečnému serveru, nebo
stávajícími jsdom / Rust testy (U2.2, U4.4, U4.6, U7.2, A2.3, A3.1 — viz sloupec Test).
| Use case |
Spec |
| U1.1 U1.2 U2.1 U2.6 U2.7 U3.1 A1.1 A1.2 U8.1 |
e2e/smoke.spec.js |
| U1.3 U1.4 |
e2e/downloads.spec.js |
| U2.3 U2.9 U4.1 U5.1 |
e2e/account.spec.js |
| U2.4 U5.2 U5.3 (passkey) |
e2e/passkey.spec.js |
| U2.5 (magic link) |
e2e/magic-link.spec.js |
| U3.4 A3.8 |
e2e/isolation-and-merge.spec.js |
| U4.2 U4.3 U4.5 U5.4 U5.5 |
e2e/sessions-and-guide.spec.js |
| U6.1 U6.2 U6.3 U7.1 U7.3 |
e2e/stats.spec.js |
| A3.2 A3.4 A9.1 A9.2 U8.2 U8.3 + info dialog admina |
e2e/admin-users.spec.js |
| A3.5 A3.7 U3.2 U3.3 U3.5 |
e2e/admin-actions.spec.js |
| A2.1 A2.2 A4.1 A4.2 A4.3 A6.1 A6.2 A7.1 |
e2e/admin-economy.spec.js |
| A1.3 A1.4 A3.3 A3.6 A5.1 A5.2 A5.3 A7.3 A8.2 A8.3 |
e2e/admin-data.spec.js |
Záměrně mimo E2E: generování guide přes skutečný LLM (hranice se ověřuje v API testech: 403 / 400 / 503,
kredit se nestrhne) a stahování instalátoru z GitHubu (jen s E2E_ONLINE=1).
Otevřené otázky
- ~~Má se kouřový sloupec přidat do
scripts/preflight.sh?~~ Rozhodnuto 2026-09-30: E2E běží samostatně (npm run e2e v ui-tests/), preflight beze změny.