← back to Quadrille Showroom
scripts/verify-roomtypes.mjs
91 lines
// Phase-2 headless verification (playwright). Loads the showroom, asserts 0
// pageerrors / console-errors (ignoring SwiftShader / GL_ / GPU-stall noise),
// switches through all 5 room types, exercises the flooring picker + resizeRoom,
// and asserts furniture is present each time. Saves recordings/roomtype-<type>.png.
//
// RUN (server must be up on :7690):
// node scripts/verify-roomtypes.mjs
//
// playwright is installed globally at ~/.npm-global/lib/node_modules/playwright.
import { createRequire } from 'module';
const require = createRequire('/Users/macstudio3/.npm-global/lib/node_modules/');
const { chromium } = require('playwright');
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const REC = path.join(__dirname, '..', 'recordings');
const URL = process.env.URL || 'http://127.0.0.1:7690/';
const IGNORE = /SwiftShader|GL_|GPU stall|WebGL|Automatic fallback|software rendering|THREE\.WebGLRenderer|Text run|deprecat/i;
const errors = [];
(async () => {
const browser = await chromium.launch({ args: ['--use-gl=swiftshader', '--ignore-gpu-blocklist', '--enable-webgl'] });
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
page.on('pageerror', e => errors.push('PAGEERROR: ' + e.message));
page.on('console', m => { if (m.type() === 'error' && !IGNORE.test(m.text())) errors.push('CONSOLE: ' + m.text()); });
console.log('→ loading', URL);
await page.goto(URL, { waitUntil: 'networkidle', timeout: 45000 });
// Wait for the _qh API + room-type engine to be live.
await page.waitForFunction(() => window._qh && window._qh.ROOM_TYPES && window._qh.buildRoomType, { timeout: 30000 });
// Let products + the deferred room-type build settle.
await page.waitForTimeout(3500);
const types = await page.evaluate(() => window._qh.ROOM_TYPE_ORDER.slice());
console.log('→ room types:', types.join(', '));
const results = [];
for (const t of types) {
const info = await page.evaluate((k) => {
window._qh.buildRoomType(k);
return { type: k, furniture: window._qh.roomTypeFurnitureCount, current: window._qh.currentRoomType, hero: window._qh.heroModelsLoaded };
}, t);
await page.waitForTimeout(1400); // allow GLB lazy-load + frame
const shot = path.join(REC, `roomtype-${t}.png`);
await page.screenshot({ path: shot });
info.furnitureAfterWait = await page.evaluate(() => window._qh.roomTypeFurnitureCount);
info.heroAfterWait = await page.evaluate(() => window._qh.heroModelsLoaded);
console.log(` ${t}: furniture=${info.furnitureAfterWait} hero=${info.heroAfterWait} → ${path.basename(shot)}`);
results.push(info);
}
// Flooring picker.
const floorTest = await page.evaluate(() => {
const before = window._qh.floorOverride;
window._qh.setFloorOverride('stone');
const stone = window._qh.floorOverride;
window._qh.setFloorOverride('oak');
const oak = window._qh.floorOverride;
window._qh.setFloorOverride('default');
return { before, stone, oak, reset: window._qh.floorOverride };
});
console.log('→ flooring:', JSON.stringify(floorTest));
// resizeRoom.
const resizeTest = await page.evaluate(() => {
const r1 = window._qh.resizeRoom(8, 8, 4.2);
return { r1, furniture: window._qh.roomTypeFurnitureCount, dims: window._qh.roomDims };
});
await page.waitForTimeout(1500);
await page.screenshot({ path: path.join(REC, 'roomtype-resized-8x8.png') });
const resizeFurniture = await page.evaluate(() => window._qh.roomTypeFurnitureCount);
console.log('→ resizeRoom(8,8,4.2):', JSON.stringify(resizeTest.r1), 'furniture=', resizeFurniture);
// Resize back to default.
await page.evaluate(() => window._qh.resizeRoom(6.1, 6.1, 2.9));
await page.waitForTimeout(1200);
await browser.close();
console.log('\n========== SUMMARY ==========');
console.log('errors:', errors.length);
errors.forEach(e => console.log(' ' + e));
const allFurnished = results.every(r => r.furnitureAfterWait > 0) && resizeFurniture > 0;
console.log('every room type furnished:', allFurnished);
console.log('resize furnished:', resizeFurniture > 0);
console.log('screenshots saved to recordings/roomtype-*.png');
process.exit(errors.length === 0 && allFurnished ? 0 : 1);
})().catch(e => { console.error('VERIFY FAILED:', e); process.exit(2); });