Diploma A4 print-first (§Design pct.9): certificat la final campanie
Buton "Vezi diploma" pe finale (+ "Joaca din nou"). Overlay #diploma: certificat A4 portret alb, chenar dublu accent, titlu serif (singurul), numele copilului = cel mai mare element. - buildDiploma(): rand de stele per camera (roomStars[], persistat in resume; camere sarite = 🔒 "sarita"), cuvant magic in dale (lacate pt sarite), footer = data + "creat de {creator}" + marcaj auriu "timpul a expirat" - camp builder nou: creator ("Creat de") - @media print izoleaza #diploma (rest visibility:hidden, margin 20mm, print-color-adjust:exact) - exemplu-campanie.html regenerat Smoke 31/31 (test nou "diploma": nume/titlu/stele/cuvant/creator/inapoi) + screenshot scratch/diploma.png (A4, camera sarita, footer expirat). Cluster T10/PR2 complet (D7 + Timer + Muzica + Diploma). Ramas Etapa 2: Adventure Mode v0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ Smoke + regresie + campanie E2E pentru jocurile generate. Verifică faptic: fiec
|
||||
până la ecranul final, fără erori de consolă.
|
||||
|
||||
## Ownership
|
||||
- `tests/smoke.mjs` — unicul fișier de teste (~30 teste).
|
||||
- `tests/smoke.mjs` — unicul fișier de teste (~31 teste).
|
||||
- `playwright.config.mjs` (la root, **gitignored**) — config dev.
|
||||
|
||||
## Local Contracts
|
||||
@@ -18,9 +18,9 @@ până la ecranul final, fără erori de consolă.
|
||||
fiecare test asertează `errors.length === 0` la final.
|
||||
- **Tag-uri:** `@regresie` (16 — exemplu-*.html + edge cases + mobil 320px + regenerare via gameHTML +
|
||||
stil top-level invalid la import + bomberman gameplay + bomberman rază/powerup-uri) și `@campanie`
|
||||
(16 — intro→hartă→camere→final, resume, cameră moartă, idempotență ușă, `$`/`$&`, beep, mobil,
|
||||
audio S1, voce/narațiune D10, a11y tap/aria/reduced-motion, navigare overworld, timer calm T10, muzica ambient T10).
|
||||
- **Status țintă: 30/30 PASS.**
|
||||
(17 — intro→hartă→camere→final, resume, cameră moartă, idempotență ușă, `$`/`$&`, beep, mobil,
|
||||
audio S1, voce/narațiune D10, a11y tap/aria/reduced-motion, navigare overworld, timer calm T10, muzica ambient T10, diploma A4).
|
||||
- **Status țintă: 31/31 PASS.**
|
||||
|
||||
## Work Guidance
|
||||
- După modificări la motoare (`escape-builder.html`): rulează suita completă; extinde `@regresie` dacă
|
||||
@@ -29,7 +29,7 @@ până la ecranul final, fără erori de consolă.
|
||||
|
||||
## Verification
|
||||
```bash
|
||||
npx playwright test tests/smoke.mjs # 30/30
|
||||
npx playwright test tests/smoke.mjs # 31/31
|
||||
npx playwright test tests/smoke.mjs --grep @regresie
|
||||
npx playwright test tests/smoke.mjs --grep @campanie
|
||||
```
|
||||
|
||||
@@ -791,6 +791,63 @@ test.describe('Campanie E2E @campanie', () => {
|
||||
expect(errors, errors.join('\n')).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('diploma — „Vezi diploma" arata certificat A4 cu nume/stele-per-camera/cuvant/creator, inapoi (§Design pct.9)',
|
||||
async ({ page }) => {
|
||||
test.setTimeout(120000);
|
||||
const errors = trackErrors(page);
|
||||
const cfg = campaignCfg(3, 'classic');
|
||||
cfg.player = 'Maria';
|
||||
cfg.creator = 'Doamna Ana';
|
||||
const tmpPath = await writeCampaignHtml(page, cfg, 'diploma');
|
||||
const gp = await page.context().newPage();
|
||||
const gameErrors = trackErrors(gp);
|
||||
|
||||
try {
|
||||
await gp.goto('file://' + tmpPath);
|
||||
await gp.locator('#btn-start').click();
|
||||
for (let i = 0; i < 3; i++) {
|
||||
await enterRoom(gp, i);
|
||||
await solveRoom(gp, 'classic', 'r' + (i + 1));
|
||||
}
|
||||
await gp.waitForFunction(() => document.getElementById('finale')?.classList.contains('show'),
|
||||
null, { timeout: 10000 });
|
||||
|
||||
// Buton „Vezi diploma" → diploma vizibila, finale ascunsa
|
||||
await gp.locator('#btn-diploma').click();
|
||||
await expect(gp.locator('#diploma')).toBeVisible();
|
||||
await expect(gp.locator('#finale')).not.toBeVisible();
|
||||
|
||||
// Numele copilului (cel mai mare element) + titlul jocului
|
||||
await expect(gp.locator('#dipl-name')).toHaveText('Maria');
|
||||
await expect(gp.locator('#dipl-game')).toContainText('Test Campanie');
|
||||
|
||||
// Rand de stele per camera: 3 randuri, fiecare cu ★ (rezolvate, nu sarite)
|
||||
await expect(gp.locator('#dipl-rooms .dipl-room')).toHaveCount(3);
|
||||
const firstRoom = await gp.locator('#dipl-rooms .dipl-room .rstars').first().innerText();
|
||||
expect(firstRoom).toMatch(/[★☆]{3}/);
|
||||
|
||||
// Cuvantul magic in dale (3 litere colectate, A B C)
|
||||
await expect(gp.locator('#dipl-word span')).toHaveCount(3);
|
||||
|
||||
// Footer: data + „creat de Doamna Ana"
|
||||
await expect(gp.locator('#dipl-footer')).toContainText('creat de Doamna Ana');
|
||||
|
||||
// Butonul de print exista (nu il apasam — window.print blocheaza headless)
|
||||
await expect(gp.locator('#dipl-print')).toBeVisible();
|
||||
|
||||
// Inapoi → finale din nou
|
||||
await gp.locator('#dipl-back').click();
|
||||
await expect(gp.locator('#finale')).toBeVisible();
|
||||
await expect(gp.locator('#diploma')).not.toBeVisible();
|
||||
|
||||
} finally {
|
||||
await gp.close();
|
||||
try { unlinkSync(tmpPath); } catch (_) {}
|
||||
}
|
||||
expect(gameErrors, 'Game errors:\n' + gameErrors.join('\n')).toHaveLength(0);
|
||||
expect(errors, errors.join('\n')).toHaveLength(0);
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// Test 3: Camera moartă — timeout 4s → skip-banner + cod eroare
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user