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