import nock from 'nock' import { gql } from 'apollo-server-micro' import { MultiMatchQuery, SearchkitConfig } from '@searchkit/sdk' import { setupTestServer, callQuery } from './support/helper' import HitsMock from './__mock-data__/HitResolver/Hits.json' import HighlightHitsMock from './__mock-data__/HitResolver/HighlightHits.json' describe('Hits Resolver', () => { describe('should return as expected', () => { const runQuery = async ( query = '', page = { size: 10, from: 0 }, sorting?: string, includeHighlight?: boolean ) => { const gql = ` { results(query: "${query}") { hits(page: {size: ${page.size}, from: ${page.from}} ${ sorting ? `, sortBy: "${sorting}"` : '' }) { sortedBy items { ... on ResultHit { id fields { writers actors } ${includeHighlight ? 'highlight' : ''} } } } } } ` const response = await callQuery({ gql }) return response } it('should return correct Results', async () => { const config: SearchkitConfig = { host: 'http://localhost:9200', index: 'movies', hits: { fields: ['actors', 'writers'] }, query: new MultiMatchQuery({ fields: ['actors', 'writers', 'title^4', 'plot'] }) } setupTestServer({ config, addToQueryType: true, typeName: 'ResultSet', hitTypeName: 'ResultHit' }) const scope = nock('http://localhost:9200') .post('/movies/_search') .reply((uri, body) => { expect(body).toMatchInlineSnapshot(` Object { "_source": Object { "includes": Array [ "actors", "writers", ], }, "aggs": Object {}, "from": 0, "size": 10, "sort": Array [ Object { "_score": "desc", }, ], } `) return [200, HitsMock] }) const response = await runQuery() expect(response.body.data).toMatchSnapshot() expect(response.status).toEqual(200) }) it('should return correct Results with https', async () => { const config: SearchkitConfig = { host: 'https://localhost:9200', index: 'movies', hits: { fields: ['actors', 'writers'] }, query: new MultiMatchQuery({ fields: ['actors', 'writers', 'title^4', 'plot'] }) } setupTestServer({ config, addToQueryType: true, typeName: 'ResultSet', hitTypeName: 'ResultHit' }) const scope = nock('https://localhost:9200') .post('/movies/_search') .reply((uri, body) => { expect(body).toMatchInlineSnapshot(` Object { "aggs": Object {}, "from": 0, "size": 10, "sort": Array [ Object { "_score": "desc", }, ], } `) return [200, HitsMock] }) const response = await runQuery() expect(response.status).toEqual(200) }) it('should return correct Results on page 2', async () => { const config: SearchkitConfig = { host: 'http://localhost:9200', index: 'movies', hits: { fields: ['actors', 'writers'] }, query: new MultiMatchQuery({ fields: ['actors', 'writers', 'title^4', 'plot'] }) } const scope = nock('http://localhost:9200') .post('/movies/_search') .reply((uri, body) => { expect(body).toMatchInlineSnapshot(` Object { "_source": Object { "includes": Array [ "actors", "writers", ], }, "aggs": Object {}, "from": 10, "size": 10, "sort": Array [ Object { "_score": "desc", }, ], } `) return [200, HitsMock] }) setupTestServer({ config, addToQueryType: true, typeName: 'ResultSet', hitTypeName: 'ResultHit' }) const response = await runQuery('', { size: 10, from: 10 }) expect(response.body.data).toMatchSnapshot() expect(response.status).toEqual(200) }) it('should provide sorting options', async () => { const config: SearchkitConfig = { host: 'http://localhost:9200', index: 'movies', hits: { fields: ['actors', 'writers'] }, sortOptions: [ { id: 'relevance', label: 'Relevance', field: '_score' }, { id: 'released', label: 'Recent Releases', field: { released: 'desc' } } ], query: new MultiMatchQuery({ fields: ['actors', 'writers', 'title^4', 'plot'] }) } setupTestServer({ config, addToQueryType: true, typeName: 'ResultSet', hitTypeName: 'ResultHit' }) const scope = nock('http://localhost:9200') .post('/movies/_search') .reply((uri, body) => { expect(body).toMatchInlineSnapshot(` Object { "_source": Object { "includes": Array [ "actors", "writers", ], }, "aggs": Object {}, "from": 10, "size": 10, "sort": "_score", } `) return [200, HitsMock] }) let response = await runQuery('', { size: 10, from: 10 }, 'relevance') expect(response.body.data).toMatchSnapshot() scope.post('/movies/_search').reply((uri, body) => { expect(body).toMatchInlineSnapshot(` Object { "_source": Object { "includes": Array [ "actors", "writers", ], }, "aggs": Object {}, "from": 10, "size": 10, "sort": Object { "released": "desc", }, } `) return [200, HitsMock] }) response = await runQuery('', { size: 10, from: 10 }, 'released') expect(response.body.data).toMatchSnapshot() expect(response.status).toEqual(200) }) it('should return correct highlight Results', async () => { const config: SearchkitConfig = { host: 'http://localhost:9200', index: 'movies', hits: { fields: ['actors', 'writers'], highlightedFields: [ 'actors', { field: 'writers', config: { pre_tags: [''], post_tags: [''] } } ] }, query: new MultiMatchQuery({ fields: ['actors', 'writers', 'title^4', 'plot'] }) } setupTestServer( { config, addToQueryType: true, typeName: 'ResultSet', hitTypeName: 'ResultHit' }, gql` type Query { root: String } type Mutation { root: String } type HitFields { title: String writers: [String] actors: [String] plot: String poster: String } type ResultHit implements SKHit { id: ID! fields: HitFields highlight: String } `, { ResultHit: { highlight: (hit: any) => JSON.stringify(hit.highlight) } } ) const scope = nock('http://localhost:9200') .post('/movies/_search') .reply((uri, body) => { expect(body).toMatchInlineSnapshot(` Object { "_source": Object { "includes": Array [ "actors", "writers", ], }, "aggs": Object {}, "from": 0, "highlight": Object { "fields": Object { "actors": Object {}, "writers": Object { "post_tags": Array [ "", ], "pre_tags": Array [ "", ], }, }, }, "query": Object { "bool": Object { "should": Array [ Object { "multi_match": Object { "fields": Array [ "actors", "writers", "title^4", "plot", ], "operator": "and", "query": "al", "type": "best_fields", }, }, Object { "multi_match": Object { "fields": Array [ "actors", "writers", "title^4", "plot", ], "query": "al", "type": "cross_fields", }, }, Object { "multi_match": Object { "fields": Array [ "actors", "writers", "title^4", "plot", ], "query": "al", "type": "phrase", }, }, Object { "multi_match": Object { "fields": Array [ "actors", "writers", "title^4", "plot", ], "query": "al", "type": "phrase_prefix", }, }, ], }, }, "size": 10, "sort": Array [ Object { "_score": "desc", }, ], } `) return [200, HighlightHitsMock] }) const response = await runQuery('al', { size: 10, from: 0 }, undefined, true) expect(response.body.data).toMatchSnapshot() expect(response.status).toEqual(200) }) }) })