uniwrtc 1.5.0 → 1.7.0
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 +1 -1
- package/src/main.js +51 -9
- package/tests/e2e.spec.js +29 -25
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -171,6 +171,25 @@ if (ICE_SERVERS.length === 0) {
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
function log(message, type = 'info') {
|
|
174
|
+
// Reduce noise in the Activity Log by default.
|
|
175
|
+
// Use ?debug=1 to see everything.
|
|
176
|
+
const debugMode = (params.get('debug') || '').toLowerCase();
|
|
177
|
+
const noisy =
|
|
178
|
+
message.startsWith('Dropped ') ||
|
|
179
|
+
message.startsWith('ICE state (') ||
|
|
180
|
+
message.startsWith('Conn state (') ||
|
|
181
|
+
message.startsWith('Relay NOTICE') ||
|
|
182
|
+
message.includes('Failed to add ICE candidate') ||
|
|
183
|
+
message.includes('Failed to add queued ICE candidate') ||
|
|
184
|
+
message.includes('Failed to send ICE batch') ||
|
|
185
|
+
message.startsWith('Disconnected');
|
|
186
|
+
|
|
187
|
+
if (noisy && debugMode !== '1' && debugMode !== 'true') {
|
|
188
|
+
// Keep available for debugging without spamming the UI.
|
|
189
|
+
console.debug(message);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
174
193
|
const logContainer = document.getElementById('logContainer');
|
|
175
194
|
const entry = document.createElement('div');
|
|
176
195
|
entry.className = `log-entry ${type}`;
|
|
@@ -213,16 +232,37 @@ function updateStatus(connected) {
|
|
|
213
232
|
|
|
214
233
|
function updatePeerList() {
|
|
215
234
|
const peerList = document.getElementById('peerList');
|
|
216
|
-
if (
|
|
235
|
+
if (!peerList) return;
|
|
236
|
+
|
|
237
|
+
const connectedPeerIds = [];
|
|
238
|
+
for (const [peerId, pc] of peerConnections.entries()) {
|
|
239
|
+
if (!(pc instanceof RTCPeerConnection)) continue;
|
|
240
|
+
|
|
241
|
+
// Prefer data channel state when available.
|
|
242
|
+
const dc = dataChannels.get(peerId);
|
|
243
|
+
const hasOpenDataChannel = dc && dc.readyState === 'open';
|
|
244
|
+
|
|
245
|
+
const connState = pc.connectionState;
|
|
246
|
+
const isActive = connState === 'connected' || connState === 'connecting' || hasOpenDataChannel;
|
|
247
|
+
|
|
248
|
+
// Explicitly hide failed/disconnected/closed peers.
|
|
249
|
+
if (!isActive) continue;
|
|
250
|
+
if (connState === 'failed' || connState === 'disconnected' || connState === 'closed') continue;
|
|
251
|
+
|
|
252
|
+
connectedPeerIds.push(peerId);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (connectedPeerIds.length === 0) {
|
|
217
256
|
peerList.innerHTML = '<p style="color: #94a3b8;">No peers connected</p>';
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
peerList.innerHTML = '';
|
|
261
|
+
for (const peerId of connectedPeerIds) {
|
|
262
|
+
const peerItem = document.createElement('div');
|
|
263
|
+
peerItem.className = 'peer-item';
|
|
264
|
+
peerItem.textContent = peerId.substring(0, 8) + '...';
|
|
265
|
+
peerList.appendChild(peerItem);
|
|
226
266
|
}
|
|
227
267
|
}
|
|
228
268
|
|
|
@@ -927,10 +967,12 @@ async function createPeerConnection(peerId, shouldInitiate) {
|
|
|
927
967
|
|
|
928
968
|
pc.oniceconnectionstatechange = () => {
|
|
929
969
|
log(`ICE state (${peerId.substring(0, 6)}...): ${pc.iceConnectionState}`, 'info');
|
|
970
|
+
updatePeerList();
|
|
930
971
|
};
|
|
931
972
|
|
|
932
973
|
pc.onconnectionstatechange = () => {
|
|
933
974
|
log(`Conn state (${peerId.substring(0, 6)}...): ${pc.connectionState}`, 'info');
|
|
975
|
+
updatePeerList();
|
|
934
976
|
};
|
|
935
977
|
|
|
936
978
|
pc.ondatachannel = (event) => {
|
package/tests/e2e.spec.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { test, expect } from '@playwright/test';
|
|
2
2
|
|
|
3
3
|
test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
4
|
-
const
|
|
4
|
+
const randomRoomId = (prefix = 'e2e') => {
|
|
5
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
6
|
+
};
|
|
5
7
|
|
|
6
8
|
test.describe('Connection and Session Management', () => {
|
|
7
9
|
test('should load demo page and display UI', async ({ page }) => {
|
|
@@ -18,6 +20,9 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
18
20
|
test('should connect to relay and join room', async ({ page }) => {
|
|
19
21
|
test.setTimeout(60_000);
|
|
20
22
|
await page.goto('/');
|
|
23
|
+
|
|
24
|
+
// Use a unique room per test run to avoid interference from relay history.
|
|
25
|
+
await page.getByTestId('roomId').fill(randomRoomId('connect'));
|
|
21
26
|
|
|
22
27
|
// Click connect
|
|
23
28
|
await page.getByTestId('connectBtn').click();
|
|
@@ -40,6 +45,9 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
40
45
|
test('should handle disconnect', async ({ page }) => {
|
|
41
46
|
test.setTimeout(60_000);
|
|
42
47
|
await page.goto('/');
|
|
48
|
+
|
|
49
|
+
// Use a unique room per test run to avoid interference from relay history.
|
|
50
|
+
await page.getByTestId('roomId').fill(randomRoomId('disconnect'));
|
|
43
51
|
|
|
44
52
|
// Connect first
|
|
45
53
|
await page.getByTestId('connectBtn').click();
|
|
@@ -56,6 +64,8 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
56
64
|
|
|
57
65
|
test.describe('Multi-peer Session', () => {
|
|
58
66
|
test('should connect three peers and see peer-joined notifications', async ({ browser }) => {
|
|
67
|
+
const roomId = randomRoomId('multi');
|
|
68
|
+
|
|
59
69
|
// Open three browser contexts (simulating three users)
|
|
60
70
|
const context1 = await browser.newContext();
|
|
61
71
|
const page1 = await context1.newPage();
|
|
@@ -73,9 +83,9 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
73
83
|
await page3.goto('/?ice=host');
|
|
74
84
|
|
|
75
85
|
// Use shared room ID for all three peers
|
|
76
|
-
await page1.getByTestId('roomId').fill(
|
|
77
|
-
await page2.getByTestId('roomId').fill(
|
|
78
|
-
await page3.getByTestId('roomId').fill(
|
|
86
|
+
await page1.getByTestId('roomId').fill(roomId);
|
|
87
|
+
await page2.getByTestId('roomId').fill(roomId);
|
|
88
|
+
await page3.getByTestId('roomId').fill(roomId);
|
|
79
89
|
|
|
80
90
|
// Connect peer 1
|
|
81
91
|
await page1.getByTestId('connectBtn').click();
|
|
@@ -95,14 +105,9 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
95
105
|
// Peer 2 should see peer 3 joined (use first() to avoid strict mode with multiple peer-joined logs)
|
|
96
106
|
await expect(page2.getByTestId('log-peer-joined').first()).toBeVisible({ timeout: 10000 });
|
|
97
107
|
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
|
|
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');
|
|
108
|
+
// The UI no longer shows a peer list; rely on peer discovery logs instead.
|
|
109
|
+
await expect(page1.getByTestId('log-peer-joined').first()).toBeVisible({ timeout: 20000 });
|
|
110
|
+
await expect(page2.getByTestId('log-peer-joined').first()).toBeVisible({ timeout: 20000 });
|
|
106
111
|
|
|
107
112
|
} finally {
|
|
108
113
|
await context1.close();
|
|
@@ -113,6 +118,7 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
113
118
|
|
|
114
119
|
test('should open P2P data channels between three peers', async ({ browser }) => {
|
|
115
120
|
test.setTimeout(90_000);
|
|
121
|
+
const roomId = randomRoomId('dc');
|
|
116
122
|
const context1 = await browser.newContext();
|
|
117
123
|
const page1 = await context1.newPage();
|
|
118
124
|
|
|
@@ -128,9 +134,9 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
128
134
|
await page2.goto('/?ice=host');
|
|
129
135
|
await page3.goto('/?ice=host');
|
|
130
136
|
|
|
131
|
-
await page1.getByTestId('roomId').fill(
|
|
132
|
-
await page2.getByTestId('roomId').fill(
|
|
133
|
-
await page3.getByTestId('roomId').fill(
|
|
137
|
+
await page1.getByTestId('roomId').fill(roomId);
|
|
138
|
+
await page2.getByTestId('roomId').fill(roomId);
|
|
139
|
+
await page3.getByTestId('roomId').fill(roomId);
|
|
134
140
|
|
|
135
141
|
await page1.getByTestId('connectBtn').click();
|
|
136
142
|
await expect(page1.getByTestId('log-connected')).toBeVisible({ timeout: 20000 });
|
|
@@ -182,6 +188,7 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
182
188
|
|
|
183
189
|
test('should send P2P chat messages between three peers', async ({ browser }) => {
|
|
184
190
|
test.setTimeout(90_000);
|
|
191
|
+
const roomId = randomRoomId('chat');
|
|
185
192
|
const context1 = await browser.newContext();
|
|
186
193
|
const page1 = await context1.newPage();
|
|
187
194
|
|
|
@@ -197,9 +204,9 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
197
204
|
await page2.goto('/?ice=host');
|
|
198
205
|
await page3.goto('/?ice=host');
|
|
199
206
|
|
|
200
|
-
await page1.getByTestId('roomId').fill(
|
|
201
|
-
await page2.getByTestId('roomId').fill(
|
|
202
|
-
await page3.getByTestId('roomId').fill(
|
|
207
|
+
await page1.getByTestId('roomId').fill(roomId);
|
|
208
|
+
await page2.getByTestId('roomId').fill(roomId);
|
|
209
|
+
await page3.getByTestId('roomId').fill(roomId);
|
|
203
210
|
|
|
204
211
|
await page1.getByTestId('connectBtn').click();
|
|
205
212
|
await expect(page1.getByTestId('log-connected')).toBeVisible({ timeout: 20000 });
|
|
@@ -292,13 +299,10 @@ test.describe('UniWRTC Demo - Full Integration Tests', () => {
|
|
|
292
299
|
|
|
293
300
|
// Wait a bit to see if peer-joined appears (it shouldn't)
|
|
294
301
|
await page1.waitForTimeout(3000);
|
|
295
|
-
|
|
296
|
-
// Neither should see
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
await expect(peerList1).toContainText('No peers connected');
|
|
301
|
-
await expect(peerList2).toContainText('No peers connected');
|
|
302
|
+
|
|
303
|
+
// Neither should see a peer join log (they're in different rooms).
|
|
304
|
+
await expect(page1.getByTestId('logContainer').locator('[data-testid="log-peer-joined"]')).toHaveCount(0);
|
|
305
|
+
await expect(page2.getByTestId('logContainer').locator('[data-testid="log-peer-joined"]')).toHaveCount(0);
|
|
302
306
|
|
|
303
307
|
} finally {
|
|
304
308
|
await context1.close();
|