coh-content-db 2.0.0-rc.4 → 2.0.0-rc.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +31 -7
  2. package/dist/coh-content-db.d.ts +353 -185
  3. package/dist/coh-content-db.js +460 -300
  4. package/dist/coh-content-db.js.map +1 -1
  5. package/dist/coh-content-db.mjs +448 -294
  6. package/dist/coh-content-db.mjs.map +1 -1
  7. package/package.json +1 -4
  8. package/src/main/api/alternate-data.ts +2 -2
  9. package/src/main/api/badge-data.ts +21 -19
  10. package/src/main/api/badge-requirement-data.ts +82 -0
  11. package/src/main/api/badge-requirement-type.ts +11 -0
  12. package/src/main/api/change.ts +5 -2
  13. package/src/main/api/contact-data.ts +46 -0
  14. package/src/main/api/content-bundle.ts +12 -7
  15. package/src/main/api/markdown-string.ts +4 -0
  16. package/src/main/api/zone-data.ts +20 -0
  17. package/src/main/changelog.ts +7 -2
  18. package/src/main/db/alignments.ts +17 -0
  19. package/src/main/db/alternates.ts +8 -14
  20. package/src/main/db/badge-index.ts +93 -0
  21. package/src/main/db/badge-requirement.ts +102 -0
  22. package/src/main/db/badge-search-options.ts +51 -0
  23. package/src/main/db/badge.ts +55 -48
  24. package/src/main/db/bundle-metadata.ts +5 -6
  25. package/src/main/db/coh-content-database.ts +65 -40
  26. package/src/main/db/contact.ts +59 -0
  27. package/src/main/db/paged.ts +7 -0
  28. package/src/main/db/zone.ts +28 -0
  29. package/src/main/index.ts +15 -11
  30. package/src/main/util.ts +68 -7
  31. package/src/test/api/alignments.test.ts +40 -0
  32. package/src/test/api/badge-data.fixture.ts +9 -7
  33. package/src/test/api/badge-requirement-data.fixture.ts +17 -0
  34. package/src/test/api/badge-requirement-type.test.ts +31 -0
  35. package/src/test/api/contact-data.fixture.ts +13 -0
  36. package/src/test/api/content-bundle.fixture.ts +2 -2
  37. package/src/test/api/content-bundle.test.ts +1 -1
  38. package/src/test/api/zone-data.fixture.ts +8 -0
  39. package/src/test/db/alternates.test.ts +16 -74
  40. package/src/test/db/badge-index.test.ts +520 -0
  41. package/src/test/db/badge-requirement.test.ts +180 -0
  42. package/src/test/db/badge.test.ts +190 -15
  43. package/src/test/db/coh-content-database.test.ts +125 -18
  44. package/src/test/db/contact.test.ts +96 -0
  45. package/src/test/db/zone.test.ts +36 -0
  46. package/src/test/index.test.ts +6 -2
  47. package/src/test/util.test.ts +91 -18
  48. package/src/main/api/badge-partial-data.ts +0 -65
  49. package/src/main/api/badge-partial-type.ts +0 -8
  50. package/src/main/api/game-map-data.ts +0 -26
  51. package/src/main/api/vidiot-map-data.ts +0 -18
  52. package/src/main/api/vidiot-map-point-of-interest-data.ts +0 -30
  53. package/src/main/db/badge-partial.ts +0 -35
  54. package/src/main/db/badge-search-document.ts +0 -16
  55. package/src/main/db/game-map.ts +0 -33
  56. package/src/main/db/vidiot-map-point-of-interest.ts +0 -40
  57. package/src/main/db/vidiot-map.ts +0 -25
  58. package/src/test/api/badge-partial-data.fixture.ts +0 -17
  59. package/src/test/api/badge-partial-type.test.ts +0 -31
  60. package/src/test/api/game-map-data.fixture.ts +0 -10
  61. package/src/test/api/vidiot-map-point-of-interest.fixture.ts +0 -10
  62. package/src/test/api/vidiot-map.fixture.ts +0 -9
  63. package/src/test/db/badge-search-document.test.ts +0 -35
  64. package/src/test/db/coh-content-database-search.test.ts +0 -119
@@ -0,0 +1,520 @@
1
+ import { badgeDataFixture } from '../api/badge-data.fixture'
2
+ import { Badge, BadgeIndex, Zone } from '../../main'
3
+ import { zoneDataFixture } from '../api/zone-data.fixture'
4
+
5
+ const TEST_Zones = [
6
+ new Zone(zoneDataFixture.create({ key: 'atlas-park', name: 'Atlas Park' })),
7
+ new Zone(zoneDataFixture.create({ key: 'perez-park', name: 'Perez Park' })),
8
+ new Zone(zoneDataFixture.create({ key: 'abandoned-sewer-network', name: 'Abandoned Sewer Network' })),
9
+ ]
10
+
11
+ describe(BadgeIndex.name, () => {
12
+ describe('Constructor', () => {
13
+ test(`should throw an error on duplicate key`, () => {
14
+ const data = [
15
+ new Badge(badgeDataFixture.create({ key: 'foo' })),
16
+ new Badge(badgeDataFixture.create({ key: 'foo' })),
17
+ ]
18
+ expect(() => new BadgeIndex(data)).toThrow('Duplicate badge key [foo]')
19
+ })
20
+ })
21
+
22
+ describe('getBadge', () => {
23
+ test(`should retrieve badge from the index`, () => {
24
+ const data = [new Badge(badgeDataFixture.create({ key: 'foo' }))]
25
+
26
+ expect(new BadgeIndex(data).getBadge('foo')).not.toBeUndefined()
27
+ })
28
+
29
+ test(`should throw error for unknown badge`, () => {
30
+ expect(() => new BadgeIndex([]).getBadge('foo')).toThrow('Unknown badge key [foo]')
31
+ })
32
+ })
33
+
34
+ describe('badgeExists', () => {
35
+ test(`should return true for a badge that exists`, () => {
36
+ const data = [new Badge(badgeDataFixture.create({ key: 'foo' }))]
37
+
38
+ expect(new BadgeIndex(data).badgeExists('foo')).toBeTruthy()
39
+ })
40
+
41
+ test(`should return false for a badge that does not exist`, () => {
42
+ expect(new BadgeIndex([]).badgeExists('foo')).toBeFalsy()
43
+ })
44
+ })
45
+
46
+ describe('searchBadges', () => {
47
+ test(`should return everything for an empty query`, () => {
48
+ const data = [
49
+ new Badge(badgeDataFixture.create({ key: 'foo-1', acquisition: 'Foo 1' })),
50
+ new Badge(badgeDataFixture.create({ key: 'foo-2', acquisition: 'Foo 2' })),
51
+ new Badge(badgeDataFixture.create({ key: 'bar-1', acquisition: 'Bar 1' })),
52
+ ]
53
+
54
+ const result = new BadgeIndex(data).searchBadges()
55
+ const keys = result.items.map(x => x.key)
56
+ expect(keys).toStrictEqual(['foo-1', 'foo-2', 'bar-1'])
57
+ expect(keys).toContain('foo-1')
58
+ expect(keys).toContain('foo-2')
59
+ expect(keys).toContain('bar-1')
60
+ })
61
+
62
+ describe('query', () => {
63
+ test(`should match on badge name`, () => {
64
+ const data = [
65
+ new Badge(badgeDataFixture.create({ key: 'match-1', name: [{ value: 'Foo 1' }] })),
66
+ new Badge(badgeDataFixture.create({ key: 'match-2', name: [{ value: 'Foo 2' }, { value: 'Bar 2' }] })),
67
+ new Badge(badgeDataFixture.create({ key: 'match-3', name: [{ value: 'Bar 3' }, { value: 'Foo 3' }] })),
68
+ new Badge(badgeDataFixture.create({ key: 'miss-1', name: [{ value: 'Bar 4' }] })),
69
+ ]
70
+
71
+ const result = new BadgeIndex(data).searchBadges({ query: { str: 'Foo', on: { name: true } } })
72
+ const keys = result.items.map(x => x.key)
73
+ expect(keys).toStrictEqual(['match-1', 'match-2', 'match-3'])
74
+ })
75
+
76
+ test(`should match on badge text`, () => {
77
+ const data = [
78
+ new Badge(badgeDataFixture.create({ key: 'match-1', badgeText: [{ value: 'Foo 1' }] })),
79
+ new Badge(badgeDataFixture.create({ key: 'match-2', badgeText: [{ value: 'Foo 2' }, { value: 'Bar 2' }] })),
80
+ new Badge(badgeDataFixture.create({ key: 'match-3', badgeText: [{ value: 'Bar 3' }, { value: 'Foo 3' }] })),
81
+ new Badge(badgeDataFixture.create({ key: 'miss-1', badgeText: [{ value: 'Bar 4' }] })),
82
+ new Badge(badgeDataFixture.create({ key: 'miss-2', badgeText: undefined })),
83
+ ]
84
+
85
+ const result = new BadgeIndex(data).searchBadges({ query: { str: 'Foo', on: { badgeText: true } } })
86
+ const keys = result.items.map(x => x.key)
87
+ expect(keys).toStrictEqual(['match-1', 'match-2', 'match-3'])
88
+ })
89
+
90
+ test(`should match on acquisition`, () => {
91
+ const data = [
92
+ new Badge(badgeDataFixture.create({ key: 'match-1', acquisition: 'Foo 1' })),
93
+ new Badge(badgeDataFixture.create({ key: 'match-2', acquisition: 'Foo 2' })),
94
+ new Badge(badgeDataFixture.create({ key: 'miss-1', acquisition: 'Bar 1' })),
95
+ new Badge(badgeDataFixture.create({ key: 'miss-2', acquisition: undefined })),
96
+ ]
97
+
98
+ const result = new BadgeIndex(data).searchBadges({ query: { str: 'Foo', on: { acquisition: true } } })
99
+ const keys = result.items.map(x => x.key)
100
+ expect(keys).toStrictEqual(['match-1', 'match-2'])
101
+ })
102
+
103
+ test(`should match on effect`, () => {
104
+ const data = [
105
+ new Badge(badgeDataFixture.create({ key: 'match-1', effect: 'Foo 1' })),
106
+ new Badge(badgeDataFixture.create({ key: 'match-2', effect: 'Foo 2' })),
107
+ new Badge(badgeDataFixture.create({ key: 'miss-1', effect: 'Bar 1' })),
108
+ new Badge(badgeDataFixture.create({ key: 'miss-2', effect: undefined })),
109
+ ]
110
+
111
+ const result = new BadgeIndex(data).searchBadges({ query: { str: 'Foo', on: { effect: true } } })
112
+ const keys = result.items.map(x => x.key)
113
+ expect(keys).toStrictEqual(['match-1', 'match-2'])
114
+ })
115
+
116
+ test(`should match on notes`, () => {
117
+ const data = [
118
+ new Badge(badgeDataFixture.create({ key: 'match-1', notes: 'Foo 1' })),
119
+ new Badge(badgeDataFixture.create({ key: 'match-2', notes: 'Foo 2' })),
120
+ new Badge(badgeDataFixture.create({ key: 'miss-1', notes: 'Bar 1' })),
121
+ new Badge(badgeDataFixture.create({ key: 'miss-2', notes: undefined })),
122
+ ]
123
+
124
+ const result = new BadgeIndex(data).searchBadges({ query: { str: 'Foo', on: { notes: true } } })
125
+ const keys = result.items.map(x => x.key)
126
+ expect(keys).toStrictEqual(['match-1', 'match-2'])
127
+ })
128
+
129
+ test(`should match on setTitle`, () => {
130
+ const data = [
131
+ new Badge(badgeDataFixture.create({ key: 'match-1', setTitle: { id: 123 } })),
132
+ new Badge(badgeDataFixture.create({ key: 'match-2', setTitle: { id: 456, praetorianId: 123 } })),
133
+ new Badge(badgeDataFixture.create({ key: 'miss-1', setTitle: { id: 456 } })),
134
+ new Badge(badgeDataFixture.create({ key: 'miss-2', setTitle: undefined })),
135
+ ]
136
+
137
+ const result = new BadgeIndex(data).searchBadges({ query: { str: '123', on: { setTitle: true } } })
138
+
139
+ expect(result.items).toHaveLength(2)
140
+ const keys = result.items.map(x => x.key)
141
+ expect(keys).toStrictEqual(['match-1', 'match-2'])
142
+ })
143
+
144
+ test(`should match the start of a string`, () => {
145
+ const data = [
146
+ new Badge(badgeDataFixture.create({ key: 'match-1', acquisition: 'Foo 1' })),
147
+ new Badge(badgeDataFixture.create({ key: 'match-2', acquisition: 'Foo 2' })),
148
+ new Badge(badgeDataFixture.create({ key: 'miss-1', acquisition: 'Bar 1' })),
149
+ ]
150
+
151
+ const result = new BadgeIndex(data).searchBadges({ query: { str: 'Fo', on: { acquisition: true } } })
152
+ const keys = result.items.map(x => x.key)
153
+ expect(keys).toStrictEqual(['match-1', 'match-2'])
154
+ })
155
+
156
+ test(`should be case insensitive`, () => {
157
+ const data = [
158
+ new Badge(badgeDataFixture.create({ key: 'match-1', acquisition: 'Foo 1' })),
159
+ new Badge(badgeDataFixture.create({ key: 'match-2', acquisition: 'Foo 2' })),
160
+ new Badge(badgeDataFixture.create({ key: 'miss-1', acquisition: 'Bar 1' })),
161
+ ]
162
+
163
+ const result = new BadgeIndex(data).searchBadges({ query: { str: 'foo', on: { acquisition: true } } })
164
+ const keys = result.items.map(x => x.key)
165
+ expect(keys).toStrictEqual(['match-1', 'match-2'])
166
+ })
167
+
168
+ test(`should default to querying on name only`, () => {
169
+ const data = [
170
+ new Badge(badgeDataFixture.create({ key: 'match-1', name: [{ value: 'Foo 1' }] })),
171
+ new Badge(badgeDataFixture.create({ key: 'miss-1', acquisition: 'Foo 2' })),
172
+ new Badge(badgeDataFixture.create({ key: 'miss-2', name: [{ value: 'Bar 1' }] })),
173
+ ]
174
+
175
+ const result = new BadgeIndex(data).searchBadges({ query: { str: 'foo' } })
176
+
177
+ const keys = result.items.map(x => x.key)
178
+ expect(keys).toStrictEqual(['match-1'])
179
+ })
180
+ })
181
+
182
+ describe('filter', () => {
183
+ test(`should filter nothing if not specified`, () => {
184
+ const data = [
185
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
186
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
187
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
188
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
189
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
190
+ new Badge(badgeDataFixture.create({ key: 'badge-6' })),
191
+ ]
192
+
193
+ const result = new BadgeIndex(data).searchBadges()
194
+ const keys = result.items.map(x => x.key)
195
+ expect(keys).toStrictEqual(['badge-1', 'badge-2', 'badge-3', 'badge-4', 'badge-5', 'badge-6'])
196
+ })
197
+
198
+ test(`should filter on badge type`, () => {
199
+ const data = [
200
+ new Badge(badgeDataFixture.create({ key: 'badge-1', type: 'EXPLORATION' })),
201
+ new Badge(badgeDataFixture.create({ key: 'badge-2', type: 'EXPLORATION' })),
202
+ new Badge(badgeDataFixture.create({ key: 'badge-3', type: 'HISTORY' })),
203
+ new Badge(badgeDataFixture.create({ key: 'badge-4', type: 'HISTORY' })),
204
+ new Badge(badgeDataFixture.create({ key: 'badge-5', type: 'ACCOLADE' })),
205
+ new Badge(badgeDataFixture.create({ key: 'badge-6', type: 'ACCOLADE' })),
206
+ ]
207
+
208
+ const result = new BadgeIndex(data).searchBadges({ filter: { type: 'HISTORY' } })
209
+ const keys = result.items.map(x => x.key)
210
+ expect(keys).toStrictEqual(['badge-3', 'badge-4'])
211
+ })
212
+
213
+ test(`should filter on badge type`, () => {
214
+ const data = [
215
+ new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
216
+ new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'perez-park' })),
217
+ new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'abandoned-sewer-network' })),
218
+ new Badge(badgeDataFixture.create({ key: 'badge-4', zoneKey: 'atlas-park' })),
219
+ new Badge(badgeDataFixture.create({ key: 'badge-5', zoneKey: 'perez-park' })),
220
+ new Badge(badgeDataFixture.create({ key: 'badge-6', zoneKey: undefined })),
221
+ ]
222
+
223
+ const result = new BadgeIndex(data).searchBadges({ filter: { zoneKey: 'perez-park' } })
224
+ const keys = result.items.map(x => x.key)
225
+ expect(keys).toStrictEqual(['badge-2', 'badge-5'])
226
+ })
227
+
228
+ test(`should filter on badge type`, () => {
229
+ const data = [
230
+ new Badge(badgeDataFixture.create({ key: 'badge-1', alignment: ['H'] })),
231
+ new Badge(badgeDataFixture.create({ key: 'badge-2', alignment: ['V'] })),
232
+ new Badge(badgeDataFixture.create({ key: 'badge-3', alignment: ['P'] })),
233
+ new Badge(badgeDataFixture.create({ key: 'badge-4', alignment: ['H', 'V'] })),
234
+ new Badge(badgeDataFixture.create({ key: 'badge-5', alignment: ['V', 'P'] })),
235
+ new Badge(badgeDataFixture.create({ key: 'badge-6', alignment: ['H', 'V', 'P'] })),
236
+ ]
237
+
238
+ const result = new BadgeIndex(data).searchBadges({ filter: { alignment: 'H' } })
239
+ const keys = result.items.map(x => x.key)
240
+ expect(keys).toStrictEqual(['badge-1', 'badge-4', 'badge-6'])
241
+ })
242
+ })
243
+
244
+ describe('pagination', () => {
245
+ test(`should return all results with no pagination data`, () => {
246
+ const data = [
247
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
248
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
249
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
250
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
251
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
252
+ new Badge(badgeDataFixture.create({ key: 'badge-6' })),
253
+ ]
254
+
255
+ const result = new BadgeIndex(data).searchBadges()
256
+ const keys = result.items.map(x => x.key)
257
+ expect(keys).toStrictEqual(['badge-1', 'badge-2', 'badge-3', 'badge-4', 'badge-5', 'badge-6'])
258
+ })
259
+
260
+ test(`should be 1-based for page number`, () => {
261
+ const result = new BadgeIndex([]).searchBadges()
262
+ expect(result.page).toBe(1)
263
+ })
264
+
265
+ test(`should return the requested page size`, () => {
266
+ const data = [
267
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
268
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
269
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
270
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
271
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
272
+ new Badge(badgeDataFixture.create({ key: 'badge-6' })),
273
+ ]
274
+
275
+ const result = new BadgeIndex(data).searchBadges({ pageSize: 2 })
276
+ expect(result.items).toHaveLength(2)
277
+ })
278
+
279
+ test(`should return the start of the array with no page specified`, () => {
280
+ const data = [
281
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
282
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
283
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
284
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
285
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
286
+ new Badge(badgeDataFixture.create({ key: 'badge-6' })),
287
+ ]
288
+
289
+ const result = new BadgeIndex(data).searchBadges({ pageSize: 2 })
290
+ const keys = result.items.map(x => x.key)
291
+ expect(keys).toStrictEqual(['badge-1', 'badge-2'])
292
+ })
293
+
294
+ test(`should return results from the middle of the array with a page specified`, () => {
295
+ const data = [
296
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
297
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
298
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
299
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
300
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
301
+ new Badge(badgeDataFixture.create({ key: 'badge-6' })),
302
+ ]
303
+
304
+ const result = new BadgeIndex(data).searchBadges({ page: 2, pageSize: 2 })
305
+ const keys = result.items.map(x => x.key)
306
+ expect(keys).toStrictEqual(['badge-3', 'badge-4'])
307
+ })
308
+
309
+ test(`should return a partial page if at the end of the array`, () => {
310
+ const data = [
311
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
312
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
313
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
314
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
315
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
316
+ ]
317
+
318
+ const result = new BadgeIndex(data).searchBadges({ page: 3, pageSize: 2 })
319
+ const keys = result.items.map(x => x.key)
320
+ expect(keys).toStrictEqual(['badge-5'])
321
+ })
322
+
323
+ test(`should return the correct total entry count`, () => {
324
+ const data = [
325
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
326
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
327
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
328
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
329
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
330
+ ]
331
+
332
+ const result = new BadgeIndex(data).searchBadges({ page: 1, pageSize: 2 })
333
+ expect(result.totalItems).toBe(5)
334
+ })
335
+
336
+ test(`should return the page size`, () => {
337
+ const data = [
338
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
339
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
340
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
341
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
342
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
343
+ ]
344
+
345
+ const result = new BadgeIndex(data).searchBadges({ pageSize: 2 })
346
+ expect(result.pageSize).toBe(2)
347
+ })
348
+
349
+ test(`should return the correct total page count`, () => {
350
+ const data = [
351
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
352
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
353
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
354
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
355
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
356
+ ]
357
+
358
+ const result = new BadgeIndex(data).searchBadges({ pageSize: 2 })
359
+ expect(result.totalPages).toBe(3)
360
+ })
361
+
362
+ test(`should return a total page count of 1 when no page size is provided`, () => {
363
+ const data = [
364
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
365
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
366
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
367
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
368
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
369
+ ]
370
+
371
+ const result = new BadgeIndex(data).searchBadges()
372
+ expect(result.totalPages).toBe(1)
373
+ })
374
+
375
+ test(`should return the last page if a page is requested past the max`, () => {
376
+ const data = [
377
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
378
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
379
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
380
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
381
+ new Badge(badgeDataFixture.create({ key: 'badge-5' })),
382
+ ]
383
+
384
+ const result = new BadgeIndex(data).searchBadges({ pageSize: 2, page: 10 })
385
+ const keys = result.items.map(x => x.key)
386
+ expect(keys).toStrictEqual(['badge-5'])
387
+ expect(result.page).toBe(3)
388
+ })
389
+
390
+ test(`should return the first page if a page is requested lower than 1`, () => {
391
+ const result = new BadgeIndex([]).searchBadges({ page: -10 })
392
+ expect(result.page).toBe(1)
393
+ })
394
+ })
395
+
396
+ describe('sort', () => {
397
+ test(`should not modify sort if not specified`, () => {
398
+ const data = [
399
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
400
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
401
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
402
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
403
+ ]
404
+
405
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges()
406
+
407
+ const keys = result.items.map(x => x.key)
408
+ expect(keys).toStrictEqual(['badge-1', 'badge-2', 'badge-3', 'badge-4'])
409
+ })
410
+
411
+ test(`should reverse default sort with desc`, () => {
412
+ const data = [
413
+ new Badge(badgeDataFixture.create({ key: 'badge-1' })),
414
+ new Badge(badgeDataFixture.create({ key: 'badge-2' })),
415
+ new Badge(badgeDataFixture.create({ key: 'badge-3' })),
416
+ new Badge(badgeDataFixture.create({ key: 'badge-4' })),
417
+ ]
418
+
419
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { dir: 'DESC' } })
420
+
421
+ const keys = result.items.map(x => x.key)
422
+ expect(keys).toStrictEqual(['badge-4', 'badge-3', 'badge-2', 'badge-1'])
423
+ })
424
+
425
+ test(`should sort by badge name`, () => {
426
+ const data = [
427
+ new Badge(badgeDataFixture.create({ key: 'badge-1', name: [{ value: 'Abc' }] })),
428
+ new Badge(badgeDataFixture.create({ key: 'badge-2', name: [{ value: 'XYZ' }] })),
429
+ new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
430
+ ]
431
+
432
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'BADGE_NAME' } })
433
+
434
+ const keys = result.items.map(x => x.key)
435
+ expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
436
+ })
437
+
438
+ test(`should sort by badge name descending`, () => {
439
+ const data = [
440
+ new Badge(badgeDataFixture.create({ key: 'badge-1', name: [{ value: 'Abc' }] })),
441
+ new Badge(badgeDataFixture.create({ key: 'badge-2', name: [{ value: 'XYZ' }] })),
442
+ new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
443
+ ]
444
+
445
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'BADGE_NAME', dir: 'DESC' } })
446
+
447
+ const keys = result.items.map(x => x.key)
448
+ expect(keys).toStrictEqual(['badge-2', 'badge-1', 'badge-3'])
449
+ })
450
+
451
+ test(`should use the default badge name when sorting by name`, () => {
452
+ const data = [
453
+ new Badge(badgeDataFixture.create({ key: 'badge-1', name: [{ value: 'Abc' }] })),
454
+ new Badge(badgeDataFixture.create({ key: 'badge-2', name: [{ value: 'XYZ' }, { sex: 'F', value: 'AAA' }] })),
455
+ new Badge(badgeDataFixture.create({ key: 'badge-3', name: [{ value: 'AAB' }] })),
456
+ ]
457
+
458
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'BADGE_NAME' } })
459
+
460
+ const keys = result.items.map(x => x.key)
461
+ expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
462
+ })
463
+
464
+ test(`should sort by zone name`, () => {
465
+ const data = [
466
+ new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
467
+ new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'perez-park' })),
468
+ new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'abandoned-sewer-network' })),
469
+ ]
470
+
471
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'ZONE_NAME' } })
472
+
473
+ const keys = result.items.map(x => x.key)
474
+ expect(keys).toStrictEqual(['badge-3', 'badge-1', 'badge-2'])
475
+ })
476
+
477
+ test(`should sort by zone name descending`, () => {
478
+ const data = [
479
+ new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
480
+ new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'perez-park' })),
481
+ new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'abandoned-sewer-network' })),
482
+ ]
483
+
484
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'ZONE_NAME', dir: 'DESC' } })
485
+
486
+ const keys = result.items.map(x => x.key)
487
+ expect(keys).toStrictEqual(['badge-2', 'badge-1', 'badge-3'])
488
+ })
489
+
490
+ test(`should maintain canonical as secondary sort when sorting by zone name`, () => {
491
+ const data = [
492
+ new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
493
+ new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'perez-park' })),
494
+ new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'atlas-park' })),
495
+ new Badge(badgeDataFixture.create({ key: 'badge-4', zoneKey: 'abandoned-sewer-network' })),
496
+ ]
497
+
498
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'ZONE_NAME' } })
499
+
500
+ const keys = result.items.map(x => x.key)
501
+ expect(keys).toStrictEqual(['badge-4', 'badge-1', 'badge-3', 'badge-2'])
502
+ })
503
+
504
+ test(`should sort unknown zone names to the end`, () => {
505
+ const data = [
506
+ new Badge(badgeDataFixture.create({ key: 'badge-1', zoneKey: 'atlas-park' })),
507
+ new Badge(badgeDataFixture.create({ key: 'badge-2', zoneKey: 'unknown' })),
508
+ new Badge(badgeDataFixture.create({ key: 'badge-3', zoneKey: 'perez-park' })),
509
+ new Badge(badgeDataFixture.create({ key: 'badge-4', zoneKey: 'unexpected' })),
510
+ new Badge(badgeDataFixture.create({ key: 'badge-5', zoneKey: 'abandoned-sewer-network' })),
511
+ ]
512
+
513
+ const result = new BadgeIndex(data, TEST_Zones).searchBadges({ sort: { by: 'ZONE_NAME' } })
514
+
515
+ const keys = result.items.map(x => x.key)
516
+ expect(keys).toStrictEqual(['badge-5', 'badge-1', 'badge-3', 'badge-2', 'badge-4'])
517
+ })
518
+ })
519
+ })
520
+ })