Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fdbef1dd7 | ||
|
|
a926ad6423 | ||
|
|
8319f58f1e | ||
|
|
21cfe8bb89 | ||
|
|
b5a38531c4 | ||
|
|
666e274140 |
@@ -1,11 +1,13 @@
|
||||
# Le Gitea Actions del gioco: girano sul runner del PC di Andrea (make runner; label ubuntu-latest = node:22-bookworm).
|
||||
# A ogni push su main e a ogni tag i test unitari; su un tag vX.Y.Z, se passano, la release con i commit dal tag prima.
|
||||
# A ogni push su main e a ogni tag i test unitari; su un tag vX.Y.Z (o a mano, «Run workflow») anche le venti prove nel
|
||||
# browser, una per job nell'immagine di Playwright, sulla scheda video del PC; se passa tutto, la release.
|
||||
# Il controllo dei file pubblicabili non sta qui (a pipeline partita il push è già pubblico): è l'hook pre-push.
|
||||
name: test
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ['v*']
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -15,8 +17,29 @@ jobs:
|
||||
- name: Test unitari
|
||||
run: node --version && node --test tests/*.test.mjs
|
||||
|
||||
release:
|
||||
# Le prove nel browser, una per job: l'elenco è SUITES di scripts/verify.mjs (verify.test.mjs pretende che coincidano),
|
||||
# l'immagine ha la stessa versione di Playwright di package-lock.json (idem).
|
||||
browser:
|
||||
needs: test
|
||||
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/playwright:v1.64.1-noble
|
||||
# La scheda video del PC (runtime NVIDIA di Docker): Chromium disegna lì, tests/chromium.mjs la trova da solo.
|
||||
options: --gpus all -e NVIDIA_DRIVER_CAPABILITIES=all
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
prova: [principale, minigiochi, telefoni, ambient, veicoli, ingorgo, smarronata, briscola, tressette, scopa, biliardo, flipper, micro, cerbottana, condor, campana, bruciate, gara, telefono, risveglio]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Playwright
|
||||
run: npm ci --no-audit --no-fund
|
||||
- name: Prova ${{ matrix.prova }}
|
||||
run: node scripts/verify.mjs ${{ matrix.prova }}
|
||||
|
||||
release:
|
||||
needs: [test, browser]
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
|
||||
@@ -18,8 +18,9 @@ i suoi ricordi: non inventare persone, luoghi o fatti del paese al posto suoi; p
|
||||
- Ogni funzionalità con il suo test; un test automatico percorre tutta la soluzione dell'avventura.
|
||||
- Le prove nel browser sono a sezioni (`scripts/verify.mjs`, dal 2026-11-01): `make verify` rifà solo quelle i cui ingressi
|
||||
sono cambiati dall'ultimo verde (la briscola se cambia la briscola, la partita intera se cambiano storia, motore, stile
|
||||
o risorse). Una prova nuova in `tests/*.browser.mjs` va aggiunta a `SUITES` (il test `verify.test.mjs` lo pretende).
|
||||
- Verifica visiva nel browser con Playwright e swiftshader prima di dichiarare finito qualcosa di grafico.
|
||||
o risorse). Un `chromium.launch` nuovo nelle prove usa `args: ARGS` di `tests/chromium.mjs`. Una prova nuova in `tests/*.browser.mjs` va aggiunta a `SUITES` (il test `verify.test.mjs` lo pretende).
|
||||
- Verifica visiva nel browser con Playwright prima di dichiarare finito qualcosa di grafico. Chromium disegna sulla scheda
|
||||
video del PC se c'è, altrimenti con swiftshader (`tests/chromium.mjs`, dal 2026-11-01: giro intero ~4 min invece di ~16).
|
||||
- Pubblicare (tag/bump/push) solo quando Andrea lo chiede.
|
||||
- Persone vere nel gioco solo con consenso; niente nomi, personaggi o musiche di giochi esistenti.
|
||||
- Prompt delle immagini in `prompts/` e fogli grezzi in `assets/raw/`: esclusi da git.
|
||||
@@ -28,4 +29,4 @@ i suoi ricordi: non inventare persone, luoghi o fatti del paese al posto suoi; p
|
||||
- **Pubblicare (dal 2026-11-01)**: origin è https://git.manzolo.it/manzolo/leggenda-del-regolo, pubblico: prima `make check-public`, poi `git push origin main --tags`, solo se Andrea lo chiede.
|
||||
`make deploy` costruisce l'immagine dal tag della versione, la spinge su `git.manzolo.it/manzolo/leggenda-regolo:vX.Y.Z` (e `:latest`); sul VPS il compose fissa quel tag e fa `docker compose pull && up -d`.
|
||||
Per tornare indietro: sul VPS (`Workspaces/docker/leggenda-regolo/docker-compose.yml`) si rimette il tag precedente e si rifà pull e up.
|
||||
Hook pre-push (`make hooks`, una volta per clone) lancia check-public; le Gitea Actions (`.gitea/workflows/test.yml`: test, e release sui tag) girano sul runner del PC, che si crea o riavvia con `make runner`.
|
||||
Hook pre-push (`make hooks`, una volta per clone) lancia check-public; le Gitea Actions (`.gitea/workflows/test.yml`: test unitari a ogni push; sui tag, o a mano, anche le venti prove nel browser, una per job, poi la release) girano sul runner del PC, che si crea o riavvia con `make runner`.
|
||||
|
||||
@@ -316,6 +316,18 @@ versione nuova.
|
||||
`make bump` dopo una modifica alla briscola riprova la briscola e basta; dopo una modifica alla storia la partita intera
|
||||
e le scene speciali (ambient, veicoli, ingorgo, smarronata), non la briscola; dopo `style.css` o `game.js` tutto.
|
||||
Le prove dei minigiochi, che prima non entravano in `make verify`, ora ci stanno. `make verify-plan` spiega.
|
||||
Nella pipeline di Gitea (runner sul PC) sui tag, o a mano, girano tutte e venti, una per job nell'immagine di
|
||||
Playwright, prima della release: il primo giro completo (1 novembre, a mano su main) verde in 17 minuti.
|
||||
|
||||
- **Prove sulla scheda video (1 novembre, Andrea: «prova con la scheda video»):** Chromium disegnava con swiftshader,
|
||||
sul processore: una schermata 633 ms. Con la RTX del PC (`--use-angle=gl-egl`) 41 ms; micro da 283 a 27 s, briscola da
|
||||
259 a 29, flipper da 186 a 10; tutte e venti da ~16 minuti (due alla volta) a ~4 (sei alla volta), tutte verdi. Le
|
||||
opzioni stanno in `tests/chromium.mjs`: scheda video se c'è (`/dev/dri`, `/dev/nvidia0`), altrimenti swiftshader;
|
||||
`REGOLO_GPU=0/1` forza. Con 6 o 8 prove insieme il giro dura uguale: il limite è la partita intera (243 s, il tempo
|
||||
del gioco, non della grafica). La pipeline dà la GPU ai job (`--gpus all`, runtime NVIDIA di Docker); runner a 6 job.
|
||||
|
||||
- **Flipper da tastiera (1 novembre, Andrea):** la freccia giù carica la molla come Spazio, i due Shift comandano le
|
||||
palette (sinistro e destro, `e.code` passato da main.js ai minigiochi). Test unitario e nel browser.
|
||||
|
||||
## Materiale ricevuto da Andrea (in `assets/raw/`, escluso da git)
|
||||
|
||||
|
||||
+3
-3
@@ -305,9 +305,9 @@
|
||||
sacco (o Invio). Contano le bruciate buone: alla bona ne bastano 10 su 18, seria 15, a fassi male 16.</p>
|
||||
</details>
|
||||
<details id="flipper-help" hidden><summary>Come si gioca</summary>
|
||||
<p>Il Regolo, il flipper del River. Tieni premuto per caricare la molla e lascia per lanciare, oppure usa
|
||||
Spazio o il pulsante Lancia. Una valvola impedisce alla pallina entrata in campo di tornare sulla molla.
|
||||
Le frecce sinistra e destra, i pulsanti Flipper o le due metà della scena comandano le palette;
|
||||
<p>Il Regolo, il flipper del River. Tieni premuto per caricare la molla e lascia per lanciare, oppure tieni
|
||||
premuto Spazio o la freccia giù, o usa il pulsante Lancia. Una valvola impedisce alla pallina entrata in campo di tornare sulla molla.
|
||||
Le frecce sinistra e destra, i due Shift, i pulsanti Flipper o le due metà della scena comandano le palette;
|
||||
puoi usare due dita insieme e il tasto destro del mouse comanda sempre la paletta destra.</p>
|
||||
<p>Le rampe FORTEZZA (ciano) e TREBBIO (ambra) valgono 15.000 punti. Tre passaggi completi sulla stessa
|
||||
rampa entro 20 secondi dal primo fanno LOCK: la pallina viene trattenuta e ne arriva una nuova gratis.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "leggenda-del-regolo",
|
||||
"version": "0.1.69",
|
||||
"version": "0.1.70",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -26,4 +26,6 @@ if [[ ! -s $RUNNER_DATA/.runner ]]; then
|
||||
fi
|
||||
# Senza token nell'ambiente del container: da qui in poi si autentica con .runner.
|
||||
docker compose -f "$COMPOSE" up -d
|
||||
# config.yaml si legge solo all'avvio: se è cambiato (capacità, opzioni) il runner riparte.
|
||||
[[ $(docker inspect -f '{{.State.StartedAt}}' gitea-runner | date -f - +%s) -lt $(stat -c %Y "$(dirname "$COMPOSE")/config.yaml") ]] && docker restart gitea-runner >/dev/null
|
||||
sleep 2; docker logs --tail 1 gitea-runner
|
||||
|
||||
+11
-5
@@ -3,7 +3,8 @@
|
||||
// si rifà solo se la loro impronta (i blob di git, più i file modificati nella cartella di lavoro) è cambiata dall'ultimo
|
||||
// verde, ricordato in .verify-ok.json (fuori da git). Se cambia la briscola si riprova la briscola; se cambia la storia, il
|
||||
// motore, l'impaginazione o le risorse si riprova la partita intera (e le prove delle scene speciali), non la briscola.
|
||||
// node scripts/verify.mjs le prove da rifare, in parallelo (JOBS=2: con quattro Chromium swiftshader insieme le schermate vanno in timeout), e aggiorna i verdi
|
||||
// node scripts/verify.mjs le prove da rifare, in parallelo, e aggiorna i verdi (JOBS: quante insieme; con la
|
||||
// scheda video JOBS_GPU, senza 2: con quattro Chromium swiftshader le schermate vanno in timeout)
|
||||
// node scripts/verify.mjs --plan dice solo cosa rifarebbe e perché
|
||||
// node scripts/verify.mjs --all tutte, senza guardare i verdi
|
||||
// node scripts/verify.mjs briscola solo quelle nominate (anche se verdi)
|
||||
@@ -13,10 +14,11 @@ import { createHash } from 'node:crypto';
|
||||
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { cpus } from 'node:os';
|
||||
import { GPU } from '../tests/chromium.mjs';
|
||||
|
||||
// Il motore comune a tutto: cambia questo e si riprova ogni minigioco.
|
||||
export const ENGINE = ['index.html', 'style.css', 'src/main.js', 'src/engine/game.js', 'src/engine/render.js',
|
||||
'tests/helpers.mjs', 'package-lock.json'];
|
||||
'tests/helpers.mjs', 'tests/chromium.mjs', 'package-lock.json'];
|
||||
// Non toccano il gioco nel browser: documenti, strumenti, pubblicazione, versione (make bump la cambia prima di verificare),
|
||||
// test unitari (girano sempre, a parte), e questo stesso script (lo prova verify.test.mjs).
|
||||
export const IGNORED = [/^docs\//, /^[^/]*\.md$/, /^src\/version\.js$/, /^package\.json$/, /^Makefile$/, /^scripts\//,
|
||||
@@ -49,6 +51,9 @@ export const SUITES = {
|
||||
risveglio: { run: ['tests/risveglio.browser.mjs'] },
|
||||
};
|
||||
|
||||
// Prove insieme con la scheda video (misurato il 1° novembre 2026 sul PC di Andrea, 16 thread e RTX 3080 Ti).
|
||||
const JOBS_GPU = 6; // con 6 e con 8 il giro intero dura uguale (~4 min): da solo «principale» ne prende 243 s
|
||||
|
||||
const ownRe = name => new RegExp(`(^|/)${name}([-_.][^/]*)?$`, 'i');
|
||||
const matches = (path, rule) => rule instanceof RegExp ? rule.test(path) : rule === path;
|
||||
export const ignored = path => IGNORED.some(r => r.test(path));
|
||||
@@ -121,9 +126,10 @@ async function main() {
|
||||
const why = all ? 'tutte' : named.includes(t.name) ? 'chiesta' : !ok[t.name] ? 'mai provata' : !t.changed.length ? "cambiato l'elenco dei file da cui dipende" : `cambiati ${t.changed.slice(0, 4).join(', ')}${t.changed.length > 4 ? ` e altri ${t.changed.length - 4}` : ''}`;
|
||||
console.log(`da rifare: ${t.name}${t.seconds ? ` (~${t.seconds} s)` : ''}: ${why}`);
|
||||
}
|
||||
if (green.length) console.log(`già verdi: ${green.join(', ')}`);
|
||||
if (green.length && !named.length) console.log(`già verdi: ${green.join(', ')}`);
|
||||
if (onlyPlan) return;
|
||||
const jobs = Math.max(1, Number(process.env.JOBS) || Math.min(2, Math.floor(cpus().length / 4)));
|
||||
const jobs = Math.max(1, Number(process.env.JOBS) || Math.min(GPU ? JOBS_GPU : 2, Math.floor(cpus().length / (GPU ? 2 : 4))));
|
||||
console.log(`Chromium ${GPU ? 'sulla scheda video' : 'con swiftshader'}, ${Math.min(jobs, todo.length)} prove alla volta.`);
|
||||
const queue = todo.sort((a, b) => (b.seconds || 999) - (a.seconds || 999)), results = [];
|
||||
const worker = async () => { for (let t; (t = queue.shift());) {
|
||||
const r = await run(t.name); results.push(r);
|
||||
@@ -137,7 +143,7 @@ async function main() {
|
||||
for (const r of results.sort((a, b) => a.name.localeCompare(b.name))) console.log(`${r.code === 0 ? 'OK ' : 'FAIL'} ${r.name} (${r.seconds} s)`);
|
||||
const failed = results.filter(r => r.code !== 0).map(r => r.name);
|
||||
if (failed.length) { console.log(`Prove fallite: ${failed.join(', ')}`); process.exit(1); }
|
||||
console.log(`Prove nel browser OK: ${results.length} rifatte, ${green.length} già verdi.`);
|
||||
console.log(`Prove nel browser OK: ${results.length} rifatte${named.length ? '' : `, ${green.length} già verdi`}.`);
|
||||
}
|
||||
|
||||
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) main();
|
||||
|
||||
@@ -498,7 +498,7 @@ export function cancel(c, pointerId) {
|
||||
for (const f of Object.values(c.flippers)) f.held = all ? [] : f.held.filter(id => id !== pointerId);
|
||||
return true;
|
||||
}
|
||||
// I pulsanti «← Flipper» e «Flipper →» (tenuti premuti; da tastiera un colpo breve), e le frecce.
|
||||
// I pulsanti «← Flipper» e «Flipper →» (tenuti premuti; da tastiera un colpo breve), le frecce e i due Shift.
|
||||
export const turn = (c, dir, who = 'button') => c.step === 'play' && hold(c, dir < 0 ? 'left' : 'right', who, true);
|
||||
export function stopTurn(c, who = 'button') {
|
||||
if (who === 'click') return false; // il colpo breve finisce da sé
|
||||
@@ -509,8 +509,9 @@ export const nudge = () => false;
|
||||
export function setPower(c, v) { if (!canThrow(c) || !Number.isFinite(v)) return false; c.power = clamp(v, 0, 1); return true; }
|
||||
export function key(c, k, down) {
|
||||
if (c.step !== 'play') return false; // a partita finita Spazio e Invio chiudono il risultato (main.js)
|
||||
if (k === 'ArrowLeft' || k === 'ArrowRight') { hold(c, k === 'ArrowLeft' ? 'left' : 'right', 'key-' + k, down); return true; }
|
||||
if (k === ' ') { if (down) { if (!c.holding && waiting(c)) press(c, 'key'); } else if (c.holding && c.pointerId === 'key') release(c, 'key'); return true; }
|
||||
if (['ArrowLeft', 'ArrowRight', 'ShiftLeft', 'ShiftRight'].includes(k)) { hold(c, k.endsWith('Left') ? 'left' : 'right', 'key-' + k, down); return true; }
|
||||
// La molla: Spazio, o la freccia giù (si tira indietro come la molla vera).
|
||||
if (k === ' ' || k === 'ArrowDown') { if (down) { if (!c.holding && waiting(c)) press(c, 'key'); } else if (c.holding && c.pointerId === 'key') release(c, 'key'); return true; }
|
||||
if (k === 'Enter') { if (down) shoot(c); return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
+5
-3
@@ -661,7 +661,7 @@ const MINI = {
|
||||
condor: { ...condor, back: 'Torna al campone', label: 'La Condor: muovi il mouse o tocca il campo per mirare, tieni premuto per trattenere il fiato e lascia per sparare; oppure premi Spara. Frecce per spostare il mirino.' },
|
||||
campana: { ...campana, back: 'Torna al campone', label: 'La campana: muovi il mouse o tocca la campana per mirare, tieni premuto per la forza e lascia per tirare il sassolino; oppure regola la forza e premi Tira (frecce su e giù per mirare, destra e sinistra per la forza). Ai salti premi, o Spazio, quando la lancetta è nel verde.' },
|
||||
bruciate: { ...bruciate, back: 'Torna alla festa', label: 'Le bruciate: tieni premuto e fai dei giri, col mouse o col dito, per girare la manovella; oppure Spazio o le frecce, una spinta a ogni colpo. Né troppo piano né troppo forte; quando son cotte, Rovescia nel sacco (o Invio).' },
|
||||
flipper: { ...flipper, toggle: true, back: 'Torna in strada', label: 'Il flipper del River: tieni premuto per caricare la molla e lascia per lanciare (o regola la forza e premi Lancia, o Spazio). In gioco, tieni premuto sulla metà sinistra o destra della scena per alzare il flipper di quel lato, anche con due dita o col tasto destro del mouse; oppure i pulsanti Flipper o le frecce sinistra e destra.' },
|
||||
flipper: { ...flipper, toggle: true, back: 'Torna in strada', label: 'Il flipper del River: tieni premuto per caricare la molla e lascia per lanciare (o regola la forza e premi Lancia; o tieni premuto Spazio o la freccia giù). In gioco, tieni premuto sulla metà sinistra o destra della scena per alzare il flipper di quel lato, anche con due dita o col tasto destro del mouse; oppure i pulsanti Flipper, le frecce sinistra e destra o i due Shift.' },
|
||||
micro: { ...micro, back: 'Torna dal Chiaru', label: 'La pista col gesso: muovi il mouse o tocca il parcheggio per mirare, tieni premuto per caricare la spinta e lascia; oppure regola la forza e premi Spingi. Frecce o pulsanti Mira per girare.' },
|
||||
basket: { ...basket, back: 'Torna in strada', label: 'Fai due tiri: muovi il mouse o tocca per mirare, tieni premuto per caricare la forza, lascia per tirare.' },
|
||||
// La gara: niente mira né forza, il pulsante alterna gas e freno (chi non può tenere premuto).
|
||||
@@ -825,6 +825,8 @@ function updateChoices() {
|
||||
}));
|
||||
}
|
||||
|
||||
// Ai minigiochi lo Shift arriva coi due lati distinti (ShiftLeft, ShiftRight): nel flipper comandano le due palette.
|
||||
const keyName = e => e.key === 'Shift' ? e.code : e.key;
|
||||
window.addEventListener('keydown', e => {
|
||||
if (e.target instanceof HTMLInputElement && e.target.type === 'range' && e.key !== 'Escape') return;
|
||||
// Nella ricerca della mappa le lettere si scrivono; Esc prima svuota la casella, poi chiude.
|
||||
@@ -917,7 +919,7 @@ window.addEventListener('keydown', e => {
|
||||
if (e.key === 'Escape') { game.closeupClose(); return; }
|
||||
const onButton = ['BUTTON', 'SUMMARY'].includes(e.target.tagName), onControl = onButton && e.target.closest?.('#bocce-controls');
|
||||
// Il GP di Fortezza: frecce, Spazio e Invio finché si tengono giù (su un pulsante Spazio e Invio lo premono).
|
||||
if (!(onButton && [' ', 'Enter'].includes(e.key)) && mini().key?.(game.closeup, e.key, true, e.shiftKey)) { e.preventDefault(); return; }
|
||||
if (!(onButton && [' ', 'Enter'].includes(e.key)) && mini().key?.(game.closeup, keyName(e), true, e.shiftKey)) { e.preventDefault(); return; }
|
||||
if (onControl && [' ', 'Enter'].includes(e.key)) return;
|
||||
const c = game.closeup, m = mini();
|
||||
if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) {
|
||||
@@ -964,7 +966,7 @@ window.addEventListener('keydown', e => {
|
||||
// Alle bocce e al biliardo, lasciando spazio o Invio parte il tiro.
|
||||
window.addEventListener('keyup', e => {
|
||||
// Il GP di Fortezza tiene conto di ogni tasto per conto suo: lasciarne uno non toglie il gas del dito o degli altri.
|
||||
if (miniState() && mini().key?.(game.closeup, e.key, false)) return;
|
||||
if (miniState() && mini().key?.(game.closeup, keyName(e), false)) return;
|
||||
if (running && [' ', 'Enter'].includes(e.key)) game?.closeupRelease();
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// La versione del gioco: la cambia scripts/bump.sh, insieme a package.json.
|
||||
export const VERSION = '0.1.69';
|
||||
export const VERSION = '0.1.70';
|
||||
|
||||
// Immagini, musiche e voci con ?v=<versione>: a ogni versione l'indirizzo cambia e il browser le riscarica,
|
||||
// mentre fra una versione e l'altra le tiene in cache a lungo (nginx.conf).
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// npm run browser:effects — immagini in /tmp/regolo-effects (oppure $OUT).
|
||||
import { chromium } from 'playwright';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
@@ -11,7 +12,7 @@ mkdirSync(out, { recursive: true });
|
||||
const server = await staticServer(), port = server.port;
|
||||
let browser;
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
const page = await browser.newPage({ viewport: { width: 640, height: 360 } });
|
||||
const errors = [];
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-biliardo';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -64,7 +65,7 @@ async function checkArtwork(page, name) {
|
||||
}
|
||||
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
for (const [name, mobile, viewport] of [
|
||||
['desktop', false, { width: 1280, height: 860 }],
|
||||
['touch', true, { width: 844, height: 390 }],
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = '/tmp/regolo-shots'; mkdirSync(out, { recursive: true });
|
||||
const server = await staticServer(), errors = [];
|
||||
@@ -51,7 +52,7 @@ async function artwork(page) {
|
||||
for (const [name, png] of Object.entries(pictures)) writeFileSync(`${out}/briscola-${name}.png`, Buffer.from(png, 'base64'));
|
||||
}
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
const scenarios = ['mouse', 'touch', 'keyboard'].flatMap(mode => [
|
||||
{ name: `desktop-${mode}`, mode, viewport: { width: 1280, height: 860 } },
|
||||
{ name: `telefono-${mode}`, mode, viewport: { width: 390, height: 844 } },
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
// attese si sovrappongono. Una parte sola: node tests/browser.mjs --parte=minigiochi (--media-only: solo multimedia).
|
||||
import { chromium } from 'playwright';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
import { mkdirSync, readFileSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { solution, route } from '../src/story/solution.js';
|
||||
@@ -31,7 +32,7 @@ if (!PARTE && !process.argv.includes('--media-only')) {
|
||||
process.exit(esiti.every(e => e.code === 0) ? 0 : 1);
|
||||
}
|
||||
const server = await staticServer(), PORT = server.port;
|
||||
const browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
const browser = await chromium.launch({ args: ARGS });
|
||||
const errors = [];
|
||||
|
||||
async function open(viewport, query = '') {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-bruciate';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -11,7 +12,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
for (const [name, mobile, viewport] of [['desktop', false, { width: 1280, height: 860 }], ['touch', true, { width: 844, height: 390 }]]) {
|
||||
const page = await browser.newPage({ viewport, hasTouch: mobile, isMobile: mobile });
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-campana';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -11,7 +12,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
for (const [name, mobile, viewport] of [['desktop', false, { width: 1280, height: 860 }], ['touch', true, { width: 844, height: 390 }]]) {
|
||||
const page = await browser.newPage({ viewport, hasTouch: mobile, isMobile: mobile });
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-cerbottana';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -11,7 +12,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
for (const [name, mobile, viewport] of [['desktop', false, { width: 1280, height: 860 }], ['touch', true, { width: 844, height: 390 }]]) {
|
||||
const page = await browser.newPage({ viewport, hasTouch: mobile, isMobile: mobile });
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Come si apre Chromium nelle prove nel browser (solo da node: helpers.mjs lo carica anche la pagina).
|
||||
// Con una scheda video (/dev/dri o /dev/nvidia0, anche nei contenitori lanciati con --gpus) si disegna lì: una
|
||||
// schermata costa ~45 ms invece di ~600 con swiftshader, e le prove girano 5-10 volte più in fretta. Senza, swiftshader.
|
||||
// REGOLO_GPU=0 forza swiftshader, REGOLO_GPU=1 la scheda video.
|
||||
import { existsSync } from 'node:fs';
|
||||
|
||||
export const GPU = process.env.REGOLO_GPU ? process.env.REGOLO_GPU === '1' : ['/dev/dri/renderD128', '/dev/nvidia0'].some(existsSync);
|
||||
const GL = GPU ? ['--use-gl=angle', '--use-angle=gl-egl', '--ignore-gpu-blocklist', '--enable-gpu-rasterization']
|
||||
: ['--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'];
|
||||
export const ARGS = ['--autoplay-policy=no-user-gesture-required', ...GL];
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-condor';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -11,7 +12,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
for (const [name, mobile, viewport] of [['desktop', false, { width: 1280, height: 860 }], ['touch', true, { width: 844, height: 390 }]]) {
|
||||
const page = await browser.newPage({ viewport, hasTouch: mobile, isMobile: mobile });
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
|
||||
@@ -5,6 +5,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-flipper';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -12,7 +13,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
for (const [name, mobile, viewport] of [['desktop', false, { width: 1280, height: 860 }], ['touch', true, { width: 844, height: 390 }]]) {
|
||||
const page = await browser.newPage({ viewport, hasTouch: mobile, isMobile: mobile });
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
@@ -45,9 +46,10 @@ try {
|
||||
await page.waitForFunction(() => game.closeup.holding && game.closeup.power > 0.3, null, { polling: 'raf' });
|
||||
await touch('touchEnd', []);
|
||||
} else {
|
||||
await page.mouse.move(...P(440, 320)); await page.mouse.down();
|
||||
// Da tastiera con la freccia giù (il mouse tiene la molla come il dito, provato sul telefono).
|
||||
await page.keyboard.down('ArrowDown');
|
||||
await page.waitForFunction(() => game.closeup.holding && game.closeup.power > 0.3, null, { polling: 'raf' });
|
||||
await page.mouse.up();
|
||||
await page.keyboard.up('ArrowDown');
|
||||
}
|
||||
await page.waitForFunction(() => game.closeup && !game.closeup.ball?.waiting, null, { timeout: 5000 });
|
||||
// Due dita sulla scena: sinistra, poi anche destra, poi si alza la sinistra e la destra resta su.
|
||||
@@ -83,6 +85,13 @@ try {
|
||||
await page.keyboard.up('ArrowLeft');
|
||||
await page.click('#resume');
|
||||
await page.waitForFunction(() => document.querySelector('#pause').hidden);
|
||||
// I due Shift: il sinistro alza la paletta sinistra, il destro la destra.
|
||||
await page.keyboard.down('ShiftRight');
|
||||
await page.waitForFunction(() => game.closeup.flippers.right.held.includes('key-ShiftRight') && !game.closeup.flippers.left.held.length);
|
||||
await page.keyboard.down('ShiftLeft');
|
||||
await page.waitForFunction(() => game.closeup.flippers.left.held.includes('key-ShiftLeft'));
|
||||
await page.keyboard.up('ShiftRight'); await page.keyboard.up('ShiftLeft');
|
||||
await page.waitForFunction(() => !game.closeup.flippers.left.held.length && !game.closeup.flippers.right.held.length);
|
||||
}
|
||||
// Il traguardo aggiunge una pallina e lascia continuare la partita.
|
||||
const reward = await page.evaluate(async () => {
|
||||
|
||||
@@ -146,10 +146,14 @@ test('comandi: la molla si carica e si lancia lasciando; annullare non lancia; d
|
||||
m.turn(c, 1, 'click'); m.stopTurn(c, 'click'); assert.ok(c.flippers.right.held.includes('click'));
|
||||
const a0 = c.flippers.right.angle; run(c, 0.1); assert.notEqual(c.flippers.right.angle, a0, 'il flipper si è mosso'); run(c, 0.3); assert.ok(!c.flippers.right.held.length);
|
||||
assert.ok(m.key(c, 'ArrowRight', true)); assert.ok(c.flippers.right.held.length); m.key(c, 'ArrowRight', false); assert.ok(!c.flippers.right.held.length);
|
||||
assert.ok(m.key(c, 'ShiftLeft', true)); assert.ok(c.flippers.left.held.includes('key-ShiftLeft') && !c.flippers.right.held.length);
|
||||
m.key(c, 'ShiftRight', true); assert.ok(c.flippers.right.held.includes('key-ShiftRight'));
|
||||
m.key(c, 'ShiftLeft', false); m.key(c, 'ShiftRight', false); assert.ok(!c.flippers.left.held.length && !c.flippers.right.held.length);
|
||||
assert.ok(!m.key(c, 'x', true));
|
||||
assert.ok(!m.setPower(c, 0.3), 'in gioco il cursore della molla non vale');
|
||||
// Spazio: carica e lancia; Invio: lancia con la forza del cursore; a partita finita i tasti non sono suoi.
|
||||
const d = m.newFlipper(9); assert.ok(m.key(d, ' ', true)); run(d, 0.3); assert.ok(d.holding); m.key(d, ' ', false); assert.ok(!m.waiting(d));
|
||||
const g = m.newFlipper(11); assert.ok(m.key(g, 'ArrowDown', true)); run(g, 0.3); assert.ok(g.holding, 'anche la freccia giù carica la molla'); m.key(g, 'ArrowDown', false); assert.ok(!m.waiting(g));
|
||||
const e = m.newFlipper(10); assert.ok(m.setPower(e, 0.5)); assert.equal(m.button(e), 'Lancia'); m.key(e, 'Enter', true); assert.ok(!m.waiting(e)); assert.equal(m.button(e), 'In gioco…');
|
||||
e.step = 'result'; e.result = { winner: 'cpu', score: 0, goal: 120000 }; assert.ok(!m.key(e, ' ', true) && !m.key(e, 'Enter', true));
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-gara';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -12,7 +13,7 @@ let browser;
|
||||
const errors = [];
|
||||
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
for (const [name, mobile, viewport, level] of [
|
||||
['touch', true, { width: 844, height: 390 }, 'seria'],
|
||||
['portrait', true, { width: 390, height: 844 }, 'bona'],
|
||||
|
||||
@@ -5,6 +5,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-ingorgo';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -12,7 +13,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
const page = await browser.newPage({ viewport: { width: 1280, height: 860 } });
|
||||
page.on('pageerror', e => { errors.push(e.message); console.log('ERR', e.message); });
|
||||
await page.goto(`http://127.0.0.1:${server.port}/`);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-micro';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -12,7 +13,7 @@ let browser;
|
||||
const errors = [];
|
||||
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
for (const [name, mobile, viewport] of [
|
||||
['desktop', false, { width: 1280, height: 860 }],
|
||||
['touch', true, { width: 844, height: 390 }],
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-risveglio';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -11,7 +12,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
// Sul computer la versione con la sfocatura vera, sul telefono (touch) quella leggera senza filtri.
|
||||
for (const mobile of [false, true]) {
|
||||
const page = await browser.newPage(mobile ? { viewport: { width: 844, height: 390 }, hasTouch: true, isMobile: true } : { viewport: { width: 1280, height: 860 } });
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = '/tmp/regolo-shots'; mkdirSync(out, { recursive: true });
|
||||
const server = await staticServer(), errors = [];
|
||||
@@ -44,7 +45,7 @@ async function wait(page) {
|
||||
});
|
||||
}
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
const scenarios = [
|
||||
{ name: 'desktop-mouse', mode: 'mouse', viewport: { width: 1280, height: 860 }, full: true },
|
||||
{ name: 'telefono-touch', mode: 'touch', viewport: { width: 390, height: 844 } },
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-smarronata';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -11,7 +12,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
const page = await browser.newPage({ viewport: { width: 1280, height: 860 } });
|
||||
page.on('pageerror', e => { errors.push(e.message); console.log('ERR', e.message); });
|
||||
await page.goto(`http://127.0.0.1:${server.port}/`);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-telefono';
|
||||
mkdirSync(out, { recursive: true });
|
||||
@@ -11,7 +12,7 @@ const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
const page = await browser.newPage({ viewport: { width: 1280, height: 860 } });
|
||||
page.on('pageerror', e => { errors.push(e.message); console.log('ERR', e.message); });
|
||||
await page.goto(`http://127.0.0.1:${server.port}/`);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = '/tmp/regolo-shots'; mkdirSync(out, { recursive: true });
|
||||
const server = await staticServer(), errors = [];
|
||||
@@ -46,7 +47,7 @@ async function wait(page) {
|
||||
});
|
||||
}
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
const scenarios = [
|
||||
{ name: 'desktop-mouse', mode: 'mouse', viewport: { width: 1280, height: 860 }, full: true },
|
||||
{ name: 'telefono-touch', mode: 'touch', viewport: { width: 390, height: 844 } },
|
||||
|
||||
@@ -4,13 +4,14 @@ import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
import { ARGS } from './chromium.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-shots';
|
||||
mkdirSync(out, { recursive: true });
|
||||
const server = await staticServer();
|
||||
let browser;
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
browser = await chromium.launch({ args: ARGS });
|
||||
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
|
||||
const errors = [];
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
|
||||
+10
-2
@@ -2,7 +2,7 @@
|
||||
// e l'impronta cambia solo se cambia un ingresso.
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readdirSync } from 'node:fs';
|
||||
import { readdirSync, readFileSync } from 'node:fs';
|
||||
import { SUITES, ENGINE, inputsOf, ignored, fingerprint, plan } from '../scripts/verify.mjs';
|
||||
|
||||
const FILES = ['index.html', 'style.css', 'src/main.js', 'src/version.js', 'package.json', 'package-lock.json', 'Makefile', 'README.md',
|
||||
@@ -10,7 +10,7 @@ const FILES = ['index.html', 'style.css', 'src/main.js', 'src/version.js', 'pack
|
||||
'src/engine/briscola.js', 'src/engine/briscola-render.js', 'src/engine/flipper.js', 'src/engine/corsa.js', 'src/story/piloti.js',
|
||||
'src/story/story.js', 'src/story/solution.js', 'assets/scenes/piazza.png', 'assets/closeups/micro-parcheggio.png',
|
||||
'assets/closeups/gp/boccino.png', 'assets/muro/index.html', 'assets/video/briscola.mp4', 'docs/BRISCOLA.md', 'docs/STATO.md',
|
||||
'tests/helpers.mjs', 'tests/browser.mjs', 'tests/briscola.browser.mjs', 'tests/briscola.test.mjs', 'tests/story.test.mjs',
|
||||
'tests/helpers.mjs', 'tests/chromium.mjs', 'tests/browser.mjs', 'tests/briscola.browser.mjs', 'tests/briscola.test.mjs', 'tests/story.test.mjs',
|
||||
'scripts/verify.mjs', 'scripts/bump.sh', 'tools/slice_sprites.py', '.verify-ok.json'];
|
||||
const suitesWith = path => Object.keys(SUITES).filter(n => inputsOf(n, FILES).includes(path));
|
||||
const islands = Object.keys(SUITES).filter(n => !SUITES[n].core), cores = Object.keys(SUITES).filter(n => SUITES[n].core);
|
||||
@@ -71,3 +71,11 @@ test("l'impronta cambia solo se cambia un ingresso, e il piano dice quali", () =
|
||||
assert.deepEqual(after.find(p => p.name === 'briscola').changed, ['src/engine/briscola.js']);
|
||||
assert.notEqual(fingerprint(['a'], () => '1'), fingerprint(['a'], () => '2'));
|
||||
});
|
||||
|
||||
test('la pipeline di Gitea prova le stesse prove, con lo stesso Playwright del progetto', () => {
|
||||
const wf = readFileSync('.gitea/workflows/test.yml', 'utf8');
|
||||
const listed = wf.match(/prova: \[([^\]]*)\]/)[1].split(',').map(s => s.trim());
|
||||
assert.deepEqual([...listed].sort(), Object.keys(SUITES).sort());
|
||||
const lock = JSON.parse(readFileSync('package-lock.json', 'utf8')).packages['node_modules/playwright'].version;
|
||||
assert.match(wf, new RegExp(`mcr\\.microsoft\\.com/playwright:v${lock.replace(/\./g, '\\.')}-`), `immagine di Playwright diversa da ${lock}`);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ log:
|
||||
level: info
|
||||
runner:
|
||||
file: .runner
|
||||
capacity: 2
|
||||
capacity: 6
|
||||
timeout: 30m
|
||||
container:
|
||||
network: ""
|
||||
|
||||
Reference in New Issue
Block a user