fix(gate-b): Svelte 5 event directives + label/input association for Select Photos

- Add id='photo-file-input' to file input and for='photo-file-input' to label
- Convert on:change → onchange, on:click → onclick, on:input → oninput
  (Svelte 5 requires native DOM event properties, not on: directives)
- Add Playwright BVT suite confirming file selection → mask step advance
- Test image: 100x60 PNG with green border (hue=66°) and white interior
This commit is contained in:
grokbot_ty
2026-09-07 19:38:46 +00:00
parent 2a8b0e5518
commit 17b6e6ccd6
6 changed files with 235 additions and 24 deletions
+64
View File
@@ -0,0 +1,64 @@
import { test, expect } from '@playwright/test';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const TEST_IMAGE = resolve(__dirname, 'test-slab.png');
test.describe('Select Photos BVT', () => {
test('label "Select Photos" has for attribute pointing to the file input id', async ({ page }) => {
await page.goto('/');
const label = page.locator('label.file-label');
await expect(label).toBeVisible();
const forAttr = await label.getAttribute('for');
expect(forAttr).toBe('photo-file-input');
const fileInput = page.locator('#photo-file-input');
await expect(fileInput).toHaveAttribute('type', 'file');
});
test('file selection advances to mask step', async ({ page }) => {
await page.goto('/');
const fileInput = page.locator('#photo-file-input');
await fileInput.setInputFiles(TEST_IMAGE);
// handleFiles runs → state.step becomes 'mask'
await expect(page.locator('h2')).toContainText('Mask & Knobs');
await expect(page.locator('.knobs-panel')).toBeVisible();
// Photo selector should have one option
const photoSelect = page.locator('.photo-selector select');
await expect(photoSelect).toBeVisible();
const optionCount = await photoSelect.locator('option').count();
expect(optionCount).toBe(1);
});
test('Process Photos button is enabled after file selection', async ({ page }) => {
await page.goto('/');
const fileInput = page.locator('#photo-file-input');
await fileInput.setInputFiles(TEST_IMAGE);
// After processing, the mask step appears with Confirm Mask button
await expect(page.locator('h2')).toContainText('Mask & Knobs');
const confirmBtn = page.locator('button:has-text("Confirm Mask")');
await expect(confirmBtn).toBeEnabled();
});
test('full flow: select photo → mask step appears → knobs can be adjusted', async ({ page }) => {
await page.goto('/');
const fileInput = page.locator('#photo-file-input');
await fileInput.setInputFiles(TEST_IMAGE);
// Should advance to mask step
await expect(page.locator('h2')).toContainText('Mask & Knobs');
await expect(page.locator('.knobs-panel')).toBeVisible();
// Verify knobs are present and adjustable
const sensitivitySlider = page.locator('input[type="range"]');
await expect(sensitivitySlider.first()).toBeVisible();
});
});