Avoids easy cheating on vidoe views
[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, completeVideoCheck, flushTests, getVideo, getVideoCategories, getVideoLanguages, getVideoLicences,
9   getVideoPrivacies, getVideosList, getVideosListPagination, getVideosListSort, killallServers, rateVideo, removeVideo, runServer,
10   searchVideo, searchVideoWithPagination, searchVideoWithSort, ServerInfo, setAccessTokensToServers, testImage, updateVideo, uploadVideo,
11   viewVideo, wait
12 } from '../../utils'
13
14 const expect = chai.expect
15
16 describe('Test a single server', function () {
17   let server: ServerInfo = null
18   let videoId = -1
19   let videoUUID = ''
20   let videosListBase: any[] = null
21
22   const getCheckAttributes = {
23     name: 'my super name',
24     category: 2,
25     licence: 6,
26     language: 3,
27     nsfw: true,
28     description: 'my super description',
29     support: 'my super support text',
30     host: 'localhost:9001',
31     account: 'root',
32     isLocal: true,
33     duration: 5,
34     tags: [ 'tag1', 'tag2', 'tag3' ],
35     privacy: VideoPrivacy.PUBLIC,
36     commentsEnabled: true,
37     channel: {
38       name: 'Default root channel',
39       description: '',
40       isLocal: true
41     },
42     fixture: 'video_short.webm',
43     files: [
44       {
45         resolution: 720,
46         size: 218910
47       }
48     ]
49   }
50
51   const updateCheckAttributes = {
52     name: 'my super video updated',
53     category: 4,
54     licence: 2,
55     language: 5,
56     nsfw: false,
57     description: 'my super description updated',
58     support: 'my super support text updated',
59     host: 'localhost:9001',
60     account: 'root',
61     isLocal: true,
62     tags: [ 'tagup1', 'tagup2' ],
63     privacy: VideoPrivacy.PUBLIC,
64     duration: 5,
65     commentsEnabled: false,
66     channel: {
67       name: 'Default root channel',
68       description: '',
69       isLocal: true
70     },
71     fixture: 'video_short3.webm',
72     files: [
73       {
74         resolution: 720,
75         size: 292677
76       }
77     ]
78   }
79
80   before(async function () {
81     this.timeout(30000)
82
83     await flushTests()
84
85     server = await runServer(1)
86
87     await setAccessTokensToServers([ server ])
88   })
89
90   it('Should list video categories', async function () {
91     const res = await getVideoCategories(server.url)
92
93     const categories = res.body
94     expect(Object.keys(categories)).to.have.length.above(10)
95
96     expect(categories[11]).to.equal('News')
97   })
98
99   it('Should list video licences', async function () {
100     const res = await getVideoLicences(server.url)
101
102     const licences = res.body
103     expect(Object.keys(licences)).to.have.length.above(5)
104
105     expect(licences[3]).to.equal('Attribution - No Derivatives')
106   })
107
108   it('Should list video languages', async function () {
109     const res = await getVideoLanguages(server.url)
110
111     const languages = res.body
112     expect(Object.keys(languages)).to.have.length.above(5)
113
114     expect(languages[3]).to.equal('Mandarin')
115   })
116
117   it('Should list video privacies', async function () {
118     const res = await getVideoPrivacies(server.url)
119
120     const privacies = res.body
121     expect(Object.keys(privacies)).to.have.length.at.least(3)
122
123     expect(privacies[3]).to.equal('Private')
124   })
125
126   it('Should not have videos', async function () {
127     const res = await getVideosList(server.url)
128
129     expect(res.body.total).to.equal(0)
130     expect(res.body.data).to.be.an('array')
131     expect(res.body.data.length).to.equal(0)
132   })
133
134   it('Should upload the video', async function () {
135     const videoAttributes = {
136       name: 'my super name',
137       category: 2,
138       nsfw: true,
139       licence: 6,
140       tags: [ 'tag1', 'tag2', 'tag3' ]
141     }
142     const res = await uploadVideo(server.url, server.accessToken, videoAttributes)
143     expect(res.body.video).to.not.be.undefined
144     expect(res.body.video.id).to.equal(1)
145     expect(res.body.video.uuid).to.have.length.above(5)
146
147     videoId = res.body.video.id
148     videoUUID = res.body.video.uuid
149   })
150
151   it('Should get and seed the uploaded video', async function () {
152     this.timeout(5000)
153
154     const res = await getVideosList(server.url)
155
156     expect(res.body.total).to.equal(1)
157     expect(res.body.data).to.be.an('array')
158     expect(res.body.data.length).to.equal(1)
159
160     const video = res.body.data[0]
161     await completeVideoCheck(server.url, video, getCheckAttributes)
162   })
163
164   it('Should get the video by UUID', async function () {
165     this.timeout(5000)
166
167     const res = await getVideo(server.url, videoUUID)
168
169     const video = res.body
170     await completeVideoCheck(server.url, video, getCheckAttributes)
171   })
172
173   it('Should have the views updated', async function () {
174     this.timeout(10000)
175
176     await viewVideo(server.url, videoId)
177     await viewVideo(server.url, videoId)
178     await viewVideo(server.url, videoId)
179
180     await wait(1500)
181
182     await viewVideo(server.url, videoId)
183     await viewVideo(server.url, videoId)
184
185     await wait(1500)
186
187     await viewVideo(server.url, videoId)
188     await viewVideo(server.url, videoId)
189
190     const res = await getVideo(server.url, videoId)
191
192     const video = res.body
193     expect(video.views).to.equal(3)
194   })
195
196   it('Should search the video by name', async function () {
197     const res = await searchVideo(server.url, 'my')
198
199     expect(res.body.total).to.equal(1)
200     expect(res.body.data).to.be.an('array')
201     expect(res.body.data.length).to.equal(1)
202
203     const video = res.body.data[0]
204     await completeVideoCheck(server.url, video, getCheckAttributes)
205   })
206
207   // Not implemented yet
208   // it('Should search the video by serverHost', async function () {
209   //     const res = await   videosUtils.searchVideo(server.url, '9001', 'host')
210
211   //     expect(res.body.total).to.equal(1)
212   //     expect(res.body.data).to.be.an('array')
213   //     expect(res.body.data.length).to.equal(1)
214
215   //     const video = res.body.data[0]
216   //     expect(video.name).to.equal('my super name')
217   //     expect(video.description).to.equal('my super description')
218   //     expect(video.serverHost).to.equal('localhost:9001')
219   //     expect(video.author).to.equal('root')
220   //     expect(video.isLocal).to.be.true
221   //     expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ])
222   //     expect(dateIsValid(video.createdAt)).to.be.true
223   //     expect(dateIsValid(video.updatedAt)).to.be.true
224
225   //     const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath)
226   //       expect(test).to.equal(true)
227
228   //       done()
229   //     })
230   //   })
231   // })
232
233   // Not implemented yet
234   // it('Should search the video by tag', async function () {
235   //   const res = await searchVideo(server.url, 'tag1')
236   //
237   //   expect(res.body.total).to.equal(1)
238   //   expect(res.body.data).to.be.an('array')
239   //   expect(res.body.data.length).to.equal(1)
240   //
241   //   const video = res.body.data[0]
242   //   expect(video.name).to.equal('my super name')
243   //   expect(video.category).to.equal(2)
244   //   expect(video.categoryLabel).to.equal('Films')
245   //   expect(video.licence).to.equal(6)
246   //   expect(video.licenceLabel).to.equal('Attribution - Non Commercial - No Derivatives')
247   //   expect(video.language).to.equal(3)
248   //   expect(video.languageLabel).to.equal('Mandarin')
249   //   expect(video.nsfw).to.be.ok
250   //   expect(video.description).to.equal('my super description')
251   //   expect(video.serverHost).to.equal('localhost:9001')
252   //   expect(video.accountName).to.equal('root')
253   //   expect(video.isLocal).to.be.true
254   //   expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ])
255   //   expect(dateIsValid(video.createdAt)).to.be.true
256   //   expect(dateIsValid(video.updatedAt)).to.be.true
257   //
258   //   const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath)
259   //   expect(test).to.equal(true)
260   // })
261
262   it('Should not find a search by name', async function () {
263     const res = await searchVideo(server.url, 'hello')
264
265     expect(res.body.total).to.equal(0)
266     expect(res.body.data).to.be.an('array')
267     expect(res.body.data.length).to.equal(0)
268   })
269
270   // Not implemented yet
271   // it('Should not find a search by author', async function () {
272   //   const res = await searchVideo(server.url, 'hello')
273   //
274   //   expect(res.body.total).to.equal(0)
275   //   expect(res.body.data).to.be.an('array')
276   //   expect(res.body.data.length).to.equal(0)
277   // })
278   //
279   // Not implemented yet
280   // it('Should not find a search by tag', async function () {
281   //   const res = await searchVideo(server.url, 'hello')
282   //
283   //   expect(res.body.total).to.equal(0)
284   //   expect(res.body.data).to.be.an('array')
285   //   expect(res.body.data.length).to.equal(0)
286   // })
287
288   it('Should remove the video', async function () {
289     await removeVideo(server.url, server.accessToken, videoId)
290
291     await checkVideoFilesWereRemoved(videoUUID, 1)
292   })
293
294   it('Should not have videos', async function () {
295     const res = await getVideosList(server.url)
296
297     expect(res.body.total).to.equal(0)
298     expect(res.body.data).to.be.an('array')
299     expect(res.body.data).to.have.lengthOf(0)
300   })
301
302   it('Should upload 6 videos', async function () {
303     this.timeout(25000)
304
305     const videos = [
306       'video_short.mp4', 'video_short.ogv', 'video_short.webm',
307       'video_short1.webm', 'video_short2.webm', 'video_short3.webm'
308     ]
309
310     const tasks: Promise<any>[] = []
311     for (const video of videos) {
312       const videoAttributes = {
313         name: video + ' name',
314         description: video + ' description',
315         category: 2,
316         licence: 1,
317         language: 1,
318         nsfw: true,
319         tags: [ 'tag1', 'tag2', 'tag3' ],
320         fixture: video
321       }
322
323       const p = uploadVideo(server.url, server.accessToken, videoAttributes)
324       tasks.push(p)
325     }
326
327     await Promise.all(tasks)
328   })
329
330   it('Should have the correct durations', async function () {
331     const res = await getVideosList(server.url)
332
333     expect(res.body.total).to.equal(6)
334     const videos = res.body.data
335     expect(videos).to.be.an('array')
336     expect(videos).to.have.lengthOf(6)
337
338     const videosByName = keyBy<{ duration: number }>(videos, 'name')
339     expect(videosByName['video_short.mp4 name'].duration).to.equal(5)
340     expect(videosByName['video_short.ogv name'].duration).to.equal(5)
341     expect(videosByName['video_short.webm name'].duration).to.equal(5)
342     expect(videosByName['video_short1.webm name'].duration).to.equal(10)
343     expect(videosByName['video_short2.webm name'].duration).to.equal(5)
344     expect(videosByName['video_short3.webm name'].duration).to.equal(5)
345   })
346
347   it('Should have the correct thumbnails', async function () {
348     const res = await getVideosList(server.url)
349
350     const videos = res.body.data
351     // For the next test
352     videosListBase = videos
353
354     for (const video of videos) {
355       const videoName = video.name.replace(' name', '')
356       await testImage(server.url, videoName, video.thumbnailPath)
357     }
358   })
359
360   it('Should list only the two first videos', async function () {
361     const res = await getVideosListPagination(server.url, 0, 2, 'name')
362
363     const videos = res.body.data
364     expect(res.body.total).to.equal(6)
365     expect(videos.length).to.equal(2)
366     expect(videos[0].name).to.equal(videosListBase[0].name)
367     expect(videos[1].name).to.equal(videosListBase[1].name)
368   })
369
370   it('Should list only the next three videos', async function () {
371     const res = await getVideosListPagination(server.url, 2, 3, 'name')
372
373     const videos = res.body.data
374     expect(res.body.total).to.equal(6)
375     expect(videos.length).to.equal(3)
376     expect(videos[0].name).to.equal(videosListBase[2].name)
377     expect(videos[1].name).to.equal(videosListBase[3].name)
378     expect(videos[2].name).to.equal(videosListBase[4].name)
379   })
380
381   it('Should list the last video', async function () {
382     const res = await getVideosListPagination(server.url, 5, 6, 'name')
383
384     const videos = res.body.data
385     expect(res.body.total).to.equal(6)
386     expect(videos.length).to.equal(1)
387     expect(videos[0].name).to.equal(videosListBase[5].name)
388   })
389
390   it('Should search the first video', async function () {
391     const res = await searchVideoWithPagination(server.url, 'webm', 0, 1, 'name')
392
393     const videos = res.body.data
394     expect(res.body.total).to.equal(4)
395     expect(videos.length).to.equal(1)
396     expect(videos[0].name).to.equal('video_short1.webm name')
397   })
398
399   it('Should search the last two videos', async function () {
400     const res = await searchVideoWithPagination(server.url, 'webm', 2, 2, 'name')
401
402     const videos = res.body.data
403     expect(res.body.total).to.equal(4)
404     expect(videos.length).to.equal(2)
405     expect(videos[0].name).to.equal('video_short3.webm name')
406     expect(videos[1].name).to.equal('video_short.webm name')
407   })
408
409   it('Should search all the webm videos', async function () {
410     const res = await searchVideoWithPagination(server.url, 'webm', 0, 15)
411
412     const videos = res.body.data
413     expect(res.body.total).to.equal(4)
414     expect(videos.length).to.equal(4)
415   })
416
417   // Not implemented yet
418   // it('Should search all the root author videos', async function () {
419   //   const res = await searchVideoWithPagination(server.url, 'root', 0, 15)
420   //
421   //   const videos = res.body.data
422   //   expect(res.body.total).to.equal(6)
423   //   expect(videos.length).to.equal(6)
424   // })
425
426   // Not implemented yet
427   // it('Should search all the 9001 port videos', async function () {
428   // const res = await   videosUtils.searchVideoWithPagination(server.url, '9001', 'host', 0, 15)
429
430   //     const videos = res.body.data
431   //     expect(res.body.total).to.equal(6)
432   //     expect(videos.length).to.equal(6)
433
434   //     done()
435   //   })
436   // })
437
438   // it('Should search all the localhost videos', async function () {
439   // const res = await   videosUtils.searchVideoWithPagination(server.url, 'localhost', 'host', 0, 15)
440
441   //     const videos = res.body.data
442   //     expect(res.body.total).to.equal(6)
443   //     expect(videos.length).to.equal(6)
444
445   //     done()
446   //   })
447   // })
448
449   it('Should list and sort by name in descending order', async function () {
450     const res = await getVideosListSort(server.url, '-name')
451
452     const videos = res.body.data
453     expect(res.body.total).to.equal(6)
454     expect(videos.length).to.equal(6)
455     expect(videos[0].name).to.equal('video_short.webm name')
456     expect(videos[1].name).to.equal('video_short.ogv name')
457     expect(videos[2].name).to.equal('video_short.mp4 name')
458     expect(videos[3].name).to.equal('video_short3.webm name')
459     expect(videos[4].name).to.equal('video_short2.webm name')
460     expect(videos[5].name).to.equal('video_short1.webm name')
461   })
462
463   it('Should search and sort by name in ascending order', async function () {
464     const res = await searchVideoWithSort(server.url, 'webm', 'name')
465
466     const videos = res.body.data
467     expect(res.body.total).to.equal(4)
468     expect(videos.length).to.equal(4)
469
470     expect(videos[0].name).to.equal('video_short1.webm name')
471     expect(videos[1].name).to.equal('video_short2.webm name')
472     expect(videos[2].name).to.equal('video_short3.webm name')
473     expect(videos[3].name).to.equal('video_short.webm name')
474
475     videoId = videos[2].id
476   })
477
478   it('Should update a video', async function () {
479     const attributes = {
480       name: 'my super video updated',
481       category: 4,
482       licence: 2,
483       language: 5,
484       nsfw: false,
485       description: 'my super description updated',
486       commentsEnabled: false,
487       tags: [ 'tagup1', 'tagup2' ]
488     }
489     await updateVideo(server.url, server.accessToken, videoId, attributes)
490   })
491
492   it('Should have the video updated', async function () {
493     this.timeout(60000)
494
495     const res = await getVideo(server.url, videoId)
496     const video = res.body
497
498     await completeVideoCheck(server.url, video, updateCheckAttributes)
499   })
500
501   it('Should update only the tags of a video', async function () {
502     const attributes = {
503       tags: [ 'supertag', 'tag1', 'tag2' ]
504     }
505     await updateVideo(server.url, server.accessToken, videoId, attributes)
506
507     const res = await getVideo(server.url, videoId)
508     const video = res.body
509
510     await completeVideoCheck(server.url, video, Object.assign(updateCheckAttributes, attributes))
511   })
512
513   it('Should update only the description of a video', async function () {
514     const attributes = {
515       description: 'hello everybody'
516     }
517     await updateVideo(server.url, server.accessToken, videoId, attributes)
518
519     const res = await getVideo(server.url, videoId)
520     const video = res.body
521
522     await completeVideoCheck(server.url, video, Object.assign(updateCheckAttributes, attributes))
523   })
524
525   it('Should like a video', async function () {
526     await rateVideo(server.url, server.accessToken, videoId, 'like')
527
528     const res = await getVideo(server.url, videoId)
529     const video = res.body
530
531     expect(video.likes).to.equal(1)
532     expect(video.dislikes).to.equal(0)
533   })
534
535   it('Should dislike the same video', async function () {
536     await rateVideo(server.url, server.accessToken, videoId, 'dislike')
537
538     const res = await getVideo(server.url, videoId)
539     const video = res.body
540
541     expect(video.likes).to.equal(0)
542     expect(video.dislikes).to.equal(1)
543   })
544
545   after(async function () {
546     killallServers([ server ])
547
548     // Keep the logs if the test failed
549     if (this['ok']) {
550       await flushTests()
551     }
552   })
553 })