Bufferize videos views in redis
[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 '../../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')
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 update a video', async function () {
343     const attributes = {
344       name: 'my super video updated',
345       category: 4,
346       licence: 2,
347       language: 'ar',
348       nsfw: false,
349       description: 'my super description updated',
350       commentsEnabled: false,
351       tags: [ 'tagup1', 'tagup2' ]
352     }
353     await updateVideo(server.url, server.accessToken, videoId, attributes)
354   })
355
356   it('Should filter by tags and category', async function () {
357     const res1 = await getVideosWithFilters(server.url, { tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: 4 })
358     expect(res1.body.total).to.equal(1)
359     expect(res1.body.data[0].name).to.equal('my super video updated')
360
361     const res2 = await getVideosWithFilters(server.url, { tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: 3 })
362     expect(res2.body.total).to.equal(0)
363   })
364
365   it('Should have the video updated', async function () {
366     this.timeout(60000)
367
368     const res = await getVideo(server.url, videoId)
369     const video = res.body
370
371     await completeVideoCheck(server.url, video, updateCheckAttributes)
372   })
373
374   it('Should update only the tags of a video', async function () {
375     const attributes = {
376       tags: [ 'supertag', 'tag1', 'tag2' ]
377     }
378     await updateVideo(server.url, server.accessToken, videoId, attributes)
379
380     const res = await getVideo(server.url, videoId)
381     const video = res.body
382
383     await completeVideoCheck(server.url, video, Object.assign(updateCheckAttributes, attributes))
384   })
385
386   it('Should update only the description of a video', async function () {
387     const attributes = {
388       description: 'hello everybody'
389     }
390     await updateVideo(server.url, server.accessToken, videoId, attributes)
391
392     const res = await getVideo(server.url, videoId)
393     const video = res.body
394
395     await completeVideoCheck(server.url, video, Object.assign(updateCheckAttributes, attributes))
396   })
397
398   it('Should like a video', async function () {
399     await rateVideo(server.url, server.accessToken, videoId, 'like')
400
401     const res = await getVideo(server.url, videoId)
402     const video = res.body
403
404     expect(video.likes).to.equal(1)
405     expect(video.dislikes).to.equal(0)
406   })
407
408   it('Should dislike the same video', async function () {
409     await rateVideo(server.url, server.accessToken, videoId, 'dislike')
410
411     const res = await getVideo(server.url, videoId)
412     const video = res.body
413
414     expect(video.likes).to.equal(0)
415     expect(video.dislikes).to.equal(1)
416   })
417
418   after(async function () {
419     killallServers([ server ])
420
421     // Keep the logs if the test failed
422     if (this['ok']) {
423       await flushTests()
424     }
425   })
426 })