← 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);
})();