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:
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();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user