Files
Toju/e2e/fixtures/multi-client.ts
2026-04-18 14:24:11 +02:00

75 lines
2.0 KiB
TypeScript

import {
test as base,
chromium,
type Page,
type BrowserContext,
type Browser
} from '@playwright/test';
import { join } from 'node:path';
import { installTestServerEndpoint } from '../helpers/seed-test-endpoint';
import { startTestServer, type TestServerHandle } from '../helpers/test-server';
export interface Client {
page: Page;
context: BrowserContext;
}
interface MultiClientFixture {
createClient: () => Promise<Client>;
testServer: TestServerHandle;
}
const FAKE_AUDIO_FILE = join(__dirname, 'test-tone.wav');
const CHROMIUM_FAKE_MEDIA_ARGS = [
'--use-fake-device-for-media-stream',
'--use-fake-ui-for-media-stream',
`--use-file-for-fake-audio-capture=${FAKE_AUDIO_FILE}`,
'--autoplay-policy=no-user-gesture-required'
];
export const test = base.extend<MultiClientFixture>({
testServer: async ({ playwright: _playwright }, use: (testServer: TestServerHandle) => Promise<void>) => {
const testServer = await startTestServer();
await use(testServer);
await testServer.stop();
},
createClient: async ({ testServer }, use) => {
const browsers: Browser[] = [];
const clients: Client[] = [];
const factory = async (): Promise<Client> => {
// Launch a dedicated browser per client so each gets its own fake
// audio device - shared browsers can starve the first context's
// audio capture under load.
const browser = await chromium.launch({ args: CHROMIUM_FAKE_MEDIA_ARGS });
browsers.push(browser);
const context = await browser.newContext({
permissions: ['microphone', 'camera'],
baseURL: 'http://localhost:4200'
});
await installTestServerEndpoint(context, testServer.port);
const page = await context.newPage();
clients.push({ page, context });
return { page, context };
};
await use(factory);
for (const client of clients) {
await client.context.close();
}
for (const browser of browsers) {
await browser.close();
}
}
});
export { expect } from '@playwright/test';