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