1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
11 setAccessTokensToServers,
12 setDefaultVideoChannel,
15 } from '@shared/extra-utils'
16 import { VideoPrivacy } from '@shared/models'
18 const expect = chai.expect
20 describe('Test videos search', function () {
21 let server: PeerTubeServer
22 let remoteServer: PeerTubeServer
25 let videoShortUUID: string
27 let command: SearchCommand
29 before(async function () {
32 const servers = await Promise.all([
33 createSingleServer(1),
37 remoteServer = servers[1]
39 await setAccessTokensToServers([ server, remoteServer ])
40 await setDefaultVideoChannel([ server, remoteServer ])
44 name: '1111 2222 3333',
45 fixture: '60fps_720p_small.mp4', // 2 seconds
51 await server.videos.upload({ attributes: attributes1 })
53 const attributes2 = { ...attributes1, name: attributes1.name + ' - 2', fixture: 'video_short.mp4' }
54 await server.videos.upload({ attributes: attributes2 })
57 const attributes3 = { ...attributes1, name: attributes1.name + ' - 3', language: undefined }
58 const { id, uuid, shortUUID } = await server.videos.upload({ attributes: attributes3 })
60 videoShortUUID = shortUUID
62 await server.captions.add({
65 fixture: 'subtitle-good2.vtt',
66 mimeType: 'application/octet-stream'
69 await server.captions.add({
72 fixture: 'subtitle-good2.vtt',
73 mimeType: 'application/octet-stream'
77 const attributes4 = { ...attributes1, name: attributes1.name + ' - 4', language: 'pl', nsfw: true }
78 await server.videos.upload({ attributes: attributes4 })
82 startDate = new Date().toISOString()
84 const attributes5 = { ...attributes1, name: attributes1.name + ' - 5', licence: 2, language: undefined }
85 await server.videos.upload({ attributes: attributes5 })
87 const attributes6 = { ...attributes1, name: attributes1.name + ' - 6', tags: [ 't1', 't2' ] }
88 await server.videos.upload({ attributes: attributes6 })
90 const attributes7 = { ...attributes1, name: attributes1.name + ' - 7', originallyPublishedAt: '2019-02-12T09:58:08.286Z' }
91 await server.videos.upload({ attributes: attributes7 })
93 const attributes8 = { ...attributes1, name: attributes1.name + ' - 8', licence: 4 }
94 await server.videos.upload({ attributes: attributes8 })
99 name: '3333 4444 5555',
100 fixture: 'video_short.mp4',
105 await server.videos.upload({ attributes: attributes })
107 await server.videos.upload({ attributes: { ...attributes, name: attributes.name + ' duplicate' } })
112 name: '6666 7777 8888',
113 fixture: 'video_short.mp4',
118 await server.videos.upload({ attributes: attributes })
122 const attributes1 = {
124 tags: [ 'aaaa', 'bbbb', 'cccc' ],
127 await server.videos.upload({ attributes: attributes1 })
128 await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
130 await server.videos.upload({ attributes: { ...attributes1, tags: [ 'cccc', 'dddd' ] } })
131 await server.videos.upload({ attributes: { ...attributes1, tags: [ 'eeee', 'ffff' ] } })
135 const attributes1 = {
139 await server.videos.upload({ attributes: attributes1 })
140 await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
144 await remoteServer.videos.upload({ attributes: { name: 'remote video 1' } })
145 await remoteServer.videos.upload({ attributes: { name: 'remote video 2' } })
148 await doubleFollow(server, remoteServer)
150 command = server.search
153 it('Should make a simple search and not have results', async function () {
154 const body = await command.searchVideos({ search: 'abc' })
156 expect(body.total).to.equal(0)
157 expect(body.data).to.have.lengthOf(0)
160 it('Should make a simple search and have results', async function () {
161 const body = await command.searchVideos({ search: '4444 5555 duplicate' })
163 expect(body.total).to.equal(2)
165 const videos = body.data
166 expect(videos).to.have.lengthOf(2)
169 expect(videos[0].name).to.equal('3333 4444 5555 duplicate')
170 expect(videos[1].name).to.equal('3333 4444 5555')
173 it('Should make a search on tags too, and have results', async function () {
178 const body = await command.advancedVideoSearch({ search })
180 expect(body.total).to.equal(2)
182 const videos = body.data
183 expect(videos).to.have.lengthOf(2)
186 expect(videos[0].name).to.equal('aaaa 2')
187 expect(videos[1].name).to.equal('9999')
190 it('Should filter on tags without a search', async function () {
192 tagsAllOf: [ 'bbbb' ]
194 const body = await command.advancedVideoSearch({ search })
196 expect(body.total).to.equal(2)
198 const videos = body.data
199 expect(videos).to.have.lengthOf(2)
201 expect(videos[0].name).to.equal('9999')
202 expect(videos[1].name).to.equal('9999')
205 it('Should filter on category without a search', async function () {
209 const body = await command.advancedVideoSearch({ search: search })
211 expect(body.total).to.equal(1)
213 const videos = body.data
214 expect(videos).to.have.lengthOf(1)
216 expect(videos[0].name).to.equal('6666 7777 8888')
219 it('Should search by tags (one of)', async function () {
222 categoryOneOf: [ 1 ],
223 tagsOneOf: [ 'aAaa', 'ffff' ]
227 const body = await command.advancedVideoSearch({ search: query })
228 expect(body.total).to.equal(2)
232 const body = await command.advancedVideoSearch({ search: { ...query, tagsOneOf: [ 'blabla' ] } })
233 expect(body.total).to.equal(0)
237 it('Should search by tags (all of)', async function () {
240 categoryOneOf: [ 1 ],
241 tagsAllOf: [ 'CCcc' ]
245 const body = await command.advancedVideoSearch({ search: query })
246 expect(body.total).to.equal(2)
250 const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'blAbla' ] } })
251 expect(body.total).to.equal(0)
255 const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'bbbb', 'CCCC' ] } })
256 expect(body.total).to.equal(1)
260 it('Should search by category', async function () {
267 const body = await command.advancedVideoSearch({ search: query })
268 expect(body.total).to.equal(1)
269 expect(body.data[0].name).to.equal('6666 7777 8888')
273 const body = await command.advancedVideoSearch({ search: { ...query, categoryOneOf: [ 2 ] } })
274 expect(body.total).to.equal(0)
278 it('Should search by licence', async function () {
285 const body = await command.advancedVideoSearch({ search: query })
286 expect(body.total).to.equal(2)
287 expect(body.data[0].name).to.equal('3333 4444 5555')
288 expect(body.data[1].name).to.equal('3333 4444 5555 duplicate')
292 const body = await command.advancedVideoSearch({ search: { ...query, licenceOneOf: [ 3 ] } })
293 expect(body.total).to.equal(0)
297 it('Should search by languages', async function () {
299 search: '1111 2222 3333',
300 languageOneOf: [ 'pl', 'en' ]
304 const body = await command.advancedVideoSearch({ search: query })
305 expect(body.total).to.equal(2)
306 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
307 expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
311 const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'pl', 'en', '_unknown' ] } })
312 expect(body.total).to.equal(3)
313 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
314 expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
315 expect(body.data[2].name).to.equal('1111 2222 3333 - 5')
319 const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'eo' ] } })
320 expect(body.total).to.equal(0)
324 it('Should search by start date', async function () {
326 search: '1111 2222 3333',
330 const body = await command.advancedVideoSearch({ search: query })
331 expect(body.total).to.equal(4)
333 const videos = body.data
334 expect(videos[0].name).to.equal('1111 2222 3333 - 5')
335 expect(videos[1].name).to.equal('1111 2222 3333 - 6')
336 expect(videos[2].name).to.equal('1111 2222 3333 - 7')
337 expect(videos[3].name).to.equal('1111 2222 3333 - 8')
340 it('Should make an advanced search', async function () {
342 search: '1111 2222 3333',
343 languageOneOf: [ 'pl', 'fr' ],
345 nsfw: 'false' as 'false',
346 licenceOneOf: [ 1, 4 ]
349 const body = await command.advancedVideoSearch({ search: query })
350 expect(body.total).to.equal(4)
352 const videos = body.data
353 expect(videos[0].name).to.equal('1111 2222 3333')
354 expect(videos[1].name).to.equal('1111 2222 3333 - 6')
355 expect(videos[2].name).to.equal('1111 2222 3333 - 7')
356 expect(videos[3].name).to.equal('1111 2222 3333 - 8')
359 it('Should make an advanced search and sort results', async function () {
361 search: '1111 2222 3333',
362 languageOneOf: [ 'pl', 'fr' ],
364 nsfw: 'false' as 'false',
365 licenceOneOf: [ 1, 4 ],
369 const body = await command.advancedVideoSearch({ search: query })
370 expect(body.total).to.equal(4)
372 const videos = body.data
373 expect(videos[0].name).to.equal('1111 2222 3333 - 8')
374 expect(videos[1].name).to.equal('1111 2222 3333 - 7')
375 expect(videos[2].name).to.equal('1111 2222 3333 - 6')
376 expect(videos[3].name).to.equal('1111 2222 3333')
379 it('Should make an advanced search and only show the first result', async function () {
381 search: '1111 2222 3333',
382 languageOneOf: [ 'pl', 'fr' ],
384 nsfw: 'false' as 'false',
385 licenceOneOf: [ 1, 4 ],
391 const body = await command.advancedVideoSearch({ search: query })
392 expect(body.total).to.equal(4)
394 const videos = body.data
395 expect(videos[0].name).to.equal('1111 2222 3333 - 8')
398 it('Should make an advanced search and only show the last result', async function () {
400 search: '1111 2222 3333',
401 languageOneOf: [ 'pl', 'fr' ],
403 nsfw: 'false' as 'false',
404 licenceOneOf: [ 1, 4 ],
410 const body = await command.advancedVideoSearch({ search: query })
411 expect(body.total).to.equal(4)
413 const videos = body.data
414 expect(videos[0].name).to.equal('1111 2222 3333')
417 it('Should search on originally published date', async function () {
419 search: '1111 2222 3333',
420 languageOneOf: [ 'pl', 'fr' ],
422 nsfw: 'false' as 'false',
423 licenceOneOf: [ 1, 4 ]
427 const query = { ...baseQuery, originallyPublishedStartDate: '2019-02-11T09:58:08.286Z' }
428 const body = await command.advancedVideoSearch({ search: query })
430 expect(body.total).to.equal(1)
431 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
435 const query = { ...baseQuery, originallyPublishedEndDate: '2019-03-11T09:58:08.286Z' }
436 const body = await command.advancedVideoSearch({ search: query })
438 expect(body.total).to.equal(1)
439 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
443 const query = { ...baseQuery, originallyPublishedEndDate: '2019-01-11T09:58:08.286Z' }
444 const body = await command.advancedVideoSearch({ search: query })
446 expect(body.total).to.equal(0)
450 const query = { ...baseQuery, originallyPublishedStartDate: '2019-03-11T09:58:08.286Z' }
451 const body = await command.advancedVideoSearch({ search: query })
453 expect(body.total).to.equal(0)
459 originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
460 originallyPublishedEndDate: '2019-01-10T09:58:08.286Z'
462 const body = await command.advancedVideoSearch({ search: query })
464 expect(body.total).to.equal(0)
470 originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
471 originallyPublishedEndDate: '2019-04-11T09:58:08.286Z'
473 const body = await command.advancedVideoSearch({ search: query })
475 expect(body.total).to.equal(1)
476 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
480 it('Should search by UUID', async function () {
481 const search = videoUUID
482 const body = await command.advancedVideoSearch({ search: { search } })
484 expect(body.total).to.equal(1)
485 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
488 it('Should filter by UUIDs', async function () {
489 for (const uuid of [ videoUUID, videoShortUUID ]) {
490 const body = await command.advancedVideoSearch({ search: { uuids: [ uuid ] } })
492 expect(body.total).to.equal(1)
493 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
497 const body = await command.advancedVideoSearch({ search: { uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] } })
499 expect(body.total).to.equal(0)
500 expect(body.data).to.have.lengthOf(0)
504 it('Should search by host', async function () {
506 const body = await command.advancedVideoSearch({ search: { search: '6666 7777 8888', host: server.host } })
507 expect(body.total).to.equal(1)
508 expect(body.data[0].name).to.equal('6666 7777 8888')
512 const body = await command.advancedVideoSearch({ search: { search: '1111', host: 'example.com' } })
513 expect(body.total).to.equal(0)
514 expect(body.data).to.have.lengthOf(0)
518 const body = await command.advancedVideoSearch({ search: { search: 'remote', host: remoteServer.host } })
519 expect(body.total).to.equal(2)
520 expect(body.data).to.have.lengthOf(2)
521 expect(body.data[0].name).to.equal('remote video 1')
522 expect(body.data[1].name).to.equal('remote video 2')
526 it('Should search by live', async function () {
532 searchIndex: { enabled: false }
534 live: { enabled: true }
536 await server.config.updateCustomSubConfig({ newConfig })
540 const body = await command.advancedVideoSearch({ search: { isLive: true } })
542 expect(body.total).to.equal(0)
543 expect(body.data).to.have.lengthOf(0)
547 const liveCommand = server.live
549 const liveAttributes = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.store.channel.id }
550 const live = await liveCommand.create({ fields: liveAttributes })
552 const ffmpegCommand = await liveCommand.sendRTMPStreamInVideo({ videoId: live.id })
553 await liveCommand.waitUntilPublished({ videoId: live.id })
555 const body = await command.advancedVideoSearch({ search: { isLive: true } })
557 expect(body.total).to.equal(1)
558 expect(body.data[0].name).to.equal('live')
560 await stopFfmpeg(ffmpegCommand)
564 after(async function () {
565 await cleanupTests([ server ])