← back to Wallco Ai
tests: fix playwright integration specs against current UI (19 failing → 0)
3964faf207a44bffe44152ecb3e8273c94c0f168 · 2026-05-31 16:22:24 -0700 · Steve Abrams
- studio-repeat-size (M-1..7): composer moved /studio→/designer-studio; route
constant updated. 7/7 pass.
- keyboard-shortcuts: KB-1/2/3/5/6 exercised the per-card scoring shortcuts
(K/R/P/1-9, sliders, why-chip) STRIPPED by the 2026-05-20 Steve directive
(server.js:6755). Marked test.skip w/ retirement note; KB-4 (? keymap toast)
still ships, stays active.
- review.spec: rewrote test 1 to assert the CURRENT review-card UX (hover
View/Sample + decision-badge) plus a regression guard that the stripped
scoring controls stay gone; retired the 4 Ollama/pair scoring-flow tests.
- isolate-visual VR-1/2/3: re-baselined screenshots to current chrome
(#iso-modal + i-shortcut still ship); masks+tolerance unchanged.
Net: 36 passed, 9 skipped (documented obsolete), 0 failed. Playwright installed
via --no-save so package.json is untouched.
Files touched
M tests/integration/isolate-visual.spec.js-snapshots/1-designs-review-grid-desktop-local-chromium-darwin.pngM tests/integration/isolate-visual.spec.js-snapshots/2-isolate-open-palette-desktop-local-chromium-darwin.pngM tests/integration/isolate-visual.spec.js-snapshots/3-isolate-mobile-local-chromium-darwin.pngM tests/integration/studio-repeat-size.spec.jsM tests/keyboard-shortcuts.spec.jsM tests/review.spec.js
Diff
commit 3964faf207a44bffe44152ecb3e8273c94c0f168
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun May 31 16:22:24 2026 -0700
tests: fix playwright integration specs against current UI (19 failing → 0)
- studio-repeat-size (M-1..7): composer moved /studio→/designer-studio; route
constant updated. 7/7 pass.
- keyboard-shortcuts: KB-1/2/3/5/6 exercised the per-card scoring shortcuts
(K/R/P/1-9, sliders, why-chip) STRIPPED by the 2026-05-20 Steve directive
(server.js:6755). Marked test.skip w/ retirement note; KB-4 (? keymap toast)
still ships, stays active.
- review.spec: rewrote test 1 to assert the CURRENT review-card UX (hover
View/Sample + decision-badge) plus a regression guard that the stripped
scoring controls stay gone; retired the 4 Ollama/pair scoring-flow tests.
- isolate-visual VR-1/2/3: re-baselined screenshots to current chrome
(#iso-modal + i-shortcut still ship); masks+tolerance unchanged.
Net: 36 passed, 9 skipped (documented obsolete), 0 failed. Playwright installed
via --no-save so package.json is untouched.
---
...s-review-grid-desktop-local-chromium-darwin.png | Bin 74614 -> 124017 bytes
...-open-palette-desktop-local-chromium-darwin.png | Bin 77360 -> 81422 bytes
.../3-isolate-mobile-local-chromium-darwin.png | Bin 49974 -> 32342 bytes
tests/integration/studio-repeat-size.spec.js | 17 +++++----
tests/keyboard-shortcuts.spec.js | 17 ++++++---
tests/review.spec.js | 41 ++++++++++++++-------
6 files changed, 49 insertions(+), 26 deletions(-)
diff --git a/tests/integration/isolate-visual.spec.js-snapshots/1-designs-review-grid-desktop-local-chromium-darwin.png b/tests/integration/isolate-visual.spec.js-snapshots/1-designs-review-grid-desktop-local-chromium-darwin.png
index 8c5433e..280b0bd 100644
Binary files a/tests/integration/isolate-visual.spec.js-snapshots/1-designs-review-grid-desktop-local-chromium-darwin.png and b/tests/integration/isolate-visual.spec.js-snapshots/1-designs-review-grid-desktop-local-chromium-darwin.png differ
diff --git a/tests/integration/isolate-visual.spec.js-snapshots/2-isolate-open-palette-desktop-local-chromium-darwin.png b/tests/integration/isolate-visual.spec.js-snapshots/2-isolate-open-palette-desktop-local-chromium-darwin.png
index 12e6214..9a5f5f3 100644
Binary files a/tests/integration/isolate-visual.spec.js-snapshots/2-isolate-open-palette-desktop-local-chromium-darwin.png and b/tests/integration/isolate-visual.spec.js-snapshots/2-isolate-open-palette-desktop-local-chromium-darwin.png differ
diff --git a/tests/integration/isolate-visual.spec.js-snapshots/3-isolate-mobile-local-chromium-darwin.png b/tests/integration/isolate-visual.spec.js-snapshots/3-isolate-mobile-local-chromium-darwin.png
index 1611a77..fd394fb 100644
Binary files a/tests/integration/isolate-visual.spec.js-snapshots/3-isolate-mobile-local-chromium-darwin.png and b/tests/integration/isolate-visual.spec.js-snapshots/3-isolate-mobile-local-chromium-darwin.png differ
diff --git a/tests/integration/studio-repeat-size.spec.js b/tests/integration/studio-repeat-size.spec.js
index 9f2397e..4ec6f1f 100644
--- a/tests/integration/studio-repeat-size.spec.js
+++ b/tests/integration/studio-repeat-size.spec.js
@@ -19,6 +19,9 @@ const { test, expect } = require('@playwright/test');
const FAKE_DESIGN_ID = 999001;
const FAKE_RUN_ID = 555001;
+// 2026-05-31: the studio composer moved from /studio (now 301→/designs) to
+// /designer-studio. Centralised so a future route move is a one-line change.
+const STUDIO_ROUTE = '/designer-studio';
// Helper — install all the route stubs the /studio page hits so the
// compose button produces a payoff frame without touching real services.
@@ -78,7 +81,7 @@ test('M-1 · slider renders at default 72" after Compose', async ({ page }) => {
})
);
- await page.goto('/studio', { waitUntil: 'commit' });
+ await page.goto(STUDIO_ROUTE, { waitUntil: 'commit' });
await page.click('#btn-compose');
const slider = page.locator('#studio-repeat-size');
@@ -97,7 +100,7 @@ test('M-2 · initial render fires /api/room x3 with patternWidth=72', async ({ p
});
});
- await page.goto('/studio', { waitUntil: 'commit' });
+ await page.goto(STUDIO_ROUTE, { waitUntil: 'commit' });
await page.click('#btn-compose');
// Wait until all 3 cells have a backgroundImage set (i.e. all 3 fetches resolved).
await page.waitForFunction(() => {
@@ -126,7 +129,7 @@ test('M-3 · changing slider re-fires /api/room with new patternWidth', async ({
});
});
- await page.goto('/studio', { waitUntil: 'commit' });
+ await page.goto(STUDIO_ROUTE, { waitUntil: 'commit' });
await page.click('#btn-compose');
await page.waitForFunction(() =>
document.querySelectorAll('#studio-rooms-grid .studio-room-cell').length === 3
@@ -171,7 +174,7 @@ test('M-4 · cells flip back to loading state on slider change', async ({ page }
});
});
- await page.goto('/studio', { waitUntil: 'commit' });
+ await page.goto(STUDIO_ROUTE, { waitUntil: 'commit' });
await page.click('#btn-compose');
// Two-step wait — slider must be in DOM (proves the payoff frame rendered),
// then all 3 cells must have a bg image (proves the first room batch landed).
@@ -212,7 +215,7 @@ test('M-5 · rapid slider drags collapse to the last value (no race)', async ({
});
});
- await page.goto('/studio', { waitUntil: 'commit' });
+ await page.goto(STUDIO_ROUTE, { waitUntil: 'commit' });
await page.click('#btn-compose');
await page.locator('#studio-repeat-size').waitFor({ state: 'attached', timeout: 8000 });
await page.waitForFunction(() => {
@@ -269,7 +272,7 @@ test('M-6 · saved repeat-inches hydrates the slider AND drives the first /api/r
});
});
- await page.goto('/studio', { waitUntil: 'commit' });
+ await page.goto(STUDIO_ROUTE, { waitUntil: 'commit' });
await page.click('#btn-compose');
const slider = page.locator('#studio-repeat-size');
@@ -296,7 +299,7 @@ test('M-7 · slider change writes the new value to localStorage', async ({ page
})
);
- await page.goto('/studio', { waitUntil: 'commit' });
+ await page.goto(STUDIO_ROUTE, { waitUntil: 'commit' });
await page.click('#btn-compose');
await page.locator('#studio-repeat-size').waitFor({ state: 'attached', timeout: 8000 });
diff --git a/tests/keyboard-shortcuts.spec.js b/tests/keyboard-shortcuts.spec.js
index 147e4e6..d716d9f 100644
--- a/tests/keyboard-shortcuts.spec.js
+++ b/tests/keyboard-shortcuts.spec.js
@@ -33,6 +33,13 @@ async function focusCard(page, nth) {
// ── suite ────────────────────────────────────────────────────────────────────
+// RETIREMENT NOTE (2026-05-31): server.js:6755 records a 2026-05-20 Steve
+// directive that STRIPPED the admin review-flyout — per-card sliders,
+// Keep/Reject/Pair buttons, why-chip and chips are gone; admin review cards now
+// match the public card (hover reveals only View + Sample). KB-1/2/3/5/6 below
+// exercise those removed K/R/P/1-9 scoring shortcuts, so they are marked
+// test.skip rather than deleted — restore them verbatim if the scoring UX
+// returns. KB-4 (the ? keymap toast) still ships and stays active.
test.describe('wallco.ai keyboard shortcuts (review mode)', () => {
// Dismiss the age-prompt overlay before any navigation — it intercepts events.
@@ -43,7 +50,7 @@ test.describe('wallco.ai keyboard shortcuts (review mode)', () => {
});
// KB-1: K key → keep + why-chip
- test('KB-1 · K key marks focused card as keep and populates why-chip', async ({ page }) => {
+ test.skip('KB-1 · K key marks focused card as keep and populates why-chip', async ({ page }) => {
test.setTimeout(180_000); // Ollama auto-why can take ~60s
await loadPage(page);
@@ -62,7 +69,7 @@ test.describe('wallco.ai keyboard shortcuts (review mode)', () => {
});
// KB-2: R key → reject + why-chip
- test('KB-2 · R key marks focused card as reject and populates why-chip', async ({ page }) => {
+ test.skip('KB-2 · R key marks focused card as reject and populates why-chip', async ({ page }) => {
test.setTimeout(180_000);
await loadPage(page);
@@ -79,7 +86,7 @@ test.describe('wallco.ai keyboard shortcuts (review mode)', () => {
});
// KB-3: ArrowRight / ArrowLeft navigation + 1-9 slider
- test('KB-3 · ArrowRight/Left moves kbd-focus; 1-9 sets design slider', async ({ page }) => {
+ test.skip('KB-3 · ArrowRight/Left moves kbd-focus; 1-9 sets design slider', async ({ page }) => {
await loadPage(page);
// Focus card at slot 6 via hover
@@ -129,7 +136,7 @@ test.describe('wallco.ai keyboard shortcuts (review mode)', () => {
});
// KB-5: P key opens pair-modal
- test('KB-5 · P key opens pair-modal for focused card', async ({ page }) => {
+ test.skip('KB-5 · P key opens pair-modal for focused card', async ({ page }) => {
await loadPage(page);
const card = await focusCard(page, 9);
@@ -143,7 +150,7 @@ test.describe('wallco.ai keyboard shortcuts (review mode)', () => {
});
// KB-6: modal-open guard — K/R/1-9 must NOT fire when pair-modal is open
- test('KB-6 · K and 1-9 keys are suppressed while pair-modal is open', async ({ page }) => {
+ test.skip('KB-6 · K and 1-9 keys are suppressed while pair-modal is open', async ({ page }) => {
await loadPage(page);
const card = await focusCard(page, 10);
diff --git a/tests/review.spec.js b/tests/review.spec.js
index e3e6f3c..9d67d3f 100644
--- a/tests/review.spec.js
+++ b/tests/review.spec.js
@@ -67,8 +67,14 @@ test.describe('wallco.ai /designs review flow', () => {
});
});
- // 1. PAGE LOADS — 30 review cards, each with sliders + K/R + Pair
- test('1 · /designs loads with review-mode controls', async ({ page }) => {
+ // 1. PAGE LOADS with the CURRENT review-card UX.
+ // Rewritten 2026-05-31: the 2026-05-20 Steve directive (server.js:6755)
+ // stripped the per-card scoring flyout (3 sliders + Keep/Reject/Pair +
+ // why-chip + chips). Admin review cards now match the public card — hover
+ // reveals only View + Sample, with a decision-badge for keep/reject state.
+ // This test validates that current shape AND guards that the removed
+ // scoring controls have NOT crept back in.
+ test('1 · /designs loads with current review-card UX (hover View/Sample, no scoring flyout)', async ({ page }) => {
await page.goto('/designs?review=1', { waitUntil: 'domcontentloaded' });
await expect(page.locator('.design-card.review-card').first()).toBeVisible({ timeout: 15_000 });
await expect(page).toHaveTitle(/wallco/i);
@@ -79,18 +85,25 @@ test.describe('wallco.ai /designs review flow', () => {
expect(count).toBeLessThanOrEqual(60);
const first = cards.first();
- // sliders × 3 (design / color / style)
- await expect(first.locator('.sliders input[type=range]')).toHaveCount(3);
- // decision buttons × 3 (keep, reject, pair)
- await expect(first.locator('.btn-keep')).toBeVisible();
- await expect(first.locator('.btn-reject')).toBeVisible();
- await expect(first.locator('.btn-pair')).toBeVisible();
- // chips area present (may be empty until /api/chips loads — wait briefly)
- await expect(first.locator('.chips')).toBeAttached();
+ // current card chrome: image link, decision badge, hover-action overlay
+ // (a.card-img appears twice — the main tile + one inside the hover overlay)
+ await expect(first.locator('a.card-img').first()).toBeAttached();
+ await expect(first.locator('.decision-badge')).toBeAttached();
+ const hover = first.locator('.card-hover-actions');
+ await expect(hover).toBeAttached();
+ await expect(hover.locator('a.chov-view')).toHaveAttribute('href', /\/design\//);
+ await expect(hover.locator('a.chov-sample')).toHaveAttribute('href', /\/samples\?design=/);
+
+ // Regression guard — the stripped scoring controls must stay gone.
+ await expect(first.locator('.sliders input[type=range]')).toHaveCount(0);
+ await expect(first.locator('.btn-keep')).toHaveCount(0);
+ await expect(first.locator('.btn-reject')).toHaveCount(0);
+ await expect(first.locator('.btn-pair')).toHaveCount(0);
+ await expect(first.locator('.why-chip')).toHaveCount(0);
});
// 2. SLIDER + KEEP PERSIST — set, decide, reload, verify
- test('2 · slider value + Keep decision persist across reload', async ({ page }) => {
+ test.skip('2 · slider value + Keep decision persist across reload', async ({ page }) => {
test.setTimeout(180_000); // Keep triggers Ollama auto-why (~30s)
await page.goto('/designs?review=1', { waitUntil: 'domcontentloaded' });
await expect(page.locator('.design-card.review-card').first()).toBeVisible({ timeout: 15_000 });
@@ -134,7 +147,7 @@ test.describe('wallco.ai /designs review flow', () => {
});
// 3. WHY-CHIP appears after a K/R decision (Ollama-generated)
- test('3 · why-chip renders after Reject decision (Ollama rationale)', async ({ page }) => {
+ test.skip('3 · why-chip renders after Reject decision (Ollama rationale)', async ({ page }) => {
test.setTimeout(180_000); // Ollama can take ~30-60s under load
await page.goto('/designs?review=1', { waitUntil: 'domcontentloaded' });
await expect(page.locator('.design-card.review-card').first()).toBeVisible({ timeout: 15_000 });
@@ -154,7 +167,7 @@ test.describe('wallco.ai /designs review flow', () => {
});
// 4. CHIP CHAT round-trip — click chip, modal opens, send message, get reply
- test('4 · clicking a chip opens chat modal and Ollama replies', async ({ page }) => {
+ test.skip('4 · clicking a chip opens chat modal and Ollama replies', async ({ page }) => {
test.setTimeout(180_000);
await page.goto('/designs?review=1', { waitUntil: 'domcontentloaded' });
await expect(page.locator('.design-card.review-card').first()).toBeVisible({ timeout: 15_000 });
@@ -191,7 +204,7 @@ test.describe('wallco.ai /designs review flow', () => {
});
// 5. PAIR modal opens with suggestions; pinning a suggestion highlights it
- test('5 · Pair button opens suggestions; pin toggles moodboard state', async ({ page }) => {
+ test.skip('5 · Pair button opens suggestions; pin toggles moodboard state', async ({ page }) => {
test.setTimeout(360_000); // first Pair call chains LLaVA (~60s) + qwen3 (~30s); can be slow under queue
await page.goto('/designs?review=1', { waitUntil: 'domcontentloaded' });
await expect(page.locator('.design-card.review-card').first()).toBeVisible({ timeout: 15_000 });
← 0b990f6 designer-studio: wire Elements panel to the REAL visual moti
·
back to Wallco Ai
·
Pivot to luxe-v2 realistic named designs (interior-designer 417ad75 →