← back to Quadrille Showroom
proto/verify-v7.cjs
75 lines
// Verify v7-moodboard: load it AT the API origin (so fetch is same-origin),
// drag two swatches onto the table, confirm pairs-well-with renders, 0 console errors.
const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');
const HTML = fs.readFileSync(path.join(__dirname, 'v7-moodboard.html'), 'utf8');
const OUT = path.join(__dirname, 'shots', 'v7-moodboard.png');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
const errors = [];
page.on('console', m => { if (m.type() === 'error') errors.push(m.text()); });
page.on('pageerror', e => errors.push('pageerror: ' + e.message));
// Serve our HTML from the API's own origin so the fetch() is same-origin.
await page.route('http://127.0.0.1:7690/__proto.html', r =>
r.fulfill({ status: 200, contentType: 'text/html', body: HTML }));
await page.goto('http://127.0.0.1:7690/__proto.html', { waitUntil: 'networkidle' });
await page.waitForFunction(() => window.__moodboard && window.__moodboard.placed, null, { timeout: 8000 });
await page.waitForSelector('.swatch', { timeout: 8000 });
const loaded = await page.evaluate(() => document.querySelectorAll('.swatch').length);
console.log('tray swatches loaded:', loaded);
// --- drag swatch 1 (real pointer drag from tray onto the board) ---
async function dragNth(n, tx, ty) {
const sw = page.locator('.swatch').nth(n);
const box = await sw.boundingBox();
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + 200, box.y + 50, { steps: 6 });
await page.mouse.move(tx, ty, { steps: 10 });
await page.mouse.up();
await page.waitForTimeout(250);
}
// index 0 = "Aga Apple", index 2 = "Aga Jungle" → same family, must surface as pairs
await dragNth(0, 720, 380);
await dragNth(2, 980, 520);
const placedCount = await page.evaluate(() => window.__moodboard.placed.length);
console.log('placed on table:', placedCount);
// click the first placed card to open Pairs Well With
await page.locator('.placed').first().click({ position: { x: 80, y: 80 } });
await page.waitForTimeout(400);
const pairs = await page.evaluate(() => {
const el = document.querySelector('.pairs');
if (!el) return null;
return {
title: el.querySelector('h3') ? el.querySelector('h3').textContent : '',
rows: [...el.querySelectorAll('.prow .pn')].map(n => n.textContent.trim()),
whys: [...el.querySelectorAll('.prow .why')].map(n => n.textContent.trim()),
};
});
console.log('pairs panel:', JSON.stringify(pairs, null, 2));
const paletteChips = await page.evaluate(() => document.querySelectorAll('.palette-strip .pchip').length);
console.log('palette chips:', paletteChips);
await page.screenshot({ path: OUT });
console.log('screenshot:', OUT);
console.log('CONSOLE ERRORS:', errors.length, errors);
await browser.close();
const ok = loaded > 0 && placedCount === 2 && pairs && pairs.rows.length > 0 && errors.length === 0;
console.log(ok ? '\nVERDICT: PASS' : '\nVERDICT: FAIL');
process.exit(ok ? 0 : 1);
})();