diff options
Diffstat (limited to 'server/tests/api/videos/multiple-servers.ts')
-rw-r--r-- | server/tests/api/videos/multiple-servers.ts | 1099 |
1 files changed, 0 insertions, 1099 deletions
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts deleted file mode 100644 index e9aa0e3a1..000000000 --- a/server/tests/api/videos/multiple-servers.ts +++ /dev/null | |||
@@ -1,1099 +0,0 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
4 | import request from 'supertest' | ||
5 | import { | ||
6 | checkTmpIsEmpty, | ||
7 | checkVideoFilesWereRemoved, | ||
8 | checkWebTorrentWorks, | ||
9 | completeVideoCheck, | ||
10 | dateIsValid, | ||
11 | saveVideoInServers, | ||
12 | testImageGeneratedByFFmpeg | ||
13 | } from '@server/tests/shared' | ||
14 | import { buildAbsoluteFixturePath, wait } from '@shared/core-utils' | ||
15 | import { HttpStatusCode, VideoCommentThreadTree, VideoPrivacy } from '@shared/models' | ||
16 | import { | ||
17 | cleanupTests, | ||
18 | createMultipleServers, | ||
19 | doubleFollow, | ||
20 | makeGetRequest, | ||
21 | PeerTubeServer, | ||
22 | setAccessTokensToServers, | ||
23 | setDefaultAccountAvatar, | ||
24 | setDefaultChannelAvatar, | ||
25 | waitJobs | ||
26 | } from '@shared/server-commands' | ||
27 | |||
28 | describe('Test multiple servers', function () { | ||
29 | let servers: PeerTubeServer[] = [] | ||
30 | const toRemove = [] | ||
31 | let videoUUID = '' | ||
32 | let videoChannelId: number | ||
33 | |||
34 | before(async function () { | ||
35 | this.timeout(120000) | ||
36 | |||
37 | servers = await createMultipleServers(3) | ||
38 | |||
39 | // Get the access tokens | ||
40 | await setAccessTokensToServers(servers) | ||
41 | |||
42 | { | ||
43 | const videoChannel = { | ||
44 | name: 'super_channel_name', | ||
45 | displayName: 'my channel', | ||
46 | description: 'super channel' | ||
47 | } | ||
48 | await servers[0].channels.create({ attributes: videoChannel }) | ||
49 | await setDefaultChannelAvatar(servers[0], videoChannel.name) | ||
50 | await setDefaultAccountAvatar(servers) | ||
51 | |||
52 | const { data } = await servers[0].channels.list({ start: 0, count: 1 }) | ||
53 | videoChannelId = data[0].id | ||
54 | } | ||
55 | |||
56 | // Server 1 and server 2 follow each other | ||
57 | await doubleFollow(servers[0], servers[1]) | ||
58 | // Server 1 and server 3 follow each other | ||
59 | await doubleFollow(servers[0], servers[2]) | ||
60 | // Server 2 and server 3 follow each other | ||
61 | await doubleFollow(servers[1], servers[2]) | ||
62 | }) | ||
63 | |||
64 | it('Should not have videos for all servers', async function () { | ||
65 | for (const server of servers) { | ||
66 | const { data } = await server.videos.list() | ||
67 | expect(data).to.be.an('array') | ||
68 | expect(data.length).to.equal(0) | ||
69 | } | ||
70 | }) | ||
71 | |||
72 | describe('Should upload the video and propagate on each server', function () { | ||
73 | |||
74 | it('Should upload the video on server 1 and propagate on each server', async function () { | ||
75 | this.timeout(60000) | ||
76 | |||
77 | const attributes = { | ||
78 | name: 'my super name for server 1', | ||
79 | category: 5, | ||
80 | licence: 4, | ||
81 | language: 'ja', | ||
82 | nsfw: true, | ||
83 | description: 'my super description for server 1', | ||
84 | support: 'my super support text for server 1', | ||
85 | originallyPublishedAt: '2019-02-10T13:38:14.449Z', | ||
86 | tags: [ 'tag1p1', 'tag2p1' ], | ||
87 | channelId: videoChannelId, | ||
88 | fixture: 'video_short1.webm' | ||
89 | } | ||
90 | await servers[0].videos.upload({ attributes }) | ||
91 | |||
92 | await waitJobs(servers) | ||
93 | |||
94 | // All servers should have this video | ||
95 | let publishedAt: string = null | ||
96 | for (const server of servers) { | ||
97 | const isLocal = server.port === servers[0].port | ||
98 | const checkAttributes = { | ||
99 | name: 'my super name for server 1', | ||
100 | category: 5, | ||
101 | licence: 4, | ||
102 | language: 'ja', | ||
103 | nsfw: true, | ||
104 | description: 'my super description for server 1', | ||
105 | support: 'my super support text for server 1', | ||
106 | originallyPublishedAt: '2019-02-10T13:38:14.449Z', | ||
107 | account: { | ||
108 | name: 'root', | ||
109 | host: servers[0].host | ||
110 | }, | ||
111 | isLocal, | ||
112 | publishedAt, | ||
113 | duration: 10, | ||
114 | tags: [ 'tag1p1', 'tag2p1' ], | ||
115 | privacy: VideoPrivacy.PUBLIC, | ||
116 | commentsEnabled: true, | ||
117 | downloadEnabled: true, | ||
118 | channel: { | ||
119 | displayName: 'my channel', | ||
120 | name: 'super_channel_name', | ||
121 | description: 'super channel', | ||
122 | isLocal | ||
123 | }, | ||
124 | fixture: 'video_short1.webm', | ||
125 | files: [ | ||
126 | { | ||
127 | resolution: 720, | ||
128 | size: 572456 | ||
129 | } | ||
130 | ] | ||
131 | } | ||
132 | |||
133 | const { data } = await server.videos.list() | ||
134 | expect(data).to.be.an('array') | ||
135 | expect(data.length).to.equal(1) | ||
136 | const video = data[0] | ||
137 | |||
138 | await completeVideoCheck({ server, originServer: servers[0], videoUUID: video.uuid, attributes: checkAttributes }) | ||
139 | publishedAt = video.publishedAt as string | ||
140 | |||
141 | expect(video.channel.avatars).to.have.lengthOf(2) | ||
142 | expect(video.account.avatars).to.have.lengthOf(2) | ||
143 | |||
144 | for (const image of [ ...video.channel.avatars, ...video.account.avatars ]) { | ||
145 | expect(image.createdAt).to.exist | ||
146 | expect(image.updatedAt).to.exist | ||
147 | expect(image.width).to.be.above(20).and.below(1000) | ||
148 | expect(image.path).to.exist | ||
149 | |||
150 | await makeGetRequest({ | ||
151 | url: server.url, | ||
152 | path: image.path, | ||
153 | expectedStatus: HttpStatusCode.OK_200 | ||
154 | }) | ||
155 | } | ||
156 | } | ||
157 | }) | ||
158 | |||
159 | it('Should upload the video on server 2 and propagate on each server', async function () { | ||
160 | this.timeout(240000) | ||
161 | |||
162 | const user = { | ||
163 | username: 'user1', | ||
164 | password: 'super_password' | ||
165 | } | ||
166 | await servers[1].users.create({ username: user.username, password: user.password }) | ||
167 | const userAccessToken = await servers[1].login.getAccessToken(user) | ||
168 | |||
169 | const attributes = { | ||
170 | name: 'my super name for server 2', | ||
171 | category: 4, | ||
172 | licence: 3, | ||
173 | language: 'de', | ||
174 | nsfw: true, | ||
175 | description: 'my super description for server 2', | ||
176 | support: 'my super support text for server 2', | ||
177 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], | ||
178 | fixture: 'video_short2.webm', | ||
179 | thumbnailfile: 'custom-thumbnail.jpg', | ||
180 | previewfile: 'custom-preview.jpg' | ||
181 | } | ||
182 | await servers[1].videos.upload({ token: userAccessToken, attributes, mode: 'resumable' }) | ||
183 | |||
184 | // Transcoding | ||
185 | await waitJobs(servers) | ||
186 | |||
187 | // All servers should have this video | ||
188 | for (const server of servers) { | ||
189 | const isLocal = server.url === servers[1].url | ||
190 | const checkAttributes = { | ||
191 | name: 'my super name for server 2', | ||
192 | category: 4, | ||
193 | licence: 3, | ||
194 | language: 'de', | ||
195 | nsfw: true, | ||
196 | description: 'my super description for server 2', | ||
197 | support: 'my super support text for server 2', | ||
198 | account: { | ||
199 | name: 'user1', | ||
200 | host: servers[1].host | ||
201 | }, | ||
202 | isLocal, | ||
203 | commentsEnabled: true, | ||
204 | downloadEnabled: true, | ||
205 | duration: 5, | ||
206 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], | ||
207 | privacy: VideoPrivacy.PUBLIC, | ||
208 | channel: { | ||
209 | displayName: 'Main user1 channel', | ||
210 | name: 'user1_channel', | ||
211 | description: 'super channel', | ||
212 | isLocal | ||
213 | }, | ||
214 | fixture: 'video_short2.webm', | ||
215 | files: [ | ||
216 | { | ||
217 | resolution: 240, | ||
218 | size: 270000 | ||
219 | }, | ||
220 | { | ||
221 | resolution: 360, | ||
222 | size: 359000 | ||
223 | }, | ||
224 | { | ||
225 | resolution: 480, | ||
226 | size: 465000 | ||
227 | }, | ||
228 | { | ||
229 | resolution: 720, | ||
230 | size: 750000 | ||
231 | } | ||
232 | ], | ||
233 | thumbnailfile: 'custom-thumbnail', | ||
234 | previewfile: 'custom-preview' | ||
235 | } | ||
236 | |||
237 | const { data } = await server.videos.list() | ||
238 | expect(data).to.be.an('array') | ||
239 | expect(data.length).to.equal(2) | ||
240 | const video = data[1] | ||
241 | |||
242 | await completeVideoCheck({ server, originServer: servers[1], videoUUID: video.uuid, attributes: checkAttributes }) | ||
243 | } | ||
244 | }) | ||
245 | |||
246 | it('Should upload two videos on server 3 and propagate on each server', async function () { | ||
247 | this.timeout(45000) | ||
248 | |||
249 | { | ||
250 | const attributes = { | ||
251 | name: 'my super name for server 3', | ||
252 | category: 6, | ||
253 | licence: 5, | ||
254 | language: 'de', | ||
255 | nsfw: true, | ||
256 | description: 'my super description for server 3', | ||
257 | support: 'my super support text for server 3', | ||
258 | tags: [ 'tag1p3' ], | ||
259 | fixture: 'video_short3.webm' | ||
260 | } | ||
261 | await servers[2].videos.upload({ attributes }) | ||
262 | } | ||
263 | |||
264 | { | ||
265 | const attributes = { | ||
266 | name: 'my super name for server 3-2', | ||
267 | category: 7, | ||
268 | licence: 6, | ||
269 | language: 'ko', | ||
270 | nsfw: false, | ||
271 | description: 'my super description for server 3-2', | ||
272 | support: 'my super support text for server 3-2', | ||
273 | tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], | ||
274 | fixture: 'video_short.webm' | ||
275 | } | ||
276 | await servers[2].videos.upload({ attributes }) | ||
277 | } | ||
278 | |||
279 | await waitJobs(servers) | ||
280 | |||
281 | // All servers should have this video | ||
282 | for (const server of servers) { | ||
283 | const isLocal = server.url === servers[2].url | ||
284 | const { data } = await server.videos.list() | ||
285 | |||
286 | expect(data).to.be.an('array') | ||
287 | expect(data.length).to.equal(4) | ||
288 | |||
289 | // We not sure about the order of the two last uploads | ||
290 | let video1 = null | ||
291 | let video2 = null | ||
292 | if (data[2].name === 'my super name for server 3') { | ||
293 | video1 = data[2] | ||
294 | video2 = data[3] | ||
295 | } else { | ||
296 | video1 = data[3] | ||
297 | video2 = data[2] | ||
298 | } | ||
299 | |||
300 | const checkAttributesVideo1 = { | ||
301 | name: 'my super name for server 3', | ||
302 | category: 6, | ||
303 | licence: 5, | ||
304 | language: 'de', | ||
305 | nsfw: true, | ||
306 | description: 'my super description for server 3', | ||
307 | support: 'my super support text for server 3', | ||
308 | account: { | ||
309 | name: 'root', | ||
310 | host: servers[2].host | ||
311 | }, | ||
312 | isLocal, | ||
313 | duration: 5, | ||
314 | commentsEnabled: true, | ||
315 | downloadEnabled: true, | ||
316 | tags: [ 'tag1p3' ], | ||
317 | privacy: VideoPrivacy.PUBLIC, | ||
318 | channel: { | ||
319 | displayName: 'Main root channel', | ||
320 | name: 'root_channel', | ||
321 | description: '', | ||
322 | isLocal | ||
323 | }, | ||
324 | fixture: 'video_short3.webm', | ||
325 | files: [ | ||
326 | { | ||
327 | resolution: 720, | ||
328 | size: 292677 | ||
329 | } | ||
330 | ] | ||
331 | } | ||
332 | await completeVideoCheck({ server, originServer: servers[2], videoUUID: video1.uuid, attributes: checkAttributesVideo1 }) | ||
333 | |||
334 | const checkAttributesVideo2 = { | ||
335 | name: 'my super name for server 3-2', | ||
336 | category: 7, | ||
337 | licence: 6, | ||
338 | language: 'ko', | ||
339 | nsfw: false, | ||
340 | description: 'my super description for server 3-2', | ||
341 | support: 'my super support text for server 3-2', | ||
342 | account: { | ||
343 | name: 'root', | ||
344 | host: servers[2].host | ||
345 | }, | ||
346 | commentsEnabled: true, | ||
347 | downloadEnabled: true, | ||
348 | isLocal, | ||
349 | duration: 5, | ||
350 | tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], | ||
351 | privacy: VideoPrivacy.PUBLIC, | ||
352 | channel: { | ||
353 | displayName: 'Main root channel', | ||
354 | name: 'root_channel', | ||
355 | description: '', | ||
356 | isLocal | ||
357 | }, | ||
358 | fixture: 'video_short.webm', | ||
359 | files: [ | ||
360 | { | ||
361 | resolution: 720, | ||
362 | size: 218910 | ||
363 | } | ||
364 | ] | ||
365 | } | ||
366 | await completeVideoCheck({ server, originServer: servers[2], videoUUID: video2.uuid, attributes: checkAttributesVideo2 }) | ||
367 | } | ||
368 | }) | ||
369 | }) | ||
370 | |||
371 | describe('It should list local videos', function () { | ||
372 | it('Should list only local videos on server 1', async function () { | ||
373 | const { data, total } = await servers[0].videos.list({ isLocal: true }) | ||
374 | |||
375 | expect(total).to.equal(1) | ||
376 | expect(data).to.be.an('array') | ||
377 | expect(data.length).to.equal(1) | ||
378 | expect(data[0].name).to.equal('my super name for server 1') | ||
379 | }) | ||
380 | |||
381 | it('Should list only local videos on server 2', async function () { | ||
382 | const { data, total } = await servers[1].videos.list({ isLocal: true }) | ||
383 | |||
384 | expect(total).to.equal(1) | ||
385 | expect(data).to.be.an('array') | ||
386 | expect(data.length).to.equal(1) | ||
387 | expect(data[0].name).to.equal('my super name for server 2') | ||
388 | }) | ||
389 | |||
390 | it('Should list only local videos on server 3', async function () { | ||
391 | const { data, total } = await servers[2].videos.list({ isLocal: true }) | ||
392 | |||
393 | expect(total).to.equal(2) | ||
394 | expect(data).to.be.an('array') | ||
395 | expect(data.length).to.equal(2) | ||
396 | expect(data[0].name).to.equal('my super name for server 3') | ||
397 | expect(data[1].name).to.equal('my super name for server 3-2') | ||
398 | }) | ||
399 | }) | ||
400 | |||
401 | describe('Should seed the uploaded video', function () { | ||
402 | |||
403 | it('Should add the file 1 by asking server 3', async function () { | ||
404 | this.retries(2) | ||
405 | this.timeout(30000) | ||
406 | |||
407 | const { data } = await servers[2].videos.list() | ||
408 | |||
409 | const video = data[0] | ||
410 | toRemove.push(data[2]) | ||
411 | toRemove.push(data[3]) | ||
412 | |||
413 | const videoDetails = await servers[2].videos.get({ id: video.id }) | ||
414 | |||
415 | await checkWebTorrentWorks(videoDetails.files[0].magnetUri) | ||
416 | }) | ||
417 | |||
418 | it('Should add the file 2 by asking server 1', async function () { | ||
419 | this.retries(2) | ||
420 | this.timeout(30000) | ||
421 | |||
422 | const { data } = await servers[0].videos.list() | ||
423 | |||
424 | const video = data[1] | ||
425 | const videoDetails = await servers[0].videos.get({ id: video.id }) | ||
426 | |||
427 | await checkWebTorrentWorks(videoDetails.files[0].magnetUri) | ||
428 | }) | ||
429 | |||
430 | it('Should add the file 3 by asking server 2', async function () { | ||
431 | this.retries(2) | ||
432 | this.timeout(30000) | ||
433 | |||
434 | const { data } = await servers[1].videos.list() | ||
435 | |||
436 | const video = data[2] | ||
437 | const videoDetails = await servers[1].videos.get({ id: video.id }) | ||
438 | |||
439 | await checkWebTorrentWorks(videoDetails.files[0].magnetUri) | ||
440 | }) | ||
441 | |||
442 | it('Should add the file 3-2 by asking server 1', async function () { | ||
443 | this.retries(2) | ||
444 | this.timeout(30000) | ||
445 | |||
446 | const { data } = await servers[0].videos.list() | ||
447 | |||
448 | const video = data[3] | ||
449 | const videoDetails = await servers[0].videos.get({ id: video.id }) | ||
450 | |||
451 | await checkWebTorrentWorks(videoDetails.files[0].magnetUri) | ||
452 | }) | ||
453 | |||
454 | it('Should add the file 2 in 360p by asking server 1', async function () { | ||
455 | this.retries(2) | ||
456 | this.timeout(30000) | ||
457 | |||
458 | const { data } = await servers[0].videos.list() | ||
459 | |||
460 | const video = data.find(v => v.name === 'my super name for server 2') | ||
461 | const videoDetails = await servers[0].videos.get({ id: video.id }) | ||
462 | |||
463 | const file = videoDetails.files.find(f => f.resolution.id === 360) | ||
464 | expect(file).not.to.be.undefined | ||
465 | |||
466 | await checkWebTorrentWorks(file.magnetUri) | ||
467 | }) | ||
468 | }) | ||
469 | |||
470 | describe('Should update video views, likes and dislikes', function () { | ||
471 | let localVideosServer3 = [] | ||
472 | let remoteVideosServer1 = [] | ||
473 | let remoteVideosServer2 = [] | ||
474 | let remoteVideosServer3 = [] | ||
475 | |||
476 | before(async function () { | ||
477 | { | ||
478 | const { data } = await servers[0].videos.list() | ||
479 | remoteVideosServer1 = data.filter(video => video.isLocal === false).map(video => video.uuid) | ||
480 | } | ||
481 | |||
482 | { | ||
483 | const { data } = await servers[1].videos.list() | ||
484 | remoteVideosServer2 = data.filter(video => video.isLocal === false).map(video => video.uuid) | ||
485 | } | ||
486 | |||
487 | { | ||
488 | const { data } = await servers[2].videos.list() | ||
489 | localVideosServer3 = data.filter(video => video.isLocal === true).map(video => video.uuid) | ||
490 | remoteVideosServer3 = data.filter(video => video.isLocal === false).map(video => video.uuid) | ||
491 | } | ||
492 | }) | ||
493 | |||
494 | it('Should view multiple videos on owned servers', async function () { | ||
495 | this.timeout(30000) | ||
496 | |||
497 | await servers[2].views.simulateView({ id: localVideosServer3[0] }) | ||
498 | await wait(1000) | ||
499 | |||
500 | await servers[2].views.simulateView({ id: localVideosServer3[0] }) | ||
501 | await servers[2].views.simulateView({ id: localVideosServer3[1] }) | ||
502 | |||
503 | await wait(1000) | ||
504 | |||
505 | await servers[2].views.simulateView({ id: localVideosServer3[0] }) | ||
506 | await servers[2].views.simulateView({ id: localVideosServer3[0] }) | ||
507 | |||
508 | await waitJobs(servers) | ||
509 | |||
510 | for (const server of servers) { | ||
511 | await server.debug.sendCommand({ body: { command: 'process-video-views-buffer' } }) | ||
512 | } | ||
513 | |||
514 | await waitJobs(servers) | ||
515 | |||
516 | for (const server of servers) { | ||
517 | const { data } = await server.videos.list() | ||
518 | |||
519 | const video0 = data.find(v => v.uuid === localVideosServer3[0]) | ||
520 | const video1 = data.find(v => v.uuid === localVideosServer3[1]) | ||
521 | |||
522 | expect(video0.views).to.equal(3) | ||
523 | expect(video1.views).to.equal(1) | ||
524 | } | ||
525 | }) | ||
526 | |||
527 | it('Should view multiple videos on each servers', async function () { | ||
528 | this.timeout(45000) | ||
529 | |||
530 | const tasks: Promise<any>[] = [] | ||
531 | tasks.push(servers[0].views.simulateView({ id: remoteVideosServer1[0] })) | ||
532 | tasks.push(servers[1].views.simulateView({ id: remoteVideosServer2[0] })) | ||
533 | tasks.push(servers[1].views.simulateView({ id: remoteVideosServer2[0] })) | ||
534 | tasks.push(servers[2].views.simulateView({ id: remoteVideosServer3[0] })) | ||
535 | tasks.push(servers[2].views.simulateView({ id: remoteVideosServer3[1] })) | ||
536 | tasks.push(servers[2].views.simulateView({ id: remoteVideosServer3[1] })) | ||
537 | tasks.push(servers[2].views.simulateView({ id: remoteVideosServer3[1] })) | ||
538 | tasks.push(servers[2].views.simulateView({ id: localVideosServer3[1] })) | ||
539 | tasks.push(servers[2].views.simulateView({ id: localVideosServer3[1] })) | ||
540 | tasks.push(servers[2].views.simulateView({ id: localVideosServer3[1] })) | ||
541 | |||
542 | await Promise.all(tasks) | ||
543 | |||
544 | await waitJobs(servers) | ||
545 | |||
546 | for (const server of servers) { | ||
547 | await server.debug.sendCommand({ body: { command: 'process-video-views-buffer' } }) | ||
548 | } | ||
549 | |||
550 | await waitJobs(servers) | ||
551 | |||
552 | let baseVideos = null | ||
553 | |||
554 | for (const server of servers) { | ||
555 | const { data } = await server.videos.list() | ||
556 | |||
557 | // Initialize base videos for future comparisons | ||
558 | if (baseVideos === null) { | ||
559 | baseVideos = data | ||
560 | continue | ||
561 | } | ||
562 | |||
563 | for (const baseVideo of baseVideos) { | ||
564 | const sameVideo = data.find(video => video.name === baseVideo.name) | ||
565 | expect(baseVideo.views).to.equal(sameVideo.views) | ||
566 | } | ||
567 | } | ||
568 | }) | ||
569 | |||
570 | it('Should like and dislikes videos on different services', async function () { | ||
571 | this.timeout(50000) | ||
572 | |||
573 | await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'like' }) | ||
574 | await wait(500) | ||
575 | await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'dislike' }) | ||
576 | await wait(500) | ||
577 | await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'like' }) | ||
578 | await servers[2].videos.rate({ id: localVideosServer3[1], rating: 'like' }) | ||
579 | await wait(500) | ||
580 | await servers[2].videos.rate({ id: localVideosServer3[1], rating: 'dislike' }) | ||
581 | await servers[2].videos.rate({ id: remoteVideosServer3[1], rating: 'dislike' }) | ||
582 | await wait(500) | ||
583 | await servers[2].videos.rate({ id: remoteVideosServer3[0], rating: 'like' }) | ||
584 | |||
585 | await waitJobs(servers) | ||
586 | await wait(5000) | ||
587 | await waitJobs(servers) | ||
588 | |||
589 | let baseVideos = null | ||
590 | for (const server of servers) { | ||
591 | const { data } = await server.videos.list() | ||
592 | |||
593 | // Initialize base videos for future comparisons | ||
594 | if (baseVideos === null) { | ||
595 | baseVideos = data | ||
596 | continue | ||
597 | } | ||
598 | |||
599 | for (const baseVideo of baseVideos) { | ||
600 | const sameVideo = data.find(video => video.name === baseVideo.name) | ||
601 | expect(baseVideo.likes).to.equal(sameVideo.likes, `Likes of ${sameVideo.uuid} do not correspond`) | ||
602 | expect(baseVideo.dislikes).to.equal(sameVideo.dislikes, `Dislikes of ${sameVideo.uuid} do not correspond`) | ||
603 | } | ||
604 | } | ||
605 | }) | ||
606 | }) | ||
607 | |||
608 | describe('Should manipulate these videos', function () { | ||
609 | let updatedAtMin: Date | ||
610 | |||
611 | it('Should update video 3', async function () { | ||
612 | this.timeout(30000) | ||
613 | |||
614 | const attributes = { | ||
615 | name: 'my super video updated', | ||
616 | category: 10, | ||
617 | licence: 7, | ||
618 | language: 'fr', | ||
619 | nsfw: true, | ||
620 | description: 'my super description updated', | ||
621 | support: 'my super support text updated', | ||
622 | tags: [ 'tag_up_1', 'tag_up_2' ], | ||
623 | thumbnailfile: 'custom-thumbnail.jpg', | ||
624 | originallyPublishedAt: '2019-02-11T13:38:14.449Z', | ||
625 | previewfile: 'custom-preview.jpg' | ||
626 | } | ||
627 | |||
628 | updatedAtMin = new Date() | ||
629 | await servers[2].videos.update({ id: toRemove[0].id, attributes }) | ||
630 | |||
631 | await waitJobs(servers) | ||
632 | }) | ||
633 | |||
634 | it('Should have the video 3 updated on each server', async function () { | ||
635 | this.timeout(30000) | ||
636 | |||
637 | for (const server of servers) { | ||
638 | const { data } = await server.videos.list() | ||
639 | |||
640 | const videoUpdated = data.find(video => video.name === 'my super video updated') | ||
641 | expect(!!videoUpdated).to.be.true | ||
642 | |||
643 | expect(new Date(videoUpdated.updatedAt)).to.be.greaterThan(updatedAtMin) | ||
644 | |||
645 | const isLocal = server.url === servers[2].url | ||
646 | const checkAttributes = { | ||
647 | name: 'my super video updated', | ||
648 | category: 10, | ||
649 | licence: 7, | ||
650 | language: 'fr', | ||
651 | nsfw: true, | ||
652 | description: 'my super description updated', | ||
653 | support: 'my super support text updated', | ||
654 | originallyPublishedAt: '2019-02-11T13:38:14.449Z', | ||
655 | account: { | ||
656 | name: 'root', | ||
657 | host: servers[2].host | ||
658 | }, | ||
659 | isLocal, | ||
660 | duration: 5, | ||
661 | commentsEnabled: true, | ||
662 | downloadEnabled: true, | ||
663 | tags: [ 'tag_up_1', 'tag_up_2' ], | ||
664 | privacy: VideoPrivacy.PUBLIC, | ||
665 | channel: { | ||
666 | displayName: 'Main root channel', | ||
667 | name: 'root_channel', | ||
668 | description: '', | ||
669 | isLocal | ||
670 | }, | ||
671 | fixture: 'video_short3.webm', | ||
672 | files: [ | ||
673 | { | ||
674 | resolution: 720, | ||
675 | size: 292677 | ||
676 | } | ||
677 | ], | ||
678 | thumbnailfile: 'custom-thumbnail', | ||
679 | previewfile: 'custom-preview' | ||
680 | } | ||
681 | await completeVideoCheck({ server, originServer: servers[2], videoUUID: videoUpdated.uuid, attributes: checkAttributes }) | ||
682 | } | ||
683 | }) | ||
684 | |||
685 | it('Should only update thumbnail and update updatedAt attribute', async function () { | ||
686 | this.timeout(30000) | ||
687 | |||
688 | const attributes = { | ||
689 | thumbnailfile: 'custom-thumbnail.jpg' | ||
690 | } | ||
691 | |||
692 | updatedAtMin = new Date() | ||
693 | await servers[2].videos.update({ id: toRemove[0].id, attributes }) | ||
694 | |||
695 | await waitJobs(servers) | ||
696 | |||
697 | for (const server of servers) { | ||
698 | const { data } = await server.videos.list() | ||
699 | |||
700 | const videoUpdated = data.find(video => video.name === 'my super video updated') | ||
701 | expect(new Date(videoUpdated.updatedAt)).to.be.greaterThan(updatedAtMin) | ||
702 | } | ||
703 | }) | ||
704 | |||
705 | it('Should remove the videos 3 and 3-2 by asking server 3 and correctly delete files', async function () { | ||
706 | this.timeout(30000) | ||
707 | |||
708 | for (const id of [ toRemove[0].id, toRemove[1].id ]) { | ||
709 | await saveVideoInServers(servers, id) | ||
710 | |||
711 | await servers[2].videos.remove({ id }) | ||
712 | |||
713 | await waitJobs(servers) | ||
714 | |||
715 | for (const server of servers) { | ||
716 | await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails }) | ||
717 | } | ||
718 | } | ||
719 | }) | ||
720 | |||
721 | it('Should have videos 1 and 3 on each server', async function () { | ||
722 | for (const server of servers) { | ||
723 | const { data } = await server.videos.list() | ||
724 | |||
725 | expect(data).to.be.an('array') | ||
726 | expect(data.length).to.equal(2) | ||
727 | expect(data[0].name).not.to.equal(data[1].name) | ||
728 | expect(data[0].name).not.to.equal(toRemove[0].name) | ||
729 | expect(data[1].name).not.to.equal(toRemove[0].name) | ||
730 | expect(data[0].name).not.to.equal(toRemove[1].name) | ||
731 | expect(data[1].name).not.to.equal(toRemove[1].name) | ||
732 | |||
733 | videoUUID = data.find(video => video.name === 'my super name for server 1').uuid | ||
734 | } | ||
735 | }) | ||
736 | |||
737 | it('Should get the same video by UUID on each server', async function () { | ||
738 | let baseVideo = null | ||
739 | for (const server of servers) { | ||
740 | const video = await server.videos.get({ id: videoUUID }) | ||
741 | |||
742 | if (baseVideo === null) { | ||
743 | baseVideo = video | ||
744 | continue | ||
745 | } | ||
746 | |||
747 | expect(baseVideo.name).to.equal(video.name) | ||
748 | expect(baseVideo.uuid).to.equal(video.uuid) | ||
749 | expect(baseVideo.category.id).to.equal(video.category.id) | ||
750 | expect(baseVideo.language.id).to.equal(video.language.id) | ||
751 | expect(baseVideo.licence.id).to.equal(video.licence.id) | ||
752 | expect(baseVideo.nsfw).to.equal(video.nsfw) | ||
753 | expect(baseVideo.account.name).to.equal(video.account.name) | ||
754 | expect(baseVideo.account.displayName).to.equal(video.account.displayName) | ||
755 | expect(baseVideo.account.url).to.equal(video.account.url) | ||
756 | expect(baseVideo.account.host).to.equal(video.account.host) | ||
757 | expect(baseVideo.tags).to.deep.equal(video.tags) | ||
758 | } | ||
759 | }) | ||
760 | |||
761 | it('Should get the preview from each server', async function () { | ||
762 | for (const server of servers) { | ||
763 | const video = await server.videos.get({ id: videoUUID }) | ||
764 | |||
765 | await testImageGeneratedByFFmpeg(server.url, 'video_short1-preview.webm', video.previewPath) | ||
766 | } | ||
767 | }) | ||
768 | }) | ||
769 | |||
770 | describe('Should comment these videos', function () { | ||
771 | let childOfFirstChild: VideoCommentThreadTree | ||
772 | |||
773 | it('Should add comment (threads and replies)', async function () { | ||
774 | this.timeout(25000) | ||
775 | |||
776 | { | ||
777 | const text = 'my super first comment' | ||
778 | await servers[0].comments.createThread({ videoId: videoUUID, text }) | ||
779 | } | ||
780 | |||
781 | { | ||
782 | const text = 'my super second comment' | ||
783 | await servers[2].comments.createThread({ videoId: videoUUID, text }) | ||
784 | } | ||
785 | |||
786 | await waitJobs(servers) | ||
787 | |||
788 | { | ||
789 | const threadId = await servers[1].comments.findCommentId({ videoId: videoUUID, text: 'my super first comment' }) | ||
790 | |||
791 | const text = 'my super answer to thread 1' | ||
792 | await servers[1].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text }) | ||
793 | } | ||
794 | |||
795 | await waitJobs(servers) | ||
796 | |||
797 | { | ||
798 | const threadId = await servers[2].comments.findCommentId({ videoId: videoUUID, text: 'my super first comment' }) | ||
799 | |||
800 | const body = await servers[2].comments.getThread({ videoId: videoUUID, threadId }) | ||
801 | const childCommentId = body.children[0].comment.id | ||
802 | |||
803 | const text3 = 'my second answer to thread 1' | ||
804 | await servers[2].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text: text3 }) | ||
805 | |||
806 | const text2 = 'my super answer to answer of thread 1' | ||
807 | await servers[2].comments.addReply({ videoId: videoUUID, toCommentId: childCommentId, text: text2 }) | ||
808 | } | ||
809 | |||
810 | await waitJobs(servers) | ||
811 | }) | ||
812 | |||
813 | it('Should have these threads', async function () { | ||
814 | for (const server of servers) { | ||
815 | const body = await server.comments.listThreads({ videoId: videoUUID }) | ||
816 | |||
817 | expect(body.total).to.equal(2) | ||
818 | expect(body.data).to.be.an('array') | ||
819 | expect(body.data).to.have.lengthOf(2) | ||
820 | |||
821 | { | ||
822 | const comment = body.data.find(c => c.text === 'my super first comment') | ||
823 | expect(comment).to.not.be.undefined | ||
824 | expect(comment.inReplyToCommentId).to.be.null | ||
825 | expect(comment.account.name).to.equal('root') | ||
826 | expect(comment.account.host).to.equal(servers[0].host) | ||
827 | expect(comment.totalReplies).to.equal(3) | ||
828 | expect(dateIsValid(comment.createdAt as string)).to.be.true | ||
829 | expect(dateIsValid(comment.updatedAt as string)).to.be.true | ||
830 | } | ||
831 | |||
832 | { | ||
833 | const comment = body.data.find(c => c.text === 'my super second comment') | ||
834 | expect(comment).to.not.be.undefined | ||
835 | expect(comment.inReplyToCommentId).to.be.null | ||
836 | expect(comment.account.name).to.equal('root') | ||
837 | expect(comment.account.host).to.equal(servers[2].host) | ||
838 | expect(comment.totalReplies).to.equal(0) | ||
839 | expect(dateIsValid(comment.createdAt as string)).to.be.true | ||
840 | expect(dateIsValid(comment.updatedAt as string)).to.be.true | ||
841 | } | ||
842 | } | ||
843 | }) | ||
844 | |||
845 | it('Should have these comments', async function () { | ||
846 | for (const server of servers) { | ||
847 | const body = await server.comments.listThreads({ videoId: videoUUID }) | ||
848 | const threadId = body.data.find(c => c.text === 'my super first comment').id | ||
849 | |||
850 | const tree = await server.comments.getThread({ videoId: videoUUID, threadId }) | ||
851 | |||
852 | expect(tree.comment.text).equal('my super first comment') | ||
853 | expect(tree.comment.account.name).equal('root') | ||
854 | expect(tree.comment.account.host).equal(servers[0].host) | ||
855 | expect(tree.children).to.have.lengthOf(2) | ||
856 | |||
857 | const firstChild = tree.children[0] | ||
858 | expect(firstChild.comment.text).to.equal('my super answer to thread 1') | ||
859 | expect(firstChild.comment.account.name).equal('root') | ||
860 | expect(firstChild.comment.account.host).equal(servers[1].host) | ||
861 | expect(firstChild.children).to.have.lengthOf(1) | ||
862 | |||
863 | childOfFirstChild = firstChild.children[0] | ||
864 | expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1') | ||
865 | expect(childOfFirstChild.comment.account.name).equal('root') | ||
866 | expect(childOfFirstChild.comment.account.host).equal(servers[2].host) | ||
867 | expect(childOfFirstChild.children).to.have.lengthOf(0) | ||
868 | |||
869 | const secondChild = tree.children[1] | ||
870 | expect(secondChild.comment.text).to.equal('my second answer to thread 1') | ||
871 | expect(secondChild.comment.account.name).equal('root') | ||
872 | expect(secondChild.comment.account.host).equal(servers[2].host) | ||
873 | expect(secondChild.children).to.have.lengthOf(0) | ||
874 | } | ||
875 | }) | ||
876 | |||
877 | it('Should delete a reply', async function () { | ||
878 | this.timeout(30000) | ||
879 | |||
880 | await servers[2].comments.delete({ videoId: videoUUID, commentId: childOfFirstChild.comment.id }) | ||
881 | |||
882 | await waitJobs(servers) | ||
883 | }) | ||
884 | |||
885 | it('Should have this comment marked as deleted', async function () { | ||
886 | for (const server of servers) { | ||
887 | const { data } = await server.comments.listThreads({ videoId: videoUUID }) | ||
888 | const threadId = data.find(c => c.text === 'my super first comment').id | ||
889 | |||
890 | const tree = await server.comments.getThread({ videoId: videoUUID, threadId }) | ||
891 | expect(tree.comment.text).equal('my super first comment') | ||
892 | |||
893 | const firstChild = tree.children[0] | ||
894 | expect(firstChild.comment.text).to.equal('my super answer to thread 1') | ||
895 | expect(firstChild.children).to.have.lengthOf(1) | ||
896 | |||
897 | const deletedComment = firstChild.children[0].comment | ||
898 | expect(deletedComment.isDeleted).to.be.true | ||
899 | expect(deletedComment.deletedAt).to.not.be.null | ||
900 | expect(deletedComment.account).to.be.null | ||
901 | expect(deletedComment.text).to.equal('') | ||
902 | |||
903 | const secondChild = tree.children[1] | ||
904 | expect(secondChild.comment.text).to.equal('my second answer to thread 1') | ||
905 | } | ||
906 | }) | ||
907 | |||
908 | it('Should delete the thread comments', async function () { | ||
909 | this.timeout(30000) | ||
910 | |||
911 | const { data } = await servers[0].comments.listThreads({ videoId: videoUUID }) | ||
912 | const commentId = data.find(c => c.text === 'my super first comment').id | ||
913 | await servers[0].comments.delete({ videoId: videoUUID, commentId }) | ||
914 | |||
915 | await waitJobs(servers) | ||
916 | }) | ||
917 | |||
918 | it('Should have the threads marked as deleted on other servers too', async function () { | ||
919 | for (const server of servers) { | ||
920 | const body = await server.comments.listThreads({ videoId: videoUUID }) | ||
921 | |||
922 | expect(body.total).to.equal(2) | ||
923 | expect(body.data).to.be.an('array') | ||
924 | expect(body.data).to.have.lengthOf(2) | ||
925 | |||
926 | { | ||
927 | const comment = body.data[0] | ||
928 | expect(comment).to.not.be.undefined | ||
929 | expect(comment.inReplyToCommentId).to.be.null | ||
930 | expect(comment.account.name).to.equal('root') | ||
931 | expect(comment.account.host).to.equal(servers[2].host) | ||
932 | expect(comment.totalReplies).to.equal(0) | ||
933 | expect(dateIsValid(comment.createdAt as string)).to.be.true | ||
934 | expect(dateIsValid(comment.updatedAt as string)).to.be.true | ||
935 | } | ||
936 | |||
937 | { | ||
938 | const deletedComment = body.data[1] | ||
939 | expect(deletedComment).to.not.be.undefined | ||
940 | expect(deletedComment.isDeleted).to.be.true | ||
941 | expect(deletedComment.deletedAt).to.not.be.null | ||
942 | expect(deletedComment.text).to.equal('') | ||
943 | expect(deletedComment.inReplyToCommentId).to.be.null | ||
944 | expect(deletedComment.account).to.be.null | ||
945 | expect(deletedComment.totalReplies).to.equal(2) | ||
946 | expect(dateIsValid(deletedComment.createdAt as string)).to.be.true | ||
947 | expect(dateIsValid(deletedComment.updatedAt as string)).to.be.true | ||
948 | expect(dateIsValid(deletedComment.deletedAt as string)).to.be.true | ||
949 | } | ||
950 | } | ||
951 | }) | ||
952 | |||
953 | it('Should delete a remote thread by the origin server', async function () { | ||
954 | this.timeout(5000) | ||
955 | |||
956 | const { data } = await servers[0].comments.listThreads({ videoId: videoUUID }) | ||
957 | const commentId = data.find(c => c.text === 'my super second comment').id | ||
958 | await servers[0].comments.delete({ videoId: videoUUID, commentId }) | ||
959 | |||
960 | await waitJobs(servers) | ||
961 | }) | ||
962 | |||
963 | it('Should have the threads marked as deleted on other servers too', async function () { | ||
964 | for (const server of servers) { | ||
965 | const body = await server.comments.listThreads({ videoId: videoUUID }) | ||
966 | |||
967 | expect(body.total).to.equal(2) | ||
968 | expect(body.data).to.have.lengthOf(2) | ||
969 | |||
970 | { | ||
971 | const comment = body.data[0] | ||
972 | expect(comment.text).to.equal('') | ||
973 | expect(comment.isDeleted).to.be.true | ||
974 | expect(comment.createdAt).to.not.be.null | ||
975 | expect(comment.deletedAt).to.not.be.null | ||
976 | expect(comment.account).to.be.null | ||
977 | expect(comment.totalReplies).to.equal(0) | ||
978 | } | ||
979 | |||
980 | { | ||
981 | const comment = body.data[1] | ||
982 | expect(comment.text).to.equal('') | ||
983 | expect(comment.isDeleted).to.be.true | ||
984 | expect(comment.createdAt).to.not.be.null | ||
985 | expect(comment.deletedAt).to.not.be.null | ||
986 | expect(comment.account).to.be.null | ||
987 | expect(comment.totalReplies).to.equal(2) | ||
988 | } | ||
989 | } | ||
990 | }) | ||
991 | |||
992 | it('Should disable comments and download', async function () { | ||
993 | this.timeout(20000) | ||
994 | |||
995 | const attributes = { | ||
996 | commentsEnabled: false, | ||
997 | downloadEnabled: false | ||
998 | } | ||
999 | |||
1000 | await servers[0].videos.update({ id: videoUUID, attributes }) | ||
1001 | |||
1002 | await waitJobs(servers) | ||
1003 | |||
1004 | for (const server of servers) { | ||
1005 | const video = await server.videos.get({ id: videoUUID }) | ||
1006 | expect(video.commentsEnabled).to.be.false | ||
1007 | expect(video.downloadEnabled).to.be.false | ||
1008 | |||
1009 | const text = 'my super forbidden comment' | ||
1010 | await server.comments.createThread({ videoId: videoUUID, text, expectedStatus: HttpStatusCode.CONFLICT_409 }) | ||
1011 | } | ||
1012 | }) | ||
1013 | }) | ||
1014 | |||
1015 | describe('With minimum parameters', function () { | ||
1016 | it('Should upload and propagate the video', async function () { | ||
1017 | this.timeout(120000) | ||
1018 | |||
1019 | const path = '/api/v1/videos/upload' | ||
1020 | |||
1021 | const req = request(servers[1].url) | ||
1022 | .post(path) | ||
1023 | .set('Accept', 'application/json') | ||
1024 | .set('Authorization', 'Bearer ' + servers[1].accessToken) | ||
1025 | .field('name', 'minimum parameters') | ||
1026 | .field('privacy', '1') | ||
1027 | .field('channelId', '1') | ||
1028 | |||
1029 | await req.attach('videofile', buildAbsoluteFixturePath('video_short.webm')) | ||
1030 | .expect(HttpStatusCode.OK_200) | ||
1031 | |||
1032 | await waitJobs(servers) | ||
1033 | |||
1034 | for (const server of servers) { | ||
1035 | const { data } = await server.videos.list() | ||
1036 | const video = data.find(v => v.name === 'minimum parameters') | ||
1037 | |||
1038 | const isLocal = server.url === servers[1].url | ||
1039 | const checkAttributes = { | ||
1040 | name: 'minimum parameters', | ||
1041 | category: null, | ||
1042 | licence: null, | ||
1043 | language: null, | ||
1044 | nsfw: false, | ||
1045 | description: null, | ||
1046 | support: null, | ||
1047 | account: { | ||
1048 | name: 'root', | ||
1049 | host: servers[1].host | ||
1050 | }, | ||
1051 | isLocal, | ||
1052 | duration: 5, | ||
1053 | commentsEnabled: true, | ||
1054 | downloadEnabled: true, | ||
1055 | tags: [], | ||
1056 | privacy: VideoPrivacy.PUBLIC, | ||
1057 | channel: { | ||
1058 | displayName: 'Main root channel', | ||
1059 | name: 'root_channel', | ||
1060 | description: '', | ||
1061 | isLocal | ||
1062 | }, | ||
1063 | fixture: 'video_short.webm', | ||
1064 | files: [ | ||
1065 | { | ||
1066 | resolution: 720, | ||
1067 | size: 61000 | ||
1068 | }, | ||
1069 | { | ||
1070 | resolution: 480, | ||
1071 | size: 40000 | ||
1072 | }, | ||
1073 | { | ||
1074 | resolution: 360, | ||
1075 | size: 32000 | ||
1076 | }, | ||
1077 | { | ||
1078 | resolution: 240, | ||
1079 | size: 23000 | ||
1080 | } | ||
1081 | ] | ||
1082 | } | ||
1083 | await completeVideoCheck({ server, originServer: servers[1], videoUUID: video.uuid, attributes: checkAttributes }) | ||
1084 | } | ||
1085 | }) | ||
1086 | }) | ||
1087 | |||
1088 | describe('TMP directory', function () { | ||
1089 | it('Should have an empty tmp directory', async function () { | ||
1090 | for (const server of servers) { | ||
1091 | await checkTmpIsEmpty(server) | ||
1092 | } | ||
1093 | }) | ||
1094 | }) | ||
1095 | |||
1096 | after(async function () { | ||
1097 | await cleanupTests(servers) | ||
1098 | }) | ||
1099 | }) | ||