Suoni d'ambiente sintetizzati (vento, acqua, uccelli, grilli, campane) col loro volume in Pausa; la fessura in primo piano: si cerca col fascio della torcia il quadro e gli occhi (lavoro di Codex). La foto del palio leggibile da nginx, e un test che lo controlla per tutti i file serviti
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ks2K99uqCZjAxvy7Rdj1R
This commit is contained in:
+35
-4
@@ -6,6 +6,7 @@ import { staticServer } from './helpers.mjs';
|
||||
import { mkdirSync, readFileSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { solution, route } from '../src/story/solution.js';
|
||||
import { checkMultimedia } from './multimedia.browser.mjs';
|
||||
|
||||
const OUT = process.env.OUT ?? '/tmp/regolo-shots';
|
||||
mkdirSync(OUT, { recursive: true });
|
||||
@@ -47,6 +48,8 @@ const hotspotCenter = async (page, id) => {
|
||||
};
|
||||
|
||||
try {
|
||||
await checkMultimedia(browser, PORT, OUT, errors);
|
||||
if (!process.argv.includes('--media-only')) {
|
||||
const page = await open({ width: 1280, height: 860 });
|
||||
// Il cartello d'apertura, poi da solo il titolo.
|
||||
assert.match(await page.textContent('#splash'), /Manzolo\s*\(Poca\)\s*Art\s*Presents/);
|
||||
@@ -66,10 +69,22 @@ try {
|
||||
// Col codice lento ad arrivare (rete vera) il cartello aspetta il titolo: non sfuma prima per conto suo.
|
||||
{
|
||||
const slow = await browser.newPage({ viewport: { width: 1280, height: 860 } });
|
||||
// Misura al momento dell'apparizione: il polling di Playwright può arrivare dopo
|
||||
// diversi fotogrammi su una macchina occupata, quando la dissolvenza è già in corso.
|
||||
await slow.addInitScript(() => {
|
||||
const observer = new MutationObserver(() => {
|
||||
const title = document.getElementById('title'), splash = document.getElementById('splash');
|
||||
if (title && !title.hidden && splash) {
|
||||
window.titleRevealOpacity = Number(getComputedStyle(splash).opacity);
|
||||
observer.disconnect();
|
||||
}
|
||||
});
|
||||
observer.observe(document, { subtree: true, childList: true, attributes: true, attributeFilter: ['hidden'] });
|
||||
});
|
||||
await slow.route('**/src/main.js', async route => { await new Promise(r => setTimeout(r, 2000)); await route.continue(); });
|
||||
await slow.goto(`http://127.0.0.1:${PORT}/`);
|
||||
await slow.waitForSelector('#title:not([hidden])', { timeout: 12000 });
|
||||
const opacity = await slow.evaluate(() => Number(getComputedStyle(document.getElementById('splash')).opacity));
|
||||
const opacity = await slow.evaluate(() => window.titleRevealOpacity);
|
||||
assert.ok(opacity > 0.9, `il cartello era già sfumato (${opacity}) quando è comparso il titolo`);
|
||||
await slow.close();
|
||||
}
|
||||
@@ -182,12 +197,13 @@ try {
|
||||
await page.click('#mute');
|
||||
await page.locator('#volume').fill('30');
|
||||
await page.locator('#voice-volume').fill('70');
|
||||
assert.deepEqual(await page.evaluate(() => JSON.parse(localStorage.getItem('leggenda-regolo-audio'))), { volume: 0.3, muted: false, voices: 0.7 });
|
||||
assert.deepEqual(await page.evaluate(() => JSON.parse(localStorage.getItem('leggenda-regolo-audio'))), { volume: 0.3, muted: false, voices: 0.7, effects: 0.45 });
|
||||
assert.equal(await page.evaluate(() => voices.volume), 0.7);
|
||||
// Sul telefono si passa a un'altra app: la pagina diventa nascosta, la musica si ferma subito e la partita va in
|
||||
// pausa; tornando la musica riparte solo con Riprendi (la pausa la tiene ferma).
|
||||
const hide = hidden => page.evaluate(h => { Object.defineProperty(document, 'hidden', { value: h, configurable: true }); document.dispatchEvent(new Event('visibilitychange')); }, hidden);
|
||||
await hide(true);
|
||||
assert.equal(await page.evaluate(() => ambience.nodes.size), 0, 'nascosta la pagina, gli effetti si fermano subito');
|
||||
assert.ok(await page.evaluate(() => music.current.audio.paused), 'nascosta la pagina, la musica è ferma');
|
||||
assert.ok(await page.isVisible('#pause'), 'e la partita è in pausa');
|
||||
await hide(false);
|
||||
@@ -211,8 +227,21 @@ try {
|
||||
if (verb === 'talk') await page.screenshot({ path: `${OUT}/03-dialogo.png` });
|
||||
// La torcia nella fessura: il palio illuminato e i due occhi gialli, prima che spariscano.
|
||||
if (target === 'fessura' && item) {
|
||||
await page.waitForFunction(() => game.state.flags.occhi_regolo, null, { timeout: 30000 });
|
||||
await page.screenshot({ path: `${OUT}/05b-occhi.png` });
|
||||
await page.waitForFunction(() => game.closeup?.id === 'fessura', null, { timeout: 30000 });
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const at = await page.evaluate(i => game.story.closeups.fessura.targets[i].at, i);
|
||||
const box = await page.locator('#scene').boundingBox();
|
||||
await page.mouse.move(box.x + at[0] / 640 * box.width, box.y + at[1] / 360 * box.height);
|
||||
await page.waitForFunction(() => game.closeup?.step === 'reveal');
|
||||
await page.screenshot({ path: `${OUT}/05b-fessura-${i}.png` });
|
||||
for (let n = 0; n < 200; n++) {
|
||||
if (await page.evaluate(i => game.closeup.found > i, i)) break;
|
||||
if (await page.evaluate(() => !!game.speech)) await page.keyboard.press('Space');
|
||||
await page.waitForTimeout(30);
|
||||
}
|
||||
assert.equal(await page.evaluate(() => game.closeup.found), i + 1);
|
||||
}
|
||||
await page.click('#closeup-close');
|
||||
}
|
||||
await settle(page);
|
||||
if (target === 'cosa_luccicante') await page.screenshot({ path: `${OUT}/04-squama.png` });
|
||||
@@ -386,6 +415,8 @@ try {
|
||||
|
||||
assert.deepEqual(errors, [], 'errori nella console');
|
||||
console.log(`Browser OK: soluzione completa, ripresa del salvataggio, telefono. Schermate in ${OUT}`);
|
||||
}
|
||||
assert.deepEqual(errors, [], 'errori nella console');
|
||||
} finally {
|
||||
await browser.close();
|
||||
server.kill();
|
||||
|
||||
Reference in New Issue
Block a user