feat(ui): redesign voice cockpit with clinical companion drawer, Svelte 5 migration, and Gemini 3.8 voice

- Re-architect VoiceSession into full-bleed studio cockpit with overlay slide-over companion drawer
- Eliminate width squishing defect on LiveInsightPanel and add native dark/light theme support
- Integrate authentic Google Gemini 3.8 Flash TTS with Fenrir persona and fallback audio pipeline
- Implement comprehensive Playwright E2E visual regression suite across Desktop, iPad, and iPhone (21 tests, 45 snapshots)
- Migrate core application to Svelte 5 runes (, , ) with reactive stores
- Maintain .NET 8 Azure Functions serverless endpoints and clean build hygiene
This commit is contained in:
jpremill committed 2026-09-29 23:35:05 -04:00
1 parent c82b112624
commit 1feea40684
148 files changed
+11230 -1706

No files matched your search

@@ -0,0 +1,66 @@
import { test, expect } from '@playwright/test';
import fs from 'fs';
import path from 'path';
test.describe('Landing Page & Scenario Navigation', () => {
test.beforeEach(async ({ page }) => {
// Clear localStorage to ensure fresh deterministic initial state
await page.addInitScript(() => {
window.localStorage.clear();
window.localStorage.setItem('cognitive-clarity-settings', JSON.stringify({
voiceName: 'Zephyr',
vocalStyle: 'Helpful',
genderPreference: 'Neutral',
openRouterApiKey: 'sk-or-v1-playwright-mock-key',
roleplayModel: 'google/gemini-3.8-flash',
supervisorModel: 'google/gemini-3.8-flash'
}));
});
});
test('01 - Home View Initial Render and Visual Snapshot', async ({ page }, testInfo) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
// Verify Brand Hero & Elements
await expect(page.locator('h1')).toContainText('Cognitive Clarity');
await expect(page.getByText('Evidence-Based Framework')).toBeVisible();
await expect(page.getByText(/Vocal Partner:/)).toBeVisible();
await expect(page.getByRole('heading', { name: 'Training Scenarios' })).toBeVisible();
// Verify all 14 default scenarios are rendered
const scenarioCards = page.locator('[data-testid="scenarios-grid"] > *');
await expect(scenarioCards).toHaveCount(15); // 14 scenarios + 1 custom trigger button
// Capture visual snapshot
const shotDir = path.join(process.cwd(), 'docs/screenshots', testInfo.project.name);
fs.mkdirSync(shotDir, { recursive: true });
await page.screenshot({ path: path.join(shotDir, '01-home-initial.png'), fullPage: true });
});
test('02 - Filter Scenarios by Difficulty', async ({ page }, testInfo) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
// Filter by Beginner
await page.getByRole('button', { name: 'Beginner', exact: true }).click();
await expect(page.getByText('The Silent Friend')).toBeVisible();
await expect(page.getByText('Inner Critic Echo')).toBeVisible();
const shotDir = path.join(process.cwd(), 'docs/screenshots', testInfo.project.name);
fs.mkdirSync(shotDir, { recursive: true });
await page.screenshot({ path: path.join(shotDir, '02-filter-beginner.png'), fullPage: true });
// Filter by Advanced
await page.getByRole('button', { name: 'Advanced', exact: true }).click();
await expect(page.getByText('The Social Spotlight')).toBeVisible();
await expect(page.getByText('The Unpaid Debt')).toBeVisible();
await expect(page.getByText('The Silent Friend')).not.toBeVisible();
await page.screenshot({ path: path.join(shotDir, '03-filter-advanced.png'), fullPage: true });
// Reset to All
await page.getByRole('button', { name: 'All', exact: true }).click();
await expect(page.getByText('The Silent Friend')).toBeVisible();
});
});