coh-content-db 1.4.1 → 2.0.0-rc.10

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