@api-client/core 0.18.2 → 0.18.4

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 (31) hide show
  1. package/build/src/modeling/ApiModel.d.ts +5 -5
  2. package/build/src/modeling/ApiModel.d.ts.map +1 -1
  3. package/build/src/modeling/ApiModel.js +8 -8
  4. package/build/src/modeling/ApiModel.js.map +1 -1
  5. package/build/src/modeling/helpers/database.d.ts +24 -0
  6. package/build/src/modeling/helpers/database.d.ts.map +1 -0
  7. package/build/src/modeling/helpers/database.js +42 -0
  8. package/build/src/modeling/helpers/database.js.map +1 -0
  9. package/build/src/modeling/importers/CsvImporter.d.ts +36 -0
  10. package/build/src/modeling/importers/CsvImporter.d.ts.map +1 -0
  11. package/build/src/modeling/importers/CsvImporter.js +81 -0
  12. package/build/src/modeling/importers/CsvImporter.js.map +1 -0
  13. package/build/src/modeling/importers/ImporterException.d.ts +10 -0
  14. package/build/src/modeling/importers/ImporterException.d.ts.map +1 -0
  15. package/build/src/modeling/importers/ImporterException.js +10 -0
  16. package/build/src/modeling/importers/ImporterException.js.map +1 -0
  17. package/build/src/modeling/importers/JsonSchemaImporter.d.ts +99 -0
  18. package/build/src/modeling/importers/JsonSchemaImporter.d.ts.map +1 -0
  19. package/build/src/modeling/importers/JsonSchemaImporter.js +525 -0
  20. package/build/src/modeling/importers/JsonSchemaImporter.js.map +1 -0
  21. package/build/tsconfig.tsbuildinfo +1 -1
  22. package/data/models/example-generator-api.json +13 -13
  23. package/package.json +5 -2
  24. package/src/modeling/ApiModel.ts +11 -10
  25. package/src/modeling/helpers/database.ts +48 -0
  26. package/src/modeling/importers/CsvImporter.ts +88 -0
  27. package/src/modeling/importers/ImporterException.ts +10 -0
  28. package/src/modeling/importers/JsonSchemaImporter.ts +642 -0
  29. package/tests/unit/modeling/api_model.spec.ts +9 -9
  30. package/tests/unit/modeling/importers/csv_importer.spec.ts +189 -0
  31. package/tests/unit/modeling/importers/json_schema_importer.spec.ts +451 -0
@@ -0,0 +1,451 @@
1
+ /* eslint-disable max-len */
2
+ import { test } from '@japa/runner'
3
+ // @ts-expect-error - No types for this package
4
+ import schemas from 'schema-org-json-schemas'
5
+ import { type InMemorySchema, JsonSchemaImporter } from '../../../../src/modeling/importers/JsonSchemaImporter.js'
6
+ import { DataDomain } from '../../../../src/modeling/DataDomain.js'
7
+ import type { JSONSchema7 } from 'json-schema'
8
+ import type { DomainEntity } from '../../../../src/modeling/DomainEntity.js'
9
+ import { DomainAssociation, DomainProperty } from '../../../../src/browser.js'
10
+
11
+ const input: InMemorySchema[] = []
12
+ for (const [key, value] of Object.entries(schemas)) {
13
+ input.push({
14
+ path: key,
15
+ contents: value as JSONSchema7,
16
+ })
17
+ }
18
+
19
+ function findEntityByName(domain: DataDomain, name: string): DomainEntity {
20
+ for (const entity of domain.listEntities()) {
21
+ if (entity.info.name === name || entity.info.displayName === name) {
22
+ return entity
23
+ }
24
+ }
25
+ throw new Error(`Entity with name "${name}" not found`)
26
+ }
27
+
28
+ function findPropertyByName(entity: DomainEntity, name: string): DomainProperty {
29
+ for (const prop of entity.listProperties()) {
30
+ if (prop.info.name === name || prop.info.displayName === name) {
31
+ return prop
32
+ }
33
+ }
34
+ throw new Error(`Property with name "${name}" not found`)
35
+ }
36
+
37
+ function findAssociationByName(entity: DomainEntity, name: string): DomainAssociation {
38
+ for (const assoc of entity.listAssociations()) {
39
+ if (assoc.info.name === name || assoc.info.displayName === name) {
40
+ return assoc
41
+ }
42
+ }
43
+ throw new Error(`Association with name "${name}" not found`)
44
+ }
45
+
46
+ test.group('JsonSchemaImporter', (g) => {
47
+ let domain: DataDomain
48
+
49
+ g.setup(async () => {
50
+ domain = new DataDomain({ info: { name: 'Test Domain' } })
51
+ const importer = new JsonSchemaImporter(domain)
52
+ await importer.import(input, 'imported_model')
53
+ // console.log('Import report:', result.messages)
54
+ })
55
+
56
+ // We won't test for all schemas, just a few to ensure the importer works
57
+
58
+ test('Book schema is imported', ({ assert }) => {
59
+ const bookEntity = findEntityByName(domain, 'Book')
60
+ assert.exists(bookEntity, 'Book entity should exist')
61
+ assert.equal(bookEntity.info.name, 'book')
62
+ assert.equal(bookEntity.info.displayName, 'Book')
63
+ assert.equal(bookEntity.info.description, 'A book.')
64
+ const abridged = findPropertyByName(bookEntity, 'abridged')
65
+ assert.exists(abridged, 'Book entity should have abridged property')
66
+ assert.isUndefined(abridged.info.displayName, 'displayName should be undefined.')
67
+ assert.equal(abridged.info.description, 'Indicates whether the book is an abridged edition.')
68
+ assert.equal(abridged.type, 'boolean')
69
+ assert.isFalse(abridged.required, 'Abridged property should not be required')
70
+ assert.isFalse(abridged.multiple, 'Abridged property should not allow multiple values')
71
+ const bookEdition = findPropertyByName(bookEntity, 'bookEdition')
72
+ assert.exists(bookEdition, 'Book entity should have bookEdition property')
73
+ assert.equal(bookEdition.info.displayName, 'bookEdition')
74
+ assert.equal(bookEdition.info.description, 'The edition of the book.')
75
+ assert.equal(bookEdition.type, 'string')
76
+ assert.isFalse(bookEdition.required, 'Book edition property should not be required')
77
+ assert.isFalse(bookEdition.multiple, 'Book edition property should not allow multiple values')
78
+ const bookFormat = findPropertyByName(bookEntity, 'bookFormat')
79
+ assert.exists(bookFormat, 'Book entity should have bookFormat property')
80
+ assert.equal(bookFormat.info.name, 'book_format')
81
+ assert.equal(bookFormat.info.displayName, 'bookFormat')
82
+ assert.equal(bookFormat.info.description, 'The format of the book.')
83
+ assert.isFalse(bookFormat.required, 'Book format property should not be required')
84
+ assert.isFalse(bookFormat.multiple, 'Book format property should not allow multiple values')
85
+ const illustrator = findAssociationByName(bookEntity, 'illustrator')
86
+ assert.exists(illustrator, 'Book entity should have illustrator association')
87
+ assert.equal(illustrator.info.name, 'illustrator')
88
+ assert.isUndefined(illustrator.info.displayName, 'displayName should be undefined.')
89
+ assert.equal(illustrator.info.description, 'The illustrator of the book.')
90
+ assert.isFalse(illustrator.required, 'Illustrator association should not be required')
91
+ assert.isFalse(illustrator.multiple, 'Illustrator association should not allow multiple values')
92
+ assert.isNotEmpty(illustrator.targets, 'Illustrator association should have targets')
93
+ assert.lengthOf([...illustrator.listTargets()], 1, 'Illustrator association should have exactly one target')
94
+ const isbn = findPropertyByName(bookEntity, 'isbn')
95
+ assert.exists(isbn, 'Book entity should have isbn property')
96
+ assert.equal(isbn.info.name, 'isbn')
97
+ assert.isUndefined(isbn.info.displayName, 'The ISBN display name is undefined.')
98
+ assert.equal(isbn.info.description, 'The ISBN of the book.')
99
+ assert.equal(isbn.type, 'string')
100
+ assert.isFalse(isbn.required, 'ISBN property should not be required')
101
+ assert.isFalse(isbn.multiple, 'ISBN property should not allow multiple values')
102
+ const numberOfPages = findPropertyByName(bookEntity, 'numberOfPages')
103
+ assert.exists(numberOfPages, 'Book entity should have numberOfPages property')
104
+ assert.equal(numberOfPages.info.name, 'number_of_pages')
105
+ assert.equal(numberOfPages.info.displayName, 'numberOfPages')
106
+ assert.equal(numberOfPages.info.description, 'The number of pages in the book.')
107
+ assert.equal(numberOfPages.type, 'number')
108
+ assert.isFalse(numberOfPages.required, 'Number of pages property should not be required')
109
+ assert.isFalse(numberOfPages.multiple, 'Number of pages property should not allow multiple values')
110
+ const numberOfPagesWebBindings = numberOfPages.getWebBinding()
111
+ assert.exists(numberOfPagesWebBindings, 'Number of pages should have web bindings')
112
+ assert.equal(numberOfPagesWebBindings?.format, 'int64', 'Web binding format should be int64')
113
+ const parents = [...bookEntity.parents]
114
+ assert.lengthOf(parents, 1, 'Book entity should have one parent')
115
+ assert.equal(parents[0].info.name, 'creative_work', 'Parent entity should be CreativeWork')
116
+ })
117
+
118
+ test('Canal schema is imported and inherits from BodyOfWater', ({ assert }) => {
119
+ const canalEntity = findEntityByName(domain, 'Canal')
120
+ assert.exists(canalEntity, 'Canal entity should exist')
121
+ assert.equal(canalEntity.info.name, 'canal')
122
+ assert.equal(canalEntity.info.displayName, 'Canal')
123
+ assert.equal(canalEntity.info.description, 'A canal, like the Panama Canal.')
124
+ // Should have one parent: BodyOfWater
125
+ const parents = [...canalEntity.parents]
126
+ assert.lengthOf(parents, 1, 'Canal entity should have one parent')
127
+ assert.equal(parents[0].info.name, 'body_of_water', 'Parent entity should be BodyOfWater')
128
+ assert.equal(parents[0].info.displayName, 'BodyOfWater')
129
+ assert.equal(parents[0].info.description, 'A body of water, such as a sea, ocean, or lake.')
130
+ // Canal should not have properties or associations of its own (unless inherited)
131
+ assert.lengthOf([...canalEntity.listProperties()], 0, 'Canal should not have direct properties')
132
+ assert.lengthOf([...canalEntity.listAssociations()], 0, 'Canal should not have direct associations')
133
+ })
134
+
135
+ test('DataFeedItem schema is imported and properties are mapped correctly', ({ assert }) => {
136
+ const dataFeedItem = findEntityByName(domain, 'DataFeedItem')
137
+ assert.exists(dataFeedItem, 'DataFeedItem entity should exist')
138
+ assert.equal(dataFeedItem.info.name, 'data_feed_item')
139
+ assert.equal(dataFeedItem.info.displayName, 'DataFeedItem')
140
+ assert.equal(dataFeedItem.info.description, 'A single item within a larger data feed.')
141
+ // Should have one parent: Intangible
142
+ const parents = [...dataFeedItem.parents]
143
+ assert.lengthOf(parents, 1, 'DataFeedItem should have one parent')
144
+ assert.equal(parents[0].info.name, 'intangible', 'Parent entity should be Intangible')
145
+
146
+ // dateCreated property
147
+ const dateCreated = findPropertyByName(dataFeedItem, 'dateCreated')
148
+ assert.exists(dateCreated, 'dateCreated property should exist')
149
+ assert.equal(dateCreated.info.name, 'date_created')
150
+ assert.equal(dateCreated.info.displayName, 'dateCreated')
151
+ assert.equal(
152
+ dateCreated.info.description,
153
+ 'The date on which the CreativeWork was created or the item was added to a DataFeed.'
154
+ )
155
+ assert.equal(dateCreated.type, 'datetime')
156
+ assert.isFalse(dateCreated.required, 'dateCreated should not be required')
157
+ assert.isFalse(dateCreated.multiple, 'dateCreated should not allow multiple values')
158
+
159
+ // dateDeleted property
160
+ const dateDeleted = findPropertyByName(dataFeedItem, 'dateDeleted')
161
+ assert.exists(dateDeleted, 'dateDeleted property should exist')
162
+ assert.equal(dateDeleted.info.name, 'date_deleted')
163
+ assert.equal(dateDeleted.info.displayName, 'dateDeleted')
164
+ assert.equal(dateDeleted.info.description, 'The datetime the item was removed from the DataFeed.')
165
+ assert.equal(dateDeleted.type, 'datetime')
166
+ assert.isFalse(dateDeleted.required, 'dateDeleted should not be required')
167
+ assert.isFalse(dateDeleted.multiple, 'dateDeleted should not allow multiple values')
168
+
169
+ // dateModified property
170
+ const dateModified = findPropertyByName(dataFeedItem, 'dateModified')
171
+ assert.exists(dateModified, 'dateModified property should exist')
172
+ assert.equal(dateModified.info.name, 'date_modified')
173
+ assert.equal(dateModified.info.displayName, 'dateModified')
174
+ assert.equal(
175
+ dateModified.info.description,
176
+ "The date on which the CreativeWork was most recently modified or when the item's entry was modified within a DataFeed."
177
+ )
178
+ assert.equal(dateModified.type, 'datetime')
179
+ assert.isFalse(dateModified.required, 'dateModified should not be required')
180
+ assert.isFalse(dateModified.multiple, 'dateModified should not allow multiple values')
181
+
182
+ // item association
183
+ const itemAssoc = findAssociationByName(dataFeedItem, 'item')
184
+ assert.exists(itemAssoc, 'item association should exist')
185
+ assert.equal(itemAssoc.info.name, 'item')
186
+ assert.isUndefined(itemAssoc.info.displayName, 'the item association display name should be undefined.')
187
+ assert.equal(
188
+ itemAssoc.info.description,
189
+ "An entity represented by an entry in a list or data feed (e.g. an 'artist' in a list of 'artists')’."
190
+ )
191
+ assert.isFalse(itemAssoc.required, 'item association should not be required')
192
+ assert.isTrue(itemAssoc.multiple, 'item association should allow multiple values (array or single)')
193
+ assert.isNotEmpty(itemAssoc.targets, 'item association should have targets')
194
+ assert.lengthOf([...itemAssoc.listTargets()], 1, 'item association should have exactly one target')
195
+ // Target should be Thing
196
+ const target = [...itemAssoc.listTargets()][0]
197
+ assert.equal(target.info.name, 'thing', 'item association target should be Thing')
198
+ })
199
+
200
+ test('Drug schema is imported and properties are mapped correctly', ({ assert }) => {
201
+ const drugEntity = findEntityByName(domain, 'Drug')
202
+ assert.exists(drugEntity, 'Drug entity should exist')
203
+ assert.equal(drugEntity.info.name, 'drug')
204
+ assert.equal(drugEntity.info.displayName, 'Drug')
205
+ assert.equal(
206
+ drugEntity.info.description,
207
+ 'A chemical or biologic substance, used as a medical therapy, that has a physiological effect on an organism. Here the term drug is used interchangeably with the term medicine although clinical knowledge make a clear difference between them.'
208
+ )
209
+ // Should have one parent: Substance
210
+ const parents = [...drugEntity.parents]
211
+ assert.lengthOf(parents, 1, 'Drug should have one parent')
212
+ assert.equal(parents[0].info.name, 'substance', 'Parent entity should be Substance')
213
+
214
+ // activeIngredient property
215
+ const activeIngredient = findPropertyByName(drugEntity, 'activeIngredient')
216
+ assert.exists(activeIngredient, 'activeIngredient property should exist')
217
+ assert.equal(activeIngredient.info.name, 'active_ingredient')
218
+ assert.equal(activeIngredient.info.displayName, 'activeIngredient')
219
+ assert.equal(
220
+ activeIngredient.info.description,
221
+ 'An active ingredient, typically chemical compounds and/or biologic substances.'
222
+ )
223
+ assert.equal(activeIngredient.type, 'string')
224
+ assert.isFalse(activeIngredient.required, 'activeIngredient should not be required')
225
+ assert.isTrue(activeIngredient.multiple, 'activeIngredient should allow multiple values')
226
+
227
+ // administrationRoute property
228
+ const administrationRoute = findPropertyByName(drugEntity, 'administrationRoute')
229
+ assert.exists(administrationRoute, 'administrationRoute property should exist')
230
+ assert.equal(administrationRoute.info.name, 'administration_route')
231
+ assert.equal(administrationRoute.info.displayName, 'administrationRoute')
232
+ assert.equal(administrationRoute.info.description, "A route by which this drug may be administered, e.g. 'oral'.")
233
+ assert.equal(administrationRoute.type, 'string')
234
+ assert.isFalse(administrationRoute.required, 'administrationRoute should not be required')
235
+ assert.isTrue(administrationRoute.multiple, 'administrationRoute should allow multiple values')
236
+
237
+ // alcoholWarning property
238
+ const alcoholWarning = findPropertyByName(drugEntity, 'alcoholWarning')
239
+ assert.exists(alcoholWarning, 'alcoholWarning property should exist')
240
+ assert.equal(alcoholWarning.info.name, 'alcohol_warning')
241
+ assert.equal(alcoholWarning.info.displayName, 'alcoholWarning')
242
+ assert.equal(
243
+ alcoholWarning.info.description,
244
+ 'Any precaution, guidance, contraindication, etc. related to consumption of alcohol while taking this drug.'
245
+ )
246
+ assert.equal(alcoholWarning.type, 'string')
247
+ assert.isFalse(alcoholWarning.required, 'alcoholWarning should not be required')
248
+ assert.isFalse(alcoholWarning.multiple, 'alcoholWarning should not allow multiple values')
249
+
250
+ // availableStrength association
251
+ const availableStrength = findAssociationByName(drugEntity, 'availableStrength')
252
+ assert.exists(availableStrength, 'availableStrength association should exist')
253
+ assert.equal(availableStrength.info.name, 'available_strength')
254
+ assert.equal(availableStrength.info.displayName, 'availableStrength')
255
+ assert.equal(availableStrength.info.description, 'An available dosage strength for the drug.')
256
+ assert.isFalse(availableStrength.required, 'availableStrength should not be required')
257
+ assert.isTrue(availableStrength.multiple, 'availableStrength should allow multiple values')
258
+ assert.isNotEmpty(availableStrength.targets, 'availableStrength should have targets')
259
+
260
+ // isAvailableGenerically property
261
+ const isAvailableGenerically = findPropertyByName(drugEntity, 'isAvailableGenerically')
262
+ assert.exists(isAvailableGenerically, 'isAvailableGenerically property should exist')
263
+ assert.equal(isAvailableGenerically.info.name, 'is_available_generically')
264
+ assert.equal(isAvailableGenerically.info.displayName, 'isAvailableGenerically')
265
+ assert.equal(
266
+ isAvailableGenerically.info.description,
267
+ 'True if the drug is available in a generic form (regardless of name).'
268
+ )
269
+ assert.equal(isAvailableGenerically.type, 'boolean')
270
+ assert.isFalse(isAvailableGenerically.required, 'isAvailableGenerically should not be required')
271
+ assert.isFalse(isAvailableGenerically.multiple, 'isAvailableGenerically should not allow multiple values')
272
+
273
+ // manufacturer association
274
+ const manufacturer = findAssociationByName(drugEntity, 'manufacturer')
275
+ assert.exists(manufacturer, 'manufacturer association should exist')
276
+ assert.equal(manufacturer.info.name, 'manufacturer')
277
+ assert.isUndefined(manufacturer.info.displayName, 'the manufacturer association display name should be undefined.')
278
+ assert.equal(manufacturer.info.description, 'The manufacturer of the product.')
279
+ assert.isFalse(manufacturer.required, 'manufacturer should not be required')
280
+ assert.isFalse(manufacturer.multiple, 'manufacturer should not allow multiple values')
281
+ assert.isNotEmpty(manufacturer.targets, 'manufacturer should have targets')
282
+
283
+ // warning property
284
+ const warning = findPropertyByName(drugEntity, 'warning')
285
+ assert.exists(warning, 'warning property should exist')
286
+ assert.equal(warning.info.name, 'warning')
287
+ assert.isUndefined(warning.info.displayName, 'the warning property display name should be undefined.')
288
+ assert.equal(warning.info.description, 'Any FDA or other warnings about the drug (text or URL).')
289
+ assert.equal(warning.type, 'string')
290
+ assert.isFalse(warning.required, 'warning should not be required')
291
+ assert.isFalse(warning.multiple, 'warning should not allow multiple values')
292
+ })
293
+
294
+ test('Enumeration schema with recursive reference is imported', ({ assert }) => {
295
+ const enumerationEntity = findEntityByName(domain, 'Enumeration')
296
+ assert.exists(enumerationEntity, 'Enumeration entity should exist')
297
+ assert.equal(enumerationEntity.info.name, 'enumeration')
298
+ assert.equal(enumerationEntity.info.displayName, 'Enumeration')
299
+ assert.equal(
300
+ enumerationEntity.info.description,
301
+ 'Lists or enumerations—for example, a list of cuisines or music genres, etc.'
302
+ )
303
+
304
+ // Parent should be Intangible
305
+ const parents = [...enumerationEntity.parents]
306
+ assert.lengthOf(parents, 1, 'Enumeration entity should have one parent')
307
+ assert.equal(parents[0].info.name, 'intangible', 'Parent entity should be Intangible')
308
+
309
+ // supersededBy association
310
+ const supersededBy = findAssociationByName(enumerationEntity, 'supersededBy')
311
+ assert.exists(supersededBy, 'supersededBy association should exist')
312
+ assert.equal(supersededBy.info.name, 'superseded_by')
313
+ assert.equal(supersededBy.info.displayName, 'supersededBy')
314
+ assert.equal(
315
+ supersededBy.info.description,
316
+ 'Relates a term (i.e. a property, class or enumeration) to one that supersedes it.'
317
+ )
318
+ assert.isFalse(supersededBy.required, 'supersededBy should not be required')
319
+ assert.isTrue(supersededBy.multiple, 'supersededBy should allow multiple values')
320
+
321
+ const targets = [...supersededBy.listTargets()].map((t) => t.info.displayName).sort()
322
+ assert.deepEqual(
323
+ targets,
324
+ ['Class', 'Enumeration', 'Property'],
325
+ 'Targets should be Class, Enumeration, and Property'
326
+ )
327
+ })
328
+
329
+ test('Event schema with complex properties is imported', ({ assert }) => {
330
+ const eventEntity = findEntityByName(domain, 'Event')
331
+ assert.exists(eventEntity, 'Event entity should exist')
332
+ assert.equal(eventEntity.info.name, 'event')
333
+ assert.equal(eventEntity.info.displayName, 'Event')
334
+
335
+ // Parent should be Thing
336
+ const parents = [...eventEntity.parents]
337
+ assert.lengthOf(parents, 1, 'Event entity should have one parent')
338
+ assert.equal(parents[0].info.name, 'thing', 'Parent entity should be Thing')
339
+
340
+ // Test a simple boolean property
341
+ const isAccessibleForFree = findPropertyByName(eventEntity, 'isAccessibleForFree')
342
+ assert.exists(isAccessibleForFree)
343
+ assert.equal(isAccessibleForFree.type, 'boolean')
344
+ assert.isFalse(isAccessibleForFree.multiple)
345
+
346
+ // Test a property with a union of string with time formats
347
+ const doorTime = findPropertyByName(eventEntity, 'doorTime')
348
+ assert.exists(doorTime)
349
+ assert.equal(doorTime.type, 'datetime')
350
+ assert.equal(doorTime.info.description, 'The time admission will commence.')
351
+
352
+ const endDate = findPropertyByName(eventEntity, 'endDate')
353
+ assert.exists(endDate)
354
+ assert.equal(endDate.type, 'datetime')
355
+
356
+ // Test a simple association
357
+ const about = findAssociationByName(eventEntity, 'about')
358
+ assert.exists(about)
359
+ assert.isFalse(about.multiple)
360
+ const aboutTargets = [...about.listTargets()]
361
+ assert.lengthOf(aboutTargets, 1)
362
+ assert.equal(aboutTargets[0].info.displayName, 'Thing')
363
+
364
+ // Test an association that can be single or an array
365
+ const actor = findAssociationByName(eventEntity, 'actor')
366
+ assert.exists(actor)
367
+ assert.isTrue(actor.multiple, 'actor should allow multiple values')
368
+ const actorTargets = [...actor.listTargets()]
369
+ assert.lengthOf(actorTargets, 1)
370
+ assert.equal(actorTargets[0].info.displayName, 'Person')
371
+
372
+ // Test an association that can be one of multiple types (and also an array)
373
+ const attendee = findAssociationByName(eventEntity, 'attendee')
374
+ assert.exists(attendee)
375
+ assert.isTrue(attendee.multiple, 'attendee should allow multiple values')
376
+ const attendeeTargets = [...attendee.listTargets()].map((t) => t.info.displayName).sort()
377
+ assert.deepEqual(attendeeTargets, ['Organization', 'Person'])
378
+
379
+ // Test a recursive association
380
+ const subEvent = findAssociationByName(eventEntity, 'subEvent')
381
+ assert.exists(subEvent)
382
+ assert.isTrue(subEvent.multiple, 'subEvent should allow multiple values')
383
+ const subEventTargets = [...subEvent.listTargets()]
384
+ assert.lengthOf(subEventTargets, 1)
385
+ assert.equal(subEventTargets[0].info.displayName, 'Event', 'Target should be self (Event)')
386
+ })
387
+
388
+ test('imports MusicAlbum enum properties correctly', ({ assert }) => {
389
+ const musicAlbumEntity = findEntityByName(domain, 'MusicAlbum')
390
+ const albumProductionType = findPropertyByName(musicAlbumEntity, 'albumProductionType')
391
+ assert.isTrue(albumProductionType.multiple, 'albumProductionType can be an array')
392
+ assert.deepEqual(albumProductionType.schema?.enum?.sort(), [
393
+ 'CompilationAlbum',
394
+ 'DJMixAlbum',
395
+ 'DemoAlbum',
396
+ 'LiveAlbum',
397
+ 'MixtapeAlbum',
398
+ 'RemixAlbum',
399
+ 'SoundtrackAlbum',
400
+ 'SpokenWordAlbum',
401
+ 'StudioAlbum',
402
+ ])
403
+
404
+ const albumReleaseType = findPropertyByName(musicAlbumEntity, 'albumReleaseType')
405
+ assert.isFalse(!!albumReleaseType.multiple, 'albumReleaseType is a single value')
406
+ assert.deepEqual(albumReleaseType.schema?.enum?.sort(), [
407
+ 'AlbumRelease',
408
+ 'BroadcastRelease',
409
+ 'EPRelease',
410
+ 'SingleRelease',
411
+ ])
412
+ })
413
+
414
+ test('imports Brewery correctly', ({ assert }) => {
415
+ const breweryEntity = findEntityByName(domain, 'Brewery')
416
+ assert.lengthOf([...breweryEntity.properties], 0, 'Brewery should not have direct properties')
417
+ assert.lengthOf([...breweryEntity.associations], 0, 'Brewery should not have direct associations')
418
+ assert.equal(breweryEntity.info.name, 'brewery')
419
+ assert.equal(breweryEntity.info.displayName, 'Brewery')
420
+ assert.lengthOf([...breweryEntity.parents], 1, 'Brewery should have one parent')
421
+ assert.equal(
422
+ [...breweryEntity.parents][0].info.name,
423
+ 'food_establishment',
424
+ 'Parent entity should be FoodEstablishment'
425
+ )
426
+ })
427
+
428
+ test('imports ComedyEvent correctly', ({ assert }) => {
429
+ const comedyEventEntity = findEntityByName(domain, 'ComedyEvent')
430
+ assert.lengthOf([...comedyEventEntity.properties], 0, 'ComedyEvent should not have direct properties')
431
+ assert.lengthOf([...comedyEventEntity.associations], 0, 'ComedyEvent should not have direct associations')
432
+ assert.equal(comedyEventEntity.info.name, 'comedy_event')
433
+ assert.equal(comedyEventEntity.info.displayName, 'ComedyEvent')
434
+ assert.lengthOf([...comedyEventEntity.parents], 1, 'ComedyEvent should have one parent')
435
+ assert.equal([...comedyEventEntity.parents][0].info.name, 'event', 'Parent entity should be Event')
436
+ })
437
+
438
+ test('imports ComicIssue correctly', ({ assert }) => {
439
+ const comicIssueEntity = findEntityByName(domain, 'ComicIssue')
440
+ assert.lengthOf([...comicIssueEntity.properties], 1, 'ComicIssue should have one direct property')
441
+ assert.lengthOf([...comicIssueEntity.associations], 5, 'ComicIssue should have five direct associations')
442
+ assert.equal(comicIssueEntity.info.name, 'comic_issue')
443
+ assert.equal(comicIssueEntity.info.displayName, 'ComicIssue')
444
+ assert.lengthOf([...comicIssueEntity.parents], 1, 'ComicIssue should have one parent')
445
+ assert.equal(
446
+ [...comicIssueEntity.parents][0].info.name,
447
+ 'publication_issue',
448
+ 'Parent entity should be PublicationIssue'
449
+ )
450
+ })
451
+ })