test(app): add E2E tests and improve form state with test coverage

This commit is contained in:
Mohamed Boudra
2026-01-20 12:12:29 +07:00
parent d9c487dd54
commit 687ea706b1
7 changed files with 255 additions and 10 deletions
+3 -1
View File
@@ -2,10 +2,12 @@ import { test, expect } from './fixtures';
import { gotoHome, openSettings } from './helpers/app';
test('daemon is connected in settings', async ({ page }) => {
const daemonPort = process.env.E2E_DAEMON_PORT ?? '6767';
await gotoHome(page);
await openSettings(page);
await expect(page.getByText('localhost', { exact: true })).toBeVisible();
await expect(page.getByText('ws://localhost:6767/ws')).toBeVisible();
await expect(page.getByText(`ws://localhost:${daemonPort}/ws`)).toBeVisible();
await expect(page.getByText('Online', { exact: true })).toBeVisible();
});
+141
View File
@@ -0,0 +1,141 @@
import { test, expect } from './fixtures';
import { createAgent, ensureHostSelected, gotoHome, setWorkingDirectory } from './helpers/app';
import { createTempGitRepo } from './helpers/workspace';
import type { Page } from '@playwright/test';
function addFakeMicrophone(page: Page) {
return page.addInitScript(() => {
const mic = {
active: 0,
getUserMediaCalls: 0,
stopCalls: 0,
lastRecorder: null as null | { state: string },
};
(window as any).__mic = mic;
const ensureMediaDevices = () => {
const nav = navigator as any;
if (!nav.mediaDevices) {
nav.mediaDevices = {};
}
if (typeof nav.mediaDevices.getUserMedia !== 'function') {
nav.mediaDevices.getUserMedia = async () => {
mic.getUserMediaCalls += 1;
mic.active += 1;
const track = {
stop: () => {
mic.stopCalls += 1;
mic.active = Math.max(0, mic.active - 1);
},
};
return {
getTracks: () => [track],
};
};
}
};
ensureMediaDevices();
class FakeMediaRecorder extends EventTarget {
public static isTypeSupported() {
return true;
}
public state: 'inactive' | 'recording' = 'inactive';
public mimeType: string;
public ondataavailable: ((event: { data: Blob }) => void) | null = null;
public onerror: ((event: unknown) => void) | null = null;
constructor(_stream: unknown, options?: MediaRecorderOptions) {
super();
this.mimeType = options?.mimeType ?? 'audio/webm';
mic.lastRecorder = this;
}
public start() {
this.state = 'recording';
}
public stop() {
if (this.state !== 'recording') {
throw new Error('Not recording');
}
this.state = 'inactive';
try {
this.ondataavailable?.({
data: new Blob(['paseo-e2e-audio'], { type: this.mimeType }),
});
} catch (err) {
this.onerror?.(err);
}
this.dispatchEvent(new Event('stop'));
}
}
(window as any).MediaRecorder = FakeMediaRecorder;
});
}
test('dictation hotkeys do not trigger on background screens', async ({ page }) => {
await addFakeMicrophone(page);
const repo = await createTempGitRepo();
try {
await gotoHome(page);
await setWorkingDirectory(page, repo.path);
await ensureHostSelected(page);
await createAgent(page, 'Respond with exactly: Hello');
await expect(page).toHaveURL(/\/agent\//);
await page.keyboard.press('Control+d');
await page.waitForTimeout(200);
const calls = await page.evaluate(() => (window as any).__mic.getUserMediaCalls as number);
const active = await page.evaluate(() => (window as any).__mic.active as number);
expect(calls).toBe(1);
expect(active).toBe(1);
await page.keyboard.press('Escape');
await expect
.poll(async () => page.evaluate(() => (window as any).__mic.active as number))
.toBe(0);
} finally {
await repo.cleanup();
}
});
test('cancel stops mic even if recorder is already inactive', async ({ page }) => {
await addFakeMicrophone(page);
const repo = await createTempGitRepo();
try {
await gotoHome(page);
await setWorkingDirectory(page, repo.path);
await ensureHostSelected(page);
await createAgent(page, 'Respond with exactly: Hello');
await expect(page).toHaveURL(/\/agent\//);
await page.keyboard.press('Control+d');
await expect
.poll(async () => page.evaluate(() => (window as any).__mic.active as number))
.toBe(1);
await page.evaluate(() => {
const mic = (window as any).__mic as { lastRecorder: null | { state: string } };
if (mic.lastRecorder) {
mic.lastRecorder.state = 'inactive';
}
});
await page.keyboard.press('Escape');
await expect
.poll(async () => page.evaluate(() => (window as any).__mic.active as number))
.toBe(0);
} finally {
await repo.cleanup();
}
});
+33
View File
@@ -0,0 +1,33 @@
import { test, expect } from './fixtures';
import { ensureHostSelected, gotoHome } from './helpers/app';
test('new agent auto-selects the previous host', async ({ page }) => {
await gotoHome(page);
await ensureHostSelected(page);
// Ensure preference is persisted so a full reload can restore it.
await page.waitForFunction(() => {
const stored = localStorage.getItem('@paseo:create-agent-preferences');
if (!stored) return false;
try {
const parsed = JSON.parse(stored);
return parsed?.serverId === 'e2e-test-daemon';
} catch {
return false;
}
});
await gotoHome(page);
const input = page.getByRole('textbox', { name: 'Message agent...' });
await expect(input).toBeEditable();
});
test('new agent respects serverId in the URL', async ({ page }) => {
await page.goto('/?serverId=e2e-test-daemon&serverId=e2e-test-daemon');
await expect(page.getByText('New Agent', { exact: true }).first()).toBeVisible();
const input = page.getByRole('textbox', { name: 'Message agent...' });
await expect(input).toBeEditable();
});