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