Merge branch 'release/2.1.0' into develop
[oweals/peertube.git] / server / tests / api / search / search-videos.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import * as chai from 'chai'
4 import 'mocha'
5 import {
6   advancedVideosSearch,
7   cleanupTests,
8   flushAndRunServer,
9   immutableAssign,
10   searchVideo,
11   ServerInfo,
12   setAccessTokensToServers,
13   uploadVideo,
14   wait
15 } from '../../../../shared/extra-utils'
16 import { createVideoCaption } from '../../../../shared/extra-utils/videos/video-captions'
17
18 const expect = chai.expect
19
20 describe('Test videos search', function () {
21   let server: ServerInfo = null
22   let startDate: string
23   let videoUUID: string
24
25   before(async function () {
26     this.timeout(30000)
27
28     server = await flushAndRunServer(1)
29
30     await setAccessTokensToServers([ server ])
31
32     {
33       const attributes1 = {
34         name: '1111 2222 3333',
35         fixture: '60fps_720p_small.mp4', // 2 seconds
36         category: 1,
37         licence: 1,
38         nsfw: false,
39         language: 'fr'
40       }
41       await uploadVideo(server.url, server.accessToken, attributes1)
42
43       const attributes2 = immutableAssign(attributes1, { name: attributes1.name + ' - 2', fixture: 'video_short.mp4' })
44       await uploadVideo(server.url, server.accessToken, attributes2)
45
46       {
47         const attributes3 = immutableAssign(attributes1, { name: attributes1.name + ' - 3', language: undefined })
48         const res = await uploadVideo(server.url, server.accessToken, attributes3)
49         const videoId = res.body.video.id
50         videoUUID = res.body.video.uuid
51
52         await createVideoCaption({
53           url: server.url,
54           accessToken: server.accessToken,
55           language: 'en',
56           videoId,
57           fixture: 'subtitle-good2.vtt',
58           mimeType: 'application/octet-stream'
59         })
60
61         await createVideoCaption({
62           url: server.url,
63           accessToken: server.accessToken,
64           language: 'aa',
65           videoId,
66           fixture: 'subtitle-good2.vtt',
67           mimeType: 'application/octet-stream'
68         })
69       }
70
71       const attributes4 = immutableAssign(attributes1, { name: attributes1.name + ' - 4', language: 'pl', nsfw: true })
72       await uploadVideo(server.url, server.accessToken, attributes4)
73
74       await wait(1000)
75
76       startDate = new Date().toISOString()
77
78       const attributes5 = immutableAssign(attributes1, { name: attributes1.name + ' - 5', licence: 2, language: undefined })
79       await uploadVideo(server.url, server.accessToken, attributes5)
80
81       const attributes6 = immutableAssign(attributes1, { name: attributes1.name + ' - 6', tags: [ 't1', 't2' ] })
82       await uploadVideo(server.url, server.accessToken, attributes6)
83
84       const attributes7 = immutableAssign(attributes1, {
85         name: attributes1.name + ' - 7',
86         originallyPublishedAt: '2019-02-12T09:58:08.286Z'
87       })
88       await uploadVideo(server.url, server.accessToken, attributes7)
89
90       const attributes8 = immutableAssign(attributes1, { name: attributes1.name + ' - 8', licence: 4 })
91       await uploadVideo(server.url, server.accessToken, attributes8)
92     }
93
94     {
95       const attributes = {
96         name: '3333 4444 5555',
97         fixture: 'video_short.mp4',
98         category: 2,
99         licence: 2,
100         language: 'en'
101       }
102       await uploadVideo(server.url, server.accessToken, attributes)
103
104       await uploadVideo(server.url, server.accessToken, immutableAssign(attributes, { name: attributes.name + ' duplicate' }))
105     }
106
107     {
108       const attributes = {
109         name: '6666 7777 8888',
110         fixture: 'video_short.mp4',
111         category: 3,
112         licence: 3,
113         language: 'pl'
114       }
115       await uploadVideo(server.url, server.accessToken, attributes)
116     }
117
118     {
119       const attributes1 = {
120         name: '9999',
121         tags: [ 'aaaa', 'bbbb', 'cccc' ],
122         category: 1
123       }
124       await uploadVideo(server.url, server.accessToken, attributes1)
125       await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { category: 2 }))
126
127       await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { tags: [ 'cccc', 'dddd' ] }))
128       await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { tags: [ 'eeee', 'ffff' ] }))
129     }
130
131     {
132       const attributes1 = {
133         name: 'aaaa 2',
134         category: 1
135       }
136       await uploadVideo(server.url, server.accessToken, attributes1)
137       await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { category: 2 }))
138     }
139   })
140
141   it('Should make a simple search and not have results', async function () {
142     const res = await searchVideo(server.url, 'abc')
143
144     expect(res.body.total).to.equal(0)
145     expect(res.body.data).to.have.lengthOf(0)
146   })
147
148   it('Should make a simple search and have results', async function () {
149     const res = await searchVideo(server.url, '4444 5555 duplicate')
150
151     expect(res.body.total).to.equal(2)
152
153     const videos = res.body.data
154     expect(videos).to.have.lengthOf(2)
155
156     // bestmatch
157     expect(videos[0].name).to.equal('3333 4444 5555 duplicate')
158     expect(videos[1].name).to.equal('3333 4444 5555')
159   })
160
161   it('Should make a search on tags too, and have results', async function () {
162     const query = {
163       search: 'aaaa',
164       categoryOneOf: [ 1 ]
165     }
166     const res = await advancedVideosSearch(server.url, query)
167
168     expect(res.body.total).to.equal(2)
169
170     const videos = res.body.data
171     expect(videos).to.have.lengthOf(2)
172
173     // bestmatch
174     expect(videos[0].name).to.equal('aaaa 2')
175     expect(videos[1].name).to.equal('9999')
176   })
177
178   it('Should filter on tags without a search', async function () {
179     const query = {
180       tagsAllOf: [ 'bbbb' ]
181     }
182     const res = await advancedVideosSearch(server.url, query)
183
184     expect(res.body.total).to.equal(2)
185
186     const videos = res.body.data
187     expect(videos).to.have.lengthOf(2)
188
189     expect(videos[0].name).to.equal('9999')
190     expect(videos[1].name).to.equal('9999')
191   })
192
193   it('Should filter on category without a search', async function () {
194     const query = {
195       categoryOneOf: [ 3 ]
196     }
197     const res = await advancedVideosSearch(server.url, query)
198
199     expect(res.body.total).to.equal(1)
200
201     const videos = res.body.data
202     expect(videos).to.have.lengthOf(1)
203
204     expect(videos[0].name).to.equal('6666 7777 8888')
205   })
206
207   it('Should search by tags (one of)', async function () {
208     const query = {
209       search: '9999',
210       categoryOneOf: [ 1 ],
211       tagsOneOf: [ 'aAaa', 'ffff' ]
212     }
213     const res1 = await advancedVideosSearch(server.url, query)
214     expect(res1.body.total).to.equal(2)
215
216     const res2 = await advancedVideosSearch(server.url, immutableAssign(query, { tagsOneOf: [ 'blabla' ] }))
217     expect(res2.body.total).to.equal(0)
218   })
219
220   it('Should search by tags (all of)', async function () {
221     const query = {
222       search: '9999',
223       categoryOneOf: [ 1 ],
224       tagsAllOf: [ 'CCcc' ]
225     }
226     const res1 = await advancedVideosSearch(server.url, query)
227     expect(res1.body.total).to.equal(2)
228
229     const res2 = await advancedVideosSearch(server.url, immutableAssign(query, { tagsAllOf: [ 'blAbla' ] }))
230     expect(res2.body.total).to.equal(0)
231
232     const res3 = await advancedVideosSearch(server.url, immutableAssign(query, { tagsAllOf: [ 'bbbb', 'CCCC' ] }))
233     expect(res3.body.total).to.equal(1)
234   })
235
236   it('Should search by category', async function () {
237     const query = {
238       search: '6666',
239       categoryOneOf: [ 3 ]
240     }
241     const res1 = await advancedVideosSearch(server.url, query)
242     expect(res1.body.total).to.equal(1)
243     expect(res1.body.data[0].name).to.equal('6666 7777 8888')
244
245     const res2 = await advancedVideosSearch(server.url, immutableAssign(query, { categoryOneOf: [ 2 ] }))
246     expect(res2.body.total).to.equal(0)
247   })
248
249   it('Should search by licence', async function () {
250     const query = {
251       search: '4444 5555',
252       licenceOneOf: [ 2 ]
253     }
254     const res1 = await advancedVideosSearch(server.url, query)
255     expect(res1.body.total).to.equal(2)
256     expect(res1.body.data[0].name).to.equal('3333 4444 5555')
257     expect(res1.body.data[1].name).to.equal('3333 4444 5555 duplicate')
258
259     const res2 = await advancedVideosSearch(server.url, immutableAssign(query, { licenceOneOf: [ 3 ] }))
260     expect(res2.body.total).to.equal(0)
261   })
262
263   it('Should search by languages', async function () {
264     const query = {
265       search: '1111 2222 3333',
266       languageOneOf: [ 'pl', 'en' ]
267     }
268
269     {
270       const res = await advancedVideosSearch(server.url, query)
271       expect(res.body.total).to.equal(2)
272       expect(res.body.data[0].name).to.equal('1111 2222 3333 - 3')
273       expect(res.body.data[1].name).to.equal('1111 2222 3333 - 4')
274     }
275
276     {
277       const res = await advancedVideosSearch(server.url, immutableAssign(query, { languageOneOf: [ 'pl', 'en', '_unknown' ] }))
278       expect(res.body.total).to.equal(3)
279       expect(res.body.data[0].name).to.equal('1111 2222 3333 - 3')
280       expect(res.body.data[1].name).to.equal('1111 2222 3333 - 4')
281       expect(res.body.data[2].name).to.equal('1111 2222 3333 - 5')
282     }
283
284     {
285       const res = await advancedVideosSearch(server.url, immutableAssign(query, { languageOneOf: [ 'eo' ] }))
286       expect(res.body.total).to.equal(0)
287     }
288   })
289
290   it('Should search by start date', async function () {
291     const query = {
292       search: '1111 2222 3333',
293       startDate
294     }
295
296     const res = await advancedVideosSearch(server.url, query)
297     expect(res.body.total).to.equal(4)
298
299     const videos = res.body.data
300     expect(videos[0].name).to.equal('1111 2222 3333 - 5')
301     expect(videos[1].name).to.equal('1111 2222 3333 - 6')
302     expect(videos[2].name).to.equal('1111 2222 3333 - 7')
303     expect(videos[3].name).to.equal('1111 2222 3333 - 8')
304   })
305
306   it('Should make an advanced search', async function () {
307     const query = {
308       search: '1111 2222 3333',
309       languageOneOf: [ 'pl', 'fr' ],
310       durationMax: 4,
311       nsfw: 'false' as 'false',
312       licenceOneOf: [ 1, 4 ]
313     }
314
315     const res = await advancedVideosSearch(server.url, query)
316     expect(res.body.total).to.equal(4)
317
318     const videos = res.body.data
319     expect(videos[0].name).to.equal('1111 2222 3333')
320     expect(videos[1].name).to.equal('1111 2222 3333 - 6')
321     expect(videos[2].name).to.equal('1111 2222 3333 - 7')
322     expect(videos[3].name).to.equal('1111 2222 3333 - 8')
323   })
324
325   it('Should make an advanced search and sort results', async function () {
326     const query = {
327       search: '1111 2222 3333',
328       languageOneOf: [ 'pl', 'fr' ],
329       durationMax: 4,
330       nsfw: 'false' as 'false',
331       licenceOneOf: [ 1, 4 ],
332       sort: '-name'
333     }
334
335     const res = await advancedVideosSearch(server.url, query)
336     expect(res.body.total).to.equal(4)
337
338     const videos = res.body.data
339     expect(videos[0].name).to.equal('1111 2222 3333 - 8')
340     expect(videos[1].name).to.equal('1111 2222 3333 - 7')
341     expect(videos[2].name).to.equal('1111 2222 3333 - 6')
342     expect(videos[3].name).to.equal('1111 2222 3333')
343   })
344
345   it('Should make an advanced search and only show the first result', async function () {
346     const query = {
347       search: '1111 2222 3333',
348       languageOneOf: [ 'pl', 'fr' ],
349       durationMax: 4,
350       nsfw: 'false' as 'false',
351       licenceOneOf: [ 1, 4 ],
352       sort: '-name',
353       start: 0,
354       count: 1
355     }
356
357     const res = await advancedVideosSearch(server.url, query)
358     expect(res.body.total).to.equal(4)
359
360     const videos = res.body.data
361     expect(videos[0].name).to.equal('1111 2222 3333 - 8')
362   })
363
364   it('Should make an advanced search and only show the last result', async function () {
365     const query = {
366       search: '1111 2222 3333',
367       languageOneOf: [ 'pl', 'fr' ],
368       durationMax: 4,
369       nsfw: 'false' as 'false',
370       licenceOneOf: [ 1, 4 ],
371       sort: '-name',
372       start: 3,
373       count: 1
374     }
375
376     const res = await advancedVideosSearch(server.url, query)
377     expect(res.body.total).to.equal(4)
378
379     const videos = res.body.data
380     expect(videos[0].name).to.equal('1111 2222 3333')
381   })
382
383   it('Should search on originally published date', async function () {
384     const baseQuery = {
385       search: '1111 2222 3333',
386       languageOneOf: [ 'pl', 'fr' ],
387       durationMax: 4,
388       nsfw: 'false' as 'false',
389       licenceOneOf: [ 1, 4 ]
390     }
391
392     {
393       const query = immutableAssign(baseQuery, { originallyPublishedStartDate: '2019-02-11T09:58:08.286Z' })
394       const res = await advancedVideosSearch(server.url, query)
395
396       expect(res.body.total).to.equal(1)
397       expect(res.body.data[0].name).to.equal('1111 2222 3333 - 7')
398     }
399
400     {
401       const query = immutableAssign(baseQuery, { originallyPublishedEndDate: '2019-03-11T09:58:08.286Z' })
402       const res = await advancedVideosSearch(server.url, query)
403
404       expect(res.body.total).to.equal(1)
405       expect(res.body.data[0].name).to.equal('1111 2222 3333 - 7')
406     }
407
408     {
409       const query = immutableAssign(baseQuery, { originallyPublishedEndDate: '2019-01-11T09:58:08.286Z' })
410       const res = await advancedVideosSearch(server.url, query)
411
412       expect(res.body.total).to.equal(0)
413     }
414
415     {
416       const query = immutableAssign(baseQuery, { originallyPublishedStartDate: '2019-03-11T09:58:08.286Z' })
417       const res = await advancedVideosSearch(server.url, query)
418
419       expect(res.body.total).to.equal(0)
420     }
421
422     {
423       const query = immutableAssign(baseQuery, {
424         originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
425         originallyPublishedEndDate: '2019-01-10T09:58:08.286Z'
426       })
427       const res = await advancedVideosSearch(server.url, query)
428
429       expect(res.body.total).to.equal(0)
430     }
431
432     {
433       const query = immutableAssign(baseQuery, {
434         originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
435         originallyPublishedEndDate: '2019-04-11T09:58:08.286Z'
436       })
437       const res = await advancedVideosSearch(server.url, query)
438
439       expect(res.body.total).to.equal(1)
440       expect(res.body.data[0].name).to.equal('1111 2222 3333 - 7')
441     }
442   })
443
444   it('Should search by UUID', async function () {
445     const search = videoUUID
446     const res = await advancedVideosSearch(server.url, { search })
447
448     expect(res.body.total).to.equal(1)
449     expect(res.body.data[0].name).to.equal('1111 2222 3333 - 3')
450   })
451
452   after(async function () {
453     await cleanupTests([ server ])
454   })
455 })