feat: Add TURN server support
All checks were successful
Queue Release Build / prepare (push) Successful in 15s
Deploy Web Apps / deploy (push) Successful in 5m35s
Queue Release Build / build-linux (push) Successful in 24m45s
Queue Release Build / build-windows (push) Successful in 13m52s
Queue Release Build / finalize (push) Successful in 23s
All checks were successful
Queue Release Build / prepare (push) Successful in 15s
Deploy Web Apps / deploy (push) Successful in 5m35s
Queue Release Build / build-linux (push) Successful in 24m45s
Queue Release Build / build-windows (push) Successful in 13m52s
Queue Release Build / finalize (push) Successful in 23s
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { test, expect } from '../../fixtures/multi-client';
|
||||
import {
|
||||
installWebRTCTracking,
|
||||
installAutoResumeAudioContext,
|
||||
waitForPeerConnected,
|
||||
isPeerStillConnected,
|
||||
getAudioStatsDelta,
|
||||
@@ -13,7 +14,7 @@ import { ServerSearchPage } from '../../pages/server-search.page';
|
||||
import { ChatRoomPage } from '../../pages/chat-room.page';
|
||||
|
||||
/**
|
||||
* Full user journey: register → create server → join → voice → verify audio
|
||||
* Full user journey: register -> create server -> join -> voice -> verify audio
|
||||
* for 10+ seconds of stable connectivity.
|
||||
*
|
||||
* Uses two independent browser contexts (Alice & Bob) to simulate real
|
||||
@@ -25,7 +26,7 @@ const BOB = { username: `bob_${Date.now()}`, displayName: 'Bob', password: 'Test
|
||||
const SERVER_NAME = `E2E Test Server ${Date.now()}`;
|
||||
const VOICE_CHANNEL = 'General';
|
||||
|
||||
test.describe('Full user journey: register → server → voice chat', () => {
|
||||
test.describe('Full user journey: register -> server -> voice chat', () => {
|
||||
test('two users register, create server, join voice, and stay connected 10+ seconds with audio', async ({ createClient }) => {
|
||||
test.setTimeout(180_000); // 3 min - covers registration, server creation, voice establishment, and 10s stability check
|
||||
|
||||
@@ -35,6 +36,20 @@ test.describe('Full user journey: register → server → voice chat', () => {
|
||||
// Install WebRTC tracking before any navigation
|
||||
await installWebRTCTracking(alice.page);
|
||||
await installWebRTCTracking(bob.page);
|
||||
await installAutoResumeAudioContext(alice.page);
|
||||
await installAutoResumeAudioContext(bob.page);
|
||||
|
||||
// Seed deterministic voice settings so noise reduction doesn't
|
||||
// swallow the fake audio tone.
|
||||
const voiceSettings = JSON.stringify({
|
||||
inputVolume: 100, outputVolume: 100, audioBitrate: 96,
|
||||
latencyProfile: 'balanced', includeSystemAudio: false,
|
||||
noiseReduction: false, screenShareQuality: 'balanced',
|
||||
askScreenShareQuality: false
|
||||
});
|
||||
|
||||
await alice.page.addInitScript((settingsValue: string) => localStorage.setItem('metoyou_voice_settings', settingsValue), voiceSettings);
|
||||
await bob.page.addInitScript((settingsValue: string) => localStorage.setItem('metoyou_voice_settings', settingsValue), voiceSettings);
|
||||
|
||||
// Forward browser console for debugging
|
||||
alice.page.on('console', msg => console.log('[Alice]', msg.text()));
|
||||
@@ -146,8 +161,38 @@ test.describe('Full user journey: register → server → voice chat', () => {
|
||||
// ── Step 7: Verify audio is flowing in both directions ───────────
|
||||
|
||||
await test.step('Audio packets are flowing between Alice and Bob', async () => {
|
||||
const aliceDelta = await waitForAudioFlow(alice.page, 30_000);
|
||||
const bobDelta = await waitForAudioFlow(bob.page, 30_000);
|
||||
// Chromium's --use-fake-device-for-media-stream can produce a
|
||||
// silent capture track on the very first getUserMedia call. If
|
||||
// bidirectional audio doesn't flow within a short window, leave
|
||||
// and rejoin voice to re-acquire the mic.
|
||||
let aliceDelta = await waitForAudioFlow(alice.page, 15_000);
|
||||
let bobDelta = await waitForAudioFlow(bob.page, 15_000);
|
||||
|
||||
const isFlowing = (delta: typeof aliceDelta) =>
|
||||
(delta.outboundBytesDelta > 0 || delta.outboundPacketsDelta > 0) &&
|
||||
(delta.inboundBytesDelta > 0 || delta.inboundPacketsDelta > 0);
|
||||
|
||||
if (!isFlowing(aliceDelta) || !isFlowing(bobDelta)) {
|
||||
const aliceRoom = new ChatRoomPage(alice.page);
|
||||
const bobRoom = new ChatRoomPage(bob.page);
|
||||
|
||||
await aliceRoom.disconnectButton.click();
|
||||
await bobRoom.disconnectButton.click();
|
||||
await alice.page.waitForTimeout(2_000);
|
||||
|
||||
await aliceRoom.joinVoiceChannel(VOICE_CHANNEL);
|
||||
await expect(alice.page.locator('app-voice-controls')).toBeVisible({ timeout: 15_000 });
|
||||
await bobRoom.joinVoiceChannel(VOICE_CHANNEL);
|
||||
await expect(bob.page.locator('app-voice-controls')).toBeVisible({ timeout: 15_000 });
|
||||
|
||||
await waitForPeerConnected(alice.page, 30_000);
|
||||
await waitForPeerConnected(bob.page, 30_000);
|
||||
await waitForAudioStatsPresent(alice.page, 20_000);
|
||||
await waitForAudioStatsPresent(bob.page, 20_000);
|
||||
|
||||
aliceDelta = await waitForAudioFlow(alice.page, 30_000);
|
||||
bobDelta = await waitForAudioFlow(bob.page, 30_000);
|
||||
}
|
||||
|
||||
if (aliceDelta.outboundBytesDelta === 0 || aliceDelta.inboundBytesDelta === 0
|
||||
|| bobDelta.outboundBytesDelta === 0 || bobDelta.inboundBytesDelta === 0) {
|
||||
|
||||
Reference in New Issue
Block a user