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
@@ -17,68 +17,33 @@ describe(BadgeRequirement.name, () => {
17
17
 
18
18
  describe('type', () => {
19
19
  test('should be set from the data', () => {
20
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ type: 'BADGE' }))
21
- expect(requirement.type).toEqual('BADGE')
20
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ type: 'badge' }))
21
+ expect(requirement.type).toEqual('badge')
22
22
  })
23
23
  })
24
24
 
25
- describe('zoneKey', () => {
25
+ describe('location', () => {
26
26
  test('should be set from the data', () => {
27
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ zoneKey: 'zone123' }))
28
- expect(requirement.zoneKey).toEqual('zone123')
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
29
  })
30
30
 
31
- test('should be optional', () => {
32
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('zoneKey').create())
33
- expect(requirement.zoneKey).toBeUndefined()
34
- })
35
- })
36
-
37
- describe('loc', () => {
38
- test('should be set from the data', () => {
39
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ loc: [1, 2, 3] }))
40
- expect(requirement.loc).toStrictEqual([1, 2, 3])
41
- })
42
-
43
- test('should be optional', () => {
44
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('loc').create())
45
- expect(requirement.loc).toBeUndefined()
46
- })
47
- })
48
-
49
- describe('plaqueType', () => {
50
- test('should be set from the data', () => {
51
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ plaqueType: 'MONUMENT' }))
52
- expect(requirement.plaqueType).toEqual('MONUMENT')
53
- })
54
-
55
- test('should be optional', () => {
56
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('plaqueType').create())
57
- expect(requirement.plaqueType).toBeUndefined()
58
- })
59
- })
60
-
61
- describe('plaqueInscription', () => {
62
- test('should be set from the data', () => {
63
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ plaqueInscription: 'foo' }))
64
- expect(requirement.plaqueInscription).toEqual('foo')
65
- })
66
-
67
- test('should be optional', () => {
68
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('plaqueInscription').create())
69
- expect(requirement.plaqueInscription).toBeUndefined()
70
- })
71
- })
72
-
73
- describe('vidiotMapKey', () => {
74
- test('should be set from the data', () => {
75
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ vidiotMapKey: 'A1' }))
76
- expect(requirement.vidiotMapKey).toEqual('A1')
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
+ ])
77
42
  })
78
43
 
79
44
  test('should be optional', () => {
80
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('vidiotMapKey').create())
81
- expect(requirement.vidiotMapKey).toBeUndefined()
45
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('location').create())
46
+ expect(requirement.location).toBeUndefined()
82
47
  })
83
48
  })
84
49
 
@@ -94,27 +59,27 @@ describe(BadgeRequirement.name, () => {
94
59
  })
95
60
  })
96
61
 
97
- describe('missionName', () => {
62
+ describe('missionKey', () => {
98
63
  test('should be set from the data', () => {
99
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ missionName: 'foo' }))
100
- expect(requirement.missionName).toEqual('foo')
64
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ missionKey: 'foo' }))
65
+ expect(requirement.missionKey).toEqual('foo')
101
66
  })
102
67
 
103
68
  test('should be optional', () => {
104
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('missionName').create())
105
- expect(requirement.missionName).toBeUndefined()
69
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('missionKey').create())
70
+ expect(requirement.missionKey).toBeUndefined()
106
71
  })
107
72
  })
108
73
 
109
- describe('contactKey', () => {
74
+ describe('monumentText', () => {
110
75
  test('should be set from the data', () => {
111
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ contactKey: 'foo' }))
112
- expect(requirement.contactKey).toEqual('foo')
76
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ monumentText: 'foo' }))
77
+ expect(requirement.monumentText).toEqual('foo')
113
78
  })
114
79
 
115
80
  test('should be optional', () => {
116
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('contactKey').create())
117
- expect(requirement.contactKey).toBeUndefined()
81
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('monumentText').create())
82
+ expect(requirement.monumentText).toBeUndefined()
118
83
  })
119
84
  })
120
85
 
@@ -132,8 +97,8 @@ describe(BadgeRequirement.name, () => {
132
97
 
133
98
  describe('inventionTypes', () => {
134
99
  test('should be set from the data', () => {
135
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ inventionTypes: ['ACCURACY', 'CONFUSE'] }))
136
- expect(requirement.inventionTypes).toStrictEqual(['ACCURACY', 'CONFUSE'])
100
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ inventionTypes: ['accuracy', 'confuse'] }))
101
+ expect(requirement.inventionTypes).toStrictEqual(['accuracy', 'confuse'])
137
102
  })
138
103
 
139
104
  test('should be optional', () => {
@@ -142,15 +107,15 @@ describe(BadgeRequirement.name, () => {
142
107
  })
143
108
  })
144
109
 
145
- describe('inventionCount', () => {
110
+ describe('count', () => {
146
111
  test('should be set from the data', () => {
147
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ inventionCount: 5 }))
148
- expect(requirement.inventionCount).toEqual(5)
112
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.create({ count: 5 }))
113
+ expect(requirement.count).toEqual(5)
149
114
  })
150
115
 
151
116
  test('should be optional', () => {
152
- const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('inventionCount').create())
153
- expect(requirement.inventionCount).toBeUndefined()
117
+ const requirement = new BadgeRequirement(badgeRequirementDataFixture.omit('count').create())
118
+ expect(requirement.count).toBeUndefined()
154
119
  })
155
120
  })
156
121
 
@@ -1,4 +1,4 @@
1
- import { Badge } from '../../main'
1
+ import { Badge, compareByDefaultName, compareByZoneKey } from '../../main'
2
2
  import { badgeDataFixture } from '../api/badge-data.fixture'
3
3
  import { badgeRequirementDataFixture } from '../api/badge-requirement-data.fixture'
4
4
 
@@ -18,8 +18,8 @@ describe(Badge.name, () => {
18
18
 
19
19
  describe('type', () => {
20
20
  test('should be set from the data', () => {
21
- const badge = new Badge(badgeDataFixture.create({ type: 'ACHIEVEMENT' }))
22
- expect(badge.type).toEqual('ACHIEVEMENT')
21
+ const badge = new Badge(badgeDataFixture.create({ type: 'achievement' }))
22
+ expect(badge.type).toEqual('achievement')
23
23
  })
24
24
  })
25
25
 
@@ -30,12 +30,22 @@ describe(Badge.name, () => {
30
30
  })
31
31
  })
32
32
 
33
- describe('alignment', () => {
33
+ describe('morality', () => {
34
34
  test('should be set from the data', () => {
35
- const badge = new Badge(badgeDataFixture.create({ alignment: ['H', 'V'] }))
36
- expect(badge.alignment.hero).toBeTruthy()
37
- expect(badge.alignment.villain).toBeTruthy()
38
- expect(badge.alignment.praetorian).toBeFalsy()
35
+ const badge = new Badge(badgeDataFixture.create({ morality: ['hero', 'villain'] }))
36
+ expect(badge.morality.hero).toBeTruthy()
37
+ expect(badge.morality.villain).toBeTruthy()
38
+ })
39
+
40
+ test('should accept a single string', () => {
41
+ const badge = new Badge(badgeDataFixture.create({ morality: 'hero' }))
42
+ expect(badge.morality.hero).toBeTruthy()
43
+ expect(badge.morality.villain).toBeFalsy()
44
+ })
45
+
46
+ test('should be optional, defaulting to all', () => {
47
+ const badge = new Badge(badgeDataFixture.omit('morality').create())
48
+ expect(badge.morality.all).toBeTruthy()
39
49
  })
40
50
  })
41
51
 
@@ -99,30 +109,6 @@ describe(Badge.name, () => {
99
109
  })
100
110
  })
101
111
 
102
- describe('zoneKey', () => {
103
- test('should be set from the data', () => {
104
- const badge = new Badge(badgeDataFixture.create({ zoneKey: 'foo' }))
105
- expect(badge.zoneKey).toEqual('foo')
106
- })
107
-
108
- test('should be optional', () => {
109
- const badge = new Badge(badgeDataFixture.omit('zoneKey').create())
110
- expect(badge.zoneKey).toBeUndefined()
111
- })
112
- })
113
-
114
- describe('loc', () => {
115
- test('should be set from the data', () => {
116
- const badge = new Badge(badgeDataFixture.create({ loc: [1, 2, 3] }))
117
- expect(badge.loc).toStrictEqual([1, 2, 3])
118
- })
119
-
120
- test('should be optional', () => {
121
- const badge = new Badge(badgeDataFixture.omit('loc').create())
122
- expect(badge.loc).toBeUndefined()
123
- })
124
- })
125
-
126
112
  describe('effect', () => {
127
113
  test('should be set from the data', () => {
128
114
  const badge = new Badge(badgeDataFixture.create({ effect: 'foo' }))
@@ -135,27 +121,20 @@ describe(Badge.name, () => {
135
121
  })
136
122
  })
137
123
 
138
- describe('vidiotMapKey', () => {
124
+ describe('setTitle', () => {
139
125
  test('should be set from the data', () => {
140
- const badge = new Badge(badgeDataFixture.create({ vidiotMapKey: 'foo' }))
141
- expect(badge.vidiotMapKey).toEqual('foo')
126
+ const badge = new Badge(badgeDataFixture.create({ setTitleId: [123, 456] }))
127
+ expect(badge.setTitleId).toStrictEqual([123, 456])
142
128
  })
143
129
 
144
- test('should be optional', () => {
145
- const badge = new Badge(badgeDataFixture.omit('vidiotMapKey').create())
146
- expect(badge.vidiotMapKey).toBeUndefined()
147
- })
148
- })
149
-
150
- describe('setTitle', () => {
151
- test('should be set from the data', () => {
152
- const badge = new Badge(badgeDataFixture.create({ setTitle: { id: 123, praetorianId: 456 } }))
153
- expect(badge.setTitle).toStrictEqual({ id: 123, praetorianId: 456 })
130
+ test('should treat the praetorian id as optional', () => {
131
+ const badge = new Badge(badgeDataFixture.create({ setTitleId: [123] }))
132
+ expect(badge.setTitleId).toStrictEqual([123])
154
133
  })
155
134
 
156
135
  test('should be optional', () => {
157
- const badge = new Badge(badgeDataFixture.omit('setTitle').create())
158
- expect(badge.setTitle).toBeUndefined()
136
+ const badge = new Badge(badgeDataFixture.omit('setTitleId').create())
137
+ expect(badge.setTitleId).toBeUndefined()
159
138
  })
160
139
  })
161
140
 
@@ -172,34 +151,22 @@ describe(Badge.name, () => {
172
151
  })
173
152
 
174
153
  describe('requirements', () => {
175
- test(`should throw an error on duplicate key in same group`, () => {
154
+ test(`should throw an error on duplicate key`, () => {
176
155
  const data = badgeDataFixture.create({
177
156
  key: 'badge',
178
- requirements: [[
157
+ requirements: [
179
158
  badgeRequirementDataFixture.create({ key: 'foo' }),
180
159
  badgeRequirementDataFixture.create({ key: 'foo' }),
181
- ]],
160
+ ],
182
161
  })
183
- expect(() => new Badge(data)).toThrow('Duplicate badge requirement key [badge:foo] in group [1]')
184
- })
185
-
186
- test(`should not throw an error on duplicate key in different group`, () => {
187
- const data = badgeDataFixture.create({
188
- key: 'badge',
189
- requirements: [[
190
- badgeRequirementDataFixture.create({ key: 'foo' }),
191
- ], [
192
- badgeRequirementDataFixture.create({ key: 'foo' }),
193
- ]],
194
- })
195
- new Badge(data)
162
+ expect(() => new Badge(data)).toThrow('Duplicate badge requirement key [badge:foo]')
196
163
  })
197
164
  })
198
165
 
199
166
  describe('getRequirement', () => {
200
167
  test(`should retrieve requirement from the index`, () => {
201
168
  const data = badgeDataFixture.create({
202
- requirements: [[badgeRequirementDataFixture.create({ key: 'foo' })]],
169
+ requirements: [badgeRequirementDataFixture.create({ key: 'foo' })],
203
170
  })
204
171
 
205
172
  expect(new Badge(data).getRequirement('foo')).not.toBeUndefined()
@@ -213,4 +180,158 @@ describe(Badge.name, () => {
213
180
  expect(() => new Badge(data).getRequirement('foo')).toThrow('Unknown badge requirement key [foo]')
214
181
  })
215
182
  })
183
+
184
+ describe('zoneKeys', () => {
185
+ test(`should return the list of keys`, () => {
186
+ const badge = new Badge(badgeDataFixture.create({
187
+ requirements: [
188
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
189
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
190
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'b' } }),
191
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
192
+ ],
193
+ }))
194
+ expect(badge.zoneKeys).toStrictEqual(['a', 'c', 'b'])
195
+ })
196
+
197
+ test(`should return undefined if there no zones`, () => {
198
+ const badge = new Badge(badgeDataFixture.create({
199
+ requirements: [
200
+ badgeRequirementDataFixture.omit('location').create(),
201
+ ],
202
+ }))
203
+ expect(badge.zoneKey).toBeUndefined()
204
+ })
205
+
206
+ test(`should ignore requirements with no location`, () => {
207
+ const badge = new Badge(badgeDataFixture.create({
208
+ requirements: [
209
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
210
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
211
+ badgeRequirementDataFixture.omit('location').create(),
212
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
213
+ ],
214
+ }))
215
+ expect(badge.zoneKeys).toStrictEqual(['a', 'c'])
216
+ })
217
+ })
218
+
219
+ describe('zoneKey', () => {
220
+ test(`should return the key for a single zone`, () => {
221
+ const badge = new Badge(badgeDataFixture.create({
222
+ requirements: [
223
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
224
+ ],
225
+ }))
226
+ expect(badge.zoneKey).toBe('a')
227
+ })
228
+
229
+ test(`should return undefined if there no zones`, () => {
230
+ const badge = new Badge(badgeDataFixture.create({
231
+ requirements: [
232
+ badgeRequirementDataFixture.omit('location').create(),
233
+ ],
234
+ }))
235
+ expect(badge.zoneKey).toBeUndefined()
236
+ })
237
+
238
+ test(`should return undefined if there are multiple zones`, () => {
239
+ const badge = new Badge(badgeDataFixture.create({
240
+ requirements: [
241
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
242
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
243
+ ],
244
+ }))
245
+ expect(badge.zoneKey).toBeUndefined()
246
+ })
247
+ })
248
+
249
+ describe(compareByDefaultName.name, () => {
250
+ test(`should compare two badges by name`, () => {
251
+ const badgeA = new Badge(badgeDataFixture.create({ name: 'A' }))
252
+ const badgeB = new Badge(badgeDataFixture.create({ name: 'B' }))
253
+ expect(compareByDefaultName(badgeA, badgeB)).toBeLessThan(0)
254
+ expect([badgeB, badgeA].sort(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
255
+ })
256
+
257
+ test(`should return 0 for equal names`, () => {
258
+ const badgeA = new Badge(badgeDataFixture.create({ name: 'A' }))
259
+ const badgeB = new Badge(badgeDataFixture.create({ name: 'A' }))
260
+ expect(compareByDefaultName(badgeA, badgeB)).toEqual(0)
261
+ })
262
+
263
+ test(`should compare two undefined values`, () => {
264
+ const badgeA = new Badge(badgeDataFixture.create({ name: [] }))
265
+ const badgeB = new Badge(badgeDataFixture.create({ name: [] }))
266
+ expect(compareByDefaultName(badgeA, badgeB)).toEqual(0)
267
+ })
268
+
269
+ test(`should sort undefined values last`, () => {
270
+ const badgeA = new Badge(badgeDataFixture.create({ name: 'A' }))
271
+ const badgeB = new Badge(badgeDataFixture.create({ name: [] }))
272
+ expect([badgeA, badgeB].sort(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
273
+ expect([badgeB, badgeA].sort(compareByDefaultName)).toStrictEqual([badgeA, badgeB])
274
+ })
275
+ })
276
+
277
+ describe(compareByZoneKey.name, () => {
278
+ test(`should compare two badges by zoneKey`, () => {
279
+ const badgeA = new Badge(badgeDataFixture.create({
280
+ requirements: [
281
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
282
+ ],
283
+ }))
284
+ const badgeB = new Badge(badgeDataFixture.create({
285
+ requirements: [
286
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'b' } }),
287
+ ],
288
+ }))
289
+ expect(compareByZoneKey(badgeA, badgeB)).toBeLessThan(0)
290
+ expect([badgeB, badgeA].sort(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
291
+ })
292
+
293
+ test(`should return 0 for equal zoneKeys`, () => {
294
+ const badgeA = new Badge(badgeDataFixture.create({
295
+ requirements: [
296
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
297
+ ],
298
+ }))
299
+ const badgeB = new Badge(badgeDataFixture.create({
300
+ requirements: [
301
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
302
+ ],
303
+ }))
304
+ expect(compareByZoneKey(badgeA, badgeB)).toEqual(0)
305
+ })
306
+
307
+ test(`should equate two undefined values`, () => {
308
+ const badgeA = new Badge(badgeDataFixture.create({
309
+ requirements: [
310
+ badgeRequirementDataFixture.omit('location').create(),
311
+ ],
312
+ }))
313
+ const badgeB = new Badge(badgeDataFixture.create({
314
+ requirements: [
315
+ badgeRequirementDataFixture.omit('location').create(),
316
+ ],
317
+ }))
318
+ expect(compareByZoneKey(badgeA, badgeB)).toEqual(0)
319
+ })
320
+
321
+ test(`should sort badges with multiple values last`, () => {
322
+ const badgeA = new Badge(badgeDataFixture.create({
323
+ requirements: [
324
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'a' } }),
325
+ ],
326
+ }))
327
+ const badgeB = new Badge(badgeDataFixture.create({
328
+ requirements: [
329
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'b' } }),
330
+ badgeRequirementDataFixture.create({ location: { zoneKey: 'c' } }),
331
+ ],
332
+ }))
333
+ expect([badgeA, badgeB].sort(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
334
+ expect([badgeB, badgeA].sort(compareByZoneKey)).toStrictEqual([badgeA, badgeB])
335
+ })
336
+ })
216
337
  })
@@ -64,4 +64,21 @@ describe(BundleMetadata.name, () => {
64
64
  expect(bundle.changelog).toHaveLength(0)
65
65
  })
66
66
  })
67
+
68
+ describe('version', () => {
69
+ test(`should be read from the latest changelog entry`, () => {
70
+ const bundle = new BundleMetadata(contentBundleFixture.create({
71
+ changelog: [
72
+ { version: 'foo', date: new Date('2025-03-12'), description: 'Foo' },
73
+ { version: 'latest', date: new Date('2025-04-12'), description: 'Bar' },
74
+ ],
75
+ }))
76
+ expect(bundle.version).toBe('latest')
77
+ })
78
+
79
+ test(`should be undefined if there is no changelog`, () => {
80
+ const bundle = new BundleMetadata(contentBundleFixture.omit('changelog').create())
81
+ expect(bundle.version).toBeUndefined()
82
+ })
83
+ })
67
84
  })