1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
3 import { expect } 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 describe('Test videos search', function () {
20 let server: PeerTubeServer
21 let remoteServer: PeerTubeServer
24 let videoShortUUID: string
26 let command: SearchCommand
28 before(async function () {
31 const servers = await Promise.all([
32 createSingleServer(1),
36 remoteServer = servers[1]
38 await setAccessTokensToServers([ server, remoteServer ])
39 await setDefaultVideoChannel([ server, remoteServer ])
40 await setDefaultChannelAvatar(server)
41 await setDefaultAccountAvatar(servers)
45 name: '1111 2222 3333',
46 fixture: '60fps_720p_small.mp4', // 2 seconds
52 await server.videos.upload({ attributes: attributes1 })
54 const attributes2 = { ...attributes1, name: attributes1.name + ' - 2', fixture: 'video_short.mp4' }
55 await server.videos.upload({ attributes: attributes2 })
58 const attributes3 = { ...attributes1, name: attributes1.name + ' - 3', language: undefined }
59 const { id, uuid, shortUUID } = await server.videos.upload({ attributes: attributes3 })
61 videoShortUUID = shortUUID
63 await server.captions.add({
66 fixture: 'subtitle-good2.vtt',
67 mimeType: 'application/octet-stream'
70 await server.captions.add({
73 fixture: 'subtitle-good2.vtt',
74 mimeType: 'application/octet-stream'
78 const attributes4 = { ...attributes1, name: attributes1.name + ' - 4', language: 'pl', nsfw: true }
79 await server.videos.upload({ attributes: attributes4 })
83 startDate = new Date().toISOString()
85 const attributes5 = { ...attributes1, name: attributes1.name + ' - 5', licence: 2, language: undefined }
86 await server.videos.upload({ attributes: attributes5 })
88 const attributes6 = { ...attributes1, name: attributes1.name + ' - 6', tags: [ 't1', 't2' ] }
89 await server.videos.upload({ attributes: attributes6 })
91 const attributes7 = { ...attributes1, name: attributes1.name + ' - 7', originallyPublishedAt: '2019-02-12T09:58:08.286Z' }
92 await server.videos.upload({ attributes: attributes7 })
94 const attributes8 = { ...attributes1, name: attributes1.name + ' - 8', licence: 4 }
95 await server.videos.upload({ attributes: attributes8 })
100 name: '3333 4444 5555',
101 fixture: 'video_short.mp4',
106 await server.videos.upload({ attributes })
108 await server.videos.upload({ attributes: { ...attributes, name: attributes.name + ' duplicate' } })
113 name: '6666 7777 8888',
114 fixture: 'video_short.mp4',
119 await server.videos.upload({ attributes })
123 const attributes1 = {
125 tags: [ 'aaaa', 'bbbb', 'cccc' ],
128 await server.videos.upload({ attributes: attributes1 })
129 await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
131 await server.videos.upload({ attributes: { ...attributes1, tags: [ 'cccc', 'dddd' ] } })
132 await server.videos.upload({ attributes: { ...attributes1, tags: [ 'eeee', 'ffff' ] } })
136 const attributes1 = {
140 await server.videos.upload({ attributes: attributes1 })
141 await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
145 await remoteServer.videos.upload({ attributes: { name: 'remote video 1' } })
146 await remoteServer.videos.upload({ attributes: { name: 'remote video 2' } })
149 await doubleFollow(server, remoteServer)
151 command = server.search
154 it('Should make a simple search and not have results', async function () {
155 const body = await command.searchVideos({ search: 'abc' })
157 expect(body.total).to.equal(0)
158 expect(body.data).to.have.lengthOf(0)
161 it('Should make a simple search and have results', async function () {
162 const body = await command.searchVideos({ search: '4444 5555 duplicate' })
164 expect(body.total).to.equal(2)
166 const videos = body.data
167 expect(videos).to.have.lengthOf(2)
170 expect(videos[0].name).to.equal('3333 4444 5555 duplicate')
171 expect(videos[1].name).to.equal('3333 4444 5555')
174 it('Should make a search on tags too, and have results', async function () {
179 const body = await command.advancedVideoSearch({ search })
181 expect(body.total).to.equal(2)
183 const videos = body.data
184 expect(videos).to.have.lengthOf(2)
187 expect(videos[0].name).to.equal('aaaa 2')
188 expect(videos[1].name).to.equal('9999')
191 it('Should filter on tags without a search', async function () {
193 tagsAllOf: [ 'bbbb' ]
195 const body = await command.advancedVideoSearch({ search })
197 expect(body.total).to.equal(2)
199 const videos = body.data
200 expect(videos).to.have.lengthOf(2)
202 expect(videos[0].name).to.equal('9999')
203 expect(videos[1].name).to.equal('9999')
206 it('Should filter on category without a search', async function () {
210 const body = await command.advancedVideoSearch({ search })
212 expect(body.total).to.equal(1)
214 const videos = body.data
215 expect(videos).to.have.lengthOf(1)
217 expect(videos[0].name).to.equal('6666 7777 8888')
220 it('Should search by tags (one of)', async function () {
223 categoryOneOf: [ 1 ],
224 tagsOneOf: [ 'aAaa', 'ffff' ]
228 const body = await command.advancedVideoSearch({ search: query })
229 expect(body.total).to.equal(2)
233 const body = await command.advancedVideoSearch({ search: { ...query, tagsOneOf: [ 'blabla' ] } })
234 expect(body.total).to.equal(0)
238 it('Should search by tags (all of)', async function () {
241 categoryOneOf: [ 1 ],
242 tagsAllOf: [ 'CCcc' ]
246 const body = await command.advancedVideoSearch({ search: query })
247 expect(body.total).to.equal(2)
251 const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'blAbla' ] } })
252 expect(body.total).to.equal(0)
256 const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'bbbb', 'CCCC' ] } })
257 expect(body.total).to.equal(1)
261 it('Should search by category', async function () {
268 const body = await command.advancedVideoSearch({ search: query })
269 expect(body.total).to.equal(1)
270 expect(body.data[0].name).to.equal('6666 7777 8888')
274 const body = await command.advancedVideoSearch({ search: { ...query, categoryOneOf: [ 2 ] } })
275 expect(body.total).to.equal(0)
279 it('Should search by licence', async function () {
286 const body = await command.advancedVideoSearch({ search: query })
287 expect(body.total).to.equal(2)
288 expect(body.data[0].name).to.equal('3333 4444 5555')
289 expect(body.data[1].name).to.equal('3333 4444 5555 duplicate')
293 const body = await command.advancedVideoSearch({ search: { ...query, licenceOneOf: [ 3 ] } })
294 expect(body.total).to.equal(0)
298 it('Should search by languages', async function () {
300 search: '1111 2222 3333',
301 languageOneOf: [ 'pl', 'en' ]
305 const body = await command.advancedVideoSearch({ search: query })
306 expect(body.total).to.equal(2)
307 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
308 expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
312 const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'pl', 'en', '_unknown' ] } })
313 expect(body.total).to.equal(3)
314 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
315 expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
316 expect(body.data[2].name).to.equal('1111 2222 3333 - 5')
320 const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'eo' ] } })
321 expect(body.total).to.equal(0)
325 it('Should search by start date', async function () {
327 search: '1111 2222 3333',
331 const body = await command.advancedVideoSearch({ search: query })
332 expect(body.total).to.equal(4)
334 const videos = body.data
335 expect(videos[0].name).to.equal('1111 2222 3333 - 5')
336 expect(videos[1].name).to.equal('1111 2222 3333 - 6')
337 expect(videos[2].name).to.equal('1111 2222 3333 - 7')
338 expect(videos[3].name).to.equal('1111 2222 3333 - 8')
341 it('Should make an advanced search', async function () {
343 search: '1111 2222 3333',
344 languageOneOf: [ 'pl', 'fr' ],
346 nsfw: 'false' as 'false',
347 licenceOneOf: [ 1, 4 ]
350 const body = await command.advancedVideoSearch({ search: query })
351 expect(body.total).to.equal(4)
353 const videos = body.data
354 expect(videos[0].name).to.equal('1111 2222 3333')
355 expect(videos[1].name).to.equal('1111 2222 3333 - 6')
356 expect(videos[2].name).to.equal('1111 2222 3333 - 7')
357 expect(videos[3].name).to.equal('1111 2222 3333 - 8')
360 it('Should make an advanced search and sort results', async function () {
362 search: '1111 2222 3333',
363 languageOneOf: [ 'pl', 'fr' ],
365 nsfw: 'false' as 'false',
366 licenceOneOf: [ 1, 4 ],
370 const body = await command.advancedVideoSearch({ search: query })
371 expect(body.total).to.equal(4)
373 const videos = body.data
374 expect(videos[0].name).to.equal('1111 2222 3333 - 8')
375 expect(videos[1].name).to.equal('1111 2222 3333 - 7')
376 expect(videos[2].name).to.equal('1111 2222 3333 - 6')
377 expect(videos[3].name).to.equal('1111 2222 3333')
380 it('Should make an advanced search and only show the first result', async function () {
382 search: '1111 2222 3333',
383 languageOneOf: [ 'pl', 'fr' ],
385 nsfw: 'false' as 'false',
386 licenceOneOf: [ 1, 4 ],
392 const body = await command.advancedVideoSearch({ search: query })
393 expect(body.total).to.equal(4)
395 const videos = body.data
396 expect(videos[0].name).to.equal('1111 2222 3333 - 8')
399 it('Should make an advanced search and only show the last result', async function () {
401 search: '1111 2222 3333',
402 languageOneOf: [ 'pl', 'fr' ],
404 nsfw: 'false' as 'false',
405 licenceOneOf: [ 1, 4 ],
411 const body = await command.advancedVideoSearch({ search: query })
412 expect(body.total).to.equal(4)
414 const videos = body.data
415 expect(videos[0].name).to.equal('1111 2222 3333')
418 it('Should search on originally published date', async function () {
420 search: '1111 2222 3333',
421 languageOneOf: [ 'pl', 'fr' ],
423 nsfw: 'false' as 'false',
424 licenceOneOf: [ 1, 4 ]
428 const query = { ...baseQuery, originallyPublishedStartDate: '2019-02-11T09:58:08.286Z' }
429 const body = await command.advancedVideoSearch({ search: query })
431 expect(body.total).to.equal(1)
432 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
436 const query = { ...baseQuery, originallyPublishedEndDate: '2019-03-11T09:58:08.286Z' }
437 const body = await command.advancedVideoSearch({ search: query })
439 expect(body.total).to.equal(1)
440 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
444 const query = { ...baseQuery, originallyPublishedEndDate: '2019-01-11T09:58:08.286Z' }
445 const body = await command.advancedVideoSearch({ search: query })
447 expect(body.total).to.equal(0)
451 const query = { ...baseQuery, originallyPublishedStartDate: '2019-03-11T09:58:08.286Z' }
452 const body = await command.advancedVideoSearch({ search: query })
454 expect(body.total).to.equal(0)
460 originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
461 originallyPublishedEndDate: '2019-01-10T09:58:08.286Z'
463 const body = await command.advancedVideoSearch({ search: query })
465 expect(body.total).to.equal(0)
471 originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
472 originallyPublishedEndDate: '2019-04-11T09:58:08.286Z'
474 const body = await command.advancedVideoSearch({ search: query })
476 expect(body.total).to.equal(1)
477 expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
481 it('Should search by UUID', async function () {
482 const search = videoUUID
483 const body = await command.advancedVideoSearch({ search: { search } })
485 expect(body.total).to.equal(1)
486 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
489 it('Should filter by UUIDs', async function () {
490 for (const uuid of [ videoUUID, videoShortUUID ]) {
491 const body = await command.advancedVideoSearch({ search: { uuids: [ uuid ] } })
493 expect(body.total).to.equal(1)
494 expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
498 const body = await command.advancedVideoSearch({ search: { uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] } })
500 expect(body.total).to.equal(0)
501 expect(body.data).to.have.lengthOf(0)
505 it('Should search by host', async function () {
507 const body = await command.advancedVideoSearch({ search: { search: '6666 7777 8888', host: server.host } })
508 expect(body.total).to.equal(1)
509 expect(body.data[0].name).to.equal('6666 7777 8888')
513 const body = await command.advancedVideoSearch({ search: { search: '1111', host: 'example.com' } })
514 expect(body.total).to.equal(0)
515 expect(body.data).to.have.lengthOf(0)
519 const body = await command.advancedVideoSearch({ search: { search: 'remote', host: remoteServer.host } })
520 expect(body.total).to.equal(2)
521 expect(body.data).to.have.lengthOf(2)
522 expect(body.data[0].name).to.equal('remote video 1')
523 expect(body.data[1].name).to.equal('remote video 2')
527 it('Should search by live', async function () {
533 searchIndex: { enabled: false }
535 live: { enabled: true }
537 await server.config.updateCustomSubConfig({ newConfig })
541 const body = await command.advancedVideoSearch({ search: { isLive: true } })
543 expect(body.total).to.equal(0)
544 expect(body.data).to.have.lengthOf(0)
548 const liveCommand = server.live
550 const liveAttributes = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.store.channel.id }
551 const live = await liveCommand.create({ fields: liveAttributes })
553 const ffmpegCommand = await liveCommand.sendRTMPStreamInVideo({ videoId: live.id })
554 await liveCommand.waitUntilPublished({ videoId: live.id })
556 const body = await command.advancedVideoSearch({ search: { isLive: true } })
558 expect(body.total).to.equal(1)
559 expect(body.data[0].name).to.equal('live')
561 await stopFfmpeg(ffmpegCommand)
565 after(async function () {
566 await cleanupTests([ server ])