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