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

+122
View File
@@ -0,0 +1,122 @@
import { test, expect } from '@playwright/test';
import fs from 'fs';
import path from 'path';
test.describe('Modals & Clinical Dialogs Suite', () => {
test.beforeEach(async ({ page }) => {
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-test-key',
roleplayModel: 'google/gemini-3.8-flash',
supervisorModel: 'google/gemini-3.8-flash'
}));
});
});
test('01 - Settings Modal and Model Selector', async ({ page }, testInfo) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
// Click Settings button
const settingsBtn = page.locator('button:has(svg)').first();
await settingsBtn.click();
// Verify Settings Modal elements
await expect(page.getByRole('heading', { name: 'Application Settings' })).toBeVisible();
await expect(page.getByText('Vocal Profile')).toBeVisible();
await expect(page.getByText('Fenrir (Salt of the Earth)')).toBeVisible();
await expect(page.getByText('Puck')).toBeVisible();
await expect(page.getByText('Kore')).toBeVisible();
await expect(page.getByText('Natural Voice Testing Lab')).toBeVisible();
// Select Fenrir (Salt of the Earth) persona
await page.getByText('Fenrir (Salt of the Earth)').click();
await expect(page.getByText(/Auditioning/)).toContainText('Fenrir (Salt of the Earth)');
// Click quick audition demo button
const auditionBtn = page.getByRole('button', { name: 'Audition Voice' });
await expect(auditionBtn).toBeVisible();
await auditionBtn.click();
const shotDir = path.join(process.cwd(), 'docs/screenshots', testInfo.project.name);
fs.mkdirSync(shotDir, { recursive: true });
await page.screenshot({ path: path.join(shotDir, '04-settings-modal-voice.png'), fullPage: true });
// Switch to OpenRouter AI Tab
await page.getByRole('tab', { name: 'OpenRouter AI' }).click();
await expect(page.getByRole('heading', { name: 'OpenRouter API Key' })).toBeVisible();
await expect(page.getByText('Google Gemini 3.8 Flash', { exact: true })).toBeVisible();
await expect(page.getByText('Frontier Ultra Low Latency')).toBeVisible();
await page.screenshot({ path: path.join(shotDir, '05-settings-modal-openrouter.png'), fullPage: true });
// Close Modal
await page.getByRole('button', { name: 'Save Preferences' }).click();
await expect(page.getByRole('heading', { name: 'Application Settings' })).not.toBeVisible();
});
test('02 - CBT Clinical Reference Glossary & Concept Search', async ({ page }, testInfo) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
// Open Reference Guide
await page.getByRole('button', { name: 'Reference Guide' }).click();
await expect(page.getByRole('heading', { name: 'CBT Clinical Reference' })).toBeVisible();
const shotDir = path.join(process.cwd(), 'docs/screenshots', testInfo.project.name);
fs.mkdirSync(shotDir, { recursive: true });
await page.screenshot({ path: path.join(shotDir, '06-cbt-reference-all.png'), fullPage: true });
// Filter by Distortion category
await page.getByRole('button', { name: 'Distortion', exact: true }).click();
await expect(page.getByRole('heading', { name: 'All-or-Nothing Thinking' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Catastrophizing' })).toBeVisible();
// Search for a specific concept
const searchInput = page.getByPlaceholder('Search concepts, distortions, or definitions...');
await searchInput.fill('Mind Reading');
await expect(page.getByRole('heading', { name: 'Mind Reading' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'All-or-Nothing Thinking' })).not.toBeVisible();
await page.screenshot({ path: path.join(shotDir, '07-cbt-reference-search.png'), fullPage: true });
// Close Reference Guide
await page.locator('div.fixed button:has(svg)').first().click();
});
test('03 - Custom Scenario Architect Generator', async ({ page }, testInfo) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
// Open Custom Scenario Generator
await page.getByRole('button', { name: 'Create Custom' }).first().click();
await expect(page.getByRole('heading', { name: 'Clinical Scenario Architect' })).toBeVisible();
await expect(page.getByText('Target Dynamic & Situation')).toBeVisible();
await expect(page.getByText('Emotional Resistance & Difficulty')).toBeVisible();
const shotDir = path.join(process.cwd(), 'docs/screenshots', testInfo.project.name);
fs.mkdirSync(shotDir, { recursive: true });
await page.screenshot({ path: path.join(shotDir, '08-scenario-generator-modal.png'), fullPage: true });
// Fill scenario prompt
await page.getByPlaceholder('e.g. Asking my manager for a delayed performance review').fill(
'Negotiating a contract renewal with a skeptical supplier who wants to raise rates by 40%.'
);
// Select difficulty
await page.getByRole('button', { name: 'Advanced Severe Friction' }).click();
// Select CBT focus distortion
await page.getByRole('button', { name: 'Emotional Reasoning' }).click();
await page.screenshot({ path: path.join(shotDir, '09-scenario-generator-filled.png'), fullPage: true });
// Cancel modal
await page.getByRole('button', { name: 'Cancel' }).click();
await expect(page.getByRole('heading', { name: 'Clinical Scenario Architect' })).not.toBeVisible();
});
});