Files
VoiceStudio/frontend/playwright.config.ts
T
Palash DebnathandClaude Opus 4.8 c857be816a fix(gallery): OmniVoice Gallery rename, dark dropdowns, and noisy/stale archetype previews (#241)
* fix(gallery): rename to "OmniVoice Gallery" + fix dark-theme dropdown colors

The gallery heading now reads "OmniVoice Gallery" (gallery.title, all 21
locales — brand prefix on each localized word).

The facet filter <select>s (Gender/Age/Pitch/Accent/Language) rendered with
the OS-default light control surface on the dark theme: .facet-select set
background/border from --bg-tertiary / --border-color, which are defined
nowhere. An undefined var() reads as transparent on the sibling <div> filters
(fine over the dark page) but falls back to the native light background on a
form control. Switch to the defined dark-chrome tokens and add
color-scheme: dark + an explicit dark option list so the popup matches across
WebKit / WebView2 / WebKitGTK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(gallery): archetype previews render a noise buzz instead of voice

The Hype Host, The Podcaster and The Vlogger previews played a loud tonal
buzz, not speech. The preview renderer pinned num_step=16 and seed=42; the
"social" sample script at that exact point lands on a degenerate diffusion
trajectory and collapses to a near-pure tone. The blank-audio guard missed it
because the buzz is loud (peaks near -2 dBFS), not silent — so the garbage was
cached and served. The cache key is (instruct, language) only, so it never
self-corrected.

- Bump preview num_step 16 -> 32: reliably converges to speech across the
  gallery's instruct/script space (one-time, cached render cost).
- Add a spectral-flatness floor (_is_unusable_audio) so a degenerate tonal
  render is rejected like a blank one, reusing the existing retry-on-new-seed
  path. Whisper/breathy voices are broadband (high flatness) so they're safe.

Verified: flatness Hype Host 0.001->0.050, Podcaster 0.0002->0.083,
Vlogger 0.004->0.039; whisper control (Calm Guide) 0.239, not flagged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(gallery): stop preview playback replaying stale cached audio

Preview audio is re-rendered server-side when an archetype is fixed, but the
URL is stable and the response carried no Cache-Control — so the WebView's
HTTP cache replayed the first clip it ever fetched (e.g. the old buzz)
indefinitely, even after the server file was corrected.

- Frontend: fetch previews with { cache: 'no-store' } so playback always
  pulls current bytes.
- Backend: send Cache-Control: no-cache on the preview response so any client
  revalidates against the ETag instead of serving a stale clip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(e2e): add Playwright UI smoke + gallery specs and preview-quality unit test

UI testing system to catch regressions like "Use design → Importing a module
script failed" (a dead Vite/module server) and the noisy-preview bug.

- Playwright (frontend/e2e): drives the system chromium (no browser download)
  against the Vite dev server. ui-smoke mounts all 12 routable views and fails
  on any code-split/import failure, uncaught exception, or ErrorBoundary
  fallback. gallery.spec asserts the "OmniVoice Gallery" heading, the dark
  facet dropdowns (computed bg = rgba(255,255,255,0.04), not the OS-default
  light surface), and that opening an archetype in the Designer mounts the
  lazy CloneDesignTab. `bun run e2e`.
- backend/tests/test_archetype_preview_quality.py: unit-tests the
  _spectral_flatness / _is_unusable_audio guard with synthetic signals
  (tone < threshold < speech < noise; loud tone + silence are unusable) and
  pins the render constants. CI-safe — no model/GPU.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 08:34:46 +05:30

32 lines
1.0 KiB
TypeScript

import { defineConfig, devices } from '@playwright/test';
// E2E runs against the Vite dev server (UI on :3901, backend on :3900). It
// drives the SYSTEM chromium (no `playwright install` browser download) — set
// PLAYWRIGHT_CHROMIUM to override the path. reuseExistingServer keeps a dev
// session you already have running; CI starts its own `bun run dev`.
const PORT = Number(process.env.E2E_PORT || 3901);
export default defineConfig({
testDir: './e2e',
timeout: 45_000,
expect: { timeout: 10_000 },
fullyParallel: false,
retries: process.env.CI ? 1 : 0,
reporter: [['list']],
use: {
baseURL: `http://localhost:${PORT}`,
headless: true,
trace: 'retain-on-failure',
launchOptions: {
executablePath: process.env.PLAYWRIGHT_CHROMIUM || '/usr/bin/chromium',
},
},
projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
webServer: {
command: 'bun run dev',
url: `http://localhost:${PORT}`,
reuseExistingServer: true,
timeout: 60_000,
},
});