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