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

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