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