const { chromium } = require('C:/Users/phenom/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright'); const fs = require('node:fs'); const path = require('node:path'); const { DEFAULT_TEST_DUNGEON_ID } = require('./playtest-defaults.cjs'); // Start the review server with node scripts/dungeon-pipeline/serve-environment-preview.mjs. // Captures are isolated asset QA, not movement or encounter proof. const output = path.resolve('artifacts/playtest/wow-environment-quality'); const resume = process.argv.includes('--resume'); const requested = process.argv.slice(2).filter((entry) => entry !== '--resume'); const baseUrl = process.env.WOW_ENVIRONMENT_REVIEW_URL || 'http://127.0.0.1:4208'; fs.mkdirSync(output, { recursive: true }); (async () => { const browser = await chromium.launch({ channel: 'msedge', headless: true }); const resultsFile = path.join(output, 'results.json'); const results = (resume || requested.length) && fs.existsSync(resultsFile) ? JSON.parse(fs.readFileSync(resultsFile, 'utf8')).results.filter((entry) => !requested.includes(entry.id)) : []; try { const discovery = await browser.newPage(); discovery.on('pageerror', (error) => console.error(`Discovery: ${error.stack}`)); await discovery.goto(`${baseUrl}/scripts/dungeon-pipeline/environment-preview.html?dungeon=${DEFAULT_TEST_DUNGEON_ID}`, { waitUntil: 'domcontentloaded', timeout: 180_000 }); await discovery.waitForFunction(() => window.wowEnvironmentReview?.ready, null, { timeout: 60_000 }); const catalog = await discovery.evaluate(() => window.wowEnvironmentReview.catalog); await discovery.close(); const ids = requested.length ? requested : [DEFAULT_TEST_DUNGEON_ID, ...catalog.map((entry) => entry.id)]; for (const id of ids) { if (resume && results.some((entry) => entry.id === id && entry.status === 'loaded')) continue; const previous = results.findIndex((entry) => entry.id === id); if (previous >= 0) results.splice(previous, 1); const context = await browser.newContext({ viewport: { width: 1280, height: 800 } }); const page = await context.newPage(); const errors = []; page.on('pageerror', (error) => errors.push(error.message)); page.on('console', (message) => { if (message.type() === 'error') errors.push(message.text()); }); try { await page.goto(`${baseUrl}/scripts/dungeon-pipeline/environment-preview.html?dungeon=${encodeURIComponent(id)}`, { waitUntil: 'domcontentloaded', timeout: 180_000 }); await page.waitForFunction(() => window.wowEnvironmentReview?.ready, null, { timeout: 180_000 }); const data = await page.evaluate(() => ({ viewpoints: window.wowEnvironmentReview.viewpoints, presentation: window.wowEnvironmentReview.presentation })); await page.waitForTimeout(300); await page.screenshot({ path: path.join(output, `${id}-standard.png`) }); const standard = await page.evaluate(() => window.wowEnvironmentReview.diagnostics()); await page.evaluate(() => window.wowEnvironmentReview.setQuality('high')); const views = [...new Set([0, Math.floor((data.viewpoints.length - 1) / 2), data.viewpoints.length - 1])]; for (const viewpoint of views) { await page.evaluate((value) => window.wowEnvironmentReview.view(value), viewpoint); await page.waitForTimeout(300); await page.screenshot({ path: path.join(output, `${id}-high-view-${viewpoint}.png`) }); } await page.evaluate(() => window.wowEnvironmentReview.view(0, Math.PI)); await page.waitForTimeout(300); await page.screenshot({ path: path.join(output, `${id}-entrance-reverse.png`) }); const high = await page.evaluate(() => window.wowEnvironmentReview.diagnostics()); if (high.lightTarget.some((value, index) => Math.abs(value - high.camera[index]) > 0.00001)) errors.push('High light target does not track the camera'); if (high.textures.some((texture) => texture.anisotropy !== Math.min(16, high.maxAnisotropy))) errors.push('High texture filtering was not applied'); results.push({ id, status: errors.length ? 'error' : 'loaded', errors, standard, high, ...data }); console.log(`${id}: ${errors.length ? 'ERROR' : 'loaded'}; ${high.textures.length} textures; ${high.casters} High casters`); } catch (error) { results.push({ id, status: 'error', errors: [...errors, error.message] }); await page.screenshot({ path: path.join(output, `${id}-failure.png`) }).catch(() => {}); console.error(`${id}: ${error.message}`); } finally { await context.close(); fs.writeFileSync(path.join(output, 'results.json'), `${JSON.stringify({ scope: 'isolated shipping asset review: entrance Standard/High, midpoint/final boss-area High, reverse entrance; no traversal or combat certification', results }, null, 2)}\n`); } } } finally { await browser.close(); } if (results.some((entry) => entry.status === 'error')) process.exitCode = 1; })().catch((error) => { console.error(error); process.exitCode = 1; });