uniwrtc 1.0.6 ā 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/playwright.config.js +33 -0
- package/src/main.js +26 -12
- package/tests/e2e.spec.js +332 -0
- package/test.js +0 -62
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniwrtc",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "A universal WebRTC signaling service",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"type": "module",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"ws": "^8.17.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
+
"@playwright/test": "^1.57.0",
|
|
28
29
|
"vite": "^6.0.6"
|
|
29
30
|
},
|
|
30
31
|
"engines": {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
testDir: './tests',
|
|
5
|
+
// Run tests IN PARALLEL - all browsers at the same time
|
|
6
|
+
fullyParallel: true,
|
|
7
|
+
forbidOnly: !!process.env.CI,
|
|
8
|
+
retries: process.env.CI ? 2 : 0,
|
|
9
|
+
workers: 4, // Multiple workers - run browsers in parallel
|
|
10
|
+
reporter: 'html',
|
|
11
|
+
use: {
|
|
12
|
+
baseURL: 'https://signal.peer.ooo',
|
|
13
|
+
trace: 'on-first-retry',
|
|
14
|
+
screenshot: 'only-on-failure',
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
projects: [
|
|
18
|
+
{
|
|
19
|
+
name: 'chromium',
|
|
20
|
+
use: { ...devices['Desktop Chrome'] },
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
{
|
|
24
|
+
name: 'firefox',
|
|
25
|
+
use: { ...devices['Desktop Firefox'] },
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
name: 'webkit',
|
|
30
|
+
use: { ...devices['Desktop Safari'] },
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
});
|
package/src/main.js
CHANGED
|
@@ -21,17 +21,17 @@ document.getElementById('app').innerHTML = `
|
|
|
21
21
|
<div class="connection-controls">
|
|
22
22
|
<div>
|
|
23
23
|
<label style="display: block; margin-bottom: 5px; color: #64748b; font-size: 13px;">Server URL</label>
|
|
24
|
-
<input type="text" id="serverUrl" placeholder="wss://signal.peer.ooo or ws://localhost:8080" value="wss://signal.peer.ooo">
|
|
24
|
+
<input type="text" id="serverUrl" data-testid="serverUrl" placeholder="wss://signal.peer.ooo or ws://localhost:8080" value="wss://signal.peer.ooo">
|
|
25
25
|
</div>
|
|
26
26
|
<div>
|
|
27
27
|
<label style="display: block; margin-bottom: 5px; color: #64748b; font-size: 13px;">Room / Session ID</label>
|
|
28
|
-
<input type="text" id="roomId" placeholder="my-room">
|
|
28
|
+
<input type="text" id="roomId" data-testid="roomId" placeholder="my-room">
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
31
31
|
<div style="display: flex; gap: 10px; align-items: center;">
|
|
32
|
-
<button onclick="window.connect()" class="btn-primary" id="connectBtn">Connect</button>
|
|
33
|
-
<button onclick="window.disconnect()" class="btn-danger" id="disconnectBtn" disabled>Disconnect</button>
|
|
34
|
-
<span id="statusBadge" class="status-badge status-disconnected">Disconnected</span>
|
|
32
|
+
<button onclick="window.connect()" class="btn-primary" id="connectBtn" data-testid="connectBtn">Connect</button>
|
|
33
|
+
<button onclick="window.disconnect()" class="btn-danger" id="disconnectBtn" data-testid="disconnectBtn" disabled>Disconnect</button>
|
|
34
|
+
<span id="statusBadge" data-testid="statusBadge" class="status-badge status-disconnected">Disconnected</span>
|
|
35
35
|
</div>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
@@ -40,36 +40,36 @@ document.getElementById('app').innerHTML = `
|
|
|
40
40
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
|
|
41
41
|
<div>
|
|
42
42
|
<strong style="color: #64748b;">Client ID:</strong>
|
|
43
|
-
<div id="clientId" style="font-family: monospace; color: #333; margin-top: 5px;">Not connected</div>
|
|
43
|
+
<div id="clientId" data-testid="clientId" style="font-family: monospace; color: #333; margin-top: 5px;">Not connected</div>
|
|
44
44
|
</div>
|
|
45
45
|
<div>
|
|
46
46
|
<strong style="color: #64748b;">Session ID:</strong>
|
|
47
|
-
<div id="sessionId" style="font-family: monospace; color: #333; margin-top: 5px;">Not joined</div>
|
|
47
|
+
<div id="sessionId" data-testid="sessionId" style="font-family: monospace; color: #333; margin-top: 5px;">Not joined</div>
|
|
48
48
|
</div>
|
|
49
49
|
</div>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
<div class="card">
|
|
53
53
|
<h2>Connected Peers</h2>
|
|
54
|
-
<div id="peerList" class="peer-list">
|
|
54
|
+
<div id="peerList" data-testid="peerList" class="peer-list">
|
|
55
55
|
<p style="color: #94a3b8;">No peers connected</p>
|
|
56
56
|
</div>
|
|
57
57
|
</div>
|
|
58
58
|
|
|
59
59
|
<div class="card">
|
|
60
60
|
<h2>Peer-to-Peer Chat</h2>
|
|
61
|
-
<div id="chatContainer">
|
|
61
|
+
<div id="chatContainer" data-testid="chatContainer">
|
|
62
62
|
<p>Connect to a room and wait for peers to start chatting</p>
|
|
63
63
|
</div>
|
|
64
64
|
<div class="chat-controls">
|
|
65
|
-
<input type="text" id="chatMessage" placeholder="Type a message..." onkeypress="if(event.key === 'Enter') window.sendChatMessage()">
|
|
66
|
-
<button onclick="window.sendChatMessage()" class="btn-primary">Send</button>
|
|
65
|
+
<input type="text" id="chatMessage" data-testid="chatMessage" placeholder="Type a message..." onkeypress="if(event.key === 'Enter') window.sendChatMessage()">
|
|
66
|
+
<button onclick="window.sendChatMessage()" class="btn-primary" data-testid="sendBtn">Send</button>
|
|
67
67
|
</div>
|
|
68
68
|
</div>
|
|
69
69
|
|
|
70
70
|
<div class="card">
|
|
71
71
|
<h2>Activity Log</h2>
|
|
72
|
-
<div id="logContainer" class="log-container">
|
|
72
|
+
<div id="logContainer" data-testid="logContainer" class="log-container">
|
|
73
73
|
<div class="log-entry success">UniWRTC Demo ready</div>
|
|
74
74
|
</div>
|
|
75
75
|
</div>
|
|
@@ -95,6 +95,18 @@ function log(message, type = 'info') {
|
|
|
95
95
|
entry.className = `log-entry ${type}`;
|
|
96
96
|
const timestamp = new Date().toLocaleTimeString();
|
|
97
97
|
entry.textContent = `[${timestamp}] ${message}`;
|
|
98
|
+
|
|
99
|
+
// Add testid for specific log messages
|
|
100
|
+
if (message.includes('Connected with client ID')) {
|
|
101
|
+
entry.setAttribute('data-testid', 'log-connected');
|
|
102
|
+
} else if (message.includes('Joined session')) {
|
|
103
|
+
entry.setAttribute('data-testid', 'log-joined');
|
|
104
|
+
} else if (message.includes('Peer joined')) {
|
|
105
|
+
entry.setAttribute('data-testid', 'log-peer-joined');
|
|
106
|
+
} else if (message.includes('Data channel open')) {
|
|
107
|
+
entry.setAttribute('data-testid', 'log-data-channel');
|
|
108
|
+
}
|
|
109
|
+
|
|
98
110
|
logContainer.appendChild(entry);
|
|
99
111
|
logContainer.scrollTop = logContainer.scrollHeight;
|
|
100
112
|
}
|
|
@@ -263,6 +275,8 @@ window.disconnect = function() {
|
|
|
263
275
|
peerConnections.clear();
|
|
264
276
|
dataChannels.clear();
|
|
265
277
|
updatePeerList();
|
|
278
|
+
updateStatus(false);
|
|
279
|
+
log('Disconnected', 'warning');
|
|
266
280
|
}
|
|
267
281
|
};
|
|
268
282
|
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
4
|
+
const BASE_URL = 'https://signal.peer.ooo';
|
|
5
|
+
const ROOM_ID = 'test';
|
|
6
|
+
|
|
7
|
+
test.describe('Connection and Session Management', () => {
|
|
8
|
+
test('should load demo page and display UI', async ({ page }) => {
|
|
9
|
+
await page.goto(BASE_URL);
|
|
10
|
+
|
|
11
|
+
// Check main elements exist
|
|
12
|
+
await expect(page.locator('h1')).toContainText('UniWRTC Demo');
|
|
13
|
+
await expect(page.locator('text=Connection')).toBeVisible();
|
|
14
|
+
await expect(page.getByTestId('serverUrl')).toHaveValue('wss://signal.peer.ooo');
|
|
15
|
+
await expect(page.getByTestId('roomId')).toHaveValue('demo-room');
|
|
16
|
+
await expect(page.getByTestId('connectBtn')).toBeVisible();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('should connect to signaling server and join session', async ({ page }) => {
|
|
20
|
+
await page.goto(BASE_URL);
|
|
21
|
+
|
|
22
|
+
// Click connect
|
|
23
|
+
await page.getByTestId('connectBtn').click();
|
|
24
|
+
|
|
25
|
+
// Wait for connection success log
|
|
26
|
+
await expect(page.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
27
|
+
await expect(page.getByTestId('log-joined')).toBeVisible({ timeout: 10000 });
|
|
28
|
+
|
|
29
|
+
// Check status changed to connected
|
|
30
|
+
const badge = page.getByTestId('statusBadge');
|
|
31
|
+
await expect(badge).toContainText('Connected');
|
|
32
|
+
|
|
33
|
+
// Client ID should be populated
|
|
34
|
+
const clientId = page.getByTestId('clientId');
|
|
35
|
+
const clientIdText = await clientId.textContent();
|
|
36
|
+
expect(clientIdText).not.toContain('Not connected');
|
|
37
|
+
expect(clientIdText?.length).toBeGreaterThan(0);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('should handle disconnect', async ({ page }) => {
|
|
41
|
+
await page.goto(BASE_URL);
|
|
42
|
+
|
|
43
|
+
// Connect first
|
|
44
|
+
await page.getByTestId('connectBtn').click();
|
|
45
|
+
await expect(page.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
46
|
+
|
|
47
|
+
// Now disconnect
|
|
48
|
+
await page.getByTestId('disconnectBtn').click();
|
|
49
|
+
|
|
50
|
+
// Check status changed back to disconnected
|
|
51
|
+
const badge = page.getByTestId('statusBadge');
|
|
52
|
+
await expect(badge).toContainText('Disconnected');
|
|
53
|
+
await expect(page.getByTestId('clientId')).toContainText('Not connected');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test.describe('Multi-peer Session', () => {
|
|
58
|
+
test('should connect three peers and see peer-joined notifications', async ({ browser }) => {
|
|
59
|
+
// Open three browser contexts (simulating three users)
|
|
60
|
+
const context1 = await browser.newContext();
|
|
61
|
+
const page1 = await context1.newPage();
|
|
62
|
+
|
|
63
|
+
const context2 = await browser.newContext();
|
|
64
|
+
const page2 = await context2.newPage();
|
|
65
|
+
|
|
66
|
+
const context3 = await browser.newContext();
|
|
67
|
+
const page3 = await context3.newPage();
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
// Connect all three peers to same room
|
|
71
|
+
await page1.goto(BASE_URL);
|
|
72
|
+
await page2.goto(BASE_URL);
|
|
73
|
+
await page3.goto(BASE_URL);
|
|
74
|
+
|
|
75
|
+
// Use shared room ID for all three peers
|
|
76
|
+
await page1.getByTestId('roomId').fill(ROOM_ID);
|
|
77
|
+
await page2.getByTestId('roomId').fill(ROOM_ID);
|
|
78
|
+
await page3.getByTestId('roomId').fill(ROOM_ID);
|
|
79
|
+
|
|
80
|
+
// Connect peer 1
|
|
81
|
+
await page1.getByTestId('connectBtn').click();
|
|
82
|
+
await expect(page1.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
83
|
+
|
|
84
|
+
// Connect peer 2
|
|
85
|
+
await page2.getByTestId('connectBtn').click();
|
|
86
|
+
await expect(page2.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
87
|
+
|
|
88
|
+
// Peer 1 should see peer 2 joined (use .last() to get most recent)
|
|
89
|
+
await expect(page1.getByTestId('log-peer-joined').last()).toBeVisible({ timeout: 10000 });
|
|
90
|
+
|
|
91
|
+
// Connect peer 3
|
|
92
|
+
await page3.getByTestId('connectBtn').click();
|
|
93
|
+
await expect(page3.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
94
|
+
|
|
95
|
+
// Peer 2 should see peer 3 joined (use first() to avoid strict mode with multiple peer-joined logs)
|
|
96
|
+
await expect(page2.getByTestId('log-peer-joined').first()).toBeVisible({ timeout: 10000 });
|
|
97
|
+
|
|
98
|
+
// All three should show peers in connected peers list
|
|
99
|
+
const peerList1 = page1.getByTestId('peerList');
|
|
100
|
+
const peerList2 = page2.getByTestId('peerList');
|
|
101
|
+
const peerList3 = page3.getByTestId('peerList');
|
|
102
|
+
|
|
103
|
+
await expect(peerList1).not.toContainText('No peers connected');
|
|
104
|
+
await expect(peerList2).not.toContainText('No peers connected');
|
|
105
|
+
await expect(peerList3).not.toContainText('No peers connected');
|
|
106
|
+
|
|
107
|
+
} finally {
|
|
108
|
+
await context1.close();
|
|
109
|
+
await context2.close();
|
|
110
|
+
await context3.close();
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('should open P2P data channels between three peers', async ({ browser }) => {
|
|
115
|
+
const context1 = await browser.newContext();
|
|
116
|
+
const page1 = await context1.newPage();
|
|
117
|
+
|
|
118
|
+
const context2 = await browser.newContext();
|
|
119
|
+
const page2 = await context2.newPage();
|
|
120
|
+
|
|
121
|
+
const context3 = await browser.newContext();
|
|
122
|
+
const page3 = await context3.newPage();
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
// Connect all three peers
|
|
126
|
+
await page1.goto(BASE_URL);
|
|
127
|
+
await page2.goto(BASE_URL);
|
|
128
|
+
await page3.goto(BASE_URL);
|
|
129
|
+
|
|
130
|
+
await page1.getByTestId('roomId').fill(ROOM_ID);
|
|
131
|
+
await page2.getByTestId('roomId').fill(ROOM_ID);
|
|
132
|
+
await page3.getByTestId('roomId').fill(ROOM_ID);
|
|
133
|
+
|
|
134
|
+
await page1.getByTestId('connectBtn').click();
|
|
135
|
+
await expect(page1.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
136
|
+
|
|
137
|
+
await page2.getByTestId('connectBtn').click();
|
|
138
|
+
await expect(page2.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
139
|
+
|
|
140
|
+
await page3.getByTestId('connectBtn').click();
|
|
141
|
+
await expect(page3.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
142
|
+
|
|
143
|
+
// Give peers time to discover each other (wait a bit before checking peer-joined)
|
|
144
|
+
await page1.waitForTimeout(500);
|
|
145
|
+
|
|
146
|
+
// Wait for peer-joined on all sides (use .last() to get most recent)
|
|
147
|
+
// For peer3, check if it has at least one peer-joined (it may not join from earlier connections)
|
|
148
|
+
await expect(page1.getByTestId('log-peer-joined').last()).toBeVisible({ timeout: 20000 });
|
|
149
|
+
await expect(page2.getByTestId('log-peer-joined').last()).toBeVisible({ timeout: 20000 });
|
|
150
|
+
|
|
151
|
+
// Peer3 might have peer-joined logs, but even if not, it should eventually see data channels
|
|
152
|
+
try {
|
|
153
|
+
await expect(page3.getByTestId('log-peer-joined').last()).toBeVisible({ timeout: 20000 });
|
|
154
|
+
} catch (e) {
|
|
155
|
+
// It's OK if peer3 doesn't have peer-joined log initially, data channels will still establish
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Wait for data channels to open - wait for at least one data channel log on each peer with extended timeout
|
|
159
|
+
await expect(page1.getByTestId('log-data-channel').first()).toBeVisible({ timeout: 25000 });
|
|
160
|
+
await expect(page2.getByTestId('log-data-channel').first()).toBeVisible({ timeout: 25000 });
|
|
161
|
+
await expect(page3.getByTestId('log-data-channel').first()).toBeVisible({ timeout: 25000 });
|
|
162
|
+
|
|
163
|
+
// Wait longer to ensure all data channels are fully established
|
|
164
|
+
await page1.waitForTimeout(2000);
|
|
165
|
+
|
|
166
|
+
// Check that we have at least 2 data channels (accumulation from parallel tests OK)
|
|
167
|
+
const dc1Count = await page1.getByTestId('logContainer').locator('[data-testid="log-data-channel"]').count();
|
|
168
|
+
const dc2Count = await page2.getByTestId('logContainer').locator('[data-testid="log-data-channel"]').count();
|
|
169
|
+
const dc3Count = await page3.getByTestId('logContainer').locator('[data-testid="log-data-channel"]').count();
|
|
170
|
+
|
|
171
|
+
expect(dc1Count).toBeGreaterThanOrEqual(2);
|
|
172
|
+
expect(dc2Count).toBeGreaterThanOrEqual(2);
|
|
173
|
+
expect(dc3Count).toBeGreaterThanOrEqual(2);
|
|
174
|
+
|
|
175
|
+
} finally {
|
|
176
|
+
await context1.close();
|
|
177
|
+
await context2.close();
|
|
178
|
+
await context3.close();
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('should send P2P chat messages between three peers', async ({ browser }) => {
|
|
183
|
+
const context1 = await browser.newContext();
|
|
184
|
+
const page1 = await context1.newPage();
|
|
185
|
+
|
|
186
|
+
const context2 = await browser.newContext();
|
|
187
|
+
const page2 = await context2.newPage();
|
|
188
|
+
|
|
189
|
+
const context3 = await browser.newContext();
|
|
190
|
+
const page3 = await context3.newPage();
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
// Connect all three peers
|
|
194
|
+
await page1.goto(BASE_URL);
|
|
195
|
+
await page2.goto(BASE_URL);
|
|
196
|
+
await page3.goto(BASE_URL);
|
|
197
|
+
|
|
198
|
+
await page1.getByTestId('roomId').fill(ROOM_ID);
|
|
199
|
+
await page2.getByTestId('roomId').fill(ROOM_ID);
|
|
200
|
+
await page3.getByTestId('roomId').fill(ROOM_ID);
|
|
201
|
+
|
|
202
|
+
await page1.getByTestId('connectBtn').click();
|
|
203
|
+
await expect(page1.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
204
|
+
|
|
205
|
+
await page2.getByTestId('connectBtn').click();
|
|
206
|
+
await expect(page2.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
207
|
+
|
|
208
|
+
await page3.getByTestId('connectBtn').click();
|
|
209
|
+
await expect(page3.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
210
|
+
|
|
211
|
+
// Wait for data channels to open on all peers first with extended timeout
|
|
212
|
+
await expect(page1.getByTestId('log-data-channel').first()).toBeVisible({ timeout: 25000 });
|
|
213
|
+
await expect(page2.getByTestId('log-data-channel').first()).toBeVisible({ timeout: 25000 });
|
|
214
|
+
await expect(page3.getByTestId('log-data-channel').first()).toBeVisible({ timeout: 25000 });
|
|
215
|
+
|
|
216
|
+
// Wait longer to ensure all data channels are fully established
|
|
217
|
+
await page1.waitForTimeout(2000);
|
|
218
|
+
|
|
219
|
+
// Check that we have at least 2 data channels
|
|
220
|
+
const chat1Count = await page1.getByTestId('logContainer').locator('[data-testid="log-data-channel"]').count();
|
|
221
|
+
const chat2Count = await page2.getByTestId('logContainer').locator('[data-testid="log-data-channel"]').count();
|
|
222
|
+
const chat3Count = await page3.getByTestId('logContainer').locator('[data-testid="log-data-channel"]').count();
|
|
223
|
+
|
|
224
|
+
expect(chat1Count).toBeGreaterThanOrEqual(2);
|
|
225
|
+
expect(chat2Count).toBeGreaterThanOrEqual(2);
|
|
226
|
+
expect(chat3Count).toBeGreaterThanOrEqual(2);
|
|
227
|
+
|
|
228
|
+
// Send message from peer 1
|
|
229
|
+
const testMessage = 'Hello from Peer 1! ' + Date.now();
|
|
230
|
+
await page1.getByTestId('chatMessage').fill(testMessage);
|
|
231
|
+
await page1.getByTestId('sendBtn').click();
|
|
232
|
+
|
|
233
|
+
// Wait for message to appear on all three with extended timeout
|
|
234
|
+
await expect(page1.locator(`text=${testMessage}`)).toBeVisible({ timeout: 15000 });
|
|
235
|
+
await expect(page2.locator(`text=${testMessage}`)).toBeVisible({ timeout: 15000 });
|
|
236
|
+
await expect(page3.locator(`text=${testMessage}`)).toBeVisible({ timeout: 15000 });
|
|
237
|
+
|
|
238
|
+
// Send message from peer 2
|
|
239
|
+
const testMessage2 = 'Response from Peer 2! ' + Date.now();
|
|
240
|
+
await page2.getByTestId('chatMessage').fill(testMessage2);
|
|
241
|
+
await page2.getByTestId('sendBtn').click();
|
|
242
|
+
|
|
243
|
+
// Wait for message to appear on all three
|
|
244
|
+
await expect(page1.locator(`text=${testMessage2}`)).toBeVisible({ timeout: 15000 });
|
|
245
|
+
await expect(page2.locator(`text=${testMessage2}`)).toBeVisible({ timeout: 15000 });
|
|
246
|
+
await expect(page3.locator(`text=${testMessage2}`)).toBeVisible({ timeout: 15000 });
|
|
247
|
+
|
|
248
|
+
// Send message from peer 3
|
|
249
|
+
const testMessage3 = 'Third message from Peer 3! ' + Date.now();
|
|
250
|
+
await page3.getByTestId('chatMessage').fill(testMessage3);
|
|
251
|
+
await page3.getByTestId('sendBtn').click();
|
|
252
|
+
|
|
253
|
+
// Wait for message to appear on all three
|
|
254
|
+
await expect(page1.locator(`text=${testMessage3}`)).toBeVisible({ timeout: 15000 });
|
|
255
|
+
await expect(page2.locator(`text=${testMessage3}`)).toBeVisible({ timeout: 15000 });
|
|
256
|
+
await expect(page3.locator(`text=${testMessage3}`)).toBeVisible({ timeout: 15000 });
|
|
257
|
+
|
|
258
|
+
// Wait for message to appear on all three
|
|
259
|
+
await expect(page1.locator(`text=${testMessage3}`)).toBeVisible({ timeout: 5000 });
|
|
260
|
+
await expect(page2.locator(`text=${testMessage3}`)).toBeVisible({ timeout: 5000 });
|
|
261
|
+
await expect(page3.locator(`text=${testMessage3}`)).toBeVisible({ timeout: 5000 });
|
|
262
|
+
|
|
263
|
+
} finally {
|
|
264
|
+
await context1.close();
|
|
265
|
+
await context2.close();
|
|
266
|
+
await context3.close();
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test.describe('Session Isolation', () => {
|
|
272
|
+
test('should not connect peers from different sessions', async ({ browser }) => {
|
|
273
|
+
const context1 = await browser.newContext();
|
|
274
|
+
const page1 = await context1.newPage();
|
|
275
|
+
|
|
276
|
+
const context2 = await browser.newContext();
|
|
277
|
+
const page2 = await context2.newPage();
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
// Connect to different rooms
|
|
281
|
+
await page1.goto(BASE_URL);
|
|
282
|
+
await page2.goto(BASE_URL);
|
|
283
|
+
|
|
284
|
+
// Use different unique room IDs to ensure isolation
|
|
285
|
+
const roomA = `iso-a-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
286
|
+
const roomB = `iso-b-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
287
|
+
await page1.getByTestId('roomId').fill(roomA);
|
|
288
|
+
await page2.getByTestId('roomId').fill(roomB);
|
|
289
|
+
|
|
290
|
+
await page1.getByTestId('connectBtn').click();
|
|
291
|
+
await expect(page1.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
292
|
+
|
|
293
|
+
await page2.getByTestId('connectBtn').click();
|
|
294
|
+
await expect(page2.getByTestId('log-connected')).toBeVisible({ timeout: 10000 });
|
|
295
|
+
|
|
296
|
+
// Wait a bit to see if peer-joined appears (it shouldn't)
|
|
297
|
+
await page1.waitForTimeout(3000);
|
|
298
|
+
|
|
299
|
+
// Neither should see the other's peer-joined
|
|
300
|
+
const peerList1 = page1.getByTestId('peerList');
|
|
301
|
+
const peerList2 = page2.getByTestId('peerList');
|
|
302
|
+
|
|
303
|
+
await expect(peerList1).toContainText('No peers connected');
|
|
304
|
+
await expect(peerList2).toContainText('No peers connected');
|
|
305
|
+
|
|
306
|
+
} finally {
|
|
307
|
+
await context1.close();
|
|
308
|
+
await context2.close();
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test.describe('Error Handling', () => {
|
|
314
|
+
test('should show error when server URL is empty', async ({ page }) => {
|
|
315
|
+
await page.goto(BASE_URL);
|
|
316
|
+
|
|
317
|
+
await page.getByTestId('serverUrl').fill('');
|
|
318
|
+
await page.getByTestId('connectBtn').click();
|
|
319
|
+
|
|
320
|
+
await expect(page.locator('text=Please enter a server URL')).toBeVisible({ timeout: 5000 });
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test('should show error when room ID is empty', async ({ page }) => {
|
|
324
|
+
await page.goto(BASE_URL);
|
|
325
|
+
|
|
326
|
+
await page.getByTestId('roomId').fill('');
|
|
327
|
+
await page.getByTestId('connectBtn').click();
|
|
328
|
+
|
|
329
|
+
await expect(page.locator('text=Please enter a room ID')).toBeVisible({ timeout: 5000 });
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
});
|
package/test.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Simple test script for UniWRTC
|
|
5
|
-
* Runs two clients and tests peer connections
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { UniWRTCClient } = require('./client.js');
|
|
9
|
-
|
|
10
|
-
async function sleep(ms) {
|
|
11
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function runTest() {
|
|
15
|
-
console.log('š Starting UniWRTC Test...\n');
|
|
16
|
-
|
|
17
|
-
// Create two clients
|
|
18
|
-
const client1 = new UniWRTCClient('ws://localhost:8080');
|
|
19
|
-
const client2 = new UniWRTCClient('ws://localhost:8080');
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
// Connect first client
|
|
23
|
-
console.log('š± Connecting Client 1...');
|
|
24
|
-
const id1 = await client1.connect();
|
|
25
|
-
console.log(`ā
Client 1 connected with ID: ${id1}\n`);
|
|
26
|
-
|
|
27
|
-
await sleep(500);
|
|
28
|
-
|
|
29
|
-
// Connect second client
|
|
30
|
-
console.log('š± Connecting Client 2...');
|
|
31
|
-
const id2 = await client2.connect();
|
|
32
|
-
console.log(`ā
Client 2 connected with ID: ${id2}\n`);
|
|
33
|
-
|
|
34
|
-
await sleep(500);
|
|
35
|
-
|
|
36
|
-
// Join same room
|
|
37
|
-
console.log('š Client 1 joining room: test-room');
|
|
38
|
-
client1.joinRoom('test-room');
|
|
39
|
-
|
|
40
|
-
await sleep(500);
|
|
41
|
-
|
|
42
|
-
console.log('š Client 2 joining room: test-room');
|
|
43
|
-
client2.joinRoom('test-room');
|
|
44
|
-
|
|
45
|
-
await sleep(1000);
|
|
46
|
-
|
|
47
|
-
console.log('\n⨠Test complete! Both clients joined the room.');
|
|
48
|
-
console.log('š Peers in Client 1:', Array.from(client1.peers.keys()));
|
|
49
|
-
console.log('š Peers in Client 2:', Array.from(client2.peers.keys()));
|
|
50
|
-
|
|
51
|
-
// Cleanup
|
|
52
|
-
client1.disconnect();
|
|
53
|
-
client2.disconnect();
|
|
54
|
-
|
|
55
|
-
process.exit(0);
|
|
56
|
-
} catch (error) {
|
|
57
|
-
console.error('ā Test failed:', error.message);
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
runTest();
|