• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2
3const figgyPudding = require('figgy-pudding')
4const getStream = require('get-stream')
5const qs = require('querystring')
6const test = require('tap').test
7const tnock = require('./util/tnock.js')
8
9const OPTS = figgyPudding({ registry: {} })({
10  registry: 'https://mock.reg/'
11})
12
13const REG = OPTS.registry
14const search = require('../index.js')
15
16test('basic test', t => {
17  const query = qs.stringify({
18    text: 'oo',
19    size: 20,
20    from: 0,
21    quality: 0.65,
22    popularity: 0.98,
23    maintenance: 0.5
24  })
25  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
26    objects: [
27      { package: { name: 'cool', version: '1.0.0' } },
28      { package: { name: 'foo', version: '2.0.0' } }
29    ]
30  })
31  return search('oo', OPTS).then(results => {
32    t.similar(results, [{
33      name: 'cool',
34      version: '1.0.0'
35    }, {
36      name: 'foo',
37      version: '2.0.0'
38    }], 'got back an array of search results')
39  })
40})
41
42test('search.stream', t => {
43  const query = qs.stringify({
44    text: 'oo',
45    size: 20,
46    from: 0,
47    quality: 0.65,
48    popularity: 0.98,
49    maintenance: 0.5
50  })
51  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
52    objects: [
53      { package: { name: 'cool', version: '1.0.0', date: new Date().toISOString() } },
54      { package: { name: 'foo', version: '2.0.0' } }
55    ]
56  })
57  return getStream.array(
58    search.stream('oo', OPTS)
59  ).then(results => {
60    t.similar(results, [{
61      name: 'cool',
62      version: '1.0.0'
63    }, {
64      name: 'foo',
65      version: '2.0.0'
66    }], 'has a stream-based API function with identical results')
67  })
68})
69
70test('accepts a limit option', t => {
71  const query = qs.stringify({
72    text: 'oo',
73    size: 3,
74    from: 0,
75    quality: 0.65,
76    popularity: 0.98,
77    maintenance: 0.5
78  })
79  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
80    objects: [
81      { package: { name: 'cool', version: '1.0.0' } },
82      { package: { name: 'cool', version: '1.0.0' } },
83      { package: { name: 'cool', version: '1.0.0' } },
84      { package: { name: 'cool', version: '1.0.0' } }
85    ]
86  })
87  return search('oo', OPTS.concat({ limit: 3 })).then(results => {
88    t.equal(results.length, 4, 'returns more results if endpoint does so')
89  })
90})
91
92test('accepts a from option', t => {
93  const query = qs.stringify({
94    text: 'oo',
95    size: 20,
96    from: 1,
97    quality: 0.65,
98    popularity: 0.98,
99    maintenance: 0.5
100  })
101  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
102    objects: [
103      { package: { name: 'cool', version: '1.0.0' } },
104      { package: { name: 'cool', version: '1.1.0' } },
105      { package: { name: 'cool', version: '1.0.0' } },
106      { package: { name: 'cool', version: '1.0.0' } }
107    ]
108  })
109  return search('oo', OPTS.concat({ from: 1 })).then(results => {
110    t.equal(results.length, 4, 'returns more results if endpoint does so')
111  })
112})
113
114test('accepts quality/mainenance/popularity options', t => {
115  const query = qs.stringify({
116    text: 'oo',
117    size: 20,
118    from: 0,
119    quality: 1,
120    popularity: 2,
121    maintenance: 3
122  })
123  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
124    objects: [
125      { package: { name: 'cool', version: '1.0.0' } },
126      { package: { name: 'cool', version: '1.0.0' } },
127      { package: { name: 'cool', version: '1.0.0' } },
128      { package: { name: 'cool', version: '1.0.0' } }
129    ]
130  })
131  return search('oo', OPTS.concat({
132    quality: 1,
133    popularity: 2,
134    maintenance: 3
135  })).then(results => {
136    t.equal(results.length, 4, 'returns more results if endpoint does so')
137  })
138})
139
140test('sortBy: quality', t => {
141  const query = qs.stringify({
142    text: 'oo',
143    size: 20,
144    from: 0,
145    quality: 1,
146    popularity: 0,
147    maintenance: 0
148  })
149  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
150    objects: [
151      { package: { name: 'cool', version: '1.0.0' } },
152      { package: { name: 'cool', version: '1.0.0' } },
153      { package: { name: 'cool', version: '1.0.0' } },
154      { package: { name: 'cool', version: '1.0.0' } }
155    ]
156  })
157  return search('oo', OPTS.concat({
158    sortBy: 'quality'
159  })).then(results => {
160    t.equal(results.length, 4, 'returns more results if endpoint does so')
161  })
162})
163
164test('sortBy: popularity', t => {
165  const query = qs.stringify({
166    text: 'oo',
167    size: 20,
168    from: 0,
169    quality: 0,
170    popularity: 1,
171    maintenance: 0
172  })
173  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
174    objects: [
175      { package: { name: 'cool', version: '1.0.0' } },
176      { package: { name: 'cool', version: '1.0.0' } },
177      { package: { name: 'cool', version: '1.0.0' } },
178      { package: { name: 'cool', version: '1.0.0' } }
179    ]
180  })
181  return search('oo', OPTS.concat({
182    sortBy: 'popularity'
183  })).then(results => {
184    t.equal(results.length, 4, 'returns more results if endpoint does so')
185  })
186})
187
188test('sortBy: maintenance', t => {
189  const query = qs.stringify({
190    text: 'oo',
191    size: 20,
192    from: 0,
193    quality: 0,
194    popularity: 0,
195    maintenance: 1
196  })
197  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
198    objects: [
199      { package: { name: 'cool', version: '1.0.0' } },
200      { package: { name: 'cool', version: '1.0.0' } },
201      { package: { name: 'cool', version: '1.0.0' } },
202      { package: { name: 'cool', version: '1.0.0' } }
203    ]
204  })
205  return search('oo', OPTS.concat({
206    sortBy: 'maintenance'
207  })).then(results => {
208    t.equal(results.length, 4, 'returns more results if endpoint does so')
209  })
210})
211
212test('sortBy: optimal', t => {
213  const query = qs.stringify({
214    text: 'oo',
215    size: 20,
216    from: 0,
217    quality: 0.65,
218    popularity: 0.98,
219    maintenance: 0.5
220  })
221  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
222    objects: [
223      { package: { name: 'cool', version: '1.0.0' } },
224      { package: { name: 'cool', version: '1.0.0' } },
225      { package: { name: 'cool', version: '1.0.0' } },
226      { package: { name: 'cool', version: '1.0.0' } }
227    ]
228  })
229  return search('oo', OPTS.concat({
230    sortBy: 'optimal'
231  })).then(results => {
232    t.equal(results.length, 4, 'returns more results if endpoint does so')
233  })
234})
235
236test('detailed format', t => {
237  const query = qs.stringify({
238    text: 'oo',
239    size: 20,
240    from: 0,
241    quality: 0,
242    popularity: 0,
243    maintenance: 1
244  })
245  const results = [
246    {
247      package: { name: 'cool', version: '1.0.0' },
248      score: {
249        final: 0.9237841281241451,
250        detail: {
251          quality: 0.9270640902288084,
252          popularity: 0.8484861649808381,
253          maintenance: 0.9962706951777409
254        }
255      },
256      searchScore: 100000.914
257    },
258    {
259      package: { name: 'ok', version: '2.0.0' },
260      score: {
261        final: 0.9237841281451,
262        detail: {
263          quality: 0.9270602288084,
264          popularity: 0.8461649808381,
265          maintenance: 0.9706951777409
266        }
267      },
268      searchScore: 1000.91
269    }
270  ]
271  tnock(t, REG).get(`/-/v1/search?${query}`).once().reply(200, {
272    objects: results
273  })
274  return search('oo', OPTS.concat({
275    sortBy: 'maintenance',
276    detailed: true
277  })).then(res => {
278    t.deepEqual(res, results, 'return full-format results with opts.detailed')
279  })
280})
281
282test('space-separates and URI-encodes multiple search params', t => {
283  const query = qs.stringify({
284    text: 'foo bar:baz quux?=',
285    size: 1,
286    from: 0,
287    quality: 1,
288    popularity: 2,
289    maintenance: 3
290  })
291  tnock(t, REG).get(`/-/v1/search?${query}`).reply(200, { objects: [] })
292  return search(['foo', 'bar:baz', 'quux?='], OPTS.concat({
293    limit: 1,
294    quality: 1,
295    popularity: 2,
296    maintenance: 3
297  })).then(
298    () => t.ok(true, 'sent parameters correctly urlencoded')
299  )
300})
301