1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
3 import * as chai from 'chai'
4 import { wait } from '@shared/core-utils'
5 import { VideoPrivacy } from '@shared/models'
12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultChannelAvatar,
15 setDefaultVideoChannel,
17 } from '@shared/server-commands'
19 const expect = chai.expect
21 describe('Test videos search', function () {
22 let server: PeerTubeServer
23 let remoteServer: PeerTubeServer
26 let videoShortUUID: string
28 let command: SearchCommand
30 before(async function () {
33 const servers = await Promise.all([
34 createSingleServer(1),
38 remoteServer = servers[1]
40 await setAccessTokensToServers([ server, remoteServer ])
41 await setDefaultVideoChannel([ server, remoteServer ])
42 await setDefaultChannelAvatar(server)
43 await setDefaultAccountAvatar(servers)
47 name: '1111 2222 3333',
48 fixture: '60fps_720p_small.mp4', // 2 seconds
54 await server.videos.upload({ attributes: attributes1 })
56 const attributes2 = { ...attributes1, name: attributes1.name + ' - 2', fixture: 'video_short.mp4' }
57 await server.videos.upload({ attributes: attributes2 })
60 const attributes3 = { ...attributes1, name: attributes1.name + ' - 3', language: undefined }
61 const { id, uuid, shortUUID } = await server.videos.upload({ attributes: attributes3 })
63 videoShortUUID = shortUUID
65 await server.captions.add({
68 fixture: 'subtitle-good2.vtt',
69 mimeType: 'application/octet-stream'
72 await server.captions.add({
75 fixture: 'subtitle-good2.vtt',
76 mimeType: 'application/octet-stream'
80 const attributes4 = { ...attributes1, name: attributes1.name + ' - 4', language: 'pl', nsfw: true }
81 await server.videos.upload({ attributes: attributes4 })
85 startDate = new Date().toISOString()
87 const attributes5 = { ...attributes1, name: attributes1.name + ' - 5', licence: 2, language: undefined }
88 await server.videos.upload({ attributes: attributes5 })
90 const attributes6 = { ...attributes1, name: attributes1.name + ' - 6', tags: [ 't1', 't2' ] }
91 await server.videos.upload({ attributes: attributes6 })
93 const attributes7 = { ...attributes1, name: attributes1.name + ' - 7', originallyPublishedAt: '2019-02-12T09:58:08.286Z' }
94 await server.videos.upload({ attributes: attributes7 })
96 const attributes8 = { ...attributes1, name: attributes1.name + ' - 8', licence: 4 }
97 await server.videos.upload({ attributes: attributes8 })
102 name: '3333 4444 5555',
103 fixture: 'video_short.mp4',
108 await server.videos.upload({ attributes })
110 await server.videos.upload({ attributes: { ...attributes, name: attributes.name + ' duplicate' } })
115 name: '6666 7777 8888',
116 fixture: 'video_short.mp4',
121 await server.videos.upload({ attributes })
125 const attributes1 = {
127 tags: [ 'aaaa', 'bbbb', 'cccc' ],
130 await server.videos.upload({ attributes: attributes1 })
131 await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
133 await server.videos.upload({ attributes: { ...attributes1, tags: [ 'cccc', 'dddd' ] } })
134 await server.videos.upload({ attributes: { ...attributes1, tags: [ 'eeee', 'ffff' ] } })
138 const attributes1 = {
142 await server.videos.upload({ attributes: attributes1 })
143 await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
147 await remoteServer.videos.upload({ attributes: { name: 'remote video 1' } })
148 await remoteServer.videos.upload({ attributes: { name: 'remote video 2' } })
151 await doubleFollow(server, remoteServer)
153 command = server.search
156 it('Should make a simple search and not have results', async function () {
157 const body = await command.searchVideos({ search: 'abc' })
159 expect(body.total).to.equal(0)
160 expect(body.data).to.have.lengthOf(0)
163 it('Should make a simple search and have results', async function () {
164 const body = await command.searchVideos({ search: '4444 5555 duplicate' })
166 expect(body.total).to.equal(2)
168 const videos = body.data
169 expect(videos).to.have.lengthOf(2)
172 expect(videos[0].name).to.equal('3333 4444 5555 duplicate')
173 expect(videos[1].name).to.equal('3333 4444 5555')
176 it('Should make a search on tags too, and have results', async function () {
181 const body = await command.advancedVideoSearch({ search })
183 expect(body.total).to.equal(2)
185 const videos = body.data
186 expect(videos).to.have.lengthOf(2)
189 expect(videos[0].name).to.equal('aaaa 2')
190 expect(videos[1].name).to.equal('9999')
193 it('Should filter on tags without a search', async function () {
195 tagsAllOf: [ 'bbbb' ]
197 const body = await command.advancedVideoSearch({ search })
199 expect(body.total).to.equal(2)
201 const videos = body.data
202 expect(videos).to.have.lengthOf(2)
204 expect(videos[0].name).to.equal('9999')
205 expect(videos[1].name).to.equal('9999')
208 it('Should filter on category without a search', async function () {
212 const body = await command.advancedVideoSearch({ search })
214 expect(body.total).to.equal(1)
216 const videos = body.data
217 expect(videos).to.have.lengthOf(1)
219 expect(videos[0].name).to.equal('6666 7777 8888')
222 it('Should search by tags (one of)', async function () {
225 categoryOneOf: [ 1 ],
226 tagsOneOf: [ 'aAaa', 'ffff' ]
230 const body = await command.advancedVideoSearch({ search: query })
231 expect(body.total).to.equal(2)
235 const body = await command.advancedVideoSearch({ search: { ...query, tagsOneOf: [ 'blabla' ] } })
236 expect(body.total).to.equal(0)
240 it('Should search by tags (all of)', async function () {
243 categoryOneOf: [ 1 ],
244 tagsAllOf: [ 'CCcc' ]
248 const body = await command.advancedVideoSearch({ search: query })
249 expect(body.total).to.equal(2)
253 const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'blAbla' ] } })
254 expect(body.total).to.equal(0)
258 const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'bbbb', 'CCCC' ] } })
259 expect(body.total).to.equal(1)
263 it('Should search by category', async function () {
270 const body = await command.advancedVideoSearch({ search: query })
271 expect(body.total).to.equal(1)
272 expect(body.data[0].name).to.equal('6666 7777 8888')
276 const body = await command.advancedVideoSearch({ search: { ...query, categoryOneOf: [ 2 ] } })
277 expect(body.total).to.equal(0)
281 it('Should search by licence', async function () {
288 const body = await command.advancedVideoSearch({ search: query })
289 expect(body.total).to.equal(2)
290 expect(body.data[0].name).to.equal('3333 4444 5555')
291 expect(body.data[1].name).to.equal('3333 4444 5555 duplicate')
295 const body = await command.advancedVideoSearch({ search: { ...query, licenceOneOf: [ 3 ] } })
296 expect(body.total).to.equal(0)
300 it('Should search by languages', async function () {
302 search: '1111 2222 3333',
303 languageOneOf: [ 'pl', 'en' ]
307 const body = await command.advancedVideoSearch({ search: query })
308 expect(body.total).to.equal(2)
309 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
310 expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
314 const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'pl', 'en', '_unknown' ] } })
315 expect(body.total).to.equal(3)
316 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
317 expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
318 expect(body.data[2].name).to.equal('1111 2222 3333 - 5')
322 const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'eo' ] } })
323 expect(body.total).to.equal(0)
327 it('Should search by start date', async function () {
329 search: '1111 2222 3333',
333 const body = await command.advancedVideoSearch({ search: query })
334 expect(body.total).to.equal(4)
336 const videos = body.data
337 expect(videos[0].name).to.equal('1111 2222 3333 - 5')
338 expect(videos[1].name).to.equal('1111 2222 3333 - 6')
339 expect(videos[2].name).to.equal('1111 2222 3333 - 7')
340 expect(videos[3].name).to.equal('1111 2222 3333 - 8')
343 it('Should make an advanced search', async function () {
345 search: '1111 2222 3333',
346 languageOneOf: [ 'pl', 'fr' ],
348 nsfw: 'false' as 'false',
349 licenceOneOf: [ 1, 4 ]
352 const body = await command.advancedVideoSearch({ search: query })
353 expect(body.total).to.equal(4)
355 const videos = body.data
356 expect(videos[0].name).to.equal('1111 2222 3333')
357 expect(videos[1].name).to.equal('1111 2222 3333 - 6')
358 expect(videos[2].name).to.equal('1111 2222 3333 - 7')
359 expect(videos[3].name).to.equal('1111 2222 3333 - 8')
362 it('Should make an advanced search and sort results', async function () {
364 search: '1111 2222 3333',
365 languageOneOf: [ 'pl', 'fr' ],
367 nsfw: 'false' as 'false',
368 licenceOneOf: [ 1, 4 ],
372 const body = await command.advancedVideoSearch({ search: query })
373 expect(body.total).to.equal(4)
375 const videos = body.data
376 expect(videos[0].name).to.equal('1111 2222 3333 - 8')
377 expect(videos[1].name).to.equal('1111 2222 3333 - 7')
378 expect(videos[2].name).to.equal('1111 2222 3333 - 6')
379 expect(videos[3].name).to.equal('1111 2222 3333')
382 it('Should make an advanced search and only show the first result', async function () {
384 search: '1111 2222 3333',
385 languageOneOf: [ 'pl', 'fr' ],
387 nsfw: 'false' as 'false',
388 licenceOneOf: [ 1, 4 ],
394 const body = await command.advancedVideoSearch({ search: query })
395 expect(body.total).to.equal(4)
397 const videos = body.data
398 expect(videos[0].name).to.equal('1111 2222 3333 - 8')
401 it('Should make an advanced search and only show the last result', async function () {
403 search: '1111 2222 3333',
404 languageOneOf: [ 'pl', 'fr' ],
406 nsfw: 'false' as 'false',
407 licenceOneOf: [ 1, 4 ],
413 const body = await command.advancedVideoSearch({ search: query })
414 expect(body.total).to.equal(4)
416 const videos = body.data
417 expect(videos[0].name).to.equal('1111 2222 3333')
420 it('Should search on originally published date', async function () {
422 search: '1111 2222 3333',
423 languageOneOf: [ 'pl', 'fr' ],
425 nsfw: 'false' as 'false',
426 licenceOneOf: [ 1, 4 ]
430 const query = { ...baseQuery, originallyPublishedStartDate: '2019-02-11T09:58:08.286Z' }
431 const body = await command.advancedVideoSearch({ search: query })
433 expect(body.total).to.equal(1)
434 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
438 const query = { ...baseQuery, originallyPublishedEndDate: '2019-03-11T09:58:08.286Z' }
439 const body = await command.advancedVideoSearch({ search: query })
441 expect(body.total).to.equal(1)
442 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
446 const query = { ...baseQuery, originallyPublishedEndDate: '2019-01-11T09:58:08.286Z' }
447 const body = await command.advancedVideoSearch({ search: query })
449 expect(body.total).to.equal(0)
453 const query = { ...baseQuery, originallyPublishedStartDate: '2019-03-11T09:58:08.286Z' }
454 const body = await command.advancedVideoSearch({ search: query })
456 expect(body.total).to.equal(0)
462 originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
463 originallyPublishedEndDate: '2019-01-10T09:58:08.286Z'
465 const body = await command.advancedVideoSearch({ search: query })
467 expect(body.total).to.equal(0)
473 originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
474 originallyPublishedEndDate: '2019-04-11T09:58:08.286Z'
476 const body = await command.advancedVideoSearch({ search: query })
478 expect(body.total).to.equal(1)
479 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
483 it('Should search by UUID', async function () {
484 const search = videoUUID
485 const body = await command.advancedVideoSearch({ search: { search } })
487 expect(body.total).to.equal(1)
488 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
491 it('Should filter by UUIDs', async function () {
492 for (const uuid of [ videoUUID, videoShortUUID ]) {
493 const body = await command.advancedVideoSearch({ search: { uuids: [ uuid ] } })
495 expect(body.total).to.equal(1)
496 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
500 const body = await command.advancedVideoSearch({ search: { uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] } })
502 expect(body.total).to.equal(0)
503 expect(body.data).to.have.lengthOf(0)
507 it('Should search by host', async function () {
509 const body = await command.advancedVideoSearch({ search: { search: '6666 7777 8888', host: server.host } })
510 expect(body.total).to.equal(1)
511 expect(body.data[0].name).to.equal('6666 7777 8888')
515 const body = await command.advancedVideoSearch({ search: { search: '1111', host: 'example.com' } })
516 expect(body.total).to.equal(0)
517 expect(body.data).to.have.lengthOf(0)
521 const body = await command.advancedVideoSearch({ search: { search: 'remote', host: remoteServer.host } })
522 expect(body.total).to.equal(2)
523 expect(body.data).to.have.lengthOf(2)
524 expect(body.data[0].name).to.equal('remote video 1')
525 expect(body.data[1].name).to.equal('remote video 2')
529 it('Should search by live', async function () {
535 searchIndex: { enabled: false }
537 live: { enabled: true }
539 await server.config.updateCustomSubConfig({ newConfig })
543 const body = await command.advancedVideoSearch({ search: { isLive: true } })
545 expect(body.total).to.equal(0)
546 expect(body.data).to.have.lengthOf(0)
550 const liveCommand = server.live
552 const liveAttributes = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.store.channel.id }
553 const live = await liveCommand.create({ fields: liveAttributes })
555 const ffmpegCommand = await liveCommand.sendRTMPStreamInVideo({ videoId: live.id })
556 await liveCommand.waitUntilPublished({ videoId: live.id })
558 const body = await command.advancedVideoSearch({ search: { isLive: true } })
560 expect(body.total).to.equal(1)
561 expect(body.data[0].name).to.equal('live')
563 await stopFfmpeg(ffmpegCommand)
567 after(async function () {
568 await cleanupTests([ server ])