From 3521ab8fc01da85fa804439ca6e297e6fb364c58 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 10 Jun 2020 10:58:44 +0200 Subject: [PATCH] Add search index tests --- server/controllers/api/config.ts | 2 +- server/controllers/api/search.ts | 6 +- server/tests/api/search/index.ts | 2 + server/tests/api/search/search-channels.ts | 79 ++++++ server/tests/api/search/search-index.ts | 252 ++++++++++++++++++++ shared/extra-utils/search/video-channels.ts | 15 +- 6 files changed, 351 insertions(+), 5 deletions(-) create mode 100644 server/tests/api/search/search-channels.ts create mode 100644 server/tests/api/search/search-index.ts diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 1d48b4b26..b80ea4902 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts @@ -463,7 +463,7 @@ function customConfig (): CustomConfig { disableLocalSearch: CONFIG.SEARCH.SEARCH_INDEX.DISABLE_LOCAL_SEARCH, isDefaultSearch: CONFIG.SEARCH.SEARCH_INDEX.IS_DEFAULT_SEARCH } - }, + } } } diff --git a/server/controllers/api/search.ts b/server/controllers/api/search.ts index e08e1d79f..1dea77d29 100644 --- a/server/controllers/api/search.ts +++ b/server/controllers/api/search.ts @@ -76,7 +76,7 @@ function searchVideoChannels (req: express.Request, res: express.Response) { // @username -> username to search in DB if (query.search.startsWith('@')) query.search = query.search.replace(/^@/, '') - if (isSearchIndexEnabled(query)) { + if (isSearchIndexSearch(query)) { return searchVideoChannelsIndex(query, res) } @@ -157,7 +157,7 @@ function searchVideos (req: express.Request, res: express.Response) { return searchVideoURI(search, res) } - if (isSearchIndexEnabled(query)) { + if (isSearchIndexSearch(query)) { return searchVideosIndex(query, res) } @@ -226,7 +226,7 @@ async function searchVideoURI (url: string, res: express.Response) { }) } -function isSearchIndexEnabled (query: SearchTargetQuery) { +function isSearchIndexSearch (query: SearchTargetQuery) { if (query.searchTarget === 'search-index') return true const searchIndexConfig = CONFIG.SEARCH.SEARCH_INDEX diff --git a/server/tests/api/search/index.ts b/server/tests/api/search/index.ts index d573c8a9e..232c1f2a4 100644 --- a/server/tests/api/search/index.ts +++ b/server/tests/api/search/index.ts @@ -1,3 +1,5 @@ import './search-activitypub-video-channels' import './search-activitypub-videos' +import './search-index' import './search-videos' +import './search-channels' diff --git a/server/tests/api/search/search-channels.ts b/server/tests/api/search/search-channels.ts new file mode 100644 index 000000000..daca2aebe --- /dev/null +++ b/server/tests/api/search/search-channels.ts @@ -0,0 +1,79 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ + +import 'mocha' +import * as chai from 'chai' +import { searchVideoChannel, advancedVideoChannelSearch } from '@shared/extra-utils/search/video-channels' +import { + addVideoChannel, + cleanupTests, + createUser, + flushAndRunServer, + ServerInfo, + setAccessTokensToServers +} from '../../../../shared/extra-utils' +import { VideoChannel } from '@shared/models' + +const expect = chai.expect + +describe('Test channels search', function () { + let server: ServerInfo = null + + before(async function () { + this.timeout(30000) + + server = await flushAndRunServer(1) + + await setAccessTokensToServers([ server ]) + + { + await createUser({ url: server.url, accessToken: server.accessToken, username: 'user1', password: 'password' }) + const channel = { + name: 'squall_channel', + displayName: 'Squall channel' + } + await addVideoChannel(server.url, server.accessToken, channel) + } + }) + + it('Should make a simple search and not have results', async function () { + const res = await searchVideoChannel(server.url, 'abc') + + expect(res.body.total).to.equal(0) + expect(res.body.data).to.have.lengthOf(0) + }) + + it('Should make a search and have results', async function () { + { + const search = { + search: 'Squall', + start: 0, + count: 1 + } + const res = await advancedVideoChannelSearch(server.url, search) + expect(res.body.total).to.equal(1) + expect(res.body.data).to.have.lengthOf(1) + + const channel: VideoChannel = res.body.data[0] + expect(channel.name).to.equal('squall_channel') + expect(channel.displayName).to.equal('Squall channel') + } + + { + const search = { + search: 'Squall', + start: 1, + count: 1 + } + + const res = await advancedVideoChannelSearch(server.url, search) + + expect(res.body.total).to.equal(1) + + expect(res.body.data).to.have.lengthOf(0) + } + }) + + after(async function () { + await cleanupTests([ server ]) + }) +}) diff --git a/server/tests/api/search/search-index.ts b/server/tests/api/search/search-index.ts new file mode 100644 index 000000000..2354aaa8b --- /dev/null +++ b/server/tests/api/search/search-index.ts @@ -0,0 +1,252 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ + +import 'mocha' +import * as chai from 'chai' +import { + cleanupTests, + flushAndRunServer, + searchVideo, + ServerInfo, + setAccessTokensToServers, + updateCustomSubConfig, + uploadVideo, + advancedVideosSearch, + immutableAssign +} from '../../../../shared/extra-utils' +import { searchVideoChannel, advancedVideoChannelSearch } from '@shared/extra-utils/search/video-channels' +import { VideosSearchQuery, Video, VideoChannel } from '@shared/models' + +const expect = chai.expect + +describe('Test videos search', function () { + let server: ServerInfo = null + const localVideoName = 'local video' + new Date().toISOString() + + before(async function () { + this.timeout(30000) + + server = await flushAndRunServer(1) + + await setAccessTokensToServers([ server ]) + + await uploadVideo(server.url, server.accessToken, { name: localVideoName }) + }) + + describe('Default search', async function () { + + it('Should make a local videos search by default', async function () { + this.timeout(10000) + + await updateCustomSubConfig(server.url, server.accessToken, { + search: { + searchIndex: { + enabled: true, + isDefaultSearch: false, + disableLocalSearch: false + } + } + }) + + const res = await searchVideo(server.url, 'local video') + + expect(res.body.total).to.equal(1) + expect(res.body.data[0].name).to.equal(localVideoName) + }) + + it('Should make a local channels search by default', async function () { + const res = await searchVideoChannel(server.url, 'root') + + expect(res.body.total).to.equal(1) + expect(res.body.data[0].name).to.equal('root_channel') + expect(res.body.data[0].host).to.equal('localhost:' + server.port) + }) + + it('Should make an index videos search by default', async function () { + await updateCustomSubConfig(server.url, server.accessToken, { + search: { + searchIndex: { + enabled: true, + isDefaultSearch: true, + disableLocalSearch: false + } + } + }) + + const res = await searchVideo(server.url, 'local video') + expect(res.body.total).to.be.greaterThan(2) + }) + + it('Should make an index channels search by default', async function () { + const res = await searchVideoChannel(server.url, 'root') + expect(res.body.total).to.be.greaterThan(2) + }) + + it('Should make an index videos search if local search is disabled', async function () { + await updateCustomSubConfig(server.url, server.accessToken, { + search: { + searchIndex: { + enabled: true, + isDefaultSearch: false, + disableLocalSearch: true + } + } + }) + + const res = await searchVideo(server.url, 'local video') + expect(res.body.total).to.be.greaterThan(2) + }) + + it('Should make an index channels search if local search is disabled', async function () { + const res = await searchVideoChannel(server.url, 'root') + expect(res.body.total).to.be.greaterThan(2) + }) + }) + + describe('Videos search', async function () { + + it('Should make a simple search and not have results', async function () { + const res = await searchVideo(server.url, 'a'.repeat(500)) + + expect(res.body.total).to.equal(0) + expect(res.body.data).to.have.lengthOf(0) + }) + + it('Should make a simple search and have results', async function () { + const res = await searchVideo(server.url, 'What is PeerTube') + + expect(res.body.total).to.be.greaterThan(1) + }) + + it('Should make a complex search', async function () { + + async function check (search: VideosSearchQuery, exists = true) { + const res = await advancedVideosSearch(server.url, search) + + if (exists === false) { + expect(res.body.total).to.equal(0) + expect(res.body.data).to.have.lengthOf(0) + return + } + + expect(res.body.total).to.equal(1) + expect(res.body.data).to.have.lengthOf(1) + + const video: Video = res.body.data[0] + + expect(video.name).to.equal('What is PeerTube?') + expect(video.category.label).to.equal('Science & Technology') + expect(video.licence.label).to.equal('Attribution - Share Alike') + expect(video.privacy.label).to.equal('Public') + expect(video.duration).to.equal(113) + expect(video.thumbnailUrl.startsWith('https://framatube.org/static/thumbnails')).to.be.true + + expect(video.account.host).to.equal('framatube.org') + expect(video.account.name).to.equal('framasoft') + expect(video.account.url).to.equal('https://framatube.org/accounts/framasoft') + expect(video.account.avatar).to.exist + + expect(video.channel.host).to.equal('framatube.org') + expect(video.channel.name).to.equal('bf54d359-cfad-4935-9d45-9d6be93f63e8') + expect(video.channel.url).to.equal('https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8') + expect(video.channel.avatar).to.exist + } + + const baseSearch: VideosSearchQuery = { + search: 'what is peertube', + start: 0, + count: 2, + categoryOneOf: [ 15 ], + licenceOneOf: [ 2 ], + tagsAllOf: [ 'framasoft', 'peertube' ], + startDate: '2018-10-01T10:50:46.396Z', + endDate: '2018-10-01T10:55:46.396Z' + } + + { + await check(baseSearch) + } + + { + const search = immutableAssign(baseSearch, { startDate: '2018-10-01T10:54:46.396Z' }) + await check(search, false) + } + + { + const search = immutableAssign(baseSearch, { tagsAllOf: [ 'toto', 'framasoft' ] }) + await check(search, false) + } + + { + const search = immutableAssign(baseSearch, { durationMin: 2000 }) + await check(search, false) + } + + { + const search = immutableAssign(baseSearch, { nsfw: 'true' }) + await check(search, false) + } + + { + const search = immutableAssign(baseSearch, { nsfw: 'false' }) + await check(search, true) + } + + { + const search = immutableAssign(baseSearch, { nsfw: 'both' }) + await check(search, true) + } + }) + + it('Should have a correct pagination', async function () { + const search = { + search: 'video', + start: 0, + count: 5 + } + + const res = await advancedVideosSearch(server.url, search) + + expect(res.body.total).to.be.greaterThan(5) + expect(res.body.data).to.have.lengthOf(5) + }) + }) + + describe('Channels search', async function () { + + it('Should make a simple search and not have results', async function () { + const res = await searchVideoChannel(server.url, 'a'.repeat(500)) + + expect(res.body.total).to.equal(0) + expect(res.body.data).to.have.lengthOf(0) + }) + + it('Should make a search and have results', async function () { + const res = await advancedVideoChannelSearch(server.url, { search: 'Framasoft', sort: 'createdAt' }) + + expect(res.body.total).to.be.greaterThan(0) + expect(res.body.data).to.have.length.greaterThan(0) + + const videoChannel: VideoChannel = res.body.data[0] + expect(videoChannel.url).to.equal('https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8') + expect(videoChannel.host).to.equal('framatube.org') + expect(videoChannel.avatar).to.exist + expect(videoChannel.displayName).to.exist + + expect(videoChannel.ownerAccount.url).to.equal('https://framatube.org/accounts/framasoft') + expect(videoChannel.ownerAccount.name).to.equal('framasoft') + expect(videoChannel.ownerAccount.host).to.equal('framatube.org') + expect(videoChannel.ownerAccount.avatar).to.exist + }) + + it('Should have a correct pagination', async function () { + const res = await advancedVideoChannelSearch(server.url, { search: 'root', start: 0, count: 2 }) + + expect(res.body.total).to.be.greaterThan(2) + expect(res.body.data).to.have.lengthOf(2) + }) + }) + + after(async function () { + await cleanupTests([ server ]) + }) +}) diff --git a/shared/extra-utils/search/video-channels.ts b/shared/extra-utils/search/video-channels.ts index 0532134ae..d16210530 100644 --- a/shared/extra-utils/search/video-channels.ts +++ b/shared/extra-utils/search/video-channels.ts @@ -1,3 +1,4 @@ +import { VideoChannelsSearchQuery } from '@shared/models' import { makeGetRequest } from '../requests/requests' function searchVideoChannel (url: string, search: string, token?: string, statusCodeExpected = 200) { @@ -15,8 +16,20 @@ function searchVideoChannel (url: string, search: string, token?: string, status }) } +function advancedVideoChannelSearch (url: string, search: VideoChannelsSearchQuery) { + const path = '/api/v1/search/video-channels' + + return makeGetRequest({ + url, + path, + query: search, + statusCodeExpected: 200 + }) +} + // --------------------------------------------------------------------------- export { - searchVideoChannel + searchVideoChannel, + advancedVideoChannelSearch }