aboutsummaryrefslogtreecommitdiffhomepage
path: root/packages/tests/src/api/live/live-save-replay.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /packages/tests/src/api/live/live-save-replay.ts
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'packages/tests/src/api/live/live-save-replay.ts')
-rw-r--r--packages/tests/src/api/live/live-save-replay.ts583
1 files changed, 583 insertions, 0 deletions
diff --git a/packages/tests/src/api/live/live-save-replay.ts b/packages/tests/src/api/live/live-save-replay.ts
new file mode 100644
index 000000000..84135365b
--- /dev/null
+++ b/packages/tests/src/api/live/live-save-replay.ts
@@ -0,0 +1,583 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { FfmpegCommand } from 'fluent-ffmpeg'
5import { wait } from '@peertube/peertube-core-utils'
6import {
7 HttpStatusCode,
8 HttpStatusCodeType,
9 LiveVideoCreate,
10 LiveVideoError,
11 VideoPrivacy,
12 VideoPrivacyType,
13 VideoState,
14 VideoStateType
15} from '@peertube/peertube-models'
16import { checkLiveCleanup } from '@tests/shared/live.js'
17import {
18 cleanupTests,
19 ConfigCommand,
20 createMultipleServers,
21 doubleFollow,
22 findExternalSavedVideo,
23 PeerTubeServer,
24 setAccessTokensToServers,
25 setDefaultVideoChannel,
26 stopFfmpeg,
27 testFfmpegStreamError,
28 waitJobs,
29 waitUntilLivePublishedOnAllServers,
30 waitUntilLiveReplacedByReplayOnAllServers,
31 waitUntilLiveWaitingOnAllServers
32} from '@peertube/peertube-server-commands'
33
34describe('Save replay setting', function () {
35 let servers: PeerTubeServer[] = []
36 let liveVideoUUID: string
37 let ffmpegCommand: FfmpegCommand
38
39 async function createLiveWrapper (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacyType } }) {
40 if (liveVideoUUID) {
41 try {
42 await servers[0].videos.remove({ id: liveVideoUUID })
43 await waitJobs(servers)
44 } catch {}
45 }
46
47 const attributes: LiveVideoCreate = {
48 channelId: servers[0].store.channel.id,
49 privacy: VideoPrivacy.PUBLIC,
50 name: 'live'.repeat(30),
51 saveReplay: options.replay,
52 replaySettings: options.replaySettings,
53 permanentLive: options.permanent
54 }
55
56 const { uuid } = await servers[0].live.create({ fields: attributes })
57 return uuid
58 }
59
60 async function publishLive (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacyType } }) {
61 liveVideoUUID = await createLiveWrapper(options)
62
63 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
64 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
65
66 const liveDetails = await servers[0].videos.get({ id: liveVideoUUID })
67
68 await waitJobs(servers)
69 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
70
71 return { ffmpegCommand, liveDetails }
72 }
73
74 async function publishLiveAndDelete (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacyType } }) {
75 const { ffmpegCommand, liveDetails } = await publishLive(options)
76
77 await Promise.all([
78 servers[0].videos.remove({ id: liveVideoUUID }),
79 testFfmpegStreamError(ffmpegCommand, true)
80 ])
81
82 await waitJobs(servers)
83 await wait(5000)
84 await waitJobs(servers)
85
86 return { liveDetails }
87 }
88
89 async function publishLiveAndBlacklist (options: {
90 permanent: boolean
91 replay: boolean
92 replaySettings?: { privacy: VideoPrivacyType }
93 }) {
94 const { ffmpegCommand, liveDetails } = await publishLive(options)
95
96 await Promise.all([
97 servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
98 testFfmpegStreamError(ffmpegCommand, true)
99 ])
100
101 await waitJobs(servers)
102 await wait(5000)
103 await waitJobs(servers)
104
105 return { liveDetails }
106 }
107
108 async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: HttpStatusCodeType) {
109 for (const server of servers) {
110 const length = existsInList ? 1 : 0
111
112 const { data, total } = await server.videos.list()
113 expect(data).to.have.lengthOf(length)
114 expect(total).to.equal(length)
115
116 if (expectedStatus) {
117 await server.videos.get({ id: videoId, expectedStatus })
118 }
119 }
120 }
121
122 async function checkVideoState (videoId: string, state: VideoStateType) {
123 for (const server of servers) {
124 const video = await server.videos.get({ id: videoId })
125 expect(video.state.id).to.equal(state)
126 }
127 }
128
129 async function checkVideoPrivacy (videoId: string, privacy: VideoPrivacyType) {
130 for (const server of servers) {
131 const video = await server.videos.get({ id: videoId })
132 expect(video.privacy.id).to.equal(privacy)
133 }
134 }
135
136 before(async function () {
137 this.timeout(120000)
138
139 servers = await createMultipleServers(2)
140
141 // Get the access tokens
142 await setAccessTokensToServers(servers)
143 await setDefaultVideoChannel(servers)
144
145 // Server 1 and server 2 follow each other
146 await doubleFollow(servers[0], servers[1])
147
148 await servers[0].config.updateCustomSubConfig({
149 newConfig: {
150 live: {
151 enabled: true,
152 allowReplay: true,
153 maxDuration: -1,
154 transcoding: {
155 enabled: false,
156 resolutions: ConfigCommand.getCustomConfigResolutions(true)
157 }
158 }
159 }
160 })
161 })
162
163 describe('With save replay disabled', function () {
164 let sessionStartDateMin: Date
165 let sessionStartDateMax: Date
166 let sessionEndDateMin: Date
167
168 it('Should correctly create and federate the "waiting for stream" live', async function () {
169 this.timeout(40000)
170
171 liveVideoUUID = await createLiveWrapper({ permanent: false, replay: false })
172
173 await waitJobs(servers)
174
175 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
176 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
177 })
178
179 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
180 this.timeout(120000)
181
182 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
183
184 sessionStartDateMin = new Date()
185 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
186 sessionStartDateMax = new Date()
187
188 await waitJobs(servers)
189
190 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
191 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
192 })
193
194 it('Should correctly delete the video files after the stream ended', async function () {
195 this.timeout(120000)
196
197 sessionEndDateMin = new Date()
198 await stopFfmpeg(ffmpegCommand)
199
200 for (const server of servers) {
201 await server.live.waitUntilEnded({ videoId: liveVideoUUID })
202 }
203 await waitJobs(servers)
204
205 // Live still exist, but cannot be played anymore
206 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
207 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
208
209 // No resolutions saved since we did not save replay
210 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
211 })
212
213 it('Should have appropriate ended session', async function () {
214 const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID })
215 expect(total).to.equal(1)
216 expect(data).to.have.lengthOf(1)
217
218 const session = data[0]
219
220 const startDate = new Date(session.startDate)
221 expect(startDate).to.be.above(sessionStartDateMin)
222 expect(startDate).to.be.below(sessionStartDateMax)
223
224 expect(session.endDate).to.exist
225 expect(new Date(session.endDate)).to.be.above(sessionEndDateMin)
226
227 expect(session.saveReplay).to.be.false
228 expect(session.error).to.not.exist
229 expect(session.replayVideo).to.not.exist
230 })
231
232 it('Should correctly terminate the stream on blacklist and delete the live', async function () {
233 this.timeout(120000)
234
235 await publishLiveAndBlacklist({ permanent: false, replay: false })
236
237 await checkVideosExist(liveVideoUUID, false)
238
239 await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
240 await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
241
242 await wait(5000)
243 await waitJobs(servers)
244 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
245 })
246
247 it('Should have blacklisted session error', async function () {
248 const session = await servers[0].live.findLatestSession({ videoId: liveVideoUUID })
249 expect(session.startDate).to.exist
250 expect(session.endDate).to.exist
251
252 expect(session.error).to.equal(LiveVideoError.BLACKLISTED)
253 expect(session.replayVideo).to.not.exist
254 })
255
256 it('Should correctly terminate the stream on delete and delete the video', async function () {
257 this.timeout(120000)
258
259 await publishLiveAndDelete({ permanent: false, replay: false })
260
261 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
262 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
263 })
264 })
265
266 describe('With save replay enabled on non permanent live', function () {
267
268 it('Should correctly create and federate the "waiting for stream" live', async function () {
269 this.timeout(120000)
270
271 liveVideoUUID = await createLiveWrapper({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.UNLISTED } })
272
273 await waitJobs(servers)
274
275 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
276 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
277 await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
278 })
279
280 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
281 this.timeout(120000)
282
283 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
284 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
285
286 await waitJobs(servers)
287
288 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
289 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
290 await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
291 })
292
293 it('Should correctly have saved the live and federated it after the streaming', async function () {
294 this.timeout(120000)
295
296 const session = await servers[0].live.findLatestSession({ videoId: liveVideoUUID })
297 expect(session.endDate).to.not.exist
298 expect(session.endingProcessed).to.be.false
299 expect(session.saveReplay).to.be.true
300 expect(session.replaySettings).to.exist
301 expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED)
302
303 await stopFfmpeg(ffmpegCommand)
304
305 await waitUntilLiveReplacedByReplayOnAllServers(servers, liveVideoUUID)
306 await waitJobs(servers)
307
308 // Live has been transcoded
309 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
310 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
311 await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.UNLISTED)
312 })
313
314 it('Should find the replay live session', async function () {
315 const session = await servers[0].live.getReplaySession({ videoId: liveVideoUUID })
316
317 expect(session).to.exist
318
319 expect(session.startDate).to.exist
320 expect(session.endDate).to.exist
321
322 expect(session.error).to.not.exist
323 expect(session.saveReplay).to.be.true
324 expect(session.endingProcessed).to.be.true
325 expect(session.replaySettings).to.exist
326 expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED)
327
328 expect(session.replayVideo).to.exist
329 expect(session.replayVideo.id).to.exist
330 expect(session.replayVideo.shortUUID).to.exist
331 expect(session.replayVideo.uuid).to.equal(liveVideoUUID)
332 })
333
334 it('Should update the saved live and correctly federate the updated attributes', async function () {
335 this.timeout(120000)
336
337 await servers[0].videos.update({ id: liveVideoUUID, attributes: { name: 'video updated', privacy: VideoPrivacy.PUBLIC } })
338 await waitJobs(servers)
339
340 for (const server of servers) {
341 const video = await server.videos.get({ id: liveVideoUUID })
342 expect(video.name).to.equal('video updated')
343 expect(video.isLive).to.be.false
344 expect(video.privacy.id).to.equal(VideoPrivacy.PUBLIC)
345 }
346 })
347
348 it('Should have cleaned up the live files', async function () {
349 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false, savedResolutions: [ 720 ] })
350 })
351
352 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
353 this.timeout(120000)
354
355 await publishLiveAndBlacklist({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } })
356
357 await checkVideosExist(liveVideoUUID, false)
358
359 await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
360 await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
361
362 await wait(5000)
363 await waitJobs(servers)
364 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false, savedResolutions: [ 720 ] })
365 })
366
367 it('Should correctly terminate the stream on delete and delete the video', async function () {
368 this.timeout(120000)
369
370 await publishLiveAndDelete({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } })
371
372 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
373 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
374 })
375 })
376
377 describe('With save replay enabled on permanent live', function () {
378 let lastReplayUUID: string
379
380 describe('With a first live and its replay', function () {
381
382 it('Should correctly create and federate the "waiting for stream" live', async function () {
383 this.timeout(120000)
384
385 liveVideoUUID = await createLiveWrapper({ permanent: true, replay: true, replaySettings: { privacy: VideoPrivacy.UNLISTED } })
386
387 await waitJobs(servers)
388
389 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
390 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
391 await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
392 })
393
394 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
395 this.timeout(120000)
396
397 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
398 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
399
400 await waitJobs(servers)
401
402 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
403 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
404 await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
405 })
406
407 it('Should correctly have saved the live and federated it after the streaming', async function () {
408 this.timeout(120000)
409
410 const liveDetails = await servers[0].videos.get({ id: liveVideoUUID })
411
412 await stopFfmpeg(ffmpegCommand)
413
414 await waitUntilLiveWaitingOnAllServers(servers, liveVideoUUID)
415 await waitJobs(servers)
416
417 const video = await findExternalSavedVideo(servers[0], liveDetails)
418 expect(video).to.exist
419
420 for (const server of servers) {
421 await server.videos.get({ id: video.uuid })
422 }
423
424 lastReplayUUID = video.uuid
425 })
426
427 it('Should have appropriate ended session and replay live session', async function () {
428 const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID })
429 expect(total).to.equal(1)
430 expect(data).to.have.lengthOf(1)
431
432 const sessionFromLive = data[0]
433 const sessionFromReplay = await servers[0].live.getReplaySession({ videoId: lastReplayUUID })
434
435 for (const session of [ sessionFromLive, sessionFromReplay ]) {
436 expect(session.startDate).to.exist
437 expect(session.endDate).to.exist
438
439 expect(session.replaySettings).to.exist
440 expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED)
441
442 expect(session.error).to.not.exist
443
444 expect(session.replayVideo).to.exist
445 expect(session.replayVideo.id).to.exist
446 expect(session.replayVideo.shortUUID).to.exist
447 expect(session.replayVideo.uuid).to.equal(lastReplayUUID)
448 }
449 })
450
451 it('Should have the first live replay with correct settings', async function () {
452 await checkVideosExist(lastReplayUUID, false, HttpStatusCode.OK_200)
453 await checkVideoState(lastReplayUUID, VideoState.PUBLISHED)
454 await checkVideoPrivacy(lastReplayUUID, VideoPrivacy.UNLISTED)
455 })
456 })
457
458 describe('With a second live and its replay', function () {
459
460 it('Should update the replay settings', async function () {
461 await servers[0].live.update({ videoId: liveVideoUUID, fields: { replaySettings: { privacy: VideoPrivacy.PUBLIC } } })
462 await waitJobs(servers)
463
464 const live = await servers[0].live.get({ videoId: liveVideoUUID })
465
466 expect(live.saveReplay).to.be.true
467 expect(live.replaySettings).to.exist
468 expect(live.replaySettings.privacy).to.equal(VideoPrivacy.PUBLIC)
469
470 })
471
472 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
473 this.timeout(120000)
474
475 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
476 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
477
478 await waitJobs(servers)
479
480 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
481 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
482 await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
483 })
484
485 it('Should correctly have saved the live and federated it after the streaming', async function () {
486 this.timeout(120000)
487
488 const liveDetails = await servers[0].videos.get({ id: liveVideoUUID })
489
490 await stopFfmpeg(ffmpegCommand)
491
492 await waitUntilLiveWaitingOnAllServers(servers, liveVideoUUID)
493 await waitJobs(servers)
494
495 const video = await findExternalSavedVideo(servers[0], liveDetails)
496 expect(video).to.exist
497
498 for (const server of servers) {
499 await server.videos.get({ id: video.uuid })
500 }
501
502 lastReplayUUID = video.uuid
503 })
504
505 it('Should have appropriate ended session and replay live session', async function () {
506 const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID })
507 expect(total).to.equal(2)
508 expect(data).to.have.lengthOf(2)
509
510 const sessionFromLive = data[1]
511 const sessionFromReplay = await servers[0].live.getReplaySession({ videoId: lastReplayUUID })
512
513 for (const session of [ sessionFromLive, sessionFromReplay ]) {
514 expect(session.startDate).to.exist
515 expect(session.endDate).to.exist
516
517 expect(session.replaySettings).to.exist
518 expect(session.replaySettings.privacy).to.equal(VideoPrivacy.PUBLIC)
519
520 expect(session.error).to.not.exist
521
522 expect(session.replayVideo).to.exist
523 expect(session.replayVideo.id).to.exist
524 expect(session.replayVideo.shortUUID).to.exist
525 expect(session.replayVideo.uuid).to.equal(lastReplayUUID)
526 }
527 })
528
529 it('Should have the first live replay with correct settings', async function () {
530 await checkVideosExist(lastReplayUUID, true, HttpStatusCode.OK_200)
531 await checkVideoState(lastReplayUUID, VideoState.PUBLISHED)
532 await checkVideoPrivacy(lastReplayUUID, VideoPrivacy.PUBLIC)
533 })
534
535 it('Should have cleaned up the live files', async function () {
536 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
537 })
538
539 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
540 this.timeout(120000)
541
542 await servers[0].videos.remove({ id: lastReplayUUID })
543 const { liveDetails } = await publishLiveAndBlacklist({
544 permanent: true,
545 replay: true,
546 replaySettings: { privacy: VideoPrivacy.PUBLIC }
547 })
548
549 const replay = await findExternalSavedVideo(servers[0], liveDetails)
550 expect(replay).to.exist
551
552 for (const videoId of [ liveVideoUUID, replay.uuid ]) {
553 await checkVideosExist(videoId, false)
554
555 await servers[0].videos.get({ id: videoId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
556 await servers[1].videos.get({ id: videoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
557 }
558
559 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
560 })
561
562 it('Should correctly terminate the stream on delete and not save the video', async function () {
563 this.timeout(120000)
564
565 const { liveDetails } = await publishLiveAndDelete({
566 permanent: true,
567 replay: true,
568 replaySettings: { privacy: VideoPrivacy.PUBLIC }
569 })
570
571 const replay = await findExternalSavedVideo(servers[0], liveDetails)
572 expect(replay).to.not.exist
573
574 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
575 await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
576 })
577 })
578 })
579
580 after(async function () {
581 await cleanupTests(servers)
582 })
583})