aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests')
-rw-r--r--server/tests/api/activitypub/refresher.ts6
-rw-r--r--server/tests/api/check-params/config.ts3
-rw-r--r--server/tests/api/check-params/index.ts1
-rw-r--r--server/tests/api/check-params/video-channels.ts2
-rw-r--r--server/tests/api/check-params/video-editor.ts385
-rw-r--r--server/tests/api/index.ts1
-rw-r--r--server/tests/api/live/live.ts4
-rw-r--r--server/tests/api/moderation/abuses.ts7
-rw-r--r--server/tests/api/moderation/blocklist.ts4
-rw-r--r--server/tests/api/moderation/video-blacklist.ts2
-rw-r--r--server/tests/api/notifications/notifications-api.ts10
-rw-r--r--server/tests/api/search/search-activitypub-video-channels.ts4
-rw-r--r--server/tests/api/search/search-activitypub-video-playlists.ts2
-rw-r--r--server/tests/api/search/search-activitypub-videos.ts4
-rw-r--r--server/tests/api/search/search-channels.ts12
-rw-r--r--server/tests/api/search/search-index.ts14
-rw-r--r--server/tests/api/search/search-playlists.ts10
-rw-r--r--server/tests/api/search/search-videos.ts8
-rw-r--r--server/tests/api/server/config.ts7
-rw-r--r--server/tests/api/server/homepage.ts6
-rw-r--r--server/tests/api/server/stats.ts8
-rw-r--r--server/tests/api/transcoding/audio-only.ts (renamed from server/tests/api/videos/audio-only.ts)7
-rw-r--r--server/tests/api/transcoding/create-transcoding.ts (renamed from server/tests/api/videos/video-create-transcoding.ts)0
-rw-r--r--server/tests/api/transcoding/hls.ts (renamed from server/tests/api/videos/video-hls.ts)0
-rw-r--r--server/tests/api/transcoding/index.ts5
-rw-r--r--server/tests/api/transcoding/transcoder.ts (renamed from server/tests/api/videos/video-transcoder.ts)39
-rw-r--r--server/tests/api/transcoding/video-editor.ts368
-rw-r--r--server/tests/api/users/user-subscriptions.ts4
-rw-r--r--server/tests/api/users/users-multiple-servers.ts18
-rw-r--r--server/tests/api/users/users.ts8
-rw-r--r--server/tests/api/videos/index.ts4
-rw-r--r--server/tests/api/videos/multiple-servers.ts24
-rw-r--r--server/tests/api/videos/single-server.ts11
-rw-r--r--server/tests/api/videos/video-channels.ts32
-rw-r--r--server/tests/api/videos/video-comments.ts17
-rw-r--r--server/tests/api/videos/video-playlist-thumbnails.ts6
-rw-r--r--server/tests/api/videos/video-playlists.ts8
-rw-r--r--server/tests/api/videos/videos-common-filters.ts4
-rw-r--r--server/tests/cli/prune-storage.ts29
-rw-r--r--server/tests/cli/update-host.ts3
-rw-r--r--server/tests/feeds/feeds.ts4
-rw-r--r--server/tests/fixtures/avatar-resized-120x120.gif (renamed from server/tests/fixtures/avatar-resized.gif)bin88318 -> 88318 bytes
-rw-r--r--server/tests/fixtures/avatar-resized-120x120.png (renamed from server/tests/fixtures/avatar-resized.png)bin1727 -> 1727 bytes
-rw-r--r--server/tests/fixtures/avatar-resized-48x48.gifbin0 -> 20462 bytes
-rw-r--r--server/tests/fixtures/avatar-resized-48x48.pngbin0 -> 727 bytes
-rw-r--r--server/tests/fixtures/avatar2-resized-120x120.png (renamed from server/tests/fixtures/avatar2-resized.png)bin1725 -> 1725 bytes
-rw-r--r--server/tests/fixtures/avatar2-resized-48x48.pngbin0 -> 760 bytes
-rw-r--r--server/tests/fixtures/peertube-plugin-test/main.js10
-rw-r--r--server/tests/plugins/filter-hooks.ts42
-rw-r--r--server/tests/plugins/plugin-transcoding.ts10
-rw-r--r--server/tests/shared/generate.ts8
-rw-r--r--server/tests/shared/notifications.ts11
-rw-r--r--server/tests/shared/videos.ts13
53 files changed, 1076 insertions, 109 deletions
diff --git a/server/tests/api/activitypub/refresher.ts b/server/tests/api/activitypub/refresher.ts
index 71e1c40ba..bb81d4565 100644
--- a/server/tests/api/activitypub/refresher.ts
+++ b/server/tests/api/activitypub/refresher.ts
@@ -25,12 +25,16 @@ describe('Test AP refresher', function () {
25 before(async function () { 25 before(async function () {
26 this.timeout(60000) 26 this.timeout(60000)
27 27
28 servers = await createMultipleServers(2, { transcoding: { enabled: false } }) 28 servers = await createMultipleServers(2)
29 29
30 // Get the access tokens 30 // Get the access tokens
31 await setAccessTokensToServers(servers) 31 await setAccessTokensToServers(servers)
32 await setDefaultVideoChannel(servers) 32 await setDefaultVideoChannel(servers)
33 33
34 for (const server of servers) {
35 await server.config.disableTranscoding()
36 }
37
34 { 38 {
35 videoUUID1 = (await servers[1].videos.quickUpload({ name: 'video1' })).uuid 39 videoUUID1 = (await servers[1].videos.quickUpload({ name: 'video1' })).uuid
36 videoUUID2 = (await servers[1].videos.quickUpload({ name: 'video2' })).uuid 40 videoUUID2 = (await servers[1].videos.quickUpload({ name: 'video2' })).uuid
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index 3cccb612a..ce067a892 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -145,6 +145,9 @@ describe('Test config API validators', function () {
145 } 145 }
146 } 146 }
147 }, 147 },
148 videoEditor: {
149 enabled: true
150 },
148 import: { 151 import: {
149 videos: { 152 videos: {
150 concurrency: 1, 153 concurrency: 1,
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts
index e052296db..c088b52cd 100644
--- a/server/tests/api/check-params/index.ts
+++ b/server/tests/api/check-params/index.ts
@@ -25,6 +25,7 @@ import './video-blacklist'
25import './video-captions' 25import './video-captions'
26import './video-channels' 26import './video-channels'
27import './video-comments' 27import './video-comments'
28import './video-editor'
28import './video-imports' 29import './video-imports'
29import './video-playlists' 30import './video-playlists'
30import './videos' 31import './videos'
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts
index 1e9732fe9..5c2650fac 100644
--- a/server/tests/api/check-params/video-channels.ts
+++ b/server/tests/api/check-params/video-channels.ts
@@ -228,7 +228,7 @@ describe('Test video channels API validator', function () {
228 }) 228 })
229 }) 229 })
230 230
231 describe('When updating video channel avatar/banner', function () { 231 describe('When updating video channel avatars/banners', function () {
232 const types = [ 'avatar', 'banner' ] 232 const types = [ 'avatar', 'banner' ]
233 let path: string 233 let path: string
234 234
diff --git a/server/tests/api/check-params/video-editor.ts b/server/tests/api/check-params/video-editor.ts
new file mode 100644
index 000000000..db284a3cc
--- /dev/null
+++ b/server/tests/api/check-params/video-editor.ts
@@ -0,0 +1,385 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { HttpStatusCode, VideoEditorTask } from '@shared/models'
5import {
6 cleanupTests,
7 createSingleServer,
8 PeerTubeServer,
9 setAccessTokensToServers,
10 VideoEditorCommand,
11 waitJobs
12} from '@shared/server-commands'
13
14describe('Test video editor API validator', function () {
15 let server: PeerTubeServer
16 let command: VideoEditorCommand
17 let userAccessToken: string
18 let videoUUID: string
19
20 // ---------------------------------------------------------------
21
22 before(async function () {
23 this.timeout(120_000)
24
25 server = await createSingleServer(1)
26
27 await setAccessTokensToServers([ server ])
28 userAccessToken = await server.users.generateUserAndToken('user1')
29
30 await server.config.enableMinimumTranscoding()
31
32 const { uuid } = await server.videos.quickUpload({ name: 'video' })
33 videoUUID = uuid
34
35 command = server.videoEditor
36
37 await waitJobs([ server ])
38 })
39
40 describe('Task creation', function () {
41
42 describe('Config settings', function () {
43
44 it('Should fail if editor is disabled', async function () {
45 await server.config.updateExistingSubConfig({
46 newConfig: {
47 videoEditor: {
48 enabled: false
49 }
50 }
51 })
52
53 await command.createEditionTasks({
54 videoId: videoUUID,
55 tasks: VideoEditorCommand.getComplexTask(),
56 expectedStatus: HttpStatusCode.BAD_REQUEST_400
57 })
58 })
59
60 it('Should fail to enable editor if transcoding is disabled', async function () {
61 await server.config.updateExistingSubConfig({
62 newConfig: {
63 videoEditor: {
64 enabled: true
65 },
66 transcoding: {
67 enabled: false
68 }
69 },
70 expectedStatus: HttpStatusCode.BAD_REQUEST_400
71 })
72 })
73
74 it('Should succeed to enable video editor', async function () {
75 await server.config.updateExistingSubConfig({
76 newConfig: {
77 videoEditor: {
78 enabled: true
79 },
80 transcoding: {
81 enabled: true
82 }
83 }
84 })
85 })
86 })
87
88 describe('Common tasks', function () {
89
90 it('Should fail without token', async function () {
91 await command.createEditionTasks({
92 token: null,
93 videoId: videoUUID,
94 tasks: VideoEditorCommand.getComplexTask(),
95 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
96 })
97 })
98
99 it('Should fail with another user token', async function () {
100 await command.createEditionTasks({
101 token: userAccessToken,
102 videoId: videoUUID,
103 tasks: VideoEditorCommand.getComplexTask(),
104 expectedStatus: HttpStatusCode.FORBIDDEN_403
105 })
106 })
107
108 it('Should fail with an invalid video', async function () {
109 await command.createEditionTasks({
110 videoId: 'tintin',
111 tasks: VideoEditorCommand.getComplexTask(),
112 expectedStatus: HttpStatusCode.BAD_REQUEST_400
113 })
114 })
115
116 it('Should fail with an unknown video', async function () {
117 await command.createEditionTasks({
118 videoId: 42,
119 tasks: VideoEditorCommand.getComplexTask(),
120 expectedStatus: HttpStatusCode.NOT_FOUND_404
121 })
122 })
123
124 it('Should fail with an already in transcoding state video', async function () {
125 await server.jobs.pauseJobQueue()
126
127 const { uuid } = await server.videos.quickUpload({ name: 'transcoded video' })
128
129 await command.createEditionTasks({
130 videoId: uuid,
131 tasks: VideoEditorCommand.getComplexTask(),
132 expectedStatus: HttpStatusCode.CONFLICT_409
133 })
134
135 await server.jobs.resumeJobQueue()
136 })
137
138 it('Should fail with a bad complex task', async function () {
139 await command.createEditionTasks({
140 videoId: videoUUID,
141 tasks: [
142 {
143 name: 'cut',
144 options: {
145 start: 1,
146 end: 2
147 }
148 },
149 {
150 name: 'hadock',
151 options: {
152 start: 1,
153 end: 2
154 }
155 }
156 ] as any,
157 expectedStatus: HttpStatusCode.BAD_REQUEST_400
158 })
159 })
160
161 it('Should fail without task', async function () {
162 await command.createEditionTasks({
163 videoId: videoUUID,
164 tasks: [],
165 expectedStatus: HttpStatusCode.BAD_REQUEST_400
166 })
167 })
168
169 it('Should fail with too many tasks', async function () {
170 const tasks: VideoEditorTask[] = []
171
172 for (let i = 0; i < 110; i++) {
173 tasks.push({
174 name: 'cut',
175 options: {
176 start: 1
177 }
178 })
179 }
180
181 await command.createEditionTasks({
182 videoId: videoUUID,
183 tasks,
184 expectedStatus: HttpStatusCode.BAD_REQUEST_400
185 })
186 })
187
188 it('Should succeed with correct parameters', async function () {
189 await server.jobs.pauseJobQueue()
190
191 await command.createEditionTasks({
192 videoId: videoUUID,
193 tasks: VideoEditorCommand.getComplexTask(),
194 expectedStatus: HttpStatusCode.NO_CONTENT_204
195 })
196 })
197
198 it('Should fail with a video that is already waiting for edition', async function () {
199 this.timeout(120000)
200
201 await command.createEditionTasks({
202 videoId: videoUUID,
203 tasks: VideoEditorCommand.getComplexTask(),
204 expectedStatus: HttpStatusCode.CONFLICT_409
205 })
206
207 await server.jobs.resumeJobQueue()
208
209 await waitJobs([ server ])
210 })
211 })
212
213 describe('Cut task', function () {
214
215 async function cut (start: number, end: number, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
216 await command.createEditionTasks({
217 videoId: videoUUID,
218 tasks: [
219 {
220 name: 'cut',
221 options: {
222 start,
223 end
224 }
225 }
226 ],
227 expectedStatus
228 })
229 }
230
231 it('Should fail with bad start/end', async function () {
232 const invalid = [
233 'tintin',
234 -1,
235 undefined
236 ]
237
238 for (const value of invalid) {
239 await cut(value as any, undefined)
240 await cut(undefined, value as any)
241 }
242 })
243
244 it('Should fail with the same start/end', async function () {
245 await cut(2, 2)
246 })
247
248 it('Should fail with inconsistents start/end', async function () {
249 await cut(2, 1)
250 })
251
252 it('Should fail without start and end', async function () {
253 await cut(undefined, undefined)
254 })
255
256 it('Should succeed with the correct params', async function () {
257 this.timeout(120000)
258
259 await cut(0, 2, HttpStatusCode.NO_CONTENT_204)
260
261 await waitJobs([ server ])
262 })
263 })
264
265 describe('Watermark task', function () {
266
267 async function addWatermark (file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
268 await command.createEditionTasks({
269 videoId: videoUUID,
270 tasks: [
271 {
272 name: 'add-watermark',
273 options: {
274 file
275 }
276 }
277 ],
278 expectedStatus
279 })
280 }
281
282 it('Should fail without waterkmark', async function () {
283 await addWatermark(undefined)
284 })
285
286 it('Should fail with an invalid watermark', async function () {
287 await addWatermark('video_short.mp4')
288 })
289
290 it('Should succeed with the correct params', async function () {
291 this.timeout(120000)
292
293 await addWatermark('thumbnail.jpg', HttpStatusCode.NO_CONTENT_204)
294
295 await waitJobs([ server ])
296 })
297 })
298
299 describe('Intro/Outro task', function () {
300
301 async function addIntroOutro (type: 'add-intro' | 'add-outro', file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
302 await command.createEditionTasks({
303 videoId: videoUUID,
304 tasks: [
305 {
306 name: type,
307 options: {
308 file
309 }
310 }
311 ],
312 expectedStatus
313 })
314 }
315
316 it('Should fail without file', async function () {
317 await addIntroOutro('add-intro', undefined)
318 await addIntroOutro('add-outro', undefined)
319 })
320
321 it('Should fail with an invalid file', async function () {
322 await addIntroOutro('add-intro', 'thumbnail.jpg')
323 await addIntroOutro('add-outro', 'thumbnail.jpg')
324 })
325
326 it('Should fail with a file that does not contain video stream', async function () {
327 await addIntroOutro('add-intro', 'sample.ogg')
328 await addIntroOutro('add-outro', 'sample.ogg')
329
330 })
331
332 it('Should succeed with the correct params', async function () {
333 this.timeout(120000)
334
335 await addIntroOutro('add-intro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
336 await waitJobs([ server ])
337
338 await addIntroOutro('add-outro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
339 await waitJobs([ server ])
340 })
341
342 it('Should check total quota when creating the task', async function () {
343 this.timeout(120000)
344
345 const user = await server.users.create({ username: 'user_quota_1' })
346 const token = await server.login.getAccessToken('user_quota_1')
347 const { uuid } = await server.videos.quickUpload({ token, name: 'video_quota_1', fixture: 'video_short.mp4' })
348
349 const addIntroOutroByUser = (type: 'add-intro' | 'add-outro', expectedStatus: HttpStatusCode) => {
350 return command.createEditionTasks({
351 token,
352 videoId: uuid,
353 tasks: [
354 {
355 name: type,
356 options: {
357 file: 'video_short.mp4'
358 }
359 }
360 ],
361 expectedStatus
362 })
363 }
364
365 await waitJobs([ server ])
366
367 const { videoQuotaUsed } = await server.users.getMyQuotaUsed({ token })
368 await server.users.update({ userId: user.id, videoQuota: Math.round(videoQuotaUsed * 2.5) })
369
370 // Still valid
371 await addIntroOutroByUser('add-intro', HttpStatusCode.NO_CONTENT_204)
372
373 await waitJobs([ server ])
374
375 // Too much quota
376 await addIntroOutroByUser('add-intro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
377 await addIntroOutroByUser('add-outro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
378 })
379 })
380 })
381
382 after(async function () {
383 await cleanupTests([ server ])
384 })
385})
diff --git a/server/tests/api/index.ts b/server/tests/api/index.ts
index 19301c0b9..61352a134 100644
--- a/server/tests/api/index.ts
+++ b/server/tests/api/index.ts
@@ -7,5 +7,6 @@ import './notifications'
7import './redundancy' 7import './redundancy'
8import './search' 8import './search'
9import './server' 9import './server'
10import './transcoding'
10import './users' 11import './users'
11import './videos' 12import './videos'
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts
index 3f9355d2d..d756a02c1 100644
--- a/server/tests/api/live/live.ts
+++ b/server/tests/api/live/live.ts
@@ -3,7 +3,7 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { basename, join } from 'path' 5import { basename, join } from 'path'
6import { ffprobePromise, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils' 6import { ffprobePromise, getVideoStream } from '@server/helpers/ffmpeg'
7import { checkLiveCleanupAfterSave, checkLiveSegmentHash, checkResolutionsInMasterPlaylist, testImage } from '@server/tests/shared' 7import { checkLiveCleanupAfterSave, checkLiveSegmentHash, checkResolutionsInMasterPlaylist, testImage } from '@server/tests/shared'
8import { wait } from '@shared/core-utils' 8import { wait } from '@shared/core-utils'
9import { 9import {
@@ -562,7 +562,7 @@ describe('Test live', function () {
562 const segmentPath = servers[0].servers.buildDirectory(join('streaming-playlists', 'hls', video.uuid, filename)) 562 const segmentPath = servers[0].servers.buildDirectory(join('streaming-playlists', 'hls', video.uuid, filename))
563 563
564 const probe = await ffprobePromise(segmentPath) 564 const probe = await ffprobePromise(segmentPath)
565 const videoStream = await getVideoStreamFromFile(segmentPath, probe) 565 const videoStream = await getVideoStream(segmentPath, probe)
566 566
567 expect(probe.format.bit_rate).to.be.below(maxBitrateLimits[videoStream.height]) 567 expect(probe.format.bit_rate).to.be.below(maxBitrateLimits[videoStream.height])
568 expect(probe.format.bit_rate).to.be.at.least(minBitrateLimits[videoStream.height]) 568 expect(probe.format.bit_rate).to.be.at.least(minBitrateLimits[videoStream.height])
diff --git a/server/tests/api/moderation/abuses.ts b/server/tests/api/moderation/abuses.ts
index 0c3bed3e7..7bf49c7ec 100644
--- a/server/tests/api/moderation/abuses.ts
+++ b/server/tests/api/moderation/abuses.ts
@@ -2,6 +2,7 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { AbuseMessage, AbusePredefinedReasonsString, AbuseState, AdminAbuse, UserAbuse } from '@shared/models'
5import { 6import {
6 AbusesCommand, 7 AbusesCommand,
7 cleanupTests, 8 cleanupTests,
@@ -9,9 +10,10 @@ import {
9 doubleFollow, 10 doubleFollow,
10 PeerTubeServer, 11 PeerTubeServer,
11 setAccessTokensToServers, 12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultChannelAvatar,
12 waitJobs 15 waitJobs
13} from '@shared/server-commands' 16} from '@shared/server-commands'
14import { AbuseMessage, AbusePredefinedReasonsString, AbuseState, AdminAbuse, UserAbuse } from '@shared/models'
15 17
16const expect = chai.expect 18const expect = chai.expect
17 19
@@ -27,8 +29,9 @@ describe('Test abuses', function () {
27 // Run servers 29 // Run servers
28 servers = await createMultipleServers(2) 30 servers = await createMultipleServers(2)
29 31
30 // Get the access tokens
31 await setAccessTokensToServers(servers) 32 await setAccessTokensToServers(servers)
33 await setDefaultChannelAvatar(servers)
34 await setDefaultAccountAvatar(servers)
32 35
33 // Server 1 and server 2 follow each other 36 // Server 1 and server 2 follow each other
34 await doubleFollow(servers[0], servers[1]) 37 await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/api/moderation/blocklist.ts b/server/tests/api/moderation/blocklist.ts
index b45460bb4..e1344a245 100644
--- a/server/tests/api/moderation/blocklist.ts
+++ b/server/tests/api/moderation/blocklist.ts
@@ -2,6 +2,7 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { UserNotificationType } from '@shared/models'
5import { 6import {
6 BlocklistCommand, 7 BlocklistCommand,
7 cleanupTests, 8 cleanupTests,
@@ -10,9 +11,9 @@ import {
10 doubleFollow, 11 doubleFollow,
11 PeerTubeServer, 12 PeerTubeServer,
12 setAccessTokensToServers, 13 setAccessTokensToServers,
14 setDefaultAccountAvatar,
13 waitJobs 15 waitJobs
14} from '@shared/server-commands' 16} from '@shared/server-commands'
15import { UserNotificationType } from '@shared/models'
16 17
17const expect = chai.expect 18const expect = chai.expect
18 19
@@ -79,6 +80,7 @@ describe('Test blocklist', function () {
79 80
80 servers = await createMultipleServers(3) 81 servers = await createMultipleServers(3)
81 await setAccessTokensToServers(servers) 82 await setAccessTokensToServers(servers)
83 await setDefaultAccountAvatar(servers)
82 84
83 command = servers[0].blocklist 85 command = servers[0].blocklist
84 commentsCommand = servers.map(s => s.comments) 86 commentsCommand = servers.map(s => s.comments)
diff --git a/server/tests/api/moderation/video-blacklist.ts b/server/tests/api/moderation/video-blacklist.ts
index 3e7f2ba33..1790210ff 100644
--- a/server/tests/api/moderation/video-blacklist.ts
+++ b/server/tests/api/moderation/video-blacklist.ts
@@ -13,6 +13,7 @@ import {
13 killallServers, 13 killallServers,
14 PeerTubeServer, 14 PeerTubeServer,
15 setAccessTokensToServers, 15 setAccessTokensToServers,
16 setDefaultChannelAvatar,
16 waitJobs 17 waitJobs
17} from '@shared/server-commands' 18} from '@shared/server-commands'
18 19
@@ -42,6 +43,7 @@ describe('Test video blacklist', function () {
42 43
43 // Server 1 and server 2 follow each other 44 // Server 1 and server 2 follow each other
44 await doubleFollow(servers[0], servers[1]) 45 await doubleFollow(servers[0], servers[1])
46 await setDefaultChannelAvatar(servers[0])
45 47
46 // Upload 2 videos on server 2 48 // Upload 2 videos on server 2
47 await servers[1].videos.upload({ attributes: { name: 'My 1st video', description: 'A video on server 2' } }) 49 await servers[1].videos.upload({ attributes: { name: 'My 1st video', description: 'A video on server 2' } })
diff --git a/server/tests/api/notifications/notifications-api.ts b/server/tests/api/notifications/notifications-api.ts
index ac08449f8..78864c8a0 100644
--- a/server/tests/api/notifications/notifications-api.ts
+++ b/server/tests/api/notifications/notifications-api.ts
@@ -38,6 +38,16 @@ describe('Test notifications API', function () {
38 await waitJobs([ server ]) 38 await waitJobs([ server ])
39 }) 39 })
40 40
41 describe('Notification list & count', function () {
42
43 it('Should correctly list notifications', async function () {
44 const { data, total } = await server.notifications.list({ token: userToken, start: 0, count: 2 })
45
46 expect(data).to.have.lengthOf(2)
47 expect(total).to.equal(10)
48 })
49 })
50
41 describe('Mark as read', function () { 51 describe('Mark as read', function () {
42 52
43 it('Should mark as read some notifications', async function () { 53 it('Should mark as read some notifications', async function () {
diff --git a/server/tests/api/search/search-activitypub-video-channels.ts b/server/tests/api/search/search-activitypub-video-channels.ts
index 2e0abc6ba..5f5322d03 100644
--- a/server/tests/api/search/search-activitypub-video-channels.ts
+++ b/server/tests/api/search/search-activitypub-video-channels.ts
@@ -10,6 +10,8 @@ import {
10 PeerTubeServer, 10 PeerTubeServer,
11 SearchCommand, 11 SearchCommand,
12 setAccessTokensToServers, 12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultVideoChannel,
13 waitJobs 15 waitJobs
14} from '@shared/server-commands' 16} from '@shared/server-commands'
15 17
@@ -28,6 +30,8 @@ describe('Test ActivityPub video channels search', function () {
28 servers = await createMultipleServers(2) 30 servers = await createMultipleServers(2)
29 31
30 await setAccessTokensToServers(servers) 32 await setAccessTokensToServers(servers)
33 await setDefaultVideoChannel(servers)
34 await setDefaultAccountAvatar(servers)
31 35
32 { 36 {
33 await servers[0].users.create({ username: 'user1_server1', password: 'password' }) 37 await servers[0].users.create({ username: 'user1_server1', password: 'password' })
diff --git a/server/tests/api/search/search-activitypub-video-playlists.ts b/server/tests/api/search/search-activitypub-video-playlists.ts
index d9243ac53..b9a424292 100644
--- a/server/tests/api/search/search-activitypub-video-playlists.ts
+++ b/server/tests/api/search/search-activitypub-video-playlists.ts
@@ -10,6 +10,7 @@ import {
10 PeerTubeServer, 10 PeerTubeServer,
11 SearchCommand, 11 SearchCommand,
12 setAccessTokensToServers, 12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
13 setDefaultVideoChannel, 14 setDefaultVideoChannel,
14 waitJobs 15 waitJobs
15} from '@shared/server-commands' 16} from '@shared/server-commands'
@@ -31,6 +32,7 @@ describe('Test ActivityPub playlists search', function () {
31 32
32 await setAccessTokensToServers(servers) 33 await setAccessTokensToServers(servers)
33 await setDefaultVideoChannel(servers) 34 await setDefaultVideoChannel(servers)
35 await setDefaultAccountAvatar(servers)
34 36
35 { 37 {
36 const video1 = (await servers[0].videos.quickUpload({ name: 'video 1' })).uuid 38 const video1 = (await servers[0].videos.quickUpload({ name: 'video 1' })).uuid
diff --git a/server/tests/api/search/search-activitypub-videos.ts b/server/tests/api/search/search-activitypub-videos.ts
index 60b95ae4c..20249b1f1 100644
--- a/server/tests/api/search/search-activitypub-videos.ts
+++ b/server/tests/api/search/search-activitypub-videos.ts
@@ -10,6 +10,8 @@ import {
10 PeerTubeServer, 10 PeerTubeServer,
11 SearchCommand, 11 SearchCommand,
12 setAccessTokensToServers, 12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultVideoChannel,
13 waitJobs 15 waitJobs
14} from '@shared/server-commands' 16} from '@shared/server-commands'
15 17
@@ -28,6 +30,8 @@ describe('Test ActivityPub videos search', function () {
28 servers = await createMultipleServers(2) 30 servers = await createMultipleServers(2)
29 31
30 await setAccessTokensToServers(servers) 32 await setAccessTokensToServers(servers)
33 await setDefaultVideoChannel(servers)
34 await setDefaultAccountAvatar(servers)
31 35
32 { 36 {
33 const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 1 on server 1' } }) 37 const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 1 on server 1' } })
diff --git a/server/tests/api/search/search-channels.ts b/server/tests/api/search/search-channels.ts
index 8a92def61..cd4c053d2 100644
--- a/server/tests/api/search/search-channels.ts
+++ b/server/tests/api/search/search-channels.ts
@@ -2,15 +2,17 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { VideoChannel } from '@shared/models'
5import { 6import {
6 cleanupTests, 7 cleanupTests,
7 createSingleServer, 8 createSingleServer,
8 doubleFollow, 9 doubleFollow,
9 PeerTubeServer, 10 PeerTubeServer,
10 SearchCommand, 11 SearchCommand,
11 setAccessTokensToServers 12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultChannelAvatar
12} from '@shared/server-commands' 15} from '@shared/server-commands'
13import { VideoChannel } from '@shared/models'
14 16
15const expect = chai.expect 17const expect = chai.expect
16 18
@@ -24,12 +26,16 @@ describe('Test channels search', function () {
24 26
25 const servers = await Promise.all([ 27 const servers = await Promise.all([
26 createSingleServer(1), 28 createSingleServer(1),
27 createSingleServer(2, { transcoding: { enabled: false } }) 29 createSingleServer(2)
28 ]) 30 ])
29 server = servers[0] 31 server = servers[0]
30 remoteServer = servers[1] 32 remoteServer = servers[1]
31 33
32 await setAccessTokensToServers([ server, remoteServer ]) 34 await setAccessTokensToServers([ server, remoteServer ])
35 await setDefaultChannelAvatar(server)
36 await setDefaultAccountAvatar(server)
37
38 await servers[1].config.disableTranscoding()
33 39
34 { 40 {
35 await server.users.create({ username: 'user1' }) 41 await server.users.create({ username: 'user1' })
diff --git a/server/tests/api/search/search-index.ts b/server/tests/api/search/search-index.ts
index f84d03345..b18d40b2a 100644
--- a/server/tests/api/search/search-index.ts
+++ b/server/tests/api/search/search-index.ts
@@ -14,7 +14,7 @@ import {
14 14
15const expect = chai.expect 15const expect = chai.expect
16 16
17describe('Test videos search', function () { 17describe('Test index search', function () {
18 const localVideoName = 'local video' + new Date().toISOString() 18 const localVideoName = 'local video' + new Date().toISOString()
19 19
20 let server: PeerTubeServer = null 20 let server: PeerTubeServer = null
@@ -134,12 +134,16 @@ describe('Test videos search', function () {
134 expect(video.account.host).to.equal('framatube.org') 134 expect(video.account.host).to.equal('framatube.org')
135 expect(video.account.name).to.equal('framasoft') 135 expect(video.account.name).to.equal('framasoft')
136 expect(video.account.url).to.equal('https://framatube.org/accounts/framasoft') 136 expect(video.account.url).to.equal('https://framatube.org/accounts/framasoft')
137 // TODO: remove, deprecated in 4.2
137 expect(video.account.avatar).to.exist 138 expect(video.account.avatar).to.exist
139 expect(video.account.avatars.length).to.equal(1, 'Account should have one avatar image')
138 140
139 expect(video.channel.host).to.equal('framatube.org') 141 expect(video.channel.host).to.equal('framatube.org')
140 expect(video.channel.name).to.equal('joinpeertube') 142 expect(video.channel.name).to.equal('joinpeertube')
141 expect(video.channel.url).to.equal('https://framatube.org/video-channels/joinpeertube') 143 expect(video.channel.url).to.equal('https://framatube.org/video-channels/joinpeertube')
144 // TODO: remove, deprecated in 4.2
142 expect(video.channel.avatar).to.exist 145 expect(video.channel.avatar).to.exist
146 expect(video.channel.avatars.length).to.equal(1, 'Channel should have one avatar image')
143 } 147 }
144 148
145 const baseSearch: VideosSearchQuery = { 149 const baseSearch: VideosSearchQuery = {
@@ -316,13 +320,17 @@ describe('Test videos search', function () {
316 const videoChannel = body.data[0] 320 const videoChannel = body.data[0]
317 expect(videoChannel.url).to.equal('https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8') 321 expect(videoChannel.url).to.equal('https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8')
318 expect(videoChannel.host).to.equal('framatube.org') 322 expect(videoChannel.host).to.equal('framatube.org')
323 // TODO: remove, deprecated in 4.2
319 expect(videoChannel.avatar).to.exist 324 expect(videoChannel.avatar).to.exist
325 expect(videoChannel.avatars.length).to.equal(1, 'Channel should have two avatar images')
320 expect(videoChannel.displayName).to.exist 326 expect(videoChannel.displayName).to.exist
321 327
322 expect(videoChannel.ownerAccount.url).to.equal('https://framatube.org/accounts/framasoft') 328 expect(videoChannel.ownerAccount.url).to.equal('https://framatube.org/accounts/framasoft')
323 expect(videoChannel.ownerAccount.name).to.equal('framasoft') 329 expect(videoChannel.ownerAccount.name).to.equal('framasoft')
324 expect(videoChannel.ownerAccount.host).to.equal('framatube.org') 330 expect(videoChannel.ownerAccount.host).to.equal('framatube.org')
331 // TODO: remove, deprecated in 4.2
325 expect(videoChannel.ownerAccount.avatar).to.exist 332 expect(videoChannel.ownerAccount.avatar).to.exist
333 expect(videoChannel.ownerAccount.avatars.length).to.equal(1, 'Account should have two avatar images')
326 } 334 }
327 335
328 it('Should make a simple search and not have results', async function () { 336 it('Should make a simple search and not have results', async function () {
@@ -388,12 +396,16 @@ describe('Test videos search', function () {
388 expect(videoPlaylist.ownerAccount.url).to.equal('https://peertube2.cpy.re/accounts/chocobozzz') 396 expect(videoPlaylist.ownerAccount.url).to.equal('https://peertube2.cpy.re/accounts/chocobozzz')
389 expect(videoPlaylist.ownerAccount.name).to.equal('chocobozzz') 397 expect(videoPlaylist.ownerAccount.name).to.equal('chocobozzz')
390 expect(videoPlaylist.ownerAccount.host).to.equal('peertube2.cpy.re') 398 expect(videoPlaylist.ownerAccount.host).to.equal('peertube2.cpy.re')
399 // TODO: remove, deprecated in 4.2
391 expect(videoPlaylist.ownerAccount.avatar).to.exist 400 expect(videoPlaylist.ownerAccount.avatar).to.exist
401 expect(videoPlaylist.ownerAccount.avatars.length).to.equal(2, 'Account should have two avatar images')
392 402
393 expect(videoPlaylist.videoChannel.url).to.equal('https://peertube2.cpy.re/video-channels/chocobozzz_channel') 403 expect(videoPlaylist.videoChannel.url).to.equal('https://peertube2.cpy.re/video-channels/chocobozzz_channel')
394 expect(videoPlaylist.videoChannel.name).to.equal('chocobozzz_channel') 404 expect(videoPlaylist.videoChannel.name).to.equal('chocobozzz_channel')
395 expect(videoPlaylist.videoChannel.host).to.equal('peertube2.cpy.re') 405 expect(videoPlaylist.videoChannel.host).to.equal('peertube2.cpy.re')
406 // TODO: remove, deprecated in 4.2
396 expect(videoPlaylist.videoChannel.avatar).to.exist 407 expect(videoPlaylist.videoChannel.avatar).to.exist
408 expect(videoPlaylist.videoChannel.avatars.length).to.equal(2, 'Channel should have two avatar images')
397 } 409 }
398 410
399 it('Should make a simple search and not have results', async function () { 411 it('Should make a simple search and not have results', async function () {
diff --git a/server/tests/api/search/search-playlists.ts b/server/tests/api/search/search-playlists.ts
index 1e9c8d4bb..d9f12d316 100644
--- a/server/tests/api/search/search-playlists.ts
+++ b/server/tests/api/search/search-playlists.ts
@@ -2,6 +2,7 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { VideoPlaylistPrivacy } from '@shared/models'
5import { 6import {
6 cleanupTests, 7 cleanupTests,
7 createSingleServer, 8 createSingleServer,
@@ -9,9 +10,10 @@ import {
9 PeerTubeServer, 10 PeerTubeServer,
10 SearchCommand, 11 SearchCommand,
11 setAccessTokensToServers, 12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultChannelAvatar,
12 setDefaultVideoChannel 15 setDefaultVideoChannel
13} from '@shared/server-commands' 16} from '@shared/server-commands'
14import { VideoPlaylistPrivacy } from '@shared/models'
15 17
16const expect = chai.expect 18const expect = chai.expect
17 19
@@ -27,13 +29,17 @@ describe('Test playlists search', function () {
27 29
28 const servers = await Promise.all([ 30 const servers = await Promise.all([
29 createSingleServer(1), 31 createSingleServer(1),
30 createSingleServer(2, { transcoding: { enabled: false } }) 32 createSingleServer(2)
31 ]) 33 ])
32 server = servers[0] 34 server = servers[0]
33 remoteServer = servers[1] 35 remoteServer = servers[1]
34 36
35 await setAccessTokensToServers([ remoteServer, server ]) 37 await setAccessTokensToServers([ remoteServer, server ])
36 await setDefaultVideoChannel([ remoteServer, server ]) 38 await setDefaultVideoChannel([ remoteServer, server ])
39 await setDefaultChannelAvatar([ remoteServer, server ])
40 await setDefaultAccountAvatar([ remoteServer, server ])
41
42 await servers[1].config.disableTranscoding()
37 43
38 { 44 {
39 const videoId = (await server.videos.upload()).uuid 45 const videoId = (await server.videos.upload()).uuid
diff --git a/server/tests/api/search/search-videos.ts b/server/tests/api/search/search-videos.ts
index c544705d3..ff4c3c161 100644
--- a/server/tests/api/search/search-videos.ts
+++ b/server/tests/api/search/search-videos.ts
@@ -2,6 +2,8 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { wait } from '@shared/core-utils'
6import { VideoPrivacy } from '@shared/models'
5import { 7import {
6 cleanupTests, 8 cleanupTests,
7 createSingleServer, 9 createSingleServer,
@@ -9,11 +11,11 @@ import {
9 PeerTubeServer, 11 PeerTubeServer,
10 SearchCommand, 12 SearchCommand,
11 setAccessTokensToServers, 13 setAccessTokensToServers,
14 setDefaultAccountAvatar,
15 setDefaultChannelAvatar,
12 setDefaultVideoChannel, 16 setDefaultVideoChannel,
13 stopFfmpeg 17 stopFfmpeg
14} from '@shared/server-commands' 18} from '@shared/server-commands'
15import { VideoPrivacy } from '@shared/models'
16import { wait } from '@shared/core-utils'
17 19
18const expect = chai.expect 20const expect = chai.expect
19 21
@@ -38,6 +40,8 @@ describe('Test videos search', function () {
38 40
39 await setAccessTokensToServers([ server, remoteServer ]) 41 await setAccessTokensToServers([ server, remoteServer ])
40 await setDefaultVideoChannel([ server, remoteServer ]) 42 await setDefaultVideoChannel([ server, remoteServer ])
43 await setDefaultChannelAvatar(server)
44 await setDefaultAccountAvatar(servers)
41 45
42 { 46 {
43 const attributes1 = { 47 const attributes1 = {
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index 2356f701c..565b2953a 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -97,6 +97,8 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
97 expect(data.live.transcoding.resolutions['1440p']).to.be.false 97 expect(data.live.transcoding.resolutions['1440p']).to.be.false
98 expect(data.live.transcoding.resolutions['2160p']).to.be.false 98 expect(data.live.transcoding.resolutions['2160p']).to.be.false
99 99
100 expect(data.videoEditor.enabled).to.be.false
101
100 expect(data.import.videos.concurrency).to.equal(2) 102 expect(data.import.videos.concurrency).to.equal(2)
101 expect(data.import.videos.http.enabled).to.be.true 103 expect(data.import.videos.http.enabled).to.be.true
102 expect(data.import.videos.torrent.enabled).to.be.true 104 expect(data.import.videos.torrent.enabled).to.be.true
@@ -197,6 +199,8 @@ function checkUpdatedConfig (data: CustomConfig) {
197 expect(data.live.transcoding.resolutions['1080p']).to.be.true 199 expect(data.live.transcoding.resolutions['1080p']).to.be.true
198 expect(data.live.transcoding.resolutions['2160p']).to.be.true 200 expect(data.live.transcoding.resolutions['2160p']).to.be.true
199 201
202 expect(data.videoEditor.enabled).to.be.true
203
200 expect(data.import.videos.concurrency).to.equal(4) 204 expect(data.import.videos.concurrency).to.equal(4)
201 expect(data.import.videos.http.enabled).to.be.false 205 expect(data.import.videos.http.enabled).to.be.false
202 expect(data.import.videos.torrent.enabled).to.be.false 206 expect(data.import.videos.torrent.enabled).to.be.false
@@ -341,6 +345,9 @@ const newCustomConfig: CustomConfig = {
341 } 345 }
342 } 346 }
343 }, 347 },
348 videoEditor: {
349 enabled: true
350 },
344 import: { 351 import: {
345 videos: { 352 videos: {
346 concurrency: 4, 353 concurrency: 4,
diff --git a/server/tests/api/server/homepage.ts b/server/tests/api/server/homepage.ts
index 552ee98cf..e7de6bfee 100644
--- a/server/tests/api/server/homepage.ts
+++ b/server/tests/api/server/homepage.ts
@@ -9,7 +9,9 @@ import {
9 CustomPagesCommand, 9 CustomPagesCommand,
10 killallServers, 10 killallServers,
11 PeerTubeServer, 11 PeerTubeServer,
12 setAccessTokensToServers 12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultChannelAvatar
13} from '../../../../shared/server-commands/index' 15} from '../../../../shared/server-commands/index'
14 16
15const expect = chai.expect 17const expect = chai.expect
@@ -29,6 +31,8 @@ describe('Test instance homepage actions', function () {
29 31
30 server = await createSingleServer(1) 32 server = await createSingleServer(1)
31 await setAccessTokensToServers([ server ]) 33 await setAccessTokensToServers([ server ])
34 await setDefaultChannelAvatar(server)
35 await setDefaultAccountAvatar(server)
32 36
33 command = server.customPage 37 command = server.customPage
34 }) 38 })
diff --git a/server/tests/api/server/stats.ts b/server/tests/api/server/stats.ts
index f0334532b..2296c0cb9 100644
--- a/server/tests/api/server/stats.ts
+++ b/server/tests/api/server/stats.ts
@@ -230,13 +230,7 @@ describe('Test stats (excluding redundancy)', function () {
230 it('Should have the correct AP stats', async function () { 230 it('Should have the correct AP stats', async function () {
231 this.timeout(60000) 231 this.timeout(60000)
232 232
233 await servers[0].config.updateCustomSubConfig({ 233 await servers[0].config.disableTranscoding()
234 newConfig: {
235 transcoding: {
236 enabled: false
237 }
238 }
239 })
240 234
241 const first = await servers[1].stats.get() 235 const first = await servers[1].stats.get()
242 236
diff --git a/server/tests/api/videos/audio-only.ts b/server/tests/api/transcoding/audio-only.ts
index e58360ffe..e7e73d382 100644
--- a/server/tests/api/videos/audio-only.ts
+++ b/server/tests/api/transcoding/audio-only.ts
@@ -2,7 +2,7 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { getAudioStream, getVideoStreamSize } from '@server/helpers/ffprobe-utils' 5import { getAudioStream, getVideoStreamDimensionsInfo } from '@server/helpers/ffmpeg'
6import { 6import {
7 cleanupTests, 7 cleanupTests,
8 createMultipleServers, 8 createMultipleServers,
@@ -91,9 +91,8 @@ describe('Test audio only video transcoding', function () {
91 expect(audioStream['codec_name']).to.be.equal('aac') 91 expect(audioStream['codec_name']).to.be.equal('aac')
92 expect(audioStream['bit_rate']).to.be.at.most(384 * 8000) 92 expect(audioStream['bit_rate']).to.be.at.most(384 * 8000)
93 93
94 const size = await getVideoStreamSize(path) 94 const size = await getVideoStreamDimensionsInfo(path)
95 expect(size.height).to.equal(0) 95 expect(size).to.not.exist
96 expect(size.width).to.equal(0)
97 } 96 }
98 }) 97 })
99 98
diff --git a/server/tests/api/videos/video-create-transcoding.ts b/server/tests/api/transcoding/create-transcoding.ts
index a4defdf51..a4defdf51 100644
--- a/server/tests/api/videos/video-create-transcoding.ts
+++ b/server/tests/api/transcoding/create-transcoding.ts
diff --git a/server/tests/api/videos/video-hls.ts b/server/tests/api/transcoding/hls.ts
index 218ec08ae..218ec08ae 100644
--- a/server/tests/api/videos/video-hls.ts
+++ b/server/tests/api/transcoding/hls.ts
diff --git a/server/tests/api/transcoding/index.ts b/server/tests/api/transcoding/index.ts
new file mode 100644
index 000000000..8a0a1d787
--- /dev/null
+++ b/server/tests/api/transcoding/index.ts
@@ -0,0 +1,5 @@
1export * from './audio-only'
2export * from './create-transcoding'
3export * from './hls'
4export * from './transcoder'
5export * from './video-editor'
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/transcoding/transcoder.ts
index d24a8f4e1..245c4c012 100644
--- a/server/tests/api/videos/video-transcoder.ts
+++ b/server/tests/api/transcoding/transcoder.ts
@@ -3,10 +3,17 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { omit } from 'lodash' 5import { omit } from 'lodash'
6import { canDoQuickTranscode } from '@server/helpers/ffprobe-utils' 6import { canDoQuickTranscode } from '@server/helpers/ffmpeg'
7import { generateHighBitrateVideo, generateVideoWithFramerate } from '@server/tests/shared' 7import { generateHighBitrateVideo, generateVideoWithFramerate, getAllFiles } from '@server/tests/shared'
8import { buildAbsoluteFixturePath, getMaxBitrate, getMinLimitBitrate } from '@shared/core-utils' 8import { buildAbsoluteFixturePath, getMaxBitrate, getMinLimitBitrate } from '@shared/core-utils'
9import { getAudioStream, getMetadataFromFile, getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '@shared/extra-utils' 9import {
10 getAudioStream,
11 buildFileMetadata,
12 getVideoStreamBitrate,
13 getVideoStreamFPS,
14 getVideoStreamDimensionsInfo,
15 hasAudioStream
16} from '@shared/extra-utils'
10import { HttpStatusCode, VideoState } from '@shared/models' 17import { HttpStatusCode, VideoState } from '@shared/models'
11import { 18import {
12 cleanupTests, 19 cleanupTests,
@@ -287,8 +294,7 @@ describe('Test video transcoding', function () {
287 const file = videoDetails.files.find(f => f.resolution.id === 240) 294 const file = videoDetails.files.find(f => f.resolution.id === 240)
288 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) 295 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
289 296
290 const probe = await getAudioStream(path) 297 expect(await hasAudioStream(path)).to.be.false
291 expect(probe).to.not.have.property('audioStream')
292 } 298 }
293 }) 299 })
294 300
@@ -478,14 +484,14 @@ describe('Test video transcoding', function () {
478 for (const resolution of [ 144, 240, 360, 480 ]) { 484 for (const resolution of [ 144, 240, 360, 480 ]) {
479 const file = videoDetails.files.find(f => f.resolution.id === resolution) 485 const file = videoDetails.files.find(f => f.resolution.id === resolution)
480 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) 486 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
481 const fps = await getVideoFileFPS(path) 487 const fps = await getVideoStreamFPS(path)
482 488
483 expect(fps).to.be.below(31) 489 expect(fps).to.be.below(31)
484 } 490 }
485 491
486 const file = videoDetails.files.find(f => f.resolution.id === 720) 492 const file = videoDetails.files.find(f => f.resolution.id === 720)
487 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) 493 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
488 const fps = await getVideoFileFPS(path) 494 const fps = await getVideoStreamFPS(path)
489 495
490 expect(fps).to.be.above(58).and.below(62) 496 expect(fps).to.be.above(58).and.below(62)
491 } 497 }
@@ -499,7 +505,7 @@ describe('Test video transcoding', function () {
499 { 505 {
500 tempFixturePath = await generateVideoWithFramerate(59) 506 tempFixturePath = await generateVideoWithFramerate(59)
501 507
502 const fps = await getVideoFileFPS(tempFixturePath) 508 const fps = await getVideoStreamFPS(tempFixturePath)
503 expect(fps).to.be.equal(59) 509 expect(fps).to.be.equal(59)
504 } 510 }
505 511
@@ -522,14 +528,14 @@ describe('Test video transcoding', function () {
522 { 528 {
523 const file = video.files.find(f => f.resolution.id === 240) 529 const file = video.files.find(f => f.resolution.id === 240)
524 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) 530 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
525 const fps = await getVideoFileFPS(path) 531 const fps = await getVideoStreamFPS(path)
526 expect(fps).to.be.equal(25) 532 expect(fps).to.be.equal(25)
527 } 533 }
528 534
529 { 535 {
530 const file = video.files.find(f => f.resolution.id === 720) 536 const file = video.files.find(f => f.resolution.id === 720)
531 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) 537 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
532 const fps = await getVideoFileFPS(path) 538 const fps = await getVideoStreamFPS(path)
533 expect(fps).to.be.equal(59) 539 expect(fps).to.be.equal(59)
534 } 540 }
535 } 541 }
@@ -563,9 +569,9 @@ describe('Test video transcoding', function () {
563 const file = video.files.find(f => f.resolution.id === resolution) 569 const file = video.files.find(f => f.resolution.id === resolution)
564 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) 570 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
565 571
566 const bitrate = await getVideoFileBitrate(path) 572 const bitrate = await getVideoStreamBitrate(path)
567 const fps = await getVideoFileFPS(path) 573 const fps = await getVideoStreamFPS(path)
568 const dataResolution = await getVideoFileResolution(path) 574 const dataResolution = await getVideoStreamDimensionsInfo(path)
569 575
570 expect(resolution).to.equal(resolution) 576 expect(resolution).to.equal(resolution)
571 577
@@ -613,7 +619,7 @@ describe('Test video transcoding', function () {
613 const file = video.files.find(f => f.resolution.id === r) 619 const file = video.files.find(f => f.resolution.id === r)
614 620
615 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) 621 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
616 const bitrate = await getVideoFileBitrate(path) 622 const bitrate = await getVideoStreamBitrate(path)
617 623
618 const inputBitrate = 60_000 624 const inputBitrate = 60_000
619 const limit = getMinLimitBitrate({ fps: 10, ratio: 1, resolution: r }) 625 const limit = getMinLimitBitrate({ fps: 10, ratio: 1, resolution: r })
@@ -637,7 +643,7 @@ describe('Test video transcoding', function () {
637 const video = await servers[1].videos.get({ id: videoUUID }) 643 const video = await servers[1].videos.get({ id: videoUUID })
638 const file = video.files.find(f => f.resolution.id === 240) 644 const file = video.files.find(f => f.resolution.id === 240)
639 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) 645 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
640 const metadata = await getMetadataFromFile(path) 646 const metadata = await buildFileMetadata(path)
641 647
642 // expected format properties 648 // expected format properties
643 for (const p of [ 649 for (const p of [
@@ -668,8 +674,7 @@ describe('Test video transcoding', function () {
668 for (const server of servers) { 674 for (const server of servers) {
669 const videoDetails = await server.videos.get({ id: videoUUID }) 675 const videoDetails = await server.videos.get({ id: videoUUID })
670 676
671 const videoFiles = videoDetails.files 677 const videoFiles = getAllFiles(videoDetails)
672 .concat(videoDetails.streamingPlaylists[0].files)
673 expect(videoFiles).to.have.lengthOf(10) 678 expect(videoFiles).to.have.lengthOf(10)
674 679
675 for (const file of videoFiles) { 680 for (const file of videoFiles) {
diff --git a/server/tests/api/transcoding/video-editor.ts b/server/tests/api/transcoding/video-editor.ts
new file mode 100644
index 000000000..a9b6950cc
--- /dev/null
+++ b/server/tests/api/transcoding/video-editor.ts
@@ -0,0 +1,368 @@
1import { expect } from 'chai'
2import { expectStartWith, getAllFiles } from '@server/tests/shared'
3import { areObjectStorageTestsDisabled } from '@shared/core-utils'
4import { VideoEditorTask } from '@shared/models'
5import {
6 cleanupTests,
7 createMultipleServers,
8 doubleFollow,
9 ObjectStorageCommand,
10 PeerTubeServer,
11 setAccessTokensToServers,
12 setDefaultVideoChannel,
13 VideoEditorCommand,
14 waitJobs
15} from '@shared/server-commands'
16
17describe('Test video editor', function () {
18 let servers: PeerTubeServer[] = []
19 let videoUUID: string
20
21 async function checkDuration (server: PeerTubeServer, duration: number) {
22 const video = await server.videos.get({ id: videoUUID })
23
24 expect(video.duration).to.be.approximately(duration, 1)
25
26 for (const file of video.files) {
27 const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
28
29 for (const stream of metadata.streams) {
30 expect(Math.round(stream.duration)).to.be.approximately(duration, 1)
31 }
32 }
33 }
34
35 async function renewVideo (fixture = 'video_short.webm') {
36 const video = await servers[0].videos.quickUpload({ name: 'video', fixture })
37 videoUUID = video.uuid
38
39 await waitJobs(servers)
40 }
41
42 async function createTasks (tasks: VideoEditorTask[]) {
43 await servers[0].videoEditor.createEditionTasks({ videoId: videoUUID, tasks })
44 await waitJobs(servers)
45 }
46
47 before(async function () {
48 this.timeout(120_000)
49
50 servers = await createMultipleServers(2)
51
52 await setAccessTokensToServers(servers)
53 await setDefaultVideoChannel(servers)
54
55 await doubleFollow(servers[0], servers[1])
56
57 await servers[0].config.enableMinimumTranscoding()
58
59 await servers[0].config.updateExistingSubConfig({
60 newConfig: {
61 videoEditor: {
62 enabled: true
63 }
64 }
65 })
66 })
67
68 describe('Cutting', function () {
69
70 it('Should cut the beginning of the video', async function () {
71 this.timeout(120_000)
72
73 await renewVideo()
74 await waitJobs(servers)
75
76 const beforeTasks = new Date()
77
78 await createTasks([
79 {
80 name: 'cut',
81 options: {
82 start: 2
83 }
84 }
85 ])
86
87 for (const server of servers) {
88 await checkDuration(server, 3)
89
90 const video = await server.videos.get({ id: videoUUID })
91 expect(new Date(video.publishedAt)).to.be.below(beforeTasks)
92 }
93 })
94
95 it('Should cut the end of the video', async function () {
96 this.timeout(120_000)
97 await renewVideo()
98
99 await createTasks([
100 {
101 name: 'cut',
102 options: {
103 end: 2
104 }
105 }
106 ])
107
108 for (const server of servers) {
109 await checkDuration(server, 2)
110 }
111 })
112
113 it('Should cut start/end of the video', async function () {
114 this.timeout(120_000)
115 await renewVideo('video_short1.webm') // 10 seconds video duration
116
117 await createTasks([
118 {
119 name: 'cut',
120 options: {
121 start: 2,
122 end: 6
123 }
124 }
125 ])
126
127 for (const server of servers) {
128 await checkDuration(server, 4)
129 }
130 })
131 })
132
133 describe('Intro/Outro', function () {
134
135 it('Should add an intro', async function () {
136 this.timeout(120_000)
137 await renewVideo()
138
139 await createTasks([
140 {
141 name: 'add-intro',
142 options: {
143 file: 'video_short.webm'
144 }
145 }
146 ])
147
148 for (const server of servers) {
149 await checkDuration(server, 10)
150 }
151 })
152
153 it('Should add an outro', async function () {
154 this.timeout(120_000)
155 await renewVideo()
156
157 await createTasks([
158 {
159 name: 'add-outro',
160 options: {
161 file: 'video_very_short_240p.mp4'
162 }
163 }
164 ])
165
166 for (const server of servers) {
167 await checkDuration(server, 7)
168 }
169 })
170
171 it('Should add an intro/outro', async function () {
172 this.timeout(120_000)
173 await renewVideo()
174
175 await createTasks([
176 {
177 name: 'add-intro',
178 options: {
179 file: 'video_very_short_240p.mp4'
180 }
181 },
182 {
183 name: 'add-outro',
184 options: {
185 // Different frame rate
186 file: 'video_short2.webm'
187 }
188 }
189 ])
190
191 for (const server of servers) {
192 await checkDuration(server, 12)
193 }
194 })
195
196 it('Should add an intro to a video without audio', async function () {
197 this.timeout(120_000)
198 await renewVideo('video_short_no_audio.mp4')
199
200 await createTasks([
201 {
202 name: 'add-intro',
203 options: {
204 file: 'video_very_short_240p.mp4'
205 }
206 }
207 ])
208
209 for (const server of servers) {
210 await checkDuration(server, 7)
211 }
212 })
213
214 it('Should add an outro without audio to a video with audio', async function () {
215 this.timeout(120_000)
216 await renewVideo()
217
218 await createTasks([
219 {
220 name: 'add-outro',
221 options: {
222 file: 'video_short_no_audio.mp4'
223 }
224 }
225 ])
226
227 for (const server of servers) {
228 await checkDuration(server, 10)
229 }
230 })
231
232 it('Should add an outro without audio to a video with audio', async function () {
233 this.timeout(120_000)
234 await renewVideo('video_short_no_audio.mp4')
235
236 await createTasks([
237 {
238 name: 'add-outro',
239 options: {
240 file: 'video_short_no_audio.mp4'
241 }
242 }
243 ])
244
245 for (const server of servers) {
246 await checkDuration(server, 10)
247 }
248 })
249 })
250
251 describe('Watermark', function () {
252
253 it('Should add a watermark to the video', async function () {
254 this.timeout(120_000)
255 await renewVideo()
256
257 const video = await servers[0].videos.get({ id: videoUUID })
258 const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
259
260 await createTasks([
261 {
262 name: 'add-watermark',
263 options: {
264 file: 'thumbnail.png'
265 }
266 }
267 ])
268
269 for (const server of servers) {
270 const video = await server.videos.get({ id: videoUUID })
271 const fileUrls = getAllFiles(video).map(f => f.fileUrl)
272
273 for (const oldUrl of oldFileUrls) {
274 expect(fileUrls).to.not.include(oldUrl)
275 }
276 }
277 })
278 })
279
280 describe('Complex tasks', function () {
281 it('Should run a complex task', async function () {
282 this.timeout(240_000)
283 await renewVideo()
284
285 await createTasks(VideoEditorCommand.getComplexTask())
286
287 for (const server of servers) {
288 await checkDuration(server, 9)
289 }
290 })
291 })
292
293 describe('HLS only video edition', function () {
294
295 before(async function () {
296 // Disable webtorrent
297 await servers[0].config.updateExistingSubConfig({
298 newConfig: {
299 transcoding: {
300 webtorrent: {
301 enabled: false
302 }
303 }
304 }
305 })
306 })
307
308 it('Should run a complex task on HLS only video', async function () {
309 this.timeout(240_000)
310 await renewVideo()
311
312 await createTasks(VideoEditorCommand.getComplexTask())
313
314 for (const server of servers) {
315 const video = await server.videos.get({ id: videoUUID })
316 expect(video.files).to.have.lengthOf(0)
317
318 await checkDuration(server, 9)
319 }
320 })
321 })
322
323 describe('Object storage video edition', function () {
324 if (areObjectStorageTestsDisabled()) return
325
326 before(async function () {
327 await ObjectStorageCommand.prepareDefaultBuckets()
328
329 await servers[0].kill()
330 await servers[0].run(ObjectStorageCommand.getDefaultConfig())
331
332 await servers[0].config.enableMinimumTranscoding()
333 })
334
335 it('Should run a complex task on a video in object storage', async function () {
336 this.timeout(240_000)
337 await renewVideo()
338
339 const video = await servers[0].videos.get({ id: videoUUID })
340 const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
341
342 await createTasks(VideoEditorCommand.getComplexTask())
343
344 for (const server of servers) {
345 const video = await server.videos.get({ id: videoUUID })
346 const files = getAllFiles(video)
347
348 for (const f of files) {
349 expect(oldFileUrls).to.not.include(f.fileUrl)
350 }
351
352 for (const webtorrentFile of video.files) {
353 expectStartWith(webtorrentFile.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl())
354 }
355
356 for (const hlsFile of video.streamingPlaylists[0].files) {
357 expectStartWith(hlsFile.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl())
358 }
359
360 await checkDuration(server, 9)
361 }
362 })
363 })
364
365 after(async function () {
366 await cleanupTests(servers)
367 })
368})
diff --git a/server/tests/api/users/user-subscriptions.ts b/server/tests/api/users/user-subscriptions.ts
index 57cca6ad4..9553a69bb 100644
--- a/server/tests/api/users/user-subscriptions.ts
+++ b/server/tests/api/users/user-subscriptions.ts
@@ -9,6 +9,8 @@ import {
9 doubleFollow, 9 doubleFollow,
10 PeerTubeServer, 10 PeerTubeServer,
11 setAccessTokensToServers, 11 setAccessTokensToServers,
12 setDefaultAccountAvatar,
13 setDefaultChannelAvatar,
12 SubscriptionsCommand, 14 SubscriptionsCommand,
13 waitJobs 15 waitJobs
14} from '@shared/server-commands' 16} from '@shared/server-commands'
@@ -29,6 +31,8 @@ describe('Test users subscriptions', function () {
29 31
30 // Get the access tokens 32 // Get the access tokens
31 await setAccessTokensToServers(servers) 33 await setAccessTokensToServers(servers)
34 await setDefaultChannelAvatar(servers)
35 await setDefaultAccountAvatar(servers)
32 36
33 // Server 1 and server 2 follow each other 37 // Server 1 and server 2 follow each other
34 await doubleFollow(servers[0], servers[1]) 38 await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts
index 5b2bbc520..3e8b932c0 100644
--- a/server/tests/api/users/users-multiple-servers.ts
+++ b/server/tests/api/users/users-multiple-servers.ts
@@ -16,6 +16,7 @@ import {
16 doubleFollow, 16 doubleFollow,
17 PeerTubeServer, 17 PeerTubeServer,
18 setAccessTokensToServers, 18 setAccessTokensToServers,
19 setDefaultChannelAvatar,
19 waitJobs 20 waitJobs
20} from '@shared/server-commands' 21} from '@shared/server-commands'
21 22
@@ -29,7 +30,7 @@ describe('Test users with multiple servers', function () {
29 30
30 let videoUUID: string 31 let videoUUID: string
31 let userAccessToken: string 32 let userAccessToken: string
32 let userAvatarFilename: string 33 let userAvatarFilenames: string[]
33 34
34 before(async function () { 35 before(async function () {
35 this.timeout(120_000) 36 this.timeout(120_000)
@@ -38,6 +39,7 @@ describe('Test users with multiple servers', function () {
38 39
39 // Get the access tokens 40 // Get the access tokens
40 await setAccessTokensToServers(servers) 41 await setAccessTokensToServers(servers)
42 await setDefaultChannelAvatar(servers)
41 43
42 // Server 1 and server 2 follow each other 44 // Server 1 and server 2 follow each other
43 await doubleFollow(servers[0], servers[1]) 45 await doubleFollow(servers[0], servers[1])
@@ -97,9 +99,11 @@ describe('Test users with multiple servers', function () {
97 await servers[0].users.updateMyAvatar({ fixture }) 99 await servers[0].users.updateMyAvatar({ fixture })
98 100
99 user = await servers[0].users.getMyInfo() 101 user = await servers[0].users.getMyInfo()
100 userAvatarFilename = user.account.avatar.path 102 userAvatarFilenames = user.account.avatars.map(({ path }) => path)
101 103
102 await testImage(servers[0].url, 'avatar2-resized', userAvatarFilename, '.png') 104 for (const avatar of user.account.avatars) {
105 await testImage(servers[0].url, `avatar2-resized-${avatar.width}x${avatar.width}`, avatar.path, '.png')
106 }
103 107
104 await waitJobs(servers) 108 await waitJobs(servers)
105 }) 109 })
@@ -129,7 +133,9 @@ describe('Test users with multiple servers', function () {
129 expect(account.userId).to.be.undefined 133 expect(account.userId).to.be.undefined
130 } 134 }
131 135
132 await testImage(server.url, 'avatar2-resized', account.avatar.path, '.png') 136 for (const avatar of account.avatars) {
137 await testImage(server.url, `avatar2-resized-${avatar.width}x${avatar.width}`, avatar.path, '.png')
138 }
133 } 139 }
134 }) 140 })
135 141
@@ -193,7 +199,9 @@ describe('Test users with multiple servers', function () {
193 199
194 it('Should not have actor files', async () => { 200 it('Should not have actor files', async () => {
195 for (const server of servers) { 201 for (const server of servers) {
196 await checkActorFilesWereRemoved(userAvatarFilename, server.internalServerNumber) 202 for (const userAvatarFilename of userAvatarFilenames) {
203 await checkActorFilesWereRemoved(userAvatarFilename, server.internalServerNumber)
204 }
197 } 205 }
198 }) 206 })
199 207
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts
index 7023b3f08..a47713bf0 100644
--- a/server/tests/api/users/users.ts
+++ b/server/tests/api/users/users.ts
@@ -604,7 +604,9 @@ describe('Test users', function () {
604 await server.users.updateMyAvatar({ token: userToken, fixture }) 604 await server.users.updateMyAvatar({ token: userToken, fixture })
605 605
606 const user = await server.users.getMyInfo({ token: userToken }) 606 const user = await server.users.getMyInfo({ token: userToken })
607 await testImage(server.url, 'avatar-resized', user.account.avatar.path, '.gif') 607 for (const avatar of user.account.avatars) {
608 await testImage(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, '.gif')
609 }
608 }) 610 })
609 611
610 it('Should be able to update my avatar with a gif, and then a png', async function () { 612 it('Should be able to update my avatar with a gif, and then a png', async function () {
@@ -614,7 +616,9 @@ describe('Test users', function () {
614 await server.users.updateMyAvatar({ token: userToken, fixture }) 616 await server.users.updateMyAvatar({ token: userToken, fixture })
615 617
616 const user = await server.users.getMyInfo({ token: userToken }) 618 const user = await server.users.getMyInfo({ token: userToken })
617 await testImage(server.url, 'avatar-resized', user.account.avatar.path, extension) 619 for (const avatar of user.account.avatars) {
620 await testImage(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, extension)
621 }
618 } 622 }
619 }) 623 })
620 624
diff --git a/server/tests/api/videos/index.ts b/server/tests/api/videos/index.ts
index bedb9b8b6..7dc826353 100644
--- a/server/tests/api/videos/index.ts
+++ b/server/tests/api/videos/index.ts
@@ -1,4 +1,3 @@
1import './audio-only'
2import './multiple-servers' 1import './multiple-servers'
3import './resumable-upload' 2import './resumable-upload'
4import './single-server' 3import './single-server'
@@ -6,17 +5,14 @@ import './video-captions'
6import './video-change-ownership' 5import './video-change-ownership'
7import './video-channels' 6import './video-channels'
8import './video-comments' 7import './video-comments'
9import './video-create-transcoding'
10import './video-description' 8import './video-description'
11import './video-files' 9import './video-files'
12import './video-hls'
13import './video-imports' 10import './video-imports'
14import './video-nsfw' 11import './video-nsfw'
15import './video-playlists' 12import './video-playlists'
16import './video-playlist-thumbnails' 13import './video-playlist-thumbnails'
17import './video-privacy' 14import './video-privacy'
18import './video-schedule-update' 15import './video-schedule-update'
19import './video-transcoder'
20import './videos-common-filters' 16import './videos-common-filters'
21import './videos-history' 17import './videos-history'
22import './videos-overview' 18import './videos-overview'
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
index ecdd36613..05ccee8ad 100644
--- a/server/tests/api/videos/multiple-servers.ts
+++ b/server/tests/api/videos/multiple-servers.ts
@@ -17,8 +17,11 @@ import {
17 cleanupTests, 17 cleanupTests,
18 createMultipleServers, 18 createMultipleServers,
19 doubleFollow, 19 doubleFollow,
20 makeGetRequest,
20 PeerTubeServer, 21 PeerTubeServer,
21 setAccessTokensToServers, 22 setAccessTokensToServers,
23 setDefaultAccountAvatar,
24 setDefaultChannelAvatar,
22 waitJobs, 25 waitJobs,
23 webtorrentAdd 26 webtorrentAdd
24} from '@shared/server-commands' 27} from '@shared/server-commands'
@@ -46,6 +49,9 @@ describe('Test multiple servers', function () {
46 description: 'super channel' 49 description: 'super channel'
47 } 50 }
48 await servers[0].channels.create({ attributes: videoChannel }) 51 await servers[0].channels.create({ attributes: videoChannel })
52 await setDefaultChannelAvatar(servers[0], videoChannel.name)
53 await setDefaultAccountAvatar(servers)
54
49 const { data } = await servers[0].channels.list({ start: 0, count: 1 }) 55 const { data } = await servers[0].channels.list({ start: 0, count: 1 })
50 videoChannelId = data[0].id 56 videoChannelId = data[0].id
51 } 57 }
@@ -133,6 +139,22 @@ describe('Test multiple servers', function () {
133 139
134 await completeVideoCheck(server, video, checkAttributes) 140 await completeVideoCheck(server, video, checkAttributes)
135 publishedAt = video.publishedAt as string 141 publishedAt = video.publishedAt as string
142
143 expect(video.channel.avatars).to.have.lengthOf(2)
144 expect(video.account.avatars).to.have.lengthOf(2)
145
146 for (const image of [ ...video.channel.avatars, ...video.account.avatars ]) {
147 expect(image.createdAt).to.exist
148 expect(image.updatedAt).to.exist
149 expect(image.width).to.be.above(20).and.below(1000)
150 expect(image.path).to.exist
151
152 await makeGetRequest({
153 url: server.url,
154 path: image.path,
155 expectedStatus: HttpStatusCode.OK_200
156 })
157 }
136 } 158 }
137 }) 159 })
138 160
@@ -207,7 +229,7 @@ describe('Test multiple servers', function () {
207 }, 229 },
208 { 230 {
209 resolution: 720, 231 resolution: 720,
210 size: 788000 232 size: 750000
211 } 233 }
212 ], 234 ],
213 thumbnailfile: 'thumbnail', 235 thumbnailfile: 'thumbnail',
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts
index 28bf018c5..d37043aef 100644
--- a/server/tests/api/videos/single-server.ts
+++ b/server/tests/api/videos/single-server.ts
@@ -5,7 +5,14 @@ import * as chai from 'chai'
5import { checkVideoFilesWereRemoved, completeVideoCheck, testImage } from '@server/tests/shared' 5import { checkVideoFilesWereRemoved, completeVideoCheck, testImage } from '@server/tests/shared'
6import { wait } from '@shared/core-utils' 6import { wait } from '@shared/core-utils'
7import { Video, VideoPrivacy } from '@shared/models' 7import { Video, VideoPrivacy } from '@shared/models'
8import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' 8import {
9 cleanupTests,
10 createSingleServer,
11 PeerTubeServer,
12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultChannelAvatar
15} from '@shared/server-commands'
9 16
10const expect = chai.expect 17const expect = chai.expect
11 18
@@ -90,6 +97,8 @@ describe('Test a single server', function () {
90 server = await createSingleServer(1) 97 server = await createSingleServer(1)
91 98
92 await setAccessTokensToServers([ server ]) 99 await setAccessTokensToServers([ server ])
100 await setDefaultChannelAvatar(server)
101 await setDefaultAccountAvatar(server)
93 }) 102 })
94 103
95 it('Should list video categories', async function () { 104 it('Should list video categories', async function () {
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts
index d435f3682..0f8227fd3 100644
--- a/server/tests/api/videos/video-channels.ts
+++ b/server/tests/api/videos/video-channels.ts
@@ -6,13 +6,14 @@ import { basename } from 'path'
6import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants' 6import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants'
7import { testFileExistsOrNot, testImage } from '@server/tests/shared' 7import { testFileExistsOrNot, testImage } from '@server/tests/shared'
8import { wait } from '@shared/core-utils' 8import { wait } from '@shared/core-utils'
9import { User, VideoChannel } from '@shared/models' 9import { ActorImageType, User, VideoChannel } from '@shared/models'
10import { 10import {
11 cleanupTests, 11 cleanupTests,
12 createMultipleServers, 12 createMultipleServers,
13 doubleFollow, 13 doubleFollow,
14 PeerTubeServer, 14 PeerTubeServer,
15 setAccessTokensToServers, 15 setAccessTokensToServers,
16 setDefaultAccountAvatar,
16 setDefaultVideoChannel, 17 setDefaultVideoChannel,
17 waitJobs 18 waitJobs
18} from '@shared/server-commands' 19} from '@shared/server-commands'
@@ -44,6 +45,7 @@ describe('Test video channels', function () {
44 45
45 await setAccessTokensToServers(servers) 46 await setAccessTokensToServers(servers)
46 await setDefaultVideoChannel(servers) 47 await setDefaultVideoChannel(servers)
48 await setDefaultAccountAvatar(servers)
47 49
48 await doubleFollow(servers[0], servers[1]) 50 await doubleFollow(servers[0], servers[1])
49 }) 51 })
@@ -281,14 +283,19 @@ describe('Test video channels', function () {
281 283
282 for (const server of servers) { 284 for (const server of servers) {
283 const videoChannel = await findChannel(server, secondVideoChannelId) 285 const videoChannel = await findChannel(server, secondVideoChannelId)
286 const expectedSizes = ACTOR_IMAGES_SIZE[ActorImageType.AVATAR]
284 287
285 avatarPaths[server.port] = videoChannel.avatar.path 288 expect(videoChannel.avatars.length).to.equal(expectedSizes.length, 'Expected avatars to be generated in all sizes')
286 await testImage(server.url, 'avatar-resized', avatarPaths[server.port], '.png')
287 await testFileExistsOrNot(server, 'avatars', basename(avatarPaths[server.port]), true)
288 289
289 const row = await server.sql.getActorImage(basename(avatarPaths[server.port])) 290 for (const avatar of videoChannel.avatars) {
290 expect(row.height).to.equal(ACTOR_IMAGES_SIZE.AVATARS.height) 291 avatarPaths[server.port] = avatar.path
291 expect(row.width).to.equal(ACTOR_IMAGES_SIZE.AVATARS.width) 292 await testImage(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatarPaths[server.port], '.png')
293 await testFileExistsOrNot(server, 'avatars', basename(avatarPaths[server.port]), true)
294
295 const row = await server.sql.getActorImage(basename(avatarPaths[server.port]))
296
297 expect(expectedSizes.some(({ height, width }) => row.height === height && row.width === width)).to.equal(true)
298 }
292 } 299 }
293 }) 300 })
294 301
@@ -308,19 +315,18 @@ describe('Test video channels', function () {
308 for (const server of servers) { 315 for (const server of servers) {
309 const videoChannel = await server.channels.get({ channelName: 'second_video_channel@' + servers[0].host }) 316 const videoChannel = await server.channels.get({ channelName: 'second_video_channel@' + servers[0].host })
310 317
311 bannerPaths[server.port] = videoChannel.banner.path 318 bannerPaths[server.port] = videoChannel.banners[0].path
312 await testImage(server.url, 'banner-resized', bannerPaths[server.port]) 319 await testImage(server.url, 'banner-resized', bannerPaths[server.port])
313 await testFileExistsOrNot(server, 'avatars', basename(bannerPaths[server.port]), true) 320 await testFileExistsOrNot(server, 'avatars', basename(bannerPaths[server.port]), true)
314 321
315 const row = await server.sql.getActorImage(basename(bannerPaths[server.port])) 322 const row = await server.sql.getActorImage(basename(bannerPaths[server.port]))
316 expect(row.height).to.equal(ACTOR_IMAGES_SIZE.BANNERS.height) 323 expect(row.height).to.equal(ACTOR_IMAGES_SIZE[ActorImageType.BANNER][0].height)
317 expect(row.width).to.equal(ACTOR_IMAGES_SIZE.BANNERS.width) 324 expect(row.width).to.equal(ACTOR_IMAGES_SIZE[ActorImageType.BANNER][0].width)
318 } 325 }
319 }) 326 })
320 327
321 it('Should delete the video channel avatar', async function () { 328 it('Should delete the video channel avatar', async function () {
322 this.timeout(15000) 329 this.timeout(15000)
323
324 await servers[0].channels.deleteImage({ channelName: 'second_video_channel', type: 'avatar' }) 330 await servers[0].channels.deleteImage({ channelName: 'second_video_channel', type: 'avatar' })
325 331
326 await waitJobs(servers) 332 await waitJobs(servers)
@@ -329,7 +335,7 @@ describe('Test video channels', function () {
329 const videoChannel = await findChannel(server, secondVideoChannelId) 335 const videoChannel = await findChannel(server, secondVideoChannelId)
330 await testFileExistsOrNot(server, 'avatars', basename(avatarPaths[server.port]), false) 336 await testFileExistsOrNot(server, 'avatars', basename(avatarPaths[server.port]), false)
331 337
332 expect(videoChannel.avatar).to.be.null 338 expect(videoChannel.avatars).to.be.empty
333 } 339 }
334 }) 340 })
335 341
@@ -344,7 +350,7 @@ describe('Test video channels', function () {
344 const videoChannel = await findChannel(server, secondVideoChannelId) 350 const videoChannel = await findChannel(server, secondVideoChannelId)
345 await testFileExistsOrNot(server, 'avatars', basename(bannerPaths[server.port]), false) 351 await testFileExistsOrNot(server, 'avatars', basename(bannerPaths[server.port]), false)
346 352
347 expect(videoChannel.banner).to.be.null 353 expect(videoChannel.banners).to.be.empty
348 } 354 }
349 }) 355 })
350 356
diff --git a/server/tests/api/videos/video-comments.ts b/server/tests/api/videos/video-comments.ts
index 2ae523970..1488ce2b5 100644
--- a/server/tests/api/videos/video-comments.ts
+++ b/server/tests/api/videos/video-comments.ts
@@ -3,7 +3,15 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { dateIsValid, testImage } from '@server/tests/shared' 5import { dateIsValid, testImage } from '@server/tests/shared'
6import { cleanupTests, CommentsCommand, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' 6import {
7 cleanupTests,
8 CommentsCommand,
9 createSingleServer,
10 PeerTubeServer,
11 setAccessTokensToServers,
12 setDefaultAccountAvatar,
13 setDefaultChannelAvatar
14} from '@shared/server-commands'
7 15
8const expect = chai.expect 16const expect = chai.expect
9 17
@@ -29,7 +37,8 @@ describe('Test video comments', function () {
29 videoUUID = uuid 37 videoUUID = uuid
30 videoId = id 38 videoId = id
31 39
32 await server.users.updateMyAvatar({ fixture: 'avatar.png' }) 40 await setDefaultChannelAvatar(server)
41 await setDefaultAccountAvatar(server)
33 42
34 userAccessTokenServer1 = await server.users.generateUserAndToken('user1') 43 userAccessTokenServer1 = await server.users.generateUserAndToken('user1')
35 44
@@ -81,7 +90,9 @@ describe('Test video comments', function () {
81 expect(comment.account.name).to.equal('root') 90 expect(comment.account.name).to.equal('root')
82 expect(comment.account.host).to.equal('localhost:' + server.port) 91 expect(comment.account.host).to.equal('localhost:' + server.port)
83 92
84 await testImage(server.url, 'avatar-resized', comment.account.avatar.path, '.png') 93 for (const avatar of comment.account.avatars) {
94 await testImage(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, '.png')
95 }
85 96
86 expect(comment.totalReplies).to.equal(0) 97 expect(comment.totalReplies).to.equal(0)
87 expect(comment.totalRepliesFromVideoAuthor).to.equal(0) 98 expect(comment.totalRepliesFromVideoAuthor).to.equal(0)
diff --git a/server/tests/api/videos/video-playlist-thumbnails.ts b/server/tests/api/videos/video-playlist-thumbnails.ts
index 5fdb0fc03..3944dc344 100644
--- a/server/tests/api/videos/video-playlist-thumbnails.ts
+++ b/server/tests/api/videos/video-playlist-thumbnails.ts
@@ -45,12 +45,16 @@ describe('Playlist thumbnail', function () {
45 before(async function () { 45 before(async function () {
46 this.timeout(120000) 46 this.timeout(120000)
47 47
48 servers = await createMultipleServers(2, { transcoding: { enabled: false } }) 48 servers = await createMultipleServers(2)
49 49
50 // Get the access tokens 50 // Get the access tokens
51 await setAccessTokensToServers(servers) 51 await setAccessTokensToServers(servers)
52 await setDefaultVideoChannel(servers) 52 await setDefaultVideoChannel(servers)
53 53
54 for (const server of servers) {
55 await server.config.disableTranscoding()
56 }
57
54 // Server 1 and server 2 follow each other 58 // Server 1 and server 2 follow each other
55 await doubleFollow(servers[0], servers[1]) 59 await doubleFollow(servers[0], servers[1])
56 60
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts
index 34327334f..c33a63df0 100644
--- a/server/tests/api/videos/video-playlists.ts
+++ b/server/tests/api/videos/video-playlists.ts
@@ -20,6 +20,7 @@ import {
20 PeerTubeServer, 20 PeerTubeServer,
21 PlaylistsCommand, 21 PlaylistsCommand,
22 setAccessTokensToServers, 22 setAccessTokensToServers,
23 setDefaultAccountAvatar,
23 setDefaultVideoChannel, 24 setDefaultVideoChannel,
24 waitJobs 25 waitJobs
25} from '@shared/server-commands' 26} from '@shared/server-commands'
@@ -74,11 +75,16 @@ describe('Test video playlists', function () {
74 before(async function () { 75 before(async function () {
75 this.timeout(120000) 76 this.timeout(120000)
76 77
77 servers = await createMultipleServers(3, { transcoding: { enabled: false } }) 78 servers = await createMultipleServers(3)
78 79
79 // Get the access tokens 80 // Get the access tokens
80 await setAccessTokensToServers(servers) 81 await setAccessTokensToServers(servers)
81 await setDefaultVideoChannel(servers) 82 await setDefaultVideoChannel(servers)
83 await setDefaultAccountAvatar(servers)
84
85 for (const server of servers) {
86 await server.config.disableTranscoding()
87 }
82 88
83 // Server 1 and server 2 follow each other 89 // Server 1 and server 2 follow each other
84 await doubleFollow(servers[0], servers[1]) 90 await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/api/videos/videos-common-filters.ts b/server/tests/api/videos/videos-common-filters.ts
index 0254662c5..317de90a9 100644
--- a/server/tests/api/videos/videos-common-filters.ts
+++ b/server/tests/api/videos/videos-common-filters.ts
@@ -3,6 +3,7 @@
3import 'mocha' 3import 'mocha'
4import { expect } from 'chai' 4import { expect } from 'chai'
5import { pick } from '@shared/core-utils' 5import { pick } from '@shared/core-utils'
6import { HttpStatusCode, UserRole, Video, VideoDetails, VideoInclude, VideoPrivacy } from '@shared/models'
6import { 7import {
7 cleanupTests, 8 cleanupTests,
8 createMultipleServers, 9 createMultipleServers,
@@ -10,10 +11,10 @@ import {
10 makeGetRequest, 11 makeGetRequest,
11 PeerTubeServer, 12 PeerTubeServer,
12 setAccessTokensToServers, 13 setAccessTokensToServers,
14 setDefaultAccountAvatar,
13 setDefaultVideoChannel, 15 setDefaultVideoChannel,
14 waitJobs 16 waitJobs
15} from '@shared/server-commands' 17} from '@shared/server-commands'
16import { HttpStatusCode, UserRole, Video, VideoDetails, VideoInclude, VideoPrivacy } from '@shared/models'
17 18
18describe('Test videos filter', function () { 19describe('Test videos filter', function () {
19 let servers: PeerTubeServer[] 20 let servers: PeerTubeServer[]
@@ -29,6 +30,7 @@ describe('Test videos filter', function () {
29 30
30 await setAccessTokensToServers(servers) 31 await setAccessTokensToServers(servers)
31 await setDefaultVideoChannel(servers) 32 await setDefaultVideoChannel(servers)
33 await setDefaultAccountAvatar(servers)
32 34
33 for (const server of servers) { 35 for (const server of servers) {
34 const moderator = { username: 'moderator', password: 'my super password' } 36 const moderator = { username: 'moderator', password: 'my super password' }
diff --git a/server/tests/cli/prune-storage.ts b/server/tests/cli/prune-storage.ts
index a723ed8b4..3ca7c19ea 100644
--- a/server/tests/cli/prune-storage.ts
+++ b/server/tests/cli/prune-storage.ts
@@ -51,7 +51,7 @@ async function assertCountAreOkay (servers: PeerTubeServer[]) {
51 expect(thumbnailsCount).to.equal(6) 51 expect(thumbnailsCount).to.equal(6)
52 52
53 const avatarsCount = await countFiles(server, 'avatars') 53 const avatarsCount = await countFiles(server, 'avatars')
54 expect(avatarsCount).to.equal(2) 54 expect(avatarsCount).to.equal(4)
55 55
56 const hlsRootCount = await countFiles(server, 'streaming-playlists/hls') 56 const hlsRootCount = await countFiles(server, 'streaming-playlists/hls')
57 expect(hlsRootCount).to.equal(2) 57 expect(hlsRootCount).to.equal(2)
@@ -87,23 +87,28 @@ describe('Test prune storage scripts', function () {
87 87
88 await doubleFollow(servers[0], servers[1]) 88 await doubleFollow(servers[0], servers[1])
89 89
90 // Lazy load the remote avatar 90 // Lazy load the remote avatars
91 { 91 {
92 const account = await servers[0].accounts.get({ accountName: 'root@localhost:' + servers[1].port }) 92 const account = await servers[0].accounts.get({ accountName: 'root@localhost:' + servers[1].port })
93 await makeGetRequest({ 93
94 url: servers[0].url, 94 for (const avatar of account.avatars) {
95 path: account.avatar.path, 95 await makeGetRequest({
96 expectedStatus: HttpStatusCode.OK_200 96 url: servers[0].url,
97 }) 97 path: avatar.path,
98 expectedStatus: HttpStatusCode.OK_200
99 })
100 }
98 } 101 }
99 102
100 { 103 {
101 const account = await servers[1].accounts.get({ accountName: 'root@localhost:' + servers[0].port }) 104 const account = await servers[1].accounts.get({ accountName: 'root@localhost:' + servers[0].port })
102 await makeGetRequest({ 105 for (const avatar of account.avatars) {
103 url: servers[1].url, 106 await makeGetRequest({
104 path: account.avatar.path, 107 url: servers[1].url,
105 expectedStatus: HttpStatusCode.OK_200 108 path: avatar.path,
106 }) 109 expectedStatus: HttpStatusCode.OK_200
110 })
111 }
107 } 112 }
108 113
109 await wait(1000) 114 await wait(1000)
diff --git a/server/tests/cli/update-host.ts b/server/tests/cli/update-host.ts
index da89ff153..7c49efd20 100644
--- a/server/tests/cli/update-host.ts
+++ b/server/tests/cli/update-host.ts
@@ -12,6 +12,7 @@ import {
12 setAccessTokensToServers, 12 setAccessTokensToServers,
13 waitJobs 13 waitJobs
14} from '@shared/server-commands' 14} from '@shared/server-commands'
15import { getAllFiles } from '../shared'
15 16
16describe('Test update host scripts', function () { 17describe('Test update host scripts', function () {
17 let server: PeerTubeServer 18 let server: PeerTubeServer
@@ -108,7 +109,7 @@ describe('Test update host scripts', function () {
108 109
109 for (const video of data) { 110 for (const video of data) {
110 const videoDetails = await server.videos.get({ id: video.id }) 111 const videoDetails = await server.videos.get({ id: video.id })
111 const files = videoDetails.files.concat(videoDetails.streamingPlaylists[0].files) 112 const files = getAllFiles(videoDetails)
112 113
113 expect(files).to.have.lengthOf(8) 114 expect(files).to.have.lengthOf(8)
114 115
diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts
index 4dcd77cca..320dc3333 100644
--- a/server/tests/feeds/feeds.ts
+++ b/server/tests/feeds/feeds.ts
@@ -3,6 +3,7 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { XMLParser, XMLValidator } from 'fast-xml-parser' 5import { XMLParser, XMLValidator } from 'fast-xml-parser'
6import { HttpStatusCode, VideoPrivacy } from '@shared/models'
6import { 7import {
7 cleanupTests, 8 cleanupTests,
8 createMultipleServers, 9 createMultipleServers,
@@ -11,9 +12,9 @@ import {
11 makeGetRequest, 12 makeGetRequest,
12 PeerTubeServer, 13 PeerTubeServer,
13 setAccessTokensToServers, 14 setAccessTokensToServers,
15 setDefaultChannelAvatar,
14 waitJobs 16 waitJobs
15} from '@shared/server-commands' 17} from '@shared/server-commands'
16import { HttpStatusCode, VideoPrivacy } from '@shared/models'
17 18
18chai.use(require('chai-xml')) 19chai.use(require('chai-xml'))
19chai.use(require('chai-json-schema')) 20chai.use(require('chai-json-schema'))
@@ -44,6 +45,7 @@ describe('Test syndication feeds', () => {
44 }) 45 })
45 46
46 await setAccessTokensToServers([ ...servers, serverHLSOnly ]) 47 await setAccessTokensToServers([ ...servers, serverHLSOnly ])
48 await setDefaultChannelAvatar(servers[0])
47 await doubleFollow(servers[0], servers[1]) 49 await doubleFollow(servers[0], servers[1])
48 50
49 { 51 {
diff --git a/server/tests/fixtures/avatar-resized.gif b/server/tests/fixtures/avatar-resized-120x120.gif
index 81a82189e..81a82189e 100644
--- a/server/tests/fixtures/avatar-resized.gif
+++ b/server/tests/fixtures/avatar-resized-120x120.gif
Binary files differ
diff --git a/server/tests/fixtures/avatar-resized.png b/server/tests/fixtures/avatar-resized-120x120.png
index 9d84151f8..9d84151f8 100644
--- a/server/tests/fixtures/avatar-resized.png
+++ b/server/tests/fixtures/avatar-resized-120x120.png
Binary files differ
diff --git a/server/tests/fixtures/avatar-resized-48x48.gif b/server/tests/fixtures/avatar-resized-48x48.gif
new file mode 100644
index 000000000..5900ff12e
--- /dev/null
+++ b/server/tests/fixtures/avatar-resized-48x48.gif
Binary files differ
diff --git a/server/tests/fixtures/avatar-resized-48x48.png b/server/tests/fixtures/avatar-resized-48x48.png
new file mode 100644
index 000000000..9e5f3b490
--- /dev/null
+++ b/server/tests/fixtures/avatar-resized-48x48.png
Binary files differ
diff --git a/server/tests/fixtures/avatar2-resized.png b/server/tests/fixtures/avatar2-resized-120x120.png
index 44149facb..44149facb 100644
--- a/server/tests/fixtures/avatar2-resized.png
+++ b/server/tests/fixtures/avatar2-resized-120x120.png
Binary files differ
diff --git a/server/tests/fixtures/avatar2-resized-48x48.png b/server/tests/fixtures/avatar2-resized-48x48.png
new file mode 100644
index 000000000..bb3939b1a
--- /dev/null
+++ b/server/tests/fixtures/avatar2-resized-48x48.png
Binary files differ
diff --git a/server/tests/fixtures/peertube-plugin-test/main.js b/server/tests/fixtures/peertube-plugin-test/main.js
index 90951d611..7715ab6e8 100644
--- a/server/tests/fixtures/peertube-plugin-test/main.js
+++ b/server/tests/fixtures/peertube-plugin-test/main.js
@@ -45,6 +45,16 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
45 }) 45 })
46 46
47 registerHook({ 47 registerHook({
48 target: 'filter:api.video-playlist.videos.list.params',
49 handler: obj => addToCount(obj)
50 })
51
52 registerHook({
53 target: 'filter:api.video-playlist.videos.list.result',
54 handler: obj => addToTotal(obj)
55 })
56
57 registerHook({
48 target: 'filter:api.accounts.videos.list.params', 58 target: 'filter:api.accounts.videos.list.params',
49 handler: obj => addToCount(obj) 59 handler: obj => addToCount(obj)
50 }) 60 })
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
index 52ba396e5..e0f25ca26 100644
--- a/server/tests/plugins/filter-hooks.ts
+++ b/server/tests/plugins/filter-hooks.ts
@@ -22,6 +22,7 @@ describe('Test plugin filter hooks', function () {
22 let servers: PeerTubeServer[] 22 let servers: PeerTubeServer[]
23 let videoUUID: string 23 let videoUUID: string
24 let threadId: number 24 let threadId: number
25 let videoPlaylistUUID: string
25 26
26 before(async function () { 27 before(async function () {
27 this.timeout(60000) 28 this.timeout(60000)
@@ -33,9 +34,20 @@ describe('Test plugin filter hooks', function () {
33 34
34 await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() }) 35 await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() })
35 await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') }) 36 await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
37 {
38 ({ uuid: videoPlaylistUUID } = await servers[0].playlists.create({
39 attributes: {
40 displayName: 'my super playlist',
41 privacy: VideoPlaylistPrivacy.PUBLIC,
42 description: 'my super description',
43 videoChannelId: servers[0].store.channel.id
44 }
45 }))
46 }
36 47
37 for (let i = 0; i < 10; i++) { 48 for (let i = 0; i < 10; i++) {
38 await servers[0].videos.upload({ attributes: { name: 'default video ' + i } }) 49 const video = await servers[0].videos.upload({ attributes: { name: 'default video ' + i } })
50 await servers[0].playlists.addElement({ playlistId: videoPlaylistUUID, attributes: { videoId: video.id } })
39 } 51 }
40 52
41 const { data } = await servers[0].videos.list() 53 const { data } = await servers[0].videos.list()
@@ -69,6 +81,26 @@ describe('Test plugin filter hooks', function () {
69 expect(total).to.equal(11) 81 expect(total).to.equal(11)
70 }) 82 })
71 83
84 it('Should run filter:api.video-playlist.videos.list.params', async function () {
85 const { data } = await servers[0].playlists.listVideos({
86 count: 2,
87 playlistId: videoPlaylistUUID
88 })
89
90 // 1 plugin do +1 to the count parameter
91 expect(data).to.have.lengthOf(3)
92 })
93
94 it('Should run filter:api.video-playlist.videos.list.result', async function () {
95 const { total } = await servers[0].playlists.listVideos({
96 count: 0,
97 playlistId: videoPlaylistUUID
98 })
99
100 // Plugin do +1 to the total result
101 expect(total).to.equal(11)
102 })
103
72 it('Should run filter:api.accounts.videos.list.params', async function () { 104 it('Should run filter:api.accounts.videos.list.params', async function () {
73 const { data } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 }) 105 const { data } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
74 106
@@ -410,13 +442,7 @@ describe('Test plugin filter hooks', function () {
410 before(async function () { 442 before(async function () {
411 this.timeout(60000) 443 this.timeout(60000)
412 444
413 await servers[0].config.updateCustomSubConfig({ 445 await servers[0].config.disableTranscoding()
414 newConfig: {
415 transcoding: {
416 enabled: false
417 }
418 }
419 })
420 446
421 for (const name of [ 'bad embed', 'good embed' ]) { 447 for (const name of [ 'bad embed', 'good embed' ]) {
422 { 448 {
diff --git a/server/tests/plugins/plugin-transcoding.ts b/server/tests/plugins/plugin-transcoding.ts
index 5ab686472..49569f1fa 100644
--- a/server/tests/plugins/plugin-transcoding.ts
+++ b/server/tests/plugins/plugin-transcoding.ts
@@ -2,7 +2,8 @@
2 2
3import 'mocha' 3import 'mocha'
4import { expect } from 'chai' 4import { expect } from 'chai'
5import { getAudioStream, getVideoFileFPS, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils' 5import { getAudioStream, getVideoStreamFPS, getVideoStream } from '@server/helpers/ffmpeg'
6import { VideoPrivacy } from '@shared/models'
6import { 7import {
7 cleanupTests, 8 cleanupTests,
8 createSingleServer, 9 createSingleServer,
@@ -13,7 +14,6 @@ import {
13 testFfmpegStreamError, 14 testFfmpegStreamError,
14 waitJobs 15 waitJobs
15} from '@shared/server-commands' 16} from '@shared/server-commands'
16import { VideoPrivacy } from '@shared/models'
17 17
18async function createLiveWrapper (server: PeerTubeServer) { 18async function createLiveWrapper (server: PeerTubeServer) {
19 const liveAttributes = { 19 const liveAttributes = {
@@ -92,7 +92,7 @@ describe('Test transcoding plugins', function () {
92 92
93 async function checkLiveFPS (uuid: string, type: 'above' | 'below', fps: number) { 93 async function checkLiveFPS (uuid: string, type: 'above' | 'below', fps: number) {
94 const playlistUrl = `${server.url}/static/streaming-playlists/hls/${uuid}/0.m3u8` 94 const playlistUrl = `${server.url}/static/streaming-playlists/hls/${uuid}/0.m3u8`
95 const videoFPS = await getVideoFileFPS(playlistUrl) 95 const videoFPS = await getVideoStreamFPS(playlistUrl)
96 96
97 if (type === 'above') { 97 if (type === 'above') {
98 expect(videoFPS).to.be.above(fps) 98 expect(videoFPS).to.be.above(fps)
@@ -252,7 +252,7 @@ describe('Test transcoding plugins', function () {
252 const audioProbe = await getAudioStream(path) 252 const audioProbe = await getAudioStream(path)
253 expect(audioProbe.audioStream.codec_name).to.equal('opus') 253 expect(audioProbe.audioStream.codec_name).to.equal('opus')
254 254
255 const videoProbe = await getVideoStreamFromFile(path) 255 const videoProbe = await getVideoStream(path)
256 expect(videoProbe.codec_name).to.equal('vp9') 256 expect(videoProbe.codec_name).to.equal('vp9')
257 }) 257 })
258 258
@@ -269,7 +269,7 @@ describe('Test transcoding plugins', function () {
269 const audioProbe = await getAudioStream(playlistUrl) 269 const audioProbe = await getAudioStream(playlistUrl)
270 expect(audioProbe.audioStream.codec_name).to.equal('opus') 270 expect(audioProbe.audioStream.codec_name).to.equal('opus')
271 271
272 const videoProbe = await getVideoStreamFromFile(playlistUrl) 272 const videoProbe = await getVideoStream(playlistUrl)
273 expect(videoProbe.codec_name).to.equal('h264') 273 expect(videoProbe.codec_name).to.equal('h264')
274 }) 274 })
275 }) 275 })
diff --git a/server/tests/shared/generate.ts b/server/tests/shared/generate.ts
index f806df2f5..9a57084e4 100644
--- a/server/tests/shared/generate.ts
+++ b/server/tests/shared/generate.ts
@@ -3,12 +3,12 @@ import ffmpeg from 'fluent-ffmpeg'
3import { ensureDir, pathExists } from 'fs-extra' 3import { ensureDir, pathExists } from 'fs-extra'
4import { dirname } from 'path' 4import { dirname } from 'path'
5import { buildAbsoluteFixturePath, getMaxBitrate } from '@shared/core-utils' 5import { buildAbsoluteFixturePath, getMaxBitrate } from '@shared/core-utils'
6import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '@shared/extra-utils' 6import { getVideoStreamBitrate, getVideoStreamFPS, getVideoStreamDimensionsInfo } from '@shared/extra-utils'
7 7
8async function ensureHasTooBigBitrate (fixturePath: string) { 8async function ensureHasTooBigBitrate (fixturePath: string) {
9 const bitrate = await getVideoFileBitrate(fixturePath) 9 const bitrate = await getVideoStreamBitrate(fixturePath)
10 const dataResolution = await getVideoFileResolution(fixturePath) 10 const dataResolution = await getVideoStreamDimensionsInfo(fixturePath)
11 const fps = await getVideoFileFPS(fixturePath) 11 const fps = await getVideoStreamFPS(fixturePath)
12 12
13 const maxBitrate = getMaxBitrate({ ...dataResolution, fps }) 13 const maxBitrate = getMaxBitrate({ ...dataResolution, fps })
14 expect(bitrate).to.be.above(maxBitrate) 14 expect(bitrate).to.be.above(maxBitrate)
diff --git a/server/tests/shared/notifications.ts b/server/tests/shared/notifications.ts
index cdc21fdc8..78d3787f0 100644
--- a/server/tests/shared/notifications.ts
+++ b/server/tests/shared/notifications.ts
@@ -10,7 +10,14 @@ import {
10 UserNotificationSettingValue, 10 UserNotificationSettingValue,
11 UserNotificationType 11 UserNotificationType
12} from '@shared/models' 12} from '@shared/models'
13import { createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' 13import {
14 createMultipleServers,
15 doubleFollow,
16 PeerTubeServer,
17 setAccessTokensToServers,
18 setDefaultAccountAvatar,
19 setDefaultChannelAvatar
20} from '@shared/server-commands'
14import { MockSmtpServer } from './mock-servers' 21import { MockSmtpServer } from './mock-servers'
15 22
16type CheckerBaseParams = { 23type CheckerBaseParams = {
@@ -646,6 +653,8 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
646 const servers = await createMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg)) 653 const servers = await createMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg))
647 654
648 await setAccessTokensToServers(servers) 655 await setAccessTokensToServers(servers)
656 await setDefaultChannelAvatar(servers)
657 await setDefaultAccountAvatar(servers)
649 658
650 if (serversCount > 1) { 659 if (serversCount > 1) {
651 await doubleFollow(servers[0], servers[1]) 660 await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/shared/videos.ts b/server/tests/shared/videos.ts
index 6be094f2b..989865a49 100644
--- a/server/tests/shared/videos.ts
+++ b/server/tests/shared/videos.ts
@@ -240,6 +240,16 @@ async function uploadRandomVideoOnServers (
240 return res 240 return res
241} 241}
242 242
243function getAllFiles (video: VideoDetails) {
244 const files = video.files
245
246 if (video.streamingPlaylists[0]) {
247 return files.concat(video.streamingPlaylists[0].files)
248 }
249
250 return files
251}
252
243// --------------------------------------------------------------------------- 253// ---------------------------------------------------------------------------
244 254
245export { 255export {
@@ -247,5 +257,6 @@ export {
247 checkUploadVideoParam, 257 checkUploadVideoParam,
248 uploadRandomVideoOnServers, 258 uploadRandomVideoOnServers,
249 checkVideoFilesWereRemoved, 259 checkVideoFilesWereRemoved,
250 saveVideoInServers 260 saveVideoInServers,
261 getAllFiles
251} 262}