// Optional UI check: install Playwright, or set CITYGEN_BROWSER_MODULES to its // node_modules folder. Run against `npm run server:dev` with a prepared city. import { createRequire } from 'node:module'; import { resolve } from 'node:path'; import { mkdir } from 'node:fs/promises'; import assert from 'node:assert/strict'; const require = createRequire(process.env.CITYGEN_BROWSER_MODULES ? resolve(process.env.CITYGEN_BROWSER_MODULES,'package.json') : import.meta.url); const { chromium } = require('playwright'); const browser = await chromium.launch({headless:true, executablePath:process.env.CITYGEN_BROWSER_EXECUTABLE}); try { const page = await browser.newPage({viewport:{width:1440,height:1000}}); const errors=[]; page.on('pageerror',error=>errors.push(error.message)); const base=process.env.CITYGEN_TEST_URL || 'http://127.0.0.1:3000'; await page.goto(`${base}/?play`); await page.locator('select option').first().waitFor({state:'attached'}); const city=process.env.CITYGEN_TEST_CITY; if (city) await page.getByRole('combobox',{name:'Город'}).selectOption(city); await page.locator('[name=nickname]').fill(`Smoke-${Date.now()}`); const room=process.env.CITYGEN_TEST_ROOM; const started=performance.now(); if(room) await page.locator(`[data-room="${room}"]`).click(); else await page.getByRole('button',{name:'Создать комнату',exact:true}).click(); await page.locator('.world-canvas').waitFor({timeout:60000}); await page.waitForFunction(()=>document.querySelector('.viewer-top [role=status]')?.textContent.includes('в загруженной области'),null,{timeout:60000}); const visibleMs=Math.round(performance.now()-started); await page.waitForFunction(()=>document.querySelector('.room-clock')?.textContent.includes('День'),null,{timeout:10000}); await page.waitForFunction(()=>document.querySelector('.room-gameplay')?.textContent.includes('Казна'),null,{timeout:10000}); await page.locator('[data-action=meal]').click(); await page.waitForFunction(()=>document.querySelector('[data-action=meal]')?.disabled,null,{timeout:5000}); await page.waitForFunction(()=>document.querySelector('.room-gameplay')?.textContent.includes('Общий обед'),null,{timeout:15000}); await page.getByRole('button',{name:'Пауза',exact:true}).click(); await page.waitForFunction(()=>document.querySelector('.room-clock')?.textContent.includes('×0'),null,{timeout:10000}); await page.getByRole('button',{name:'1',exact:true}).click(); await page.locator('.world-canvas').hover();await page.mouse.wheel(0,-550); await mkdir('.tools',{recursive:true}); await page.screenshot({path:'.tools/browser-room.png'}); assert.deepEqual(errors,[]); console.log(JSON.stringify({ui:'passed',visibleMs,status:await page.locator('.viewer-top').innerText(),screenshot:resolve('.tools/browser-room.png')})); if (process.env.CITYGEN_TEST_ADMIN_TOKEN) { await page.goto(`${base}/?admin`); await page.getByLabel('Токен оператора').fill(process.env.CITYGEN_TEST_ADMIN_TOKEN); await page.getByRole('button',{name:'Обновить',exact:true}).click(); await page.waitForFunction(()=>document.querySelector('[role=status]')?.textContent.includes('МиБ'),null,{timeout:10000}); const saved = page.waitForResponse(r=>r.url().endsWith('/checkpoint') && r.request().method()==='POST'); await page.getByRole('button',{name:'Сохранить',exact:true}).first().click(); assert.equal((await saved).status(),200); console.log(JSON.stringify({admin:'passed'})); } } finally {await browser.close();}