]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/videos/video-channels.ts
Fix missing delete cascade video -> channel
[github/Chocobozzz/PeerTube.git] / server / tests / api / videos / video-channels.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
5f04dd2f 2
2422c46b 3import 'mocha'
8eb07b01 4import * as chai from 'chai'
84531547 5import { basename } from 'path'
e024fd6a 6import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants'
4bbfc6c6 7import {
7c3b7976 8 cleanupTests,
8a19bee1 9 createUser,
213e30ef 10 deleteVideoChannelImage,
4bbfc6c6 11 doubleFollow,
a1587156 12 flushAndRunMultipleServers,
84531547 13 getActorImage,
a1587156 14 getVideo,
cdeddff1 15 getVideoChannel,
d175a6f7 16 getVideoChannelVideos,
e024fd6a 17 setDefaultVideoChannel,
d175a6f7 18 testImage,
4bbfc6c6 19 updateVideo,
213e30ef 20 updateVideoChannelImage,
d175a6f7 21 uploadVideo,
714bfcc5
RK
22 userLogin,
23 wait
94565d52 24} from '../../../../shared/extra-utils'
5f04dd2f 25import {
2422c46b
C
26 addVideoChannel,
27 deleteVideoChannel,
2422c46b 28 getAccountVideoChannelsList,
5f04dd2f
C
29 getMyUserInformation,
30 getVideoChannelsList,
2422c46b
C
31 ServerInfo,
32 setAccessTokensToServers,
714bfcc5
RK
33 updateVideoChannel,
34 viewVideo
94565d52
C
35} from '../../../../shared/extra-utils/index'
36import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
8eb07b01 37import { User, Video, VideoChannel, VideoDetails } from '../../../../shared/index'
5f04dd2f 38
2422c46b
C
39const expect = chai.expect
40
213e30ef
C
41async function findChannel (server: ServerInfo, channelId: number) {
42 const res = await getVideoChannelsList(server.url, 0, 5, '-name')
43 const videoChannel = res.body.data.find(c => c.id === channelId)
44
45 return videoChannel as VideoChannel
46}
47
2422c46b
C
48describe('Test video channels', function () {
49 let servers: ServerInfo[]
5f04dd2f 50 let userInfo: User
0f320037 51 let secondVideoChannelId: number
e024fd6a 52 let totoChannel: number
0f320037 53 let videoUUID: string
e024fd6a 54 let accountName: string
5f04dd2f
C
55
56 before(async function () {
48f07b4a 57 this.timeout(60000)
5f04dd2f 58
2422c46b
C
59 servers = await flushAndRunMultipleServers(2)
60
61 await setAccessTokensToServers(servers)
e024fd6a 62 await setDefaultVideoChannel(servers)
48dce1c9 63
e024fd6a 64 await doubleFollow(servers[0], servers[1])
5f04dd2f
C
65 })
66
67 it('Should have one video channel (created with root)', async () => {
2422c46b 68 const res = await getVideoChannelsList(servers[0].url, 0, 2)
5f04dd2f
C
69
70 expect(res.body.total).to.equal(1)
71 expect(res.body.data).to.be.an('array')
72 expect(res.body.data).to.have.lengthOf(1)
73 })
74
2422c46b
C
75 it('Should create another video channel', async function () {
76 this.timeout(10000)
77
0f320037
C
78 {
79 const videoChannel = {
8a19bee1 80 name: 'second_video_channel',
0f320037
C
81 displayName: 'second video channel',
82 description: 'super video channel description',
83 support: 'super video channel support text'
84 }
a1587156 85 const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
0f320037 86 secondVideoChannelId = res.body.videoChannel.id
5f04dd2f 87 }
2422c46b
C
88
89 // The channel is 1 is propagated to servers 2
0f320037 90 {
7d14d4d2 91 const videoAttributesArg = { name: 'my video name', channelId: secondVideoChannelId, support: 'video support field' }
a1587156 92 const res = await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributesArg)
0f320037
C
93 videoUUID = res.body.video.uuid
94 }
2422c46b 95
3cd0734f 96 await waitJobs(servers)
5f04dd2f
C
97 })
98
99 it('Should have two video channels when getting my information', async () => {
2422c46b 100 const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
5f04dd2f
C
101 userInfo = res.body
102
103 expect(userInfo.videoChannels).to.be.an('array')
104 expect(userInfo.videoChannels).to.have.lengthOf(2)
105
106 const videoChannels = userInfo.videoChannels
8a19bee1
C
107 expect(videoChannels[0].name).to.equal('root_channel')
108 expect(videoChannels[0].displayName).to.equal('Main root channel')
109
110 expect(videoChannels[1].name).to.equal('second_video_channel')
7bc29171 111 expect(videoChannels[1].displayName).to.equal('second video channel')
5f04dd2f 112 expect(videoChannels[1].description).to.equal('super video channel description')
2422c46b 113 expect(videoChannels[1].support).to.equal('super video channel support text')
e024fd6a
C
114
115 accountName = userInfo.account.name + '@' + userInfo.account.host
5f04dd2f
C
116 })
117
2422c46b 118 it('Should have two video channels when getting account channels on server 1', async function () {
91b66319 119 const res = await getAccountVideoChannelsList({
a1587156 120 url: servers[0].url,
e024fd6a 121 accountName
91b66319
C
122 })
123
5f04dd2f
C
124 expect(res.body.total).to.equal(2)
125 expect(res.body.data).to.be.an('array')
126 expect(res.body.data).to.have.lengthOf(2)
127
128 const videoChannels = res.body.data
8a19bee1
C
129 expect(videoChannels[0].name).to.equal('root_channel')
130 expect(videoChannels[0].displayName).to.equal('Main root channel')
131
132 expect(videoChannels[1].name).to.equal('second_video_channel')
7bc29171 133 expect(videoChannels[1].displayName).to.equal('second video channel')
5f04dd2f 134 expect(videoChannels[1].description).to.equal('super video channel description')
2422c46b
C
135 expect(videoChannels[1].support).to.equal('super video channel support text')
136 })
137
91b66319
C
138 it('Should paginate and sort account channels', async function () {
139 {
140 const res = await getAccountVideoChannelsList({
a1587156 141 url: servers[0].url,
e024fd6a 142 accountName,
91b66319
C
143 start: 0,
144 count: 1,
145 sort: 'createdAt'
146 })
147
148 expect(res.body.total).to.equal(2)
149 expect(res.body.data).to.have.lengthOf(1)
150
a1587156 151 const videoChannel: VideoChannel = res.body.data[0]
91b66319
C
152 expect(videoChannel.name).to.equal('root_channel')
153 }
154
155 {
156 const res = await getAccountVideoChannelsList({
a1587156 157 url: servers[0].url,
e024fd6a 158 accountName,
91b66319
C
159 start: 0,
160 count: 1,
161 sort: '-createdAt'
162 })
163
164 expect(res.body.total).to.equal(2)
165 expect(res.body.data).to.have.lengthOf(1)
166
a1587156 167 const videoChannel: VideoChannel = res.body.data[0]
91b66319
C
168 expect(videoChannel.name).to.equal('second_video_channel')
169 }
170
171 {
172 const res = await getAccountVideoChannelsList({
a1587156 173 url: servers[0].url,
e024fd6a 174 accountName,
91b66319
C
175 start: 1,
176 count: 1,
177 sort: '-createdAt'
178 })
179
180 expect(res.body.total).to.equal(2)
181 expect(res.body.data).to.have.lengthOf(1)
182
a1587156 183 const videoChannel: VideoChannel = res.body.data[0]
91b66319
C
184 expect(videoChannel.name).to.equal('root_channel')
185 }
186 })
187
2422c46b 188 it('Should have one video channel when getting account channels on server 2', async function () {
91b66319 189 const res = await getAccountVideoChannelsList({
a1587156 190 url: servers[1].url,
e024fd6a 191 accountName
91b66319
C
192 })
193
2422c46b
C
194 expect(res.body.total).to.equal(1)
195 expect(res.body.data).to.be.an('array')
196 expect(res.body.data).to.have.lengthOf(1)
5f04dd2f 197
2422c46b 198 const videoChannels = res.body.data
8a19bee1 199 expect(videoChannels[0].name).to.equal('second_video_channel')
2422c46b
C
200 expect(videoChannels[0].displayName).to.equal('second video channel')
201 expect(videoChannels[0].description).to.equal('super video channel description')
202 expect(videoChannels[0].support).to.equal('super video channel support text')
5f04dd2f
C
203 })
204
2422c46b
C
205 it('Should list video channels', async function () {
206 const res = await getVideoChannelsList(servers[0].url, 1, 1, '-name')
5f04dd2f
C
207
208 expect(res.body.total).to.equal(2)
209 expect(res.body.data).to.be.an('array')
210 expect(res.body.data).to.have.lengthOf(1)
8a19bee1
C
211 expect(res.body.data[0].name).to.equal('root_channel')
212 expect(res.body.data[0].displayName).to.equal('Main root channel')
5f04dd2f
C
213 })
214
2422c46b 215 it('Should update video channel', async function () {
7d14d4d2 216 this.timeout(15000)
2422c46b 217
5f04dd2f 218 const videoChannelAttributes = {
08c1efbe 219 displayName: 'video channel updated',
2422c46b 220 description: 'video channel description updated',
7d14d4d2 221 support: 'support updated'
5f04dd2f
C
222 }
223
8a19bee1 224 await updateVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel', videoChannelAttributes)
2422c46b 225
3cd0734f 226 await waitJobs(servers)
5f04dd2f
C
227 })
228
2422c46b
C
229 it('Should have video channel updated', async function () {
230 for (const server of servers) {
231 const res = await getVideoChannelsList(server.url, 0, 1, '-name')
5f04dd2f 232
2422c46b
C
233 expect(res.body.total).to.equal(2)
234 expect(res.body.data).to.be.an('array')
235 expect(res.body.data).to.have.lengthOf(1)
8a19bee1 236 expect(res.body.data[0].name).to.equal('second_video_channel')
2422c46b
C
237 expect(res.body.data[0].displayName).to.equal('video channel updated')
238 expect(res.body.data[0].description).to.equal('video channel description updated')
7d14d4d2
C
239 expect(res.body.data[0].support).to.equal('support updated')
240 }
241 })
242
243 it('Should not have updated the video support field', async function () {
244 for (const server of servers) {
245 const res = await getVideo(server.url, videoUUID)
246 const video: VideoDetails = res.body
247
248 expect(video.support).to.equal('video support field')
249 }
250 })
251
252 it('Should update the channel support field and update videos too', async function () {
253 this.timeout(35000)
254
255 const videoChannelAttributes = {
256 support: 'video channel support text updated',
257 bulkVideosSupportUpdate: true
258 }
259
260 await updateVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel', videoChannelAttributes)
261
262 await waitJobs(servers)
263
264 for (const server of servers) {
265 const res = await getVideo(server.url, videoUUID)
266 const video: VideoDetails = res.body
267
268 expect(video.support).to.equal(videoChannelAttributes.support)
2422c46b 269 }
5f04dd2f
C
270 })
271
4bbfc6c6 272 it('Should update video channel avatar', async function () {
213e30ef 273 this.timeout(15000)
4bbfc6c6
C
274
275 const fixture = 'avatar.png'
276
213e30ef 277 await updateVideoChannelImage({
4bbfc6c6
C
278 url: servers[0].url,
279 accessToken: servers[0].accessToken,
8a19bee1 280 videoChannelName: 'second_video_channel',
213e30ef
C
281 fixture,
282 type: 'avatar'
4bbfc6c6
C
283 })
284
285 await waitJobs(servers)
213e30ef
C
286
287 for (const server of servers) {
288 const videoChannel = await findChannel(server, secondVideoChannelId)
289
290 await testImage(server.url, 'avatar-resized', videoChannel.avatar.path, '.png')
84531547
C
291
292 const row = await getActorImage(server.internalServerNumber, basename(videoChannel.avatar.path))
293 expect(row.height).to.equal(ACTOR_IMAGES_SIZE.AVATARS.height)
294 expect(row.width).to.equal(ACTOR_IMAGES_SIZE.AVATARS.width)
213e30ef 295 }
4bbfc6c6
C
296 })
297
213e30ef
C
298 it('Should update video channel banner', async function () {
299 this.timeout(15000)
300
301 const fixture = 'banner.jpg'
302
303 await updateVideoChannelImage({
304 url: servers[0].url,
305 accessToken: servers[0].accessToken,
306 videoChannelName: 'second_video_channel',
307 fixture,
308 type: 'banner'
309 })
310
311 await waitJobs(servers)
312
4bbfc6c6 313 for (const server of servers) {
cdeddff1
C
314 const res = await getVideoChannel(server.url, 'second_video_channel@' + servers[0].host)
315 const videoChannel = res.body
4bbfc6c6 316
213e30ef 317 await testImage(server.url, 'banner-resized', videoChannel.banner.path)
84531547
C
318
319 const row = await getActorImage(server.internalServerNumber, basename(videoChannel.banner.path))
320 expect(row.height).to.equal(ACTOR_IMAGES_SIZE.BANNERS.height)
321 expect(row.width).to.equal(ACTOR_IMAGES_SIZE.BANNERS.width)
213e30ef
C
322 }
323 })
4bbfc6c6 324
213e30ef
C
325 it('Should delete the video channel avatar', async function () {
326 this.timeout(15000)
327
328 await deleteVideoChannelImage({
329 url: servers[0].url,
330 accessToken: servers[0].accessToken,
331 videoChannelName: 'second_video_channel',
332 type: 'avatar'
333 })
334
335 await waitJobs(servers)
336
337 for (const server of servers) {
338 const videoChannel = await findChannel(server, secondVideoChannelId)
339
340 expect(videoChannel.avatar).to.be.null
4bbfc6c6
C
341 }
342 })
343
213e30ef
C
344 it('Should delete the video channel banner', async function () {
345 this.timeout(15000)
346
347 await deleteVideoChannelImage({
348 url: servers[0].url,
349 accessToken: servers[0].accessToken,
350 videoChannelName: 'second_video_channel',
351 type: 'banner'
352 })
5f04dd2f 353
213e30ef
C
354 await waitJobs(servers)
355
356 for (const server of servers) {
357 const videoChannel = await findChannel(server, secondVideoChannelId)
358
359 expect(videoChannel.banner).to.be.null
360 }
5f04dd2f
C
361 })
362
0f320037 363 it('Should list the second video channel videos', async function () {
6b738c7a
C
364 this.timeout(10000)
365
366 for (const server of servers) {
48f07b4a 367 const channelURI = 'second_video_channel@localhost:' + servers[0].port
8a19bee1 368 const res1 = await getVideoChannelVideos(server.url, server.accessToken, channelURI, 0, 5)
0f320037
C
369 expect(res1.body.total).to.equal(1)
370 expect(res1.body.data).to.be.an('array')
371 expect(res1.body.data).to.have.lengthOf(1)
372 expect(res1.body.data[0].name).to.equal('my video name')
373 }
374 })
375
376 it('Should change the video channel of a video', async function () {
377 this.timeout(10000)
378
e024fd6a 379 await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, { channelId: servers[0].videoChannel.id })
0f320037 380
3cd0734f 381 await waitJobs(servers)
0f320037
C
382 })
383
384 it('Should list the first video channel videos', async function () {
385 this.timeout(10000)
386
387 for (const server of servers) {
48f07b4a 388 const secondChannelURI = 'second_video_channel@localhost:' + servers[0].port
8a19bee1 389 const res1 = await getVideoChannelVideos(server.url, server.accessToken, secondChannelURI, 0, 5)
0f320037
C
390 expect(res1.body.total).to.equal(0)
391
48f07b4a 392 const channelURI = 'root_channel@localhost:' + servers[0].port
8a19bee1 393 const res2 = await getVideoChannelVideos(server.url, server.accessToken, channelURI, 0, 5)
0f320037
C
394 expect(res2.body.total).to.equal(1)
395
396 const videos: Video[] = res2.body.data
397 expect(videos).to.be.an('array')
398 expect(videos).to.have.lengthOf(1)
399 expect(videos[0].name).to.equal('my video name')
6b738c7a
C
400 }
401 })
402
2422c46b 403 it('Should delete video channel', async function () {
8a19bee1 404 await deleteVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel')
5f04dd2f
C
405 })
406
2422c46b
C
407 it('Should have video channel deleted', async function () {
408 const res = await getVideoChannelsList(servers[0].url, 0, 10)
5f04dd2f
C
409
410 expect(res.body.total).to.equal(1)
411 expect(res.body.data).to.be.an('array')
412 expect(res.body.data).to.have.lengthOf(1)
8a19bee1
C
413 expect(res.body.data[0].displayName).to.equal('Main root channel')
414 })
415
416 it('Should create the main channel with an uuid if there is a conflict', async function () {
417 {
418 const videoChannel = { name: 'toto_channel', displayName: 'My toto channel' }
e024fd6a
C
419 const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
420 totoChannel = res.body.videoChannel.id
8a19bee1
C
421 }
422
423 {
a1587156
C
424 await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: 'toto', password: 'password' })
425 const accessToken = await userLogin(servers[0], { username: 'toto', password: 'password' })
8a19bee1 426
a1587156
C
427 const res = await getMyUserInformation(servers[0].url, accessToken)
428 const videoChannel = res.body.videoChannels[0]
8a19bee1
C
429 expect(videoChannel.name).to.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/)
430 }
5f04dd2f
C
431 })
432
1ba471c5 433 it('Should report correct channel views per days', async function () {
5a61ffbb 434 this.timeout(10000)
714bfcc5
RK
435
436 {
437 const res = await getAccountVideoChannelsList({
438 url: servers[0].url,
e024fd6a 439 accountName,
714bfcc5
RK
440 withStats: true
441 })
1ba471c5
C
442
443 const channels: VideoChannel[] = res.body.data
444
445 for (const channel of channels) {
714bfcc5
RK
446 expect(channel).to.haveOwnProperty('viewsPerDay')
447 expect(channel.viewsPerDay).to.have.length(30 + 1) // daysPrior + today
1ba471c5
C
448
449 for (const v of channel.viewsPerDay) {
714bfcc5
RK
450 expect(v.date).to.be.an('string')
451 expect(v.views).to.equal(0)
1ba471c5
C
452 }
453 }
714bfcc5
RK
454 }
455
456 {
e024fd6a 457 // video has been posted on channel servers[0].videoChannel.id since last update
714bfcc5
RK
458 await viewVideo(servers[0].url, videoUUID, 204, '0.0.0.1,127.0.0.1')
459 await viewVideo(servers[0].url, videoUUID, 204, '0.0.0.2,127.0.0.1')
460
461 // Wait the repeatable job
462 await wait(8000)
463
464 const res = await getAccountVideoChannelsList({
465 url: servers[0].url,
e024fd6a 466 accountName,
714bfcc5
RK
467 withStats: true
468 })
e024fd6a 469 const channelWithView = res.body.data.find((channel: VideoChannel) => channel.id === servers[0].videoChannel.id)
714bfcc5
RK
470 expect(channelWithView.viewsPerDay.slice(-1)[0].views).to.equal(2)
471 }
472 })
473
1ba471c5
C
474 it('Should report correct videos count', async function () {
475 const res = await getAccountVideoChannelsList({
476 url: servers[0].url,
e024fd6a 477 accountName,
1ba471c5
C
478 withStats: true
479 })
480 const channels: VideoChannel[] = res.body.data
481
482 const totoChannel = channels.find(c => c.name === 'toto_channel')
483 const rootChannel = channels.find(c => c.name === 'root_channel')
484
485 expect(rootChannel.videosCount).to.equal(1)
486 expect(totoChannel.videosCount).to.equal(0)
487 })
488
7b390964
RK
489 it('Should search among account video channels', async function () {
490 {
491 const res = await getAccountVideoChannelsList({
492 url: servers[0].url,
e024fd6a 493 accountName,
7b390964
RK
494 search: 'root'
495 })
496 expect(res.body.total).to.equal(1)
497
498 const channels = res.body.data
499 expect(channels).to.have.lengthOf(1)
500 }
501
502 {
503 const res = await getAccountVideoChannelsList({
504 url: servers[0].url,
e024fd6a 505 accountName,
7b390964
RK
506 search: 'does not exist'
507 })
508 expect(res.body.total).to.equal(0)
509
510 const channels = res.body.data
511 expect(channels).to.have.lengthOf(0)
512 }
513 })
514
e024fd6a
C
515 it('Should list channels by updatedAt desc if a video has been uploaded', async function () {
516 this.timeout(30000)
517
518 await uploadVideo(servers[0].url, servers[0].accessToken, { channelId: totoChannel })
519 await waitJobs(servers)
520
521 for (const server of servers) {
522 const res = await getAccountVideoChannelsList({
523 url: server.url,
524 accountName,
525 sort: '-updatedAt'
526 })
527
528 const channels: VideoChannel[] = res.body.data
529 expect(channels[0].name).to.equal('toto_channel')
530 expect(channels[1].name).to.equal('root_channel')
531 }
532
533 await uploadVideo(servers[0].url, servers[0].accessToken, { channelId: servers[0].videoChannel.id })
534 await waitJobs(servers)
535
536 for (const server of servers) {
537 const res = await getAccountVideoChannelsList({
538 url: server.url,
539 accountName,
540 sort: '-updatedAt'
541 })
542
543 const channels: VideoChannel[] = res.body.data
544 expect(channels[0].name).to.equal('root_channel')
545 expect(channels[1].name).to.equal('toto_channel')
546 }
547 })
548
7c3b7976
C
549 after(async function () {
550 await cleanupTests(servers)
5f04dd2f
C
551 })
552})