-
Notifications
You must be signed in to change notification settings - Fork 66.9k
Expand file tree
/
Copy pathapi-combined-search.ts
More file actions
162 lines (141 loc) · 5.94 KB
/
api-combined-search.ts
File metadata and controls
162 lines (141 loc) · 5.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/**
* To be able to run these tests you need to index the fixtures!
* And you need to have an Elasticsearch URL to connect to for the server.
*
* To index the fixtures, run:
*
* ELASTICSEARCH_URL=http://localhost:9200 npm run index-test-fixtures
*
* This will replace any "real" Elasticsearch indexes you might have so
* once you're done working on vitest tests you need to index real
* content again.
*/
import { expect, test, vi } from 'vitest'
import { describeIfElasticsearchURL } from '@/tests/helpers/conditional-runs'
import { get } from '@/tests/helpers/e2etest'
import type { CombinedSearchResponse } from '@/search/types'
if (!process.env.ELASTICSEARCH_URL) {
console.warn(
'None of the API search middleware tests are run because ' +
"the environment variable 'ELASTICSEARCH_URL' is currently not set.",
)
}
const combinedSearchEndpoint = '/api/search/combined-search/v1'
const getSearchEndpointWithParams = (searchParams: URLSearchParams) =>
`${combinedSearchEndpoint}?${searchParams}`
// This suite only runs if $ELASTICSEARCH_URL is set.
describeIfElasticsearchURL('search/combined-autocomplete v1 middleware', () => {
vi.setConfig({ testTimeout: 60 * 1000 })
test('basic search', async () => {
const sp = new URLSearchParams()
sp.set('query', 'how do I')
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(200)
const results = JSON.parse(res.body) as CombinedSearchResponse
expect(results.aiAutocompleteSuggestions.meta).toBeTruthy()
expect(results.aiAutocompleteSuggestions.meta.found.value).toBeGreaterThanOrEqual(1)
expect(results.aiAutocompleteSuggestions.meta.found.relation).toBeTruthy()
expect(results.aiAutocompleteSuggestions.hits).toBeTruthy()
const aiHit = results.aiAutocompleteSuggestions.hits[0]
expect(aiHit.term).toBe('How do I clone a repository?')
expect(aiHit.highlights).toBeTruthy()
expect(aiHit.highlights[0]).toBe('<mark>How do I</mark> clone a repository?')
expect(results.generalSearchResults.meta).toBeTruthy()
expect(results.generalSearchResults.meta.found.value).toBe(0)
// Check that it can be cached at the CDN
expect(res.headers['set-cookie']).toBeUndefined()
expect(res.headers['cache-control']).toContain('public')
expect(res.headers['cache-control']).toMatch(/max-age=[1-9]/)
expect(res.headers['surrogate-control']).toContain('public')
expect(res.headers['surrogate-control']).toMatch(/max-age=[1-9]/)
expect(res.headers['surrogate-key']).toBe('manual-purge')
})
test('invalid version', async () => {
const sp = new URLSearchParams()
sp.set('query', 'rest')
sp.set('version', 'never-heard-of')
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(400)
expect(JSON.parse(res.body).error).toBeTruthy()
})
test('variations on version name', async () => {
const sp = new URLSearchParams()
sp.set('query', 'rest')
const versions = ['enterprise-cloud', 'ghec', 'fpt', 'free-pro-team@latest']
for (const version of versions) {
sp.set('version', version)
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(200)
}
})
test('invalid language', async () => {
const sp = new URLSearchParams()
sp.set('query', 'rest')
sp.set('language', 'xx')
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(400)
expect(JSON.parse(res.body).error).toBeTruthy()
})
test('only english supported', async () => {
const sp = new URLSearchParams()
sp.set('query', 'rest')
sp.set('language', 'ja')
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(400)
expect(JSON.parse(res.body).error).toBeTruthy()
})
test('autocomplete term search', async () => {
const sp = new URLSearchParams()
sp.set('query', 'rest')
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(200)
const results = JSON.parse(res.body) as CombinedSearchResponse
const aiHits = results.aiAutocompleteSuggestions.hits
expect(aiHits.length).toBeGreaterThanOrEqual(2)
expect(aiHits[0].term).toBe(
'How do I manage OAuth app access restrictions for my organization?',
)
expect(aiHits[0].highlights[0]).toBe(
'How do I manage OAuth app access <mark>restrictions</mark> for my organization?',
)
expect(aiHits[1].term).toBe('How do I test my SSH connection to GitHub?')
expect(aiHits[1].highlights[0]).toBe('How do I <mark>test</mark> my SSH connection to GitHub?')
const generalHits = results.generalSearchResults.hits
expect(generalHits.length).toBe(0)
})
test('empty query returns default results', async () => {
const sp = new URLSearchParams()
// No query at all
{
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(200)
const results = JSON.parse(res.body) as CombinedSearchResponse
expect(results).toBeTruthy()
}
// Empty query
{
sp.set('query', '')
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(200)
const results = JSON.parse(res.body) as CombinedSearchResponse
expect(results).toBeTruthy()
}
// Empty when trimmed
{
sp.set('query', ' ')
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(200)
const results = JSON.parse(res.body) as CombinedSearchResponse
expect(results).toBeTruthy()
}
})
test('general search returns fixture results', async () => {
const sp = new URLSearchParams()
sp.set('query', 'foo')
const res = await get(getSearchEndpointWithParams(sp))
expect(res.statusCode).toBe(200)
const results = JSON.parse(res.body) as CombinedSearchResponse
expect(results.generalSearchResults.hits.length).toBeGreaterThanOrEqual(1)
expect(results.generalSearchResults.hits[0].title).toBe('Foo')
})
})