Merge branch 'release/v1.2.0'
[oweals/peertube.git] / server / tests / api / videos / single-server.ts
1 /* tslint:disable:no-unused-expression */
2
3 import * as chai from 'chai'
4 import { keyBy } from 'lodash'
5 import 'mocha'
6 import { VideoPrivacy } from '../../../../shared/models/videos'
7 import {
8   checkVideoFilesWereRemoved,
9   completeVideoCheck,
10   flushTests,
11   getVideo,
12   getVideoCategories,
13   getVideoLanguages,
14   getVideoLicences,
15   getVideoPrivacies,
16   getVideosList,
17   getVideosListPagination,
18   getVideosListSort,
19   getVideosWithFilters,
20   killallServers,
21   rateVideo,
22   removeVideo,
23   runServer,
24   ServerInfo,
25   setAccessTokensToServers,
26   testImage,
27   updateVideo,
28   uploadVideo,
29   viewVideo,
30   wait
31 } from '../../../../shared/utils'
32
33 const expect = chai.expect
34
35 describe('Test a single server', function () {
36   let server: ServerInfo = null
37   let videoId = -1
38   let videoUUID = ''
39   let videosListBase: any[] = null
40
41   const getCheckAttributes = {
42     name: 'my super name',
43     category: 2,
44     licence: 6,
45     language: 'zh',
46     nsfw: true,
47     description: 'my super description',
48     support: 'my super support text',
49     account: {
50       name: 'root',
51       host: 'localhost:9001'
52     },
53     isLocal: true,
54     duration: 5,
55     tags: [ 'tag1', 'tag2', 'tag3' ],
56     privacy: VideoPrivacy.PUBLIC,
57     commentsEnabled: true,
58     channel: {
59       displayName: 'Main root channel',
60       name: 'root_channel',
61       description: '',
62       isLocal: true
63     },
64     fixture: 'video_short.webm',
65     files: [
66       {
67         resolution: 720,
68         size: 218910
69       }
70     ]
71   }
72
73   const updateCheckAttributes = {
74     name: 'my super video updated',
75     category: 4,
76     licence: 2,
77     language: 'ar',
78     nsfw: false,
79     description: 'my super description updated',
80     support: 'my super support text updated',
81     account: {
82       name: 'root',
83       host: 'localhost:9001'
84     },
85     isLocal: true,
86     tags: [ 'tagup1', 'tagup2' ],
87     privacy: VideoPrivacy.PUBLIC,
88     duration: 5,
89     commentsEnabled: false,
90     channel: {
91       name: 'root_channel',
92       displayName: 'Main root channel',
93       description: '',
94       isLocal: true
95     },
96     fixture: 'video_short3.webm',
97     files: [
98       {
99         resolution: 720,
100         size: 292677
101       }
102     ]
103   }
104
105   before(async function () {
106     this.timeout(30000)
107
108     await flushTests()
109
110     server = await runServer(1)
111
112     await setAccessTokensToServers([ server ])
113   })
114
115   it('Should list video categories', async function () {
116     const res = await getVideoCategories(server.url)
117
118     const categories = res.body
119     expect(Object.keys(categories)).to.have.length.above(10)
120
121     expect(categories[11]).to.equal('News & Politics')
122   })
123
124   it('Should list video licences', async function () {
125     const res = await getVideoLicences(server.url)
126
127     const licences = res.body
128     expect(Object.keys(licences)).to.have.length.above(5)
129
130     expect(licences[3]).to.equal('Attribution - No Derivatives')
131   })
132
133   it('Should list video languages', async function () {
134     const res = await getVideoLanguages(server.url)
135
136     const languages = res.body
137     expect(Object.keys(languages)).to.have.length.above(5)
138
139     expect(languages['ru']).to.equal('Russian')
140   })
141
142   it('Should list video privacies', async function () {
143     const res = await getVideoPrivacies(server.url)
144
145     const privacies = res.body
146     expect(Object.keys(privacies)).to.have.length.at.least(3)
147
148     expect(privacies[3]).to.equal('Private')
149   })
150
151   it('Should not have videos', async function () {
152     const res = await getVideosList(server.url)
153
154     expect(res.body.total).to.equal(0)
155     expect(res.body.data).to.be.an('array')
156     expect(res.body.data.length).to.equal(0)
157   })
158
159   it('Should upload the video', async function () {
160     const videoAttributes = {
161       name: 'my super name',
162       category: 2,
163       nsfw: true,
164       licence: 6,
165       tags: [ 'tag1', 'tag2', 'tag3' ]
166     }
167     const res = await uploadVideo(server.url, server.accessToken, videoAttributes)
168     expect(res.body.video).to.not.be.undefined
169     expect(res.body.video.id).to.equal(1)
170     expect(res.body.video.uuid).to.have.length.above(5)
171
172     videoId = res.body.video.id
173     videoUUID = res.body.video.uuid
174   })
175
176   it('Should get and seed the uploaded video', async function () {
177     this.timeout(5000)
178
179     const res = await getVideosList(server.url)
180
181     expect(res.body.total).to.equal(1)
182     expect(res.body.data).to.be.an('array')
183     expect(res.body.data.length).to.equal(1)
184
185     const video = res.body.data[0]
186     await completeVideoCheck(server.url, video, getCheckAttributes)
187   })
188
189   it('Should get the video by UUID', async function () {
190     this.timeout(5000)
191
192     const res = await getVideo(server.url, videoUUID)
193
194     const video = res.body
195     await completeVideoCheck(server.url, video, getCheckAttributes)
196   })
197
198   it('Should have the views updated', async function () {
199     this.timeout(20000)
200
201     await viewVideo(server.url, videoId)
202     await viewVideo(server.url, videoId)
203     await viewVideo(server.url, videoId)
204
205     await wait(1500)
206
207     await viewVideo(server.url, videoId)
208     await viewVideo(server.url, videoId)
209
210     await wait(1500)
211
212     await viewVideo(server.url, videoId)
213     await viewVideo(server.url, videoId)
214
215     // Wait the repeatable job
216     await wait(8000)
217
218     const res = await getVideo(server.url, videoId)
219
220     const video = res.body
221     expect(video.views).to.equal(3)
222   })
223
224   it('Should remove the video', async function () {
225     await removeVideo(server.url, server.accessToken, videoId)
226
227     await checkVideoFilesWereRemoved(videoUUID, 1)
228   })
229
230   it('Should not have videos', async function () {
231     const res = await getVideosList(server.url)
232
233     expect(res.body.total).to.equal(0)
234     expect(res.body.data).to.be.an('array')
235     expect(res.body.data).to.have.lengthOf(0)
236   })
237
238   it('Should upload 6 videos', async function () {
239     this.timeout(25000)
240
241     const videos = [
242       'video_short.mp4', 'video_short.ogv', 'video_short.webm',
243       'video_short1.webm', 'video_short2.webm', 'video_short3.webm'
244     ]
245
246     const tasks: Promise<any>[] = []
247     for (const video of videos) {
248       const videoAttributes = {
249         name: video + ' name',
250         description: video + ' description',
251         category: 2,
252         licence: 1,
253         language: 'en',
254         nsfw: true,
255         tags: [ 'tag1', 'tag2', 'tag3' ],
256         fixture: video
257       }
258
259       const p = uploadVideo(server.url, server.accessToken, videoAttributes)
260       tasks.push(p)
261     }
262
263     await Promise.all(tasks)
264   })
265
266   it('Should have the correct durations', async function () {
267     const res = await getVideosList(server.url)
268
269     expect(res.body.total).to.equal(6)
270     const videos = res.body.data
271     expect(videos).to.be.an('array')
272     expect(videos).to.have.lengthOf(6)
273
274     const videosByName = keyBy<{ duration: number }>(videos, 'name')
275     expect(videosByName['video_short.mp4 name'].duration).to.equal(5)
276     expect(videosByName['video_short.ogv name'].duration).to.equal(5)
277     expect(videosByName['video_short.webm name'].duration).to.equal(5)
278     expect(videosByName['video_short1.webm name'].duration).to.equal(10)
279     expect(videosByName['video_short2.webm name'].duration).to.equal(5)
280     expect(videosByName['video_short3.webm name'].duration).to.equal(5)
281   })
282
283   it('Should have the correct thumbnails', async function () {
284     const res = await getVideosList(server.url)
285
286     const videos = res.body.data
287     // For the next test
288     videosListBase = videos
289
290     for (const video of videos) {
291       const videoName = video.name.replace(' name', '')
292       await testImage(server.url, videoName, video.thumbnailPath)
293     }
294   })
295
296   it('Should list only the two first videos', async function () {
297     const res = await getVideosListPagination(server.url, 0, 2, 'name')
298
299     const videos = res.body.data
300     expect(res.body.total).to.equal(6)
301     expect(videos.length).to.equal(2)
302     expect(videos[0].name).to.equal(videosListBase[0].name)
303     expect(videos[1].name).to.equal(videosListBase[1].name)
304   })
305
306   it('Should list only the next three videos', async function () {
307     const res = await getVideosListPagination(server.url, 2, 3, 'name')
308
309     const videos = res.body.data
310     expect(res.body.total).to.equal(6)
311     expect(videos.length).to.equal(3)
312     expect(videos[0].name).to.equal(videosListBase[2].name)
313     expect(videos[1].name).to.equal(videosListBase[3].name)
314     expect(videos[2].name).to.equal(videosListBase[4].name)
315   })
316
317   it('Should list the last video', async function () {
318     const res = await getVideosListPagination(server.url, 5, 6, 'name')
319
320     const videos = res.body.data
321     expect(res.body.total).to.equal(6)
322     expect(videos.length).to.equal(1)
323     expect(videos[0].name).to.equal(videosListBase[5].name)
324   })
325
326   it('Should list and sort by name in descending order', async function () {
327     const res = await getVideosListSort(server.url, '-name')
328
329     const videos = res.body.data
330     expect(res.body.total).to.equal(6)
331     expect(videos.length).to.equal(6)
332     expect(videos[0].name).to.equal('video_short.webm name')
333     expect(videos[1].name).to.equal('video_short.ogv name')
334     expect(videos[2].name).to.equal('video_short.mp4 name')
335     expect(videos[3].name).to.equal('video_short3.webm name')
336     expect(videos[4].name).to.equal('video_short2.webm name')
337     expect(videos[5].name).to.equal('video_short1.webm name')
338
339     videoId = videos[3].uuid
340   })
341
342   it('Should list and sort by trending in descending order', async function () {
343     const res = await getVideosListPagination(server.url, 0, 2, '-trending')
344
345     const videos = res.body.data
346     expect(res.body.total).to.equal(6)
347     expect(videos.length).to.equal(2)
348   })
349
350   it('Should update a video', async function () {
351     const attributes = {
352       name: 'my super video updated',
353       category: 4,
354       licence: 2,
355       language: 'ar',
356       nsfw: false,
357       description: 'my super description updated',
358       commentsEnabled: false,
359       tags: [ 'tagup1', 'tagup2' ]
360     }
361     await updateVideo(server.url, server.accessToken, videoId, attributes)
362   })
363
364   it('Should filter by tags and category', async function () {
365     const res1 = await getVideosWithFilters(server.url, { tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: 4 })
366     expect(res1.body.total).to.equal(1)
367     expect(res1.body.data[0].name).to.equal('my super video updated')
368
369     const res2 = await getVideosWithFilters(server.url, { tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: 3 })
370     expect(res2.body.total).to.equal(0)
371   })
372
373   it('Should have the video updated', async function () {
374     this.timeout(60000)
375
376     const res = await getVideo(server.url, videoId)
377     const video = res.body
378
379     await completeVideoCheck(server.url, video, updateCheckAttributes)
380   })
381
382   it('Should update only the tags of a video', async function () {
383     const attributes = {
384       tags: [ 'supertag', 'tag1', 'tag2' ]
385     }
386     await updateVideo(server.url, server.accessToken, videoId, attributes)
387
388     const res = await getVideo(server.url, videoId)
389     const video = res.body
390
391     await completeVideoCheck(server.url, video, Object.assign(updateCheckAttributes, attributes))
392   })
393
394   it('Should update only the description of a video', async function () {
395     const attributes = {
396       description: 'hello everybody'
397     }
398     await updateVideo(server.url, server.accessToken, videoId, attributes)
399
400     const res = await getVideo(server.url, videoId)
401     const video = res.body
402
403     await completeVideoCheck(server.url, video, Object.assign(updateCheckAttributes, attributes))
404   })
405
406   it('Should like a video', async function () {
407     await rateVideo(server.url, server.accessToken, videoId, 'like')
408
409     const res = await getVideo(server.url, videoId)
410     const video = res.body
411
412     expect(video.likes).to.equal(1)
413     expect(video.dislikes).to.equal(0)
414   })
415
416   it('Should dislike the same video', async function () {
417     await rateVideo(server.url, server.accessToken, videoId, 'dislike')
418
419     const res = await getVideo(server.url, videoId)
420     const video = res.body
421
422     expect(video.likes).to.equal(0)
423     expect(video.dislikes).to.equal(1)
424   })
425
426   after(async function () {
427     killallServers([ server ])
428
429     // Keep the logs if the test failed
430     if (this['ok']) {
431       await flushTests()
432     }
433   })
434 })