Skip to content

Commit f1e5cd5

Browse files
committed
Fix the stats test
1 parent da4f22d commit f1e5cd5

File tree

2 files changed

+96
-37
lines changed

2 files changed

+96
-37
lines changed

packages/millicast-sdk/tests/e2e/FunctionalPublish.steps.js

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ const defaultOptions = {
2424
let browser = null
2525
const sleep = ms => new Promise(function (resolve) { setTimeout(resolve, ms) })
2626

27+
const waitForCondition = async (page, expression, timeout = 15000) => {
28+
const start = Date.now()
29+
while (Date.now() - start < timeout) {
30+
const result = await page.evaluate(expression)
31+
if (result) {
32+
return result
33+
}
34+
await new Promise(resolve => setTimeout(resolve, 500))
35+
}
36+
return await page.evaluate(expression)
37+
}
38+
2739
afterEach(async () => {
2840
if (browser) {
2941
const pages = await browser.pages()
@@ -76,13 +88,11 @@ defineFeature(feature, test => {
7688
return startViewer(streamName, accountId)
7789
}, { streamName, accountId: process.env.ACCOUNT_ID })
7890

79-
await sleep(3000)
8091
isActive = await broadcastPage.evaluate('window.publish.isActive()')
8192
videoFrame1 = await viewerPage.evaluate('getVideoPixelSums()')
82-
await sleep(500)
93+
await sleep(1000)
8394
videoFrame2 = await viewerPage.evaluate('getVideoPixelSums()')
8495
})
85-
8696
then('broadcast is active and Viewer receive video data', async () => {
8797
expect(isActive).toBeTruthy()
8898
expect(videoFrame1).not.toBe(0)
@@ -181,26 +191,47 @@ defineFeature(feature, test => {
181191
test('Simulcast layer generation', ({ given, when, then }) => {
182192
let broadcastPage
183193
given(/^a broadcaster with simulcast enabled and codec (.*)$/, async (codec) => {
184-
if (!browser) browser = await puppeteer.launch({ headless: true, executablePath: puppeteer.executablePath(), args: ['--no-sandbox', '--use-fake-ui-for-media-stream', '--use-fake-device-for-media-stream', '--allow-file-access-from-files'] })
194+
if (!browser) {
195+
browser = await puppeteer.launch({
196+
headless: true,
197+
executablePath: puppeteer.executablePath(),
198+
args: [
199+
'--no-sandbox',
200+
'--use-fake-ui-for-media-stream',
201+
'--use-fake-device-for-media-stream',
202+
'--allow-file-access-from-files'
203+
]
204+
})
205+
}
185206
broadcastPage = await browser.newPage()
186207
await broadcastPage.goto(pageLocation)
187208
await broadcastPage.evaluate(({ token, streamName, codec }) => {
188-
return startPublisher(token, streamName, { codec, simulcast: true })
209+
return startPublisher(token, streamName, {
210+
codec,
211+
simulcast: true,
212+
metadata: true
213+
})
189214
}, { token: process.env.PUBLISH_TOKEN, streamName, codec })
190215
})
191216

192217
when('the stream is active', async () => {
193-
await sleep(6000)
218+
await waitForCondition(broadcastPage, 'window.publish.isActive()')
194219
})
195220

196221
then('the publisher reports multiple active simulcast layers', async () => {
197-
const layers = await broadcastPage.evaluate(async () => {
198-
const stats = await window.publish.getRTCPeerConnection().getStats()
199-
let count = 0
200-
stats.forEach(r => { if (r.type === 'outbound-rtp' && r.kind === 'video') count++ })
201-
return count
202-
})
203-
expect(layers).toBeGreaterThan(1)
222+
const layersFound = await waitForCondition(broadcastPage, `
223+
(async () => {
224+
const pc = window.publish?.getRTCPeerConnection();
225+
if (!pc) return false;
226+
const stats = await pc.getStats();
227+
let count = 0;
228+
stats.forEach(r => {
229+
if (r.type === 'outbound-rtp' && r.kind === 'video') count++;
230+
});
231+
return count > 1 ? count : false;
232+
})()
233+
`, 20000)
234+
expect(layersFound).toBeGreaterThan(1)
204235
})
205236
})
206237
})

packages/millicast-sdk/tests/e2e/PuppeteerJest.html

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
const tokenGenerator=() => millicast.Director.getPublisher(publishToken, streamName);
1515
const publish=new millicast.Publish(undefined, tokenGenerator);
1616

17-
publish.on('stats', () => {window.pubStatsCount++;});
17+
publish.webRTCPeer.on('stats', () => {window.pubStatsCount++;});
1818

1919
const mediaStream=await navigator.mediaDevices.getUserMedia({audio: true, video: true});
2020
document.getElementById('my-video').srcObject=mediaStream;
@@ -27,32 +27,60 @@
2727
}
2828

2929
const startViewer=(streamName, accountId) => {
30-
return new Promise(resolve => {
31-
const millicast=window.millicast;
32-
const video=document.getElementById('my-video');
33-
const tokenGenerator=() => millicast.Director.getSubscriber({
34-
streamName: streamName,
35-
streamAccountId: accountId
36-
});
37-
const view=new millicast.View(undefined, tokenGenerator);
30+
return new Promise((resolve, reject) => {
31+
const millicast=window.millicast;
32+
const video=document.getElementById('my-video');
33+
const tokenGenerator=() => millicast.Director.getSubscriber(streamName, accountId);
3834

39-
view.on('stats', () => {window.viewStatsCount++;});
40-
view.on('metadata', (data) => {window.lastReceivedMetadata=data;});
35+
const view=new millicast.View(streamName, tokenGenerator);
36+
window.view=view;
4137

42-
video.addEventListener('timeupdate', () => {
43-
if (video.currentTime>1) resolve();
44-
});
45-
view.on('track', (event) => {video.srcObject=event.streams[0];});
46-
view.connect({
47-
metadata: true, metadata: true,
48-
peerConfig: {
49-
autoInitStats: true,
50-
statsIntervalMs: 1000,
51-
},
38+
view.webRTCPeer.on('stats', () => {
39+
window.viewStatsCount++;
40+
});
41+
42+
view.on('metadata', (data) => {
43+
window.lastReceivedMetadata=data;
44+
});
45+
46+
view.on("broadcastEvent", async (event) => {
47+
const {name, data}=event;
48+
if (name==="active") {
49+
const tracksMapping=data.tracks.map(track => ({
50+
...track,
51+
mediaId: track.media==="video"? "0":"1"
52+
}));
53+
try {
54+
await view.project(data.sourceId, tracksMapping);
55+
} catch (e) {
56+
console.error("Project failed", e);
57+
}
58+
}
59+
});
60+
61+
view.on("track", (event) => {
62+
if (event.track.kind==="video") {
63+
video.srcObject=event.streams[0];
64+
65+
video.onplaying=() => {
66+
console.log("Video is playing, resolving promise");
67+
resolve();
68+
};
69+
}
70+
});
71+
72+
// Set a timeout so the test doesn't hang forever if projection fails
73+
setTimeout(() => reject(new Error("Viewer connection timeout")), 15000);
74+
75+
view.connect({
76+
metadata: true,
77+
peerConfig: {
78+
autoInitStats: true,
79+
statsIntervalMs: 1000
80+
}
81+
}).catch(reject);
5282
});
53-
window.view=view;
54-
})
55-
}
83+
}
5684

5785
const getVideoPixelSums=() => {
5886
const canvas=document.createElement('canvas');

0 commit comments

Comments
 (0)