test: Add playwright main usage test
Some checks failed
Deploy Web Apps / deploy (push) Has been cancelled
Queue Release Build / prepare (push) Successful in 21s
Queue Release Build / build-linux (push) Successful in 27m44s
Queue Release Build / build-windows (push) Successful in 32m16s
Queue Release Build / finalize (push) Successful in 1m54s
Some checks failed
Deploy Web Apps / deploy (push) Has been cancelled
Queue Release Build / prepare (push) Successful in 21s
Queue Release Build / build-linux (push) Successful in 27m44s
Queue Release Build / build-windows (push) Successful in 32m16s
Queue Release Build / finalize (push) Successful in 1m54s
This commit is contained in:
@@ -31,14 +31,14 @@ If missing, scaffold it. See [reference/project-setup.md](./reference/project-se
|
||||
|
||||
## Step 2 — Identify Test Category
|
||||
|
||||
| Request | Category | Key Patterns |
|
||||
|---------|----------|-------------|
|
||||
| Login, register, invite | **Auth** | Single browser context, form interaction |
|
||||
| Send message, rooms, chat UI | **Chat** | May need 2 clients for real-time sync |
|
||||
| Request | Category | Key Patterns |
|
||||
| ------------------------------- | ---------------- | ---------------------------------------------- |
|
||||
| Login, register, invite | **Auth** | Single browser context, form interaction |
|
||||
| Send message, rooms, chat UI | **Chat** | May need 2 clients for real-time sync |
|
||||
| Voice call, mute, deafen, audio | **Voice/WebRTC** | Multi-client, fake media, WebRTC introspection |
|
||||
| Camera, video tiles | **Video** | Multi-client, fake video, stream validation |
|
||||
| Screen share | **Screen Share** | Multi-client, display media mocking |
|
||||
| Settings, themes | **Settings** | Single client, preference persistence |
|
||||
| Camera, video tiles | **Video** | Multi-client, fake video, stream validation |
|
||||
| Screen share | **Screen Share** | Multi-client, display media mocking |
|
||||
| Settings, themes | **Settings** | Single client, preference persistence |
|
||||
|
||||
For **Voice/WebRTC** and **Multi-client** tests, read [reference/multi-client-webrtc.md](./reference/multi-client-webrtc.md) immediately.
|
||||
|
||||
@@ -52,17 +52,17 @@ import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests',
|
||||
timeout: 60_000, // WebRTC needs longer timeouts
|
||||
timeout: 60_000, // WebRTC needs longer timeouts
|
||||
expect: { timeout: 10_000 },
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: 1, // Sequential — shared server state
|
||||
workers: 1, // Sequential — shared server state
|
||||
reporter: [['html'], ['list']],
|
||||
use: {
|
||||
baseURL: 'http://localhost:4200',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
video: 'on-first-retry',
|
||||
permissions: ['microphone', 'camera'],
|
||||
permissions: ['microphone', 'camera']
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
@@ -72,28 +72,28 @@ export default defineConfig({
|
||||
launchOptions: {
|
||||
args: [
|
||||
'--use-fake-device-for-media-stream',
|
||||
'--use-fake-ui-for-media-stream',
|
||||
'--use-fake-ui-for-media-stream'
|
||||
// Feed a specific audio file as fake mic input:
|
||||
// '--use-file-for-fake-audio-capture=/path/to/audio.wav',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
webServer: [
|
||||
{
|
||||
command: 'cd server && npm run dev',
|
||||
port: 3001,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 30_000,
|
||||
timeout: 30_000
|
||||
},
|
||||
{
|
||||
command: 'cd toju-app && npx ng serve',
|
||||
port: 4200,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 60_000,
|
||||
},
|
||||
],
|
||||
timeout: 60_000
|
||||
}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
@@ -125,14 +125,14 @@ expect(text).toBe('Saved');
|
||||
|
||||
### Anti-Patterns
|
||||
|
||||
| ❌ Don't | ✅ Do | Why |
|
||||
|----------|-------|-----|
|
||||
| `page.waitForTimeout(3000)` | `await expect(locator).toBeVisible()` | Hard waits are flaky |
|
||||
| `expect(await el.isVisible())` | `await expect(el).toBeVisible()` | No auto-retry |
|
||||
| `page.$('.btn')` | `page.getByRole('button')` | Fragile selector |
|
||||
| `page.click('.submit')` | `page.getByRole('button', {name:'Submit'}).click()` | Not accessible |
|
||||
| Shared state between tests | `test.beforeEach` for setup | Tests must be independent |
|
||||
| `try/catch` around assertions | Let Playwright handle retries | Swallows real failures |
|
||||
| ❌ Don't | ✅ Do | Why |
|
||||
| ------------------------------ | --------------------------------------------------- | ------------------------- |
|
||||
| `page.waitForTimeout(3000)` | `await expect(locator).toBeVisible()` | Hard waits are flaky |
|
||||
| `expect(await el.isVisible())` | `await expect(el).toBeVisible()` | No auto-retry |
|
||||
| `page.$('.btn')` | `page.getByRole('button')` | Fragile selector |
|
||||
| `page.click('.submit')` | `page.getByRole('button', {name:'Submit'}).click()` | Not accessible |
|
||||
| Shared state between tests | `test.beforeEach` for setup | Tests must be independent |
|
||||
| `try/catch` around assertions | Let Playwright handle retries | Swallows real failures |
|
||||
|
||||
### Test Structure
|
||||
|
||||
@@ -191,14 +191,14 @@ export class LoginPage {
|
||||
|
||||
**Key pages to model (match `app.routes.ts`):**
|
||||
|
||||
| Route | Page Object | Component |
|
||||
|-------|-------------|-----------|
|
||||
| `/login` | `LoginPage` | `LoginComponent` |
|
||||
| `/register` | `RegisterPage` | `RegisterComponent` |
|
||||
| `/search` | `ServerSearchPage` | `ServerSearchComponent` |
|
||||
| `/room/:roomId` | `ChatRoomPage` | `ChatRoomComponent` |
|
||||
| `/settings` | `SettingsPage` | `SettingsComponent` |
|
||||
| `/invite/:inviteId` | `InvitePage` | `InviteComponent` |
|
||||
| Route | Page Object | Component |
|
||||
| ------------------- | ------------------ | ----------------------- |
|
||||
| `/login` | `LoginPage` | `LoginComponent` |
|
||||
| `/register` | `RegisterPage` | `RegisterComponent` |
|
||||
| `/search` | `ServerSearchPage` | `ServerSearchComponent` |
|
||||
| `/room/:roomId` | `ChatRoomPage` | `ChatRoomComponent` |
|
||||
| `/settings` | `SettingsPage` | `SettingsComponent` |
|
||||
| `/invite/:inviteId` | `InvitePage` | `InviteComponent` |
|
||||
|
||||
## Step 5 — MetoYou App Architecture Context
|
||||
|
||||
@@ -206,35 +206,35 @@ The agent writing tests MUST understand these domain boundaries:
|
||||
|
||||
### Voice/WebRTC Stack
|
||||
|
||||
| Layer | What It Does | Test Relevance |
|
||||
|-------|-------------|----------------|
|
||||
| `VoiceConnectionFacade` | High-level voice API (connect/disconnect/mute/deafen) | State signals to assert against |
|
||||
| `VoiceSessionFacade` | Session lifecycle, workspace layout | UI mode changes |
|
||||
| `VoiceActivityService` | Speaking detection (RMS threshold 0.015) | `isSpeaking()` signal validation |
|
||||
| `VoicePlaybackService` | Per-peer GainNode (0–200% volume) | Volume level assertions |
|
||||
| `PeerConnectionManager` | RTCPeerConnection lifecycle | Connection state introspection |
|
||||
| `MediaManager` | getUserMedia, mute, gain chain | Track state validation |
|
||||
| `SignalingManager` | WebSocket per signal URL | Connection establishment |
|
||||
| Layer | What It Does | Test Relevance |
|
||||
| ----------------------- | ----------------------------------------------------- | -------------------------------- |
|
||||
| `VoiceConnectionFacade` | High-level voice API (connect/disconnect/mute/deafen) | State signals to assert against |
|
||||
| `VoiceSessionFacade` | Session lifecycle, workspace layout | UI mode changes |
|
||||
| `VoiceActivityService` | Speaking detection (RMS threshold 0.015) | `isSpeaking()` signal validation |
|
||||
| `VoicePlaybackService` | Per-peer GainNode (0–200% volume) | Volume level assertions |
|
||||
| `PeerConnectionManager` | RTCPeerConnection lifecycle | Connection state introspection |
|
||||
| `MediaManager` | getUserMedia, mute, gain chain | Track state validation |
|
||||
| `SignalingManager` | WebSocket per signal URL | Connection establishment |
|
||||
|
||||
### Voice UI Components
|
||||
|
||||
| Component | Selector | Contains |
|
||||
|-----------|----------|----------|
|
||||
| `VoiceWorkspaceComponent` | `app-voice-workspace` | Stream tiles, layout |
|
||||
| `VoiceControlsComponent` | `app-voice-controls` | Mute, camera, screen share, hang-up buttons |
|
||||
| `FloatingVoiceControlsComponent` | `app-floating-voice-controls` | Floating variant of controls |
|
||||
| `VoiceWorkspaceStreamTileComponent` | `app-voice-workspace-stream-tile` | Per-peer audio/video tile |
|
||||
| Component | Selector | Contains |
|
||||
| ----------------------------------- | --------------------------------- | ------------------------------------------- |
|
||||
| `VoiceWorkspaceComponent` | `app-voice-workspace` | Stream tiles, layout |
|
||||
| `VoiceControlsComponent` | `app-voice-controls` | Mute, camera, screen share, hang-up buttons |
|
||||
| `FloatingVoiceControlsComponent` | `app-floating-voice-controls` | Floating variant of controls |
|
||||
| `VoiceWorkspaceStreamTileComponent` | `app-voice-workspace-stream-tile` | Per-peer audio/video tile |
|
||||
|
||||
### Voice UI Icons (Lucide)
|
||||
|
||||
| Icon | Meaning |
|
||||
|------|---------|
|
||||
| `lucideMic` / `lucideMicOff` | Mute toggle |
|
||||
| `lucideVideo` / `lucideVideoOff` | Camera toggle |
|
||||
| `lucideMonitor` / `lucideMonitorOff` | Screen share toggle |
|
||||
| `lucidePhoneOff` | Hang up / disconnect |
|
||||
| `lucideHeadphones` | Deafen state |
|
||||
| `lucideVolume2` / `lucideVolumeX` | Volume indicator |
|
||||
| Icon | Meaning |
|
||||
| ------------------------------------ | -------------------- |
|
||||
| `lucideMic` / `lucideMicOff` | Mute toggle |
|
||||
| `lucideVideo` / `lucideVideoOff` | Camera toggle |
|
||||
| `lucideMonitor` / `lucideMonitorOff` | Screen share toggle |
|
||||
| `lucidePhoneOff` | Hang up / disconnect |
|
||||
| `lucideHeadphones` | Deafen state |
|
||||
| `lucideVolume2` / `lucideVolumeX` | Volume indicator |
|
||||
|
||||
### Server & Signaling
|
||||
|
||||
@@ -256,6 +256,7 @@ After generating any test:
|
||||
```
|
||||
|
||||
If the test involves WebRTC, always verify:
|
||||
|
||||
- Fake media flags are set in config
|
||||
- Timeouts are sufficient (60s+ for connection establishment)
|
||||
- `workers: 1` if tests share server state
|
||||
@@ -276,7 +277,7 @@ npx playwright codegen http://localhost:4200 # Record test
|
||||
|
||||
## Reference Files
|
||||
|
||||
| File | When to Read |
|
||||
|------|-------------|
|
||||
| File | When to Read |
|
||||
| ---------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
||||
| [reference/multi-client-webrtc.md](./reference/multi-client-webrtc.md) | Voice/video/WebRTC tests, multi-browser contexts, audio validation |
|
||||
| [reference/project-setup.md](./reference/project-setup.md) | First-time scaffold, dependency installation, config creation |
|
||||
| [reference/project-setup.md](./reference/project-setup.md) | First-time scaffold, dependency installation, config creation |
|
||||
|
||||
Reference in New Issue
Block a user