@api-client/core 0.14.0 → 0.14.1

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 (140) hide show
  1. package/build/src/amf/AmfTypes.d.ts +1 -1
  2. package/build/src/amf/AmfTypes.js +1 -1
  3. package/build/src/amf/AmfTypes.js.map +1 -1
  4. package/build/src/amf/Utils.d.ts +0 -6
  5. package/build/src/amf/Utils.d.ts.map +1 -1
  6. package/build/src/amf/Utils.js +0 -14
  7. package/build/src/amf/Utils.js.map +1 -1
  8. package/build/src/browser.d.ts +1 -0
  9. package/build/src/browser.d.ts.map +1 -1
  10. package/build/src/browser.js +1 -0
  11. package/build/src/browser.js.map +1 -1
  12. package/build/src/index.d.ts +1 -0
  13. package/build/src/index.d.ts.map +1 -1
  14. package/build/src/index.js +1 -0
  15. package/build/src/index.js.map +1 -1
  16. package/build/src/legacy.d.ts +0 -8
  17. package/build/src/legacy.d.ts.map +1 -1
  18. package/build/src/legacy.js +0 -9
  19. package/build/src/legacy.js.map +1 -1
  20. package/build/src/modeling/Bindings.d.ts +1 -1
  21. package/build/src/modeling/Bindings.js.map +1 -1
  22. package/build/src/modeling/DataDomain.js +2 -2
  23. package/build/src/modeling/DataDomain.js.map +1 -1
  24. package/build/src/modeling/DataFormat.d.ts +0 -40
  25. package/build/src/modeling/DataFormat.d.ts.map +1 -1
  26. package/build/src/modeling/DataFormat.js +0 -27
  27. package/build/src/modeling/DataFormat.js.map +1 -1
  28. package/build/src/modeling/DomainAssociation.d.ts +28 -0
  29. package/build/src/modeling/DomainAssociation.d.ts.map +1 -1
  30. package/build/src/modeling/DomainAssociation.js +73 -4
  31. package/build/src/modeling/DomainAssociation.js.map +1 -1
  32. package/build/src/modeling/DomainEntity.d.ts +25 -9
  33. package/build/src/modeling/DomainEntity.d.ts.map +1 -1
  34. package/build/src/modeling/DomainEntity.js +65 -21
  35. package/build/src/modeling/DomainEntity.js.map +1 -1
  36. package/build/src/modeling/DomainFile.d.ts +1 -1
  37. package/build/src/modeling/DomainFile.js +1 -1
  38. package/build/src/modeling/DomainFile.js.map +1 -1
  39. package/build/src/modeling/DomainImpactAnalysis.d.ts +1 -1
  40. package/build/src/modeling/DomainImpactAnalysis.d.ts.map +1 -1
  41. package/build/src/modeling/DomainImpactAnalysis.js +3 -3
  42. package/build/src/modeling/DomainImpactAnalysis.js.map +1 -1
  43. package/build/src/modeling/DomainModel.d.ts +2 -2
  44. package/build/src/modeling/DomainModel.js +2 -2
  45. package/build/src/modeling/DomainModel.js.map +1 -1
  46. package/build/src/modeling/DomainProperty.d.ts +28 -12
  47. package/build/src/modeling/DomainProperty.d.ts.map +1 -1
  48. package/build/src/modeling/DomainProperty.js +61 -26
  49. package/build/src/modeling/DomainProperty.js.map +1 -1
  50. package/build/src/modeling/Semantics.d.ts +109 -0
  51. package/build/src/modeling/Semantics.d.ts.map +1 -0
  52. package/build/src/modeling/Semantics.js +97 -0
  53. package/build/src/modeling/Semantics.js.map +1 -0
  54. package/build/src/models/kinds.d.ts +0 -24
  55. package/build/src/models/kinds.d.ts.map +1 -1
  56. package/build/src/models/kinds.js +0 -24
  57. package/build/src/models/kinds.js.map +1 -1
  58. package/build/src/models/store/data_catalog.d.ts +1 -1
  59. package/build/src/models/store/data_catalog.js.map +1 -1
  60. package/build/tsconfig.tsbuildinfo +1 -1
  61. package/data/models/example-generator-api.json +11 -11
  62. package/package.json +1 -1
  63. package/src/amf/AmfTypes.ts +1 -1
  64. package/src/amf/Utils.ts +0 -15
  65. package/src/modeling/Bindings.ts +1 -1
  66. package/src/modeling/DataDomain.ts +2 -2
  67. package/src/modeling/DataFormat.ts +0 -48
  68. package/src/modeling/DomainAssociation.ts +66 -3
  69. package/src/modeling/DomainEntity.ts +56 -17
  70. package/src/modeling/DomainFile.ts +1 -1
  71. package/src/modeling/DomainImpactAnalysis.ts +3 -3
  72. package/src/modeling/DomainModel.ts +2 -2
  73. package/src/modeling/DomainProperty.ts +60 -21
  74. package/src/modeling/Semantics.ts +178 -0
  75. package/src/modeling/graph.md +14 -14
  76. package/src/modeling/readme.md +29 -29
  77. package/src/models/kinds.ts +0 -25
  78. package/src/models/store/data_catalog.ts +1 -1
  79. package/tests/unit/modeling/data_domain_change_observers.spec.ts +11 -10
  80. package/tests/unit/modeling/data_domain_entities.spec.ts +129 -1
  81. package/tests/unit/modeling/data_domain_property.spec.ts +1 -1
  82. package/tests/unit/modeling/domain_asociation.spec.ts +177 -0
  83. package/tests/unit/modeling/domain_entity.spec.ts +27 -26
  84. package/tests/unit/modeling/domain_entity_example_generator_json.spec.ts +11 -11
  85. package/tests/unit/modeling/domain_entity_example_generator_xml.spec.ts +10 -10
  86. package/tests/unit/modeling/{domain.property.spec.ts → domain_property.spec.ts} +139 -23
  87. package/build/src/amf/AmfShapeGenerator.d.ts +0 -103
  88. package/build/src/amf/AmfShapeGenerator.d.ts.map +0 -1
  89. package/build/src/amf/AmfShapeGenerator.js +0 -416
  90. package/build/src/amf/AmfShapeGenerator.js.map +0 -1
  91. package/build/src/modeling/legacy/DataAssociation.d.ts +0 -284
  92. package/build/src/modeling/legacy/DataAssociation.d.ts.map +0 -1
  93. package/build/src/modeling/legacy/DataAssociation.js +0 -443
  94. package/build/src/modeling/legacy/DataAssociation.js.map +0 -1
  95. package/build/src/modeling/legacy/DataEntity.d.ts +0 -358
  96. package/build/src/modeling/legacy/DataEntity.d.ts.map +0 -1
  97. package/build/src/modeling/legacy/DataEntity.js +0 -855
  98. package/build/src/modeling/legacy/DataEntity.js.map +0 -1
  99. package/build/src/modeling/legacy/DataEntityBuilder.d.ts +0 -162
  100. package/build/src/modeling/legacy/DataEntityBuilder.d.ts.map +0 -1
  101. package/build/src/modeling/legacy/DataEntityBuilder.js +0 -221
  102. package/build/src/modeling/legacy/DataEntityBuilder.js.map +0 -1
  103. package/build/src/modeling/legacy/DataImpactAnalysis.d.ts +0 -298
  104. package/build/src/modeling/legacy/DataImpactAnalysis.d.ts.map +0 -1
  105. package/build/src/modeling/legacy/DataImpactAnalysis.js +0 -441
  106. package/build/src/modeling/legacy/DataImpactAnalysis.js.map +0 -1
  107. package/build/src/modeling/legacy/DataModel.d.ts +0 -99
  108. package/build/src/modeling/legacy/DataModel.d.ts.map +0 -1
  109. package/build/src/modeling/legacy/DataModel.js +0 -237
  110. package/build/src/modeling/legacy/DataModel.js.map +0 -1
  111. package/build/src/modeling/legacy/DataNamespace.d.ts +0 -340
  112. package/build/src/modeling/legacy/DataNamespace.d.ts.map +0 -1
  113. package/build/src/modeling/legacy/DataNamespace.js +0 -784
  114. package/build/src/modeling/legacy/DataNamespace.js.map +0 -1
  115. package/build/src/modeling/legacy/DataProperty.d.ts +0 -332
  116. package/build/src/modeling/legacy/DataProperty.d.ts.map +0 -1
  117. package/build/src/modeling/legacy/DataProperty.js +0 -415
  118. package/build/src/modeling/legacy/DataProperty.js.map +0 -1
  119. package/build/src/models/store/DataFile.d.ts +0 -29
  120. package/build/src/models/store/DataFile.d.ts.map +0 -1
  121. package/build/src/models/store/DataFile.js +0 -87
  122. package/build/src/models/store/DataFile.js.map +0 -1
  123. package/src/amf/AmfShapeGenerator.ts +0 -477
  124. package/src/modeling/legacy/DataAssociation.ts +0 -554
  125. package/src/modeling/legacy/DataEntity.ts +0 -1019
  126. package/src/modeling/legacy/DataEntityBuilder.ts +0 -236
  127. package/src/modeling/legacy/DataImpactAnalysis.ts +0 -530
  128. package/src/modeling/legacy/DataModel.ts +0 -276
  129. package/src/modeling/legacy/DataNamespace.ts +0 -929
  130. package/src/modeling/legacy/DataProperty.ts +0 -630
  131. package/src/models/store/DataFile.ts +0 -95
  132. package/tests/unit/modeling/legacy/amf_shape_generator.spec.ts +0 -1041
  133. package/tests/unit/modeling/legacy/data_association.spec.ts +0 -710
  134. package/tests/unit/modeling/legacy/data_entity.spec.ts +0 -2061
  135. package/tests/unit/modeling/legacy/data_entity_generator_json.spec.ts +0 -987
  136. package/tests/unit/modeling/legacy/data_entity_generator_xml.spec.ts +0 -1451
  137. package/tests/unit/modeling/legacy/data_model.spec.ts +0 -395
  138. package/tests/unit/modeling/legacy/data_namespace.spec.ts +0 -1312
  139. package/tests/unit/modeling/legacy/data_property.spec.ts +0 -887
  140. package/tests/unit/modeling/legacy/impact_analysis.spec.ts +0 -373
@@ -1,2061 +0,0 @@
1
- import { test } from '@japa/runner'
2
- import {
3
- DataEntityKind,
4
- Thing,
5
- ValidationError,
6
- RemovePropertyException,
7
- RemoveAssociationException,
8
- RemoveEntityException,
9
- ForeignAssociationException,
10
- } from '../../../../src/index.js'
11
- import {
12
- DataNamespace,
13
- DataEntity,
14
- DataProperty,
15
- IDataEntity,
16
- DataModel,
17
- DataAssociation,
18
- } from '../../../../src/legacy.js'
19
-
20
- test.group('constructor() with defaults', (group) => {
21
- let root: DataNamespace
22
- group.each.setup(() => {
23
- root = new DataNamespace()
24
- })
25
-
26
- test('sets the kind', ({ assert }) => {
27
- const assoc = new DataEntity(root)
28
- assert.equal(assoc.kind, DataEntityKind)
29
- })
30
-
31
- test('sets the key', ({ assert }) => {
32
- const assoc = new DataEntity(root)
33
- assert.typeOf(assoc.key, 'string')
34
- assert.isNotEmpty(assoc.key)
35
- })
36
-
37
- test('sets the default "info"', ({ assert }) => {
38
- const assoc = new DataEntity(root)
39
- assert.typeOf(assoc.info, 'EventTarget')
40
- assert.equal(assoc.info.name, '')
41
- })
42
-
43
- test('sets the default "tags"', ({ assert }) => {
44
- const assoc = new DataEntity(root)
45
- assert.deepEqual(assoc.tags, [])
46
- })
47
-
48
- test('sets the default "taxonomy"', ({ assert }) => {
49
- const assoc = new DataEntity(root)
50
- assert.deepEqual(assoc.taxonomy, [])
51
- })
52
-
53
- test('sets the default "properties"', ({ assert }) => {
54
- const assoc = new DataEntity(root)
55
- assert.deepEqual(assoc.properties, [])
56
- })
57
-
58
- test('sets the default "associations"', ({ assert }) => {
59
- const assoc = new DataEntity(root)
60
- assert.deepEqual(assoc.associations, [])
61
- })
62
-
63
- test('sets the default "parents"', ({ assert }) => {
64
- const assoc = new DataEntity(root)
65
- assert.deepEqual(assoc.parents, [])
66
- })
67
-
68
- test('does not set deprecated', ({ assert }) => {
69
- const assoc = new DataProperty(root)
70
- assert.isUndefined(assoc.deprecated)
71
- })
72
- })
73
-
74
- test.group('constructor() from schema initialization', (group) => {
75
- let root: DataNamespace
76
- group.each.setup(() => {
77
- root = new DataNamespace()
78
- })
79
-
80
- test('sets the key', ({ assert }) => {
81
- const orig = new DataEntity(root).toJSON()
82
- orig.key = 'test'
83
- const instance = new DataEntity(root, orig)
84
- assert.equal(instance.key, 'test')
85
- })
86
-
87
- test('sets the info', ({ assert }) => {
88
- const orig = new DataEntity(root).toJSON()
89
- orig.info.name = 'test'
90
- const instance = new DataEntity(root, orig)
91
- assert.equal(instance.info.name, 'test')
92
- })
93
-
94
- test('sets the "tags"', ({ assert }) => {
95
- const orig = new DataEntity(root).toJSON()
96
- orig.tags = ['test']
97
- const assoc = new DataEntity(root, orig)
98
- assert.deepEqual(assoc.tags, ['test'])
99
- })
100
-
101
- test('sets the "taxonomy"', ({ assert }) => {
102
- const orig = new DataEntity(root).toJSON()
103
- orig.taxonomy = ['test']
104
- const assoc = new DataEntity(root, orig)
105
- assert.deepEqual(assoc.taxonomy, ['test'])
106
- })
107
-
108
- test('initializes from JSON schema ', ({ assert }) => {
109
- const orig = new DataEntity(root).toJSON()
110
- orig.key = 'test'
111
- const instance = new DataEntity(root, JSON.stringify(orig))
112
- assert.equal(instance.key, 'test')
113
- })
114
-
115
- test('sets the deprecated', ({ assert }) => {
116
- const orig = new DataEntity(root).toJSON()
117
- orig.deprecated = true
118
- const assoc = new DataEntity(root, orig)
119
- assert.isTrue(assoc.deprecated)
120
- })
121
- })
122
-
123
- test.group('fromName()', (group) => {
124
- let root: DataNamespace
125
- group.each.setup(() => {
126
- root = new DataNamespace()
127
- })
128
-
129
- test('sets the name', ({ assert }) => {
130
- const assoc = DataEntity.fromName(root, 'test')
131
- assert.equal(assoc.info.name, 'test')
132
- })
133
- })
134
-
135
- test.group('new()', (group) => {
136
- let root: DataNamespace
137
- let base: IDataEntity
138
- group.each.setup(() => {
139
- root = new DataNamespace()
140
- base = {
141
- info: Thing.fromName('test name').toJSON(),
142
- key: 'test123',
143
- kind: DataEntityKind,
144
- }
145
- })
146
-
147
- test('sets the key', ({ assert }) => {
148
- const assoc = new DataEntity(root)
149
- assoc.new(base)
150
- assert.equal(assoc.key, 'test123')
151
- })
152
-
153
- test('sets the info', ({ assert }) => {
154
- const assoc = new DataEntity(root)
155
- assoc.new(base)
156
- assert.equal(assoc.info.name, 'test name')
157
- })
158
-
159
- test('sets default info', ({ assert }) => {
160
- const assoc = new DataEntity(root)
161
- // @ts-expect-error Used in testing
162
- delete base.info
163
- assoc.new(base)
164
- assert.equal(assoc.info.name, '')
165
- })
166
-
167
- test('sets the tags as a copy', ({ assert }) => {
168
- const assoc = new DataEntity(root)
169
- const init = { ...base, tags: ['a'] }
170
- assoc.new(init)
171
- assert.deepEqual(assoc.tags, ['a'])
172
- init.tags.push('b')
173
- assert.deepEqual(assoc.tags, ['a'])
174
- })
175
-
176
- test('resets tags when not in the input', ({ assert }) => {
177
- const assoc = new DataEntity(root)
178
- assoc.tags = ['a']
179
- assoc.new(base)
180
- assert.deepEqual(assoc.tags, [])
181
- })
182
-
183
- test('sets the parents as a copy', ({ assert }) => {
184
- const assoc = new DataEntity(root)
185
- const init = { ...base, parents: ['a'] }
186
- assoc.new(init)
187
- assert.deepEqual(assoc.parents, ['a'])
188
- init.parents.push('b')
189
- assert.deepEqual(assoc.parents, ['a'])
190
- })
191
-
192
- test('resets parents when not in the input', ({ assert }) => {
193
- const assoc = new DataEntity(root)
194
- assoc.parents = ['a']
195
- assoc.new(base)
196
- assert.deepEqual(assoc.parents, [])
197
- })
198
-
199
- test('sets the properties as a copy', ({ assert }) => {
200
- const src = new DataEntity(root)
201
- const p1 = src.addNamedProperty('p1')
202
- const assoc = new DataEntity(root)
203
- const init = src.toJSON()
204
- assoc.new(init)
205
- assert.deepEqual(assoc.properties, [p1])
206
- const p2 = src.addNamedProperty('p2')
207
- init.properties!.push(p2.key)
208
- assert.deepEqual(assoc.properties, [p1])
209
- })
210
-
211
- test('resets properties when not in the input', ({ assert }) => {
212
- const assoc = new DataEntity(root)
213
- assoc.addNamedProperty('test')
214
- assoc.new(base)
215
- assert.deepEqual(assoc.properties, [])
216
- })
217
-
218
- test('sets the associations as a copy', ({ assert }) => {
219
- const src = new DataEntity(root)
220
- const a1 = src.addNamedAssociation('a1')
221
- const assoc = new DataEntity(root)
222
- const init = src.toJSON()
223
- assoc.new(init)
224
- assert.deepEqual(assoc.associations, [a1])
225
- const a2 = src.addNamedAssociation('a2')
226
- init.associations!.push(a2.key)
227
- assert.deepEqual(assoc.associations, [a1])
228
- })
229
-
230
- test('resets associations when not in the input', ({ assert }) => {
231
- const assoc = new DataEntity(root)
232
- assoc.addNamedAssociation('test')
233
- assoc.new(base)
234
- assert.deepEqual(assoc.associations, [])
235
- })
236
-
237
- test('sets the taxonomy as a copy', ({ assert }) => {
238
- const assoc = new DataEntity(root)
239
- const init = { ...base, taxonomy: ['a'] }
240
- assoc.new(init)
241
- assert.deepEqual(assoc.taxonomy, ['a'])
242
- init.taxonomy.push('b')
243
- assert.deepEqual(assoc.taxonomy, ['a'])
244
- })
245
-
246
- test('resets taxonomy when not in the input', ({ assert }) => {
247
- const assoc = new DataEntity(root)
248
- assoc.taxonomy = ['a']
249
- assoc.new(base)
250
- assert.deepEqual(assoc.taxonomy, [])
251
- })
252
-
253
- test('sets the deprecated', ({ assert }) => {
254
- const assoc = new DataEntity(root)
255
- assoc.new({ ...base, deprecated: true })
256
- assert.isTrue(assoc.deprecated)
257
- })
258
-
259
- test('does not set deprecated when not in the input', ({ assert }) => {
260
- const assoc = new DataEntity(root)
261
- assoc.new(base)
262
- assert.isUndefined(assoc.deprecated)
263
- })
264
-
265
- test('throws when unknown input', ({ assert }) => {
266
- const assoc = new DataEntity(root)
267
- assert.throws(() => {
268
- // @ts-expect-error Used in testing
269
- assoc.new({})
270
- }, 'Invalid data entity definition.')
271
- })
272
-
273
- test('sets the fields as a copy', ({ assert }) => {
274
- const src = new DataEntity(root)
275
- const p1 = src.addNamedProperty('p1')
276
- const a1 = src.addNamedAssociation('a1')
277
- const assoc = new DataEntity(root)
278
- const init = src.toJSON()
279
- assoc.new(init)
280
- assert.deepEqual(assoc.fields, [
281
- { type: 'property', key: p1.key },
282
- { type: 'association', key: a1.key },
283
- ])
284
- const p2 = src.addNamedProperty('p2')
285
- init.fields!.push({ type: 'property', key: p2.key })
286
- assert.deepEqual(assoc.fields, [
287
- { type: 'property', key: p1.key },
288
- { type: 'association', key: a1.key },
289
- ])
290
- })
291
-
292
- test('resets fields when not in the input', ({ assert }) => {
293
- const assoc = new DataEntity(root)
294
- assoc.addNamedProperty('p1')
295
- assoc.addNamedAssociation('a1')
296
- assoc.new(base)
297
- assert.deepEqual(assoc.fields, [])
298
- })
299
-
300
- test('creates fields when missing', ({ assert }) => {
301
- const assoc = new DataEntity(root)
302
- const p1 = assoc.addNamedProperty('p1')
303
- const a1 = assoc.addNamedAssociation('a1')
304
- const init = assoc.toJSON()
305
- delete init.fields
306
- const instance = new DataEntity(root)
307
- instance.new(init)
308
- assert.deepEqual(instance.fields, [
309
- { type: 'property', key: p1.key },
310
- { type: 'association', key: a1.key },
311
- ])
312
- })
313
- })
314
-
315
- test.group('toJSON()', (group) => {
316
- let root: DataNamespace
317
- let base: DataEntity
318
- group.each.setup(() => {
319
- root = new DataNamespace()
320
- base = new DataEntity(root, {
321
- info: Thing.fromName('test name').toJSON(),
322
- key: 'test123',
323
- kind: DataEntityKind,
324
- })
325
- })
326
-
327
- test('serializes the kind', ({ assert }) => {
328
- const result = base.toJSON()
329
- assert.equal(result.kind, DataEntityKind)
330
- })
331
-
332
- test('serializes the key', ({ assert }) => {
333
- const result = base.toJSON()
334
- assert.equal(result.key, base.key)
335
- })
336
-
337
- test('serializes the info', ({ assert }) => {
338
- const result = base.toJSON()
339
- assert.equal(result.info.name, 'test name')
340
- })
341
-
342
- test('does not serialize taxonomy by default', ({ assert }) => {
343
- const result = base.toJSON()
344
- assert.isUndefined(result.taxonomy)
345
- })
346
-
347
- test('does not serialize tags by default', ({ assert }) => {
348
- const result = base.toJSON()
349
- assert.isUndefined(result.tags)
350
- })
351
-
352
- test('does not serialize parents by default', ({ assert }) => {
353
- const result = base.toJSON()
354
- assert.isUndefined(result.parents)
355
- })
356
-
357
- test('does not serialize properties by default', ({ assert }) => {
358
- const result = base.toJSON()
359
- assert.isUndefined(result.properties)
360
- })
361
-
362
- test('does not serialize associations by default', ({ assert }) => {
363
- const result = base.toJSON()
364
- assert.isUndefined(result.associations)
365
- })
366
-
367
- test('serializes tags as a copy', ({ assert }) => {
368
- base.tags = ['a']
369
- const result = base.toJSON()
370
- assert.deepEqual(result.tags, ['a'])
371
- base.tags.push('b')
372
- assert.deepEqual(result.tags, ['a'])
373
- })
374
-
375
- test('serializes taxonomy as a copy', ({ assert }) => {
376
- base.taxonomy = ['a']
377
- const result = base.toJSON()
378
- assert.deepEqual(result.taxonomy, ['a'])
379
- base.taxonomy.push('b')
380
- assert.deepEqual(result.taxonomy, ['a'])
381
- })
382
-
383
- test('serializes parents as a copy', ({ assert }) => {
384
- base.parents = ['a']
385
- const result = base.toJSON()
386
- assert.deepEqual(result.parents, ['a'])
387
- base.parents.push('b')
388
- assert.deepEqual(result.parents, ['a'])
389
- })
390
-
391
- test('serializes properties as a copy', ({ assert }) => {
392
- const p1 = base.addNamedProperty('p1')
393
- const result = base.toJSON()
394
- assert.deepEqual(result.properties, [p1.key])
395
- base.addNamedProperty('p2')
396
- assert.deepEqual(result.properties, [p1.key])
397
- })
398
-
399
- test('serializes associations as a copy', ({ assert }) => {
400
- const a1 = base.addNamedAssociation('a1')
401
- const result = base.toJSON()
402
- assert.deepEqual(result.associations, [a1.key])
403
- base.addNamedAssociation('a2')
404
- assert.deepEqual(result.associations, [a1.key])
405
- })
406
-
407
- test('serializes fields as a copy', ({ assert }) => {
408
- const p1 = base.addNamedProperty('p1')
409
- const a1 = base.addNamedAssociation('a1')
410
- const result = base.toJSON()
411
- assert.deepEqual(result.fields, [
412
- { type: 'property', key: p1.key },
413
- { type: 'association', key: a1.key },
414
- ])
415
- base.addNamedProperty('p2')
416
- assert.deepEqual(result.fields, [
417
- { type: 'property', key: p1.key },
418
- { type: 'association', key: a1.key },
419
- ])
420
- })
421
-
422
- test('does not serialize fields when empty', ({ assert }) => {
423
- const result = base.toJSON()
424
- assert.isUndefined(result.fields)
425
- })
426
-
427
- test('does not serialize deprecated by default', ({ assert }) => {
428
- const result = base.toJSON()
429
- assert.isUndefined(result.deprecated)
430
- })
431
-
432
- test('serialize the set deprecated', ({ assert }) => {
433
- base.deprecated = false
434
- const result = base.toJSON()
435
- assert.isFalse(result.deprecated)
436
- })
437
- })
438
-
439
- test.group('remove()', (group) => {
440
- let root: DataNamespace
441
- let m1: DataModel
442
- let e1: DataEntity
443
- let e2: DataEntity
444
-
445
- group.each.setup(() => {
446
- root = new DataNamespace()
447
- m1 = root.addDataModel('m1')
448
- e1 = m1.addEntity('e1')
449
- e2 = m1.addEntity('e2')
450
- e1.addNamedProperty('test prop')
451
- e1.addTargetAssociation(e2.key)
452
- })
453
-
454
- test('removes self from the parent data model', ({ assert }) => {
455
- e1.remove()
456
- assert.deepEqual(m1.entities, [e2])
457
- })
458
-
459
- test('removes self from the root definitions', ({ assert }) => {
460
- e1.remove()
461
- assert.deepEqual(root.definitions.entities, [e2])
462
- })
463
-
464
- test('removes own properties', ({ assert }) => {
465
- const p2 = e2.addNamedProperty('other')
466
- e1.remove()
467
- assert.deepEqual(e2.properties, [p2])
468
- assert.deepEqual(root.definitions.properties, [p2])
469
- })
470
-
471
- test('removes own associations', ({ assert }) => {
472
- const e3 = m1.addEntity('e3')
473
- const a2 = e2.addTargetAssociation(e3.key)
474
- e1.remove()
475
- assert.deepEqual(e2.associations, [a2])
476
- assert.deepEqual(root.definitions.associations, [a2])
477
- })
478
-
479
- test('throws when removing an entity that is a target', ({ assert }) => {
480
- e2.addTargetAssociation(e1.key)
481
- assert.throws(
482
- () => e1.remove(),
483
- RemoveEntityException as unknown as ErrorConstructor,
484
- `Cannot remove entity ${e1.info.name} because it is used as a target in associations in entities: e2.`
485
- )
486
- })
487
-
488
- test('force removes an entity that is a target', ({ assert }) => {
489
- e2.addTargetAssociation(e1.key)
490
- e1.remove({ force: true })
491
- assert.deepEqual(m1.entities, [e2])
492
- assert.deepEqual(root.definitions.entities, [e2])
493
- assert.deepEqual(e2.associations, [], 'removes the association from the target entity')
494
- assert.deepEqual(e2.fields, [], 'removes the association from the entity fields')
495
- assert.deepEqual(root.definitions.associations, [], 'removes the association from the root definitions')
496
- })
497
-
498
- test('throws when removing an entity that is a parent', ({ assert }) => {
499
- const e3 = m1.addEntity('e3')
500
- e3.addParent(e1.key)
501
- assert.throws(
502
- () => e1.remove(),
503
- RemoveEntityException as unknown as ErrorConstructor,
504
- `Cannot remove entity ${e1.info.name} because it is a parent for the following entities: e3.`
505
- )
506
- })
507
-
508
- test('force removes an entity that is a parent', ({ assert }) => {
509
- const e3 = m1.addEntity('e3')
510
- e3.addParent(e1.key)
511
- e1.remove({ force: true })
512
- assert.deepEqual(m1.entities, [e2, e3])
513
- assert.deepEqual(root.definitions.entities, [e2, e3])
514
- assert.deepEqual(e3.parents, [], 'removes the parent from the child entity')
515
- })
516
-
517
- test('force removes an entity that is a parent and a target', ({ assert }) => {
518
- const e3 = m1.addEntity('e3')
519
- e3.addParent(e1.key)
520
- e2.addTargetAssociation(e1.key)
521
- e1.remove({ force: true })
522
- assert.deepEqual(m1.entities, [e2, e3])
523
- assert.deepEqual(root.definitions.entities, [e2, e3])
524
- assert.deepEqual(e3.parents, [], 'removes the parent from the child entity')
525
- assert.deepEqual(e2.associations, [], 'removes the association from the target entity')
526
- assert.deepEqual(root.definitions.associations, [], 'removes the association from the root definitions')
527
- })
528
- })
529
-
530
- test.group('addTypedProperty()', (group) => {
531
- let root: DataNamespace
532
- let m1: DataModel
533
- let e1: DataEntity
534
- let e2: DataEntity
535
-
536
- group.each.setup(() => {
537
- root = new DataNamespace()
538
- m1 = root.addDataModel('m1')
539
- e1 = m1.addEntity('e1')
540
- e2 = m1.addEntity('e2')
541
- })
542
-
543
- test('adds the property to the entity', ({ assert }) => {
544
- const p1 = e1.addTypedProperty('boolean')
545
- assert.deepEqual(e1.properties, [p1])
546
- })
547
-
548
- test('adds the property type', ({ assert }) => {
549
- const p1 = e1.addTypedProperty('boolean')
550
- assert.equal(p1.type, 'boolean')
551
- })
552
-
553
- test('adds the property to the root definitions', ({ assert }) => {
554
- const p1 = e1.addTypedProperty('boolean')
555
- assert.deepEqual(root.definitions.properties, [p1])
556
- })
557
-
558
- test('does not change other entities', ({ assert }) => {
559
- e1.addTypedProperty('boolean')
560
- assert.deepEqual(e2.properties, [])
561
- })
562
- })
563
-
564
- test.group('addNamedProperty()', (group) => {
565
- let root: DataNamespace
566
- let m1: DataModel
567
- let e1: DataEntity
568
- let e2: DataEntity
569
-
570
- group.each.setup(() => {
571
- root = new DataNamespace()
572
- m1 = root.addDataModel('m1')
573
- e1 = m1.addEntity('e1')
574
- e2 = m1.addEntity('e2')
575
- })
576
-
577
- test('adds the property to the entity', ({ assert }) => {
578
- const p1 = e1.addNamedProperty('hello')
579
- assert.deepEqual(e1.properties, [p1])
580
- })
581
-
582
- test('adds the property type', ({ assert }) => {
583
- const p1 = e1.addNamedProperty('hello')
584
- assert.equal(p1.info.name, 'hello')
585
- })
586
-
587
- test('adds the property to the root definitions', ({ assert }) => {
588
- const p1 = e1.addNamedProperty('hello')
589
- assert.deepEqual(root.definitions.properties, [p1])
590
- })
591
-
592
- test('does not change other entities', ({ assert }) => {
593
- e1.addNamedProperty('hello')
594
- assert.deepEqual(e2.properties, [])
595
- })
596
- })
597
-
598
- test.group('removeProperty()', (group) => {
599
- let root: DataNamespace
600
- let m1: DataModel
601
- let e1: DataEntity
602
- let e2: DataEntity
603
- let p1: DataProperty
604
-
605
- group.each.setup(() => {
606
- root = new DataNamespace()
607
- m1 = root.addDataModel('m1')
608
- e1 = m1.addEntity('e1')
609
- e2 = m1.addEntity('e2')
610
- p1 = e1.addNamedProperty('p2')
611
- })
612
-
613
- test('removes the property from the entity', ({ assert }) => {
614
- e1.removeProperty(p1.key)
615
- assert.deepEqual(e1.properties, [])
616
- })
617
-
618
- test('removes the property from the root definitions', ({ assert }) => {
619
- e1.removeProperty(p1.key)
620
- assert.deepEqual(root.definitions.properties, [])
621
- })
622
-
623
- test('keeps other properties', ({ assert }) => {
624
- const p2 = e1.addNamedProperty('p2')
625
- const p3 = e2.addNamedProperty('p3')
626
- e1.removeProperty(p1.key)
627
- assert.deepEqual(e1.properties, [p2])
628
- assert.deepEqual(root.definitions.properties, [p2, p3])
629
- })
630
-
631
- test('throws when the property belongs to another data entity', ({ assert }) => {
632
- const p2 = e1.addNamedProperty('p2')
633
- const p3 = e2.addNamedProperty('p3')
634
- assert.throws(
635
- () => {
636
- e1.removeProperty(p3.key)
637
- },
638
- RemovePropertyException as unknown as ErrorConstructor,
639
- `Trying to remove the ${p3.key} property, but it doesn't exist.`
640
- )
641
- assert.deepEqual(e1.properties, [p1, p2])
642
- assert.deepEqual(root.definitions.properties, [p1, p2, p3])
643
- })
644
-
645
- test('throws when the property does not exist', ({ assert }) => {
646
- assert.throws(
647
- () => {
648
- e1.removeProperty('test')
649
- },
650
- RemovePropertyException as unknown as ErrorConstructor,
651
- `Trying to remove the test property, but it doesn't exist.`
652
- )
653
- assert.deepEqual(e1.properties, [p1])
654
- assert.deepEqual(root.definitions.properties, [p1])
655
- })
656
- })
657
-
658
- test.group('addNamedAssociation()', (group) => {
659
- let root: DataNamespace
660
- let m1: DataModel
661
- let e1: DataEntity
662
- let e2: DataEntity
663
-
664
- group.each.setup(() => {
665
- root = new DataNamespace()
666
- m1 = root.addDataModel('m1')
667
- e1 = m1.addEntity('e1')
668
- e2 = m1.addEntity('e2')
669
- })
670
-
671
- test('adds the association to the entity', ({ assert }) => {
672
- const a1 = e1.addNamedAssociation('test')
673
- assert.deepEqual(e1.associations, [a1])
674
- })
675
-
676
- test('adds the association to the root definitions', ({ assert }) => {
677
- const a1 = e1.addNamedAssociation('test')
678
- assert.deepEqual(root.definitions.associations, [a1])
679
- })
680
-
681
- test('adds the association name', ({ assert }) => {
682
- const a1 = e1.addNamedAssociation('test')
683
- assert.deepEqual(a1.info.name, 'test')
684
- })
685
-
686
- test('does not change other entities', ({ assert }) => {
687
- e1.addNamedAssociation('test')
688
- assert.deepEqual(e2.associations, [])
689
- })
690
- })
691
-
692
- test.group('addTargetAssociation()', (group) => {
693
- let root: DataNamespace
694
- let m1: DataModel
695
- let e1: DataEntity
696
- let e2: DataEntity
697
-
698
- group.each.setup(() => {
699
- root = new DataNamespace()
700
- m1 = root.addDataModel('m1')
701
- e1 = m1.addEntity('e1')
702
- e2 = m1.addEntity('e2')
703
- })
704
-
705
- test('adds the association to the entity', ({ assert }) => {
706
- const a1 = e1.addTargetAssociation(e2.key)
707
- assert.deepEqual(e1.associations, [a1])
708
- })
709
-
710
- test('adds the association to the root definitions', ({ assert }) => {
711
- const a1 = e1.addTargetAssociation(e2.key)
712
- assert.deepEqual(root.definitions.associations, [a1])
713
- })
714
-
715
- test('adds the association target', ({ assert }) => {
716
- const a1 = e1.addTargetAssociation(e2.key)
717
- assert.deepEqual(a1.targets, [{ key: e2.key }])
718
- })
719
-
720
- test('does not change other entities', ({ assert }) => {
721
- e1.addTargetAssociation(e2.key)
722
- assert.deepEqual(e2.associations, [])
723
- })
724
- })
725
-
726
- test.group('addForeignAssociation()', (group) => {
727
- let n1: DataNamespace
728
- let n2: DataNamespace
729
- let m1: DataModel
730
- let m2: DataModel
731
- let e1: DataEntity
732
- let e2: DataEntity
733
-
734
- group.each.setup(() => {
735
- n1 = new DataNamespace()
736
- n2 = new DataNamespace()
737
- n1.foreign.push(n2)
738
- m1 = n1.addDataModel('m1')
739
- m2 = n2.addDataModel('m2')
740
- e1 = m1.addEntity('e1')
741
- e2 = m2.addEntity('e2')
742
- })
743
-
744
- test('adds the association to the entity', ({ assert }) => {
745
- const a1 = e1.addForeignAssociation(e2.key, n2.key)
746
- assert.deepEqual(e1.associations, [a1])
747
- })
748
-
749
- test('adds the association to the root definitions', ({ assert }) => {
750
- const a1 = e1.addForeignAssociation(e2.key, n2.key)
751
- assert.deepEqual(n1.definitions.associations, [a1])
752
- })
753
-
754
- test('adds the association target', ({ assert }) => {
755
- const a1 = e1.addForeignAssociation(e2.key, n2.key)
756
- assert.deepEqual(a1.targets, [{ key: e2.key, namespace: n2.key }])
757
- })
758
-
759
- test('does not change other entities', ({ assert }) => {
760
- e1.addForeignAssociation(e2.key, n2.key)
761
- assert.deepEqual(e2.associations, [])
762
- })
763
-
764
- test('sets the association name', ({ assert }) => {
765
- const a1 = e1.addForeignAssociation(e2.key, n2.key, 'my name')
766
- assert.equal(a1.info.name, 'my name')
767
- })
768
-
769
- test('throws when the foreign namespace is not defined', ({ assert }) => {
770
- assert.throws(
771
- () => e1.addForeignAssociation(e2.key, 'unknown'),
772
- ForeignAssociationException as unknown as ErrorConstructor,
773
- 'Trying to add a foreign association but the foreign namespace is not defined.'
774
- )
775
- })
776
-
777
- test('throws when adding a foreign association that targets the same entity', ({ assert }) => {
778
- assert.throws(
779
- () => e1.addForeignAssociation(e1.key, n1.key),
780
- ForeignAssociationException as unknown as ErrorConstructor,
781
- 'Trying to add a foreign association but the foreign namespace is not defined.'
782
- )
783
- })
784
- })
785
-
786
- test.group('removeAssociation()', (group) => {
787
- let root: DataNamespace
788
- let m1: DataModel
789
- let e1: DataEntity
790
- let e2: DataEntity
791
- let a1: DataAssociation
792
-
793
- group.each.setup(() => {
794
- root = new DataNamespace()
795
- m1 = root.addDataModel('m1')
796
- e1 = m1.addEntity('e1')
797
- e2 = m1.addEntity('e2')
798
- a1 = e1.addTargetAssociation(e2.key)
799
- })
800
-
801
- test('removes the association from the entity', ({ assert }) => {
802
- e1.removeAssociation(a1.key)
803
- assert.deepEqual(e1.associations, [])
804
- })
805
-
806
- test('removes the association from the root definitions', ({ assert }) => {
807
- e1.removeAssociation(a1.key)
808
- assert.deepEqual(root.definitions.associations, [])
809
- })
810
-
811
- test('keeps other associations', ({ assert }) => {
812
- const e3 = m1.addEntity('e3')
813
- const a2 = e1.addTargetAssociation(e2.key)
814
- const a3 = e2.addTargetAssociation(e3.key)
815
- e1.removeAssociation(a1.key)
816
- assert.deepEqual(e1.associations, [a2])
817
- assert.deepEqual(root.definitions.associations, [a2, a3])
818
- })
819
-
820
- test('throws when the association belongs to another data entity', ({ assert }) => {
821
- const e3 = m1.addEntity('e3')
822
- const a2 = e1.addTargetAssociation(e2.key)
823
- const a3 = e2.addTargetAssociation(e3.key)
824
- assert.throws(
825
- () => e1.removeAssociation(a3.key),
826
- RemoveAssociationException as unknown as ErrorConstructor,
827
- `Trying to remove the ${a3.key} association, but it doesn't exist.`
828
- )
829
- assert.deepEqual(e1.associations, [a1, a2])
830
- assert.deepEqual(root.definitions.associations, [a1, a2, a3])
831
- })
832
-
833
- test('throws when the association does not exist', ({ assert }) => {
834
- assert.throws(
835
- () => e1.removeAssociation('test'),
836
- RemoveAssociationException as unknown as ErrorConstructor,
837
- `Trying to remove the test association, but it doesn't exist.`
838
- )
839
- assert.deepEqual(e1.associations, [a1])
840
- assert.deepEqual(root.definitions.associations, [a1])
841
- })
842
- })
843
-
844
- test.group('getComputedParents()', (group) => {
845
- let root: DataNamespace
846
- let m1: DataModel
847
- let e1: DataEntity
848
-
849
- group.each.setup(() => {
850
- root = new DataNamespace()
851
- m1 = root.addDataModel('m1')
852
- e1 = m1.addEntity('e1')
853
- })
854
-
855
- test('returns empty array when no parents', ({ assert }) => {
856
- const result = e1.getComputedParents()
857
- assert.deepEqual(result, [])
858
- })
859
-
860
- test('returns a parent', ({ assert }) => {
861
- const e2 = m1.addEntity('e2')
862
- e1.parents.push(e2.key)
863
- const result = e1.getComputedParents()
864
- assert.deepEqual(result, [e2])
865
- })
866
-
867
- test('returns only direct parents by default', ({ assert }) => {
868
- const e2 = m1.addEntity('e2')
869
- const e3 = m1.addEntity('e3')
870
- e2.parents.push(e3.key)
871
- e1.parents.push(e2.key)
872
- const result = e1.getComputedParents()
873
- assert.deepEqual(result, [e2])
874
- })
875
-
876
- test('returns a parent with their parents', ({ assert }) => {
877
- const e2 = m1.addEntity('e2')
878
- const e3 = m1.addEntity('e3')
879
- e2.parents.push(e3.key)
880
- e1.parents.push(e2.key)
881
- const result = e1.getComputedParents(true)
882
- assert.deepEqual(result, [e2, e3])
883
- })
884
-
885
- test('returns all parents and their parents', ({ assert }) => {
886
- const e2 = m1.addEntity('e2')
887
- const e3 = m1.addEntity('e3')
888
- const e4 = m1.addEntity('e4')
889
- e2.parents.push(e3.key)
890
- e1.parents.push(e2.key)
891
- e1.parents.push(e4.key)
892
- const result = e1.getComputedParents(true)
893
- assert.deepEqual(result, [e2, e3, e4])
894
- })
895
- })
896
-
897
- test.group('getComputedChildren()', (group) => {
898
- let root: DataNamespace
899
- let m1: DataModel
900
- let e1: DataEntity
901
-
902
- group.each.setup(() => {
903
- root = new DataNamespace()
904
- m1 = root.addDataModel('m1')
905
- e1 = m1.addEntity('e1')
906
- })
907
-
908
- test('returns empty array when no children', ({ assert }) => {
909
- const result = e1.getComputedChildren()
910
- assert.deepEqual(result, [])
911
- })
912
-
913
- test('returns the direct children', ({ assert }) => {
914
- const e2 = m1.addEntity('e2')
915
- const e3 = m1.addEntity('e3')
916
- e2.parents.push(e1.key)
917
- e3.parents.push(e2.key)
918
-
919
- const result = e1.getComputedChildren()
920
- assert.deepEqual(result, [e2])
921
- })
922
-
923
- test('returns grandchildren', ({ assert }) => {
924
- const e2 = m1.addEntity('e2')
925
- const e3 = m1.addEntity('e3')
926
- e2.addParent(e1.key)
927
- e3.addParent(e2.key)
928
- const result = e1.getComputedChildren()
929
- assert.deepEqual(result, [e2])
930
- })
931
-
932
- test('returns empty array when no direct children', ({ assert }) => {
933
- const e2 = m1.addEntity('e2')
934
- const e3 = m1.addEntity('e3')
935
- e3.addParent(e2.key)
936
- const result = e1.getComputedChildren()
937
- assert.deepEqual(result, [])
938
- })
939
- })
940
-
941
- test.group('getComputedAssociations()', (group) => {
942
- let root: DataNamespace
943
- let m1: DataModel
944
- let e1: DataEntity
945
-
946
- group.each.setup(() => {
947
- root = new DataNamespace()
948
- m1 = root.addDataModel('m1')
949
- e1 = m1.addEntity('e1')
950
- })
951
-
952
- test('returns empty array when no association', ({ assert }) => {
953
- const result = e1.getComputedAssociations()
954
- assert.deepEqual(result, [])
955
- })
956
-
957
- test('returns the association targets', ({ assert }) => {
958
- const e2 = m1.addEntity('e2')
959
- const e3 = m1.addEntity('e3')
960
- e1.addTargetAssociation(e2.key)
961
- e2.addTargetAssociation(e3.key)
962
-
963
- const result = e1.getComputedAssociations()
964
- assert.deepEqual(result, [e2])
965
- })
966
-
967
- test('ignores when the target is not defined', ({ assert }) => {
968
- e1.addNamedAssociation('hello')
969
- const result = e1.getComputedAssociations()
970
- assert.deepEqual(result, [])
971
- })
972
-
973
- test('ignores when the target schema is not defined', ({ assert }) => {
974
- e1.addTargetAssociation('other')
975
- const result = e1.getComputedAssociations()
976
- assert.deepEqual(result, [])
977
- })
978
-
979
- test('throws for missing foreign entities', ({ assert }) => {
980
- assert.throws(() => {
981
- e1.addForeignAssociation('entity', 'namespace')
982
- }, `Trying to add a foreign association but the foreign namespace is not defined.`)
983
- })
984
-
985
- test('finds entities in a foreign namespaces', ({ assert }) => {
986
- const f1 = new DataNamespace()
987
- const fm1 = f1.addDataModel('fm1')
988
- const fe1 = fm1.addEntity('fe1')
989
- root.foreign.push(f1)
990
- e1.addForeignAssociation(fe1.key, f1.key)
991
- const result = e1.getComputedAssociations()
992
- assert.deepEqual(result, [fe1])
993
- })
994
-
995
- test('ignores unknown entities in a foreign namespaces', ({ assert }) => {
996
- const f1 = new DataNamespace()
997
- const fm1 = f1.addDataModel('fm1')
998
- fm1.addEntity('fe1')
999
- root.foreign.push(f1)
1000
- e1.addForeignAssociation('other', f1.key)
1001
- const result = e1.getComputedAssociations()
1002
- assert.deepEqual(result, [])
1003
- })
1004
-
1005
- test('returns multiple associations', ({ assert }) => {
1006
- const e2 = m1.addEntity('e2')
1007
- const e3 = m1.addEntity('e3')
1008
- e1.addTargetAssociation(e2.key)
1009
- e1.addTargetAssociation(e3.key)
1010
-
1011
- const result = e1.getComputedAssociations()
1012
- assert.deepEqual(result.sort(), [e2, e3].sort())
1013
- })
1014
-
1015
- test('returns indirect associations', ({ assert }) => {
1016
- const e2 = m1.addEntity('e2')
1017
- const e3 = m1.addEntity('e3')
1018
- e1.addTargetAssociation(e2.key)
1019
- e2.addTargetAssociation(e3.key)
1020
-
1021
- const result = e1.getComputedAssociations()
1022
- assert.deepEqual(result, [e2])
1023
- })
1024
-
1025
- test('returns multiple targets', ({ assert }) => {
1026
- const e2 = m1.addEntity('e2')
1027
- const e3 = m1.addEntity('e3')
1028
- const a1 = e1.addNamedAssociation('a1')
1029
- a1.addTarget(e2)
1030
- a1.addTarget(e3)
1031
-
1032
- const result = e1.getComputedAssociations()
1033
- assert.deepEqual(result.sort(), [e2, e3].sort())
1034
- })
1035
- })
1036
-
1037
- test.group('associationPath()', (group) => {
1038
- let root: DataNamespace
1039
- let m1: DataModel
1040
- let e1: DataEntity
1041
- let e2: DataEntity
1042
- let e3: DataEntity
1043
- let e4: DataEntity
1044
- let e5: DataEntity
1045
-
1046
- group.each.setup(() => {
1047
- root = new DataNamespace()
1048
- m1 = root.addDataModel('m1')
1049
- e1 = m1.addEntity('e1')
1050
- e2 = m1.addEntity('e2')
1051
- e3 = m1.addEntity('e3')
1052
- e4 = m1.addEntity('e4')
1053
- e5 = m1.addEntity('e5')
1054
- })
1055
-
1056
- test('finds a direct connection', ({ assert }) => {
1057
- e1.addTargetAssociation(e2.key)
1058
- const paths: string[][] = []
1059
- for (const path of e1.associationPath(e2.key)) {
1060
- paths.push(path)
1061
- }
1062
- assert.lengthOf(paths, 1, 'has a single path')
1063
- assert.deepEqual(paths[0], [e1.key, e2.key], 'has the path')
1064
- })
1065
-
1066
- test('finds a connection through another entity', ({ assert }) => {
1067
- e1.addTargetAssociation(e2.key)
1068
- e2.addTargetAssociation(e3.key)
1069
- const paths: string[][] = []
1070
- for (const path of e1.associationPath(e3.key)) {
1071
- paths.push(path)
1072
- }
1073
- assert.lengthOf(paths, 1, 'has a single path')
1074
- assert.deepEqual(paths[0], [e1.key, e2.key, e3.key], 'has the path')
1075
- })
1076
-
1077
- test('returns a connection to self', ({ assert }) => {
1078
- e1.addTargetAssociation(e1.key)
1079
- const paths: string[][] = []
1080
- for (const path of e1.associationPath(e1.key)) {
1081
- paths.push(path)
1082
- }
1083
- assert.lengthOf(paths, 1, 'has a single path')
1084
- assert.deepEqual(paths[0], [e1.key], 'has the path')
1085
- })
1086
-
1087
- test('yields multiple directions', ({ assert }) => {
1088
- e1.addTargetAssociation(e5.key)
1089
- e1.addTargetAssociation(e2.key)
1090
- e2.addTargetAssociation(e3.key)
1091
- e3.addTargetAssociation(e4.key)
1092
- e4.addTargetAssociation(e5.key)
1093
- const paths: string[][] = []
1094
- for (const path of e1.associationPath(e5.key)) {
1095
- paths.push(path)
1096
- }
1097
- assert.lengthOf(paths, 2, 'has both paths')
1098
- assert.deepEqual(paths[0], [e1.key, e2.key, e3.key, e4.key, e5.key], 'has the 1st path')
1099
- assert.deepEqual(paths[1], [e1.key, e5.key], 'has the 2nd path')
1100
- })
1101
-
1102
- test('ignores broken paths', ({ assert }) => {
1103
- e1.addTargetAssociation(e5.key)
1104
- e1.addTargetAssociation(e2.key)
1105
- e2.addTargetAssociation(e3.key)
1106
- // no e3 -> e4
1107
- e4.addTargetAssociation(e5.key)
1108
- const paths: string[][] = []
1109
- for (const path of e1.associationPath(e5.key)) {
1110
- paths.push(path)
1111
- }
1112
- assert.lengthOf(paths, 1, 'has both paths')
1113
- assert.deepEqual(paths[0], [e1.key, e5.key], 'has the 1st path')
1114
- })
1115
- })
1116
-
1117
- test.group('associationPath() - More Complex Scenarios', (group) => {
1118
- let root: DataNamespace
1119
- let model: DataModel
1120
- let entityA: DataEntity
1121
- let entityB: DataEntity
1122
- let entityC: DataEntity
1123
- let entityD: DataEntity
1124
- let foreignRoot: DataNamespace
1125
- let foreignEntity: DataEntity
1126
-
1127
- group.each.setup(() => {
1128
- root = new DataNamespace()
1129
- model = root.addDataModel('model')
1130
- entityA = model.addEntity('entityA')
1131
- entityB = model.addEntity('entityB')
1132
- entityC = model.addEntity('entityC')
1133
- entityD = model.addEntity('entityD')
1134
-
1135
- foreignRoot = new DataNamespace()
1136
- root.addForeign(foreignRoot)
1137
- const foreignModel = foreignRoot.addDataModel('foreignModel')
1138
- foreignEntity = foreignModel.addEntity('foreignEntity')
1139
- })
1140
-
1141
- test('returns multiple paths when multiple indirect associations', ({ assert }) => {
1142
- entityA.addTargetAssociation(entityB.key)
1143
- entityA.addTargetAssociation(entityC.key)
1144
- entityB.addTargetAssociation(entityD.key)
1145
- entityC.addTargetAssociation(entityD.key)
1146
- const result = [...entityA.associationPath(entityD.key)]
1147
- assert.deepEqual(result, [
1148
- [entityA.key, entityC.key, entityD.key],
1149
- [entityA.key, entityB.key, entityD.key],
1150
- ])
1151
- })
1152
-
1153
- test('returns empty array when not associated', ({ assert }) => {
1154
- entityA.addTargetAssociation(entityB.key)
1155
- const result = [...entityA.associationPath(entityC.key)]
1156
- assert.deepEqual(result, [])
1157
- })
1158
-
1159
- test('returns empty array when no associations in foreign namespaces', ({ assert }) => {
1160
- entityA.addForeignAssociation(foreignEntity.key, foreignRoot.key)
1161
- const result = [...entityA.associationPath(entityB.key)]
1162
- assert.deepEqual(result, [])
1163
- })
1164
-
1165
- test('returns the path when foreign association', ({ assert }) => {
1166
- entityA.addForeignAssociation(foreignEntity.key, foreignRoot.key)
1167
- const result = [...entityA.associationPath(foreignEntity.key)]
1168
- assert.deepEqual(result, [[entityA.key, foreignEntity.key]])
1169
- })
1170
- })
1171
-
1172
- test.group('isAssociated()', (group) => {
1173
- let root: DataNamespace
1174
- let m1: DataModel
1175
- let e1: DataEntity
1176
- let e2: DataEntity
1177
- let e3: DataEntity
1178
- let e4: DataEntity
1179
-
1180
- let foreignRoot: DataNamespace
1181
- let foreignEntity: DataEntity
1182
-
1183
- group.each.setup(() => {
1184
- root = new DataNamespace()
1185
- m1 = root.addDataModel('m1')
1186
- e1 = m1.addEntity('e1')
1187
- e2 = m1.addEntity('e2')
1188
- e3 = m1.addEntity('e3')
1189
- e4 = m1.addEntity('e4')
1190
-
1191
- foreignRoot = new DataNamespace()
1192
- root.addForeign(foreignRoot)
1193
- const foreignModel = foreignRoot.addDataModel('foreignModel')
1194
- foreignEntity = foreignModel.addEntity('foreignEntity')
1195
- })
1196
-
1197
- test('returns true when testing self', ({ assert }) => {
1198
- const result = e1.isAssociated(e1.key)
1199
- assert.isTrue(result)
1200
- })
1201
-
1202
- test('returns true when has direct association', ({ assert }) => {
1203
- e1.addTargetAssociation(e2.key)
1204
- const result = e1.isAssociated(e2.key)
1205
- assert.isTrue(result)
1206
- })
1207
-
1208
- test('returns true when has an association', ({ assert }) => {
1209
- e1.addTargetAssociation(e2.key)
1210
- e2.addTargetAssociation(e3.key)
1211
- const result = e1.isAssociated(e3.key)
1212
- assert.isTrue(result)
1213
- })
1214
-
1215
- test('returns false when has no association', ({ assert }) => {
1216
- e1.addTargetAssociation(e2.key)
1217
- const result = e1.isAssociated(e3.key)
1218
- assert.isFalse(result)
1219
- })
1220
-
1221
- test('returns true when has multiple paths', ({ assert }) => {
1222
- e1.addTargetAssociation(e2.key)
1223
- e1.addTargetAssociation(e3.key)
1224
- e3.addTargetAssociation(e4.key)
1225
- e2.addTargetAssociation(e4.key)
1226
- const result = e1.isAssociated(e4.key)
1227
- assert.isTrue(result)
1228
- })
1229
-
1230
- test('returns false when has no path', ({ assert }) => {
1231
- e1.addTargetAssociation(e2.key)
1232
- const result = e1.isAssociated(e3.key)
1233
- assert.isFalse(result)
1234
- })
1235
-
1236
- test('returns false when no association', ({ assert }) => {
1237
- const result = DataEntity.isAssociated(e1, e2)
1238
- assert.isFalse(result)
1239
- })
1240
-
1241
- test('returns true when foreign association', ({ assert }) => {
1242
- e1.addForeignAssociation(foreignEntity.key, foreignRoot.key)
1243
- const result = DataEntity.isAssociated(e1, foreignEntity)
1244
- assert.isTrue(result)
1245
- })
1246
-
1247
- test('returns true when has multiple paths', ({ assert }) => {
1248
- e1.addTargetAssociation(e2.key)
1249
- e1.addTargetAssociation(e3.key)
1250
- e3.addTargetAssociation(e4.key)
1251
- e2.addTargetAssociation(e4.key)
1252
- const result = DataEntity.isAssociated(e1, e4)
1253
- assert.isTrue(result)
1254
- })
1255
- })
1256
-
1257
- test.group('getRelatedEntities()', (group) => {
1258
- let n1: DataNamespace
1259
- let n2: DataNamespace
1260
- let m1: DataModel
1261
- let m2: DataModel
1262
- let e1a: DataEntity
1263
- let e1b: DataEntity
1264
- let e2a: DataEntity
1265
-
1266
- group.each.setup(() => {
1267
- n1 = new DataNamespace()
1268
- n2 = new DataNamespace()
1269
- n1.foreign.push(n2)
1270
- m1 = n1.addDataModel('m1')
1271
- m2 = n2.addDataModel('m2')
1272
- e1a = m1.addEntity('e1a')
1273
- e1b = m1.addEntity('e1b')
1274
- e2a = m2.addEntity('e2a')
1275
- m2.addEntity('e2b')
1276
- m2.addEntity('e2b')
1277
- })
1278
-
1279
- test('reads entities from the same namespace', ({ assert }) => {
1280
- // associate e1b with e1a and the result is the reverse
1281
- e1b.addTargetAssociation(e1a.key)
1282
- const result = e1a.getRelatedEntities()
1283
- assert.deepEqual(result, [e1b])
1284
- })
1285
-
1286
- test('reads entities from another namespace', ({ assert }) => {
1287
- // associate e1b with e1a and the result is the reverse
1288
- e2a.addTargetAssociation(e1a.key)
1289
- const result = e1a.getRelatedEntities()
1290
- assert.deepEqual(result, [e2a])
1291
- })
1292
-
1293
- test('reads mixed entities from own and another namespace', ({ assert }) => {
1294
- // associate e1b with e1a and the result is the reverse
1295
- e1b.addTargetAssociation(e1a.key)
1296
- e2a.addTargetAssociation(e1a.key)
1297
- const result = e1a.getRelatedEntities()
1298
- assert.deepEqual(result, [e1b, e2a])
1299
- })
1300
-
1301
- test('returns multiple related entities', ({ assert }) => {
1302
- e1b.addTargetAssociation(e1a)
1303
- e2a.addTargetAssociation(e1a)
1304
- const result = e1a.getRelatedEntities()
1305
- assert.deepEqual(result.sort(), [e1b, e2a].sort())
1306
- })
1307
- })
1308
-
1309
- test.group('breadcrumbs()', (group) => {
1310
- let root: DataNamespace
1311
- group.each.setup(() => {
1312
- root = new DataNamespace()
1313
- })
1314
-
1315
- test('adds root and self', ({ assert }) => {
1316
- const e1 = new DataEntity(root)
1317
- const result = e1.breadcrumbs()
1318
- assert.lengthOf(result, 2, 'has the entire path')
1319
- assert.equal(result[0].key, root.key, 'has the root as first')
1320
- assert.equal(result[1].key, e1.key, 'has the entity as last')
1321
- })
1322
-
1323
- test('adds root, data model, and self', ({ assert }) => {
1324
- const m1 = root.addDataModel('m1')
1325
- const e1 = m1.addEntity('e1')
1326
- const result = e1.breadcrumbs()
1327
- assert.lengthOf(result, 3, 'has the entire path')
1328
- assert.equal(result[0].key, root.key, 'has the root as first')
1329
- assert.equal(result[1].key, m1.key, 'has the model as parent')
1330
- assert.equal(result[2].key, e1.key, 'has self last')
1331
- })
1332
-
1333
- test('adds root, sub-ns, data model, and self', ({ assert }) => {
1334
- const n1 = root.addNamespace('n1')
1335
- const m1 = n1.addDataModel('m1')
1336
- const e1 = m1.addEntity('e1')
1337
- const result = e1.breadcrumbs()
1338
- assert.lengthOf(result, 4, 'has the entire path')
1339
- assert.equal(result[0].key, root.key, 'has the root as first')
1340
- assert.equal(result[1].key, n1.key, 'has the child-namespace')
1341
- assert.equal(result[2].key, m1.key, 'has the model as parent')
1342
- assert.equal(result[3].key, e1.key, 'has self last')
1343
- })
1344
-
1345
- test('adds root, sub-ns, sub-ns, data model, and self', ({ assert }) => {
1346
- const n1 = root.addNamespace('n1')
1347
- const n2 = n1.addNamespace('n2')
1348
- const m1 = n2.addDataModel('m1')
1349
- const e1 = m1.addEntity('e1')
1350
- const result = e1.breadcrumbs()
1351
- assert.lengthOf(result, 5, 'has the entire path')
1352
- assert.equal(result[0].key, root.key, 'has the root as first')
1353
- assert.equal(result[1].key, n1.key, 'has the child-namespace')
1354
- assert.equal(result[2].key, n2.key, 'has the child-namespace')
1355
- assert.equal(result[3].key, m1.key, 'has the model as parent')
1356
- assert.equal(result[4].key, e1.key, 'has self last')
1357
- })
1358
- })
1359
-
1360
- test.group('addTag()', (group) => {
1361
- let root: DataNamespace
1362
- let m1: DataModel
1363
- let e1: DataEntity
1364
-
1365
- group.each.setup(() => {
1366
- root = new DataNamespace()
1367
- m1 = root.addDataModel('m1')
1368
- e1 = m1.addEntity('e1')
1369
- })
1370
-
1371
- test('ignores when empty', ({ assert }) => {
1372
- e1.addTag('')
1373
- assert.deepEqual(e1.tags, [])
1374
- })
1375
-
1376
- test('adds a tag to the property', ({ assert }) => {
1377
- e1.addTag('Test')
1378
- assert.deepEqual(e1.tags, ['Test'])
1379
- })
1380
-
1381
- test('ignores a tag case insensitive', ({ assert }) => {
1382
- e1.addTag('Test')
1383
- e1.addTag('teSt')
1384
- assert.deepEqual(e1.tags, ['Test'])
1385
- })
1386
-
1387
- test('adds a tag the root definitions', ({ assert }) => {
1388
- e1.addTag('Test')
1389
- assert.deepEqual(root.definitions.tags, ['Test'])
1390
- })
1391
-
1392
- test('ignores adding to root definitions when tag exists case insensitive', ({ assert }) => {
1393
- e1.addTag('Test')
1394
- e1.addTag('TeSt')
1395
- assert.deepEqual(root.definitions.tags, ['Test'])
1396
- })
1397
- })
1398
-
1399
- test.group('removeTag()', (group) => {
1400
- let root: DataNamespace
1401
- let m1: DataModel
1402
- let e1: DataEntity
1403
-
1404
- group.each.setup(() => {
1405
- root = new DataNamespace()
1406
- m1 = root.addDataModel('m1')
1407
- e1 = m1.addEntity('e1')
1408
- })
1409
-
1410
- test('ignores when empty', ({ assert }) => {
1411
- e1.addTag('t1')
1412
- e1.removeTag('')
1413
- assert.deepEqual(e1.tags, ['t1'])
1414
- })
1415
-
1416
- test('removes the tag from the property', ({ assert }) => {
1417
- e1.addTag('t1')
1418
- e1.removeTag('t1')
1419
- assert.deepEqual(e1.tags, [])
1420
- })
1421
-
1422
- test('removes only the selected tag', ({ assert }) => {
1423
- e1.addTag('t1')
1424
- e1.addTag('t2')
1425
- e1.addTag('t3')
1426
- e1.removeTag('t2')
1427
- assert.deepEqual(e1.tags, ['t1', 't3'])
1428
- })
1429
-
1430
- test('does not remove root tags', ({ assert }) => {
1431
- e1.addTag('t1')
1432
- e1.removeTag('t1')
1433
- assert.deepEqual(root.definitions.tags, ['t1'])
1434
- })
1435
- })
1436
-
1437
- test.group('addTag() and removeTag() - More Scenarios', (group) => {
1438
- let root: DataNamespace
1439
- let m1: DataModel
1440
- let e1: DataEntity
1441
-
1442
- group.each.setup(() => {
1443
- root = new DataNamespace()
1444
- m1 = root.addDataModel('m1')
1445
- e1 = m1.addEntity('e1')
1446
- })
1447
-
1448
- test('adds multiple tags to the property', ({ assert }) => {
1449
- e1.addTag('Test1')
1450
- e1.addTag('Test2')
1451
- assert.deepEqual(e1.tags, ['Test1', 'Test2'])
1452
- })
1453
-
1454
- test('removes multiple tags from the property', ({ assert }) => {
1455
- e1.addTag('t1')
1456
- e1.addTag('t2')
1457
- e1.addTag('t3')
1458
- e1.removeTag('t1')
1459
- e1.removeTag('t3')
1460
- assert.deepEqual(e1.tags, ['t2'])
1461
- })
1462
-
1463
- test('removes a tag case insensitive', ({ assert }) => {
1464
- e1.addTag('Test')
1465
- e1.removeTag('teSt')
1466
- assert.deepEqual(e1.tags, [])
1467
- })
1468
- })
1469
-
1470
- test.group('toApiShape()', (group) => {
1471
- let root: DataNamespace
1472
- let m1: DataModel
1473
- let e1: DataEntity
1474
-
1475
- group.each.setup(() => {
1476
- root = new DataNamespace()
1477
- m1 = root.addDataModel('m1')
1478
- e1 = m1.addEntity('e1')
1479
- })
1480
-
1481
- // these tests only check whether the AmfShapeGenerator is called.
1482
- // specific tests are performed elsewhere
1483
-
1484
- test('returns an object', ({ assert }) => {
1485
- const result = e1.toApiShape()
1486
- assert.typeOf(result, 'object')
1487
- assert.typeOf(result.inherits, 'array')
1488
- })
1489
- })
1490
-
1491
- test.group('hasClosedCycle()', (group) => {
1492
- let root: DataNamespace
1493
- let m1: DataModel
1494
- let e1: DataEntity
1495
- let e2: DataEntity
1496
- let e3: DataEntity
1497
-
1498
- group.each.setup(() => {
1499
- root = new DataNamespace()
1500
- m1 = root.addDataModel('m1')
1501
- e1 = m1.addEntity('e1')
1502
- e2 = m1.addEntity('e2')
1503
- e3 = m1.addEntity('e3')
1504
- })
1505
-
1506
- test('returns false when no association', ({ assert }) => {
1507
- const result = e1.hasClosedCycle(e1.key, e2.key)
1508
- assert.isFalse(result)
1509
- })
1510
-
1511
- test('returns false when not recursive', ({ assert }) => {
1512
- e1.addTargetAssociation(e2.key)
1513
- const result = e2.hasClosedCycle(e1.key, e3.key)
1514
- assert.isFalse(result)
1515
- })
1516
-
1517
- test('returns true when testing self-association', ({ assert }) => {
1518
- const result = e1.hasClosedCycle(e1.key, e1.key)
1519
- assert.isTrue(result)
1520
- })
1521
-
1522
- test('returns true when referencing a closest neighbor', ({ assert }) => {
1523
- e1.addTargetAssociation(e2.key)
1524
- const result = e2.hasClosedCycle(e1.key, e1.key)
1525
- assert.isTrue(result)
1526
- })
1527
-
1528
- test('multiple cycles', ({ assert }) => {
1529
- const e4 = m1.addEntity('e4')
1530
- e1.addTargetAssociation(e2.key)
1531
- e2.addTargetAssociation(e3.key)
1532
- e3.addTargetAssociation(e4.key)
1533
-
1534
- assert.isTrue(e1.hasClosedCycle(e1.key, e1.key), 'e1 -> e1')
1535
- assert.isFalse(e1.hasClosedCycle(e1.key, e2.key), 'e1 -> e2')
1536
- assert.isFalse(e1.hasClosedCycle(e1.key, e3.key), 'e1 -> e3')
1537
- assert.isFalse(e1.hasClosedCycle(e1.key, e4.key), 'e1 -> e4')
1538
-
1539
- assert.isTrue(e2.hasClosedCycle(e1.key, e1.key), 'e2 -> e1')
1540
- assert.isTrue(e2.hasClosedCycle(e1.key, e2.key), 'e2 -> e2')
1541
- assert.isFalse(e2.hasClosedCycle(e1.key, e3.key), 'e2 -> e3')
1542
- // this does not create a forward cycle just yet. It is safe to render this connection in the UI
1543
- // but it is unsafe to render connection e4 -> e2.
1544
- assert.isFalse(e2.hasClosedCycle(e1.key, e4.key), 'e2 -> e4')
1545
-
1546
- assert.isTrue(e3.hasClosedCycle(e1.key, e1.key), 'e3 -> e1')
1547
- assert.isTrue(e3.hasClosedCycle(e1.key, e2.key), 'e3 -> e2')
1548
- assert.isTrue(e3.hasClosedCycle(e1.key, e3.key), 'e3 -> e3')
1549
- assert.isFalse(e3.hasClosedCycle(e1.key, e4.key), 'e3 -> e4')
1550
-
1551
- assert.isTrue(e4.hasClosedCycle(e1.key, e1.key), 'e4 -> e1')
1552
- assert.isTrue(e4.hasClosedCycle(e1.key, e2.key), 'e4 -> e2')
1553
- assert.isTrue(e4.hasClosedCycle(e1.key, e3.key), 'e4 -> e3')
1554
- assert.isTrue(e4.hasClosedCycle(e1.key, e4.key), 'e4 -> e4')
1555
- })
1556
-
1557
- test('returns false when testing for the next associated node', ({ assert }) => {
1558
- e1.addTargetAssociation(e2.key)
1559
- e2.addTargetAssociation(e3.key)
1560
- e3.addTargetAssociation(e2.key)
1561
-
1562
- assert.isFalse(e2.hasClosedCycle(e1.key, e3.key))
1563
- })
1564
-
1565
- test('returns true when testing for last node going back to the parent', ({ assert }) => {
1566
- e1.addTargetAssociation(e2.key)
1567
- e2.addTargetAssociation(e3.key)
1568
- e3.addTargetAssociation(e2.key)
1569
-
1570
- assert.isTrue(e3.hasClosedCycle(e1.key, e2.key))
1571
- })
1572
- })
1573
-
1574
- test.group('addParent()', (group) => {
1575
- let root: DataNamespace
1576
- let model: DataModel
1577
- let entity1: DataEntity
1578
- let entity2: DataEntity
1579
- let entity3: DataEntity
1580
-
1581
- group.each.setup(() => {
1582
- root = new DataNamespace()
1583
- model = root.addDataModel('model')
1584
- entity1 = model.addEntity('entity1')
1585
- entity2 = model.addEntity('entity2')
1586
- entity3 = model.addEntity('entity3')
1587
- })
1588
-
1589
- test('adds a valid parent', ({ assert }) => {
1590
- entity2.addParent(entity1.key)
1591
- assert.deepEqual(entity2.parents, [entity1.key])
1592
- })
1593
-
1594
- test('throws an error when adding self as parent', ({ assert }) => {
1595
- assert.throws(
1596
- () => entity1.addParent(entity1.key),
1597
- ValidationError as unknown as ErrorConstructor,
1598
- 'Entity cannot be a parent of itself.'
1599
- )
1600
- })
1601
-
1602
- test('throws an error when parent does not exist', ({ assert }) => {
1603
- assert.throws(
1604
- () => entity1.addParent('non-existent-key'),
1605
- ValidationError as unknown as ErrorConstructor,
1606
- 'Entity with key "non-existent-key" not found.'
1607
- )
1608
- })
1609
-
1610
- test('throws an error when circular inheritance is detected - direct', ({ assert }) => {
1611
- entity1.addParent(entity2.key)
1612
- assert.throws(
1613
- () => entity2.addParent(entity1.key),
1614
- ValidationError as unknown as ErrorConstructor,
1615
- 'Circular inheritance detected.'
1616
- )
1617
- })
1618
-
1619
- test('throws an error when circular inheritance is detected - indirect', ({ assert }) => {
1620
- entity1.addParent(entity2.key)
1621
- entity2.addParent(entity3.key)
1622
- assert.throws(
1623
- () => entity3.addParent(entity1.key),
1624
- ValidationError as unknown as ErrorConstructor,
1625
- 'Circular inheritance detected.'
1626
- )
1627
- })
1628
-
1629
- test('does not throw an error when entity1 has entity2 as a parent and entity 2 has entity3 as parent', ({
1630
- assert,
1631
- }) => {
1632
- entity1.addParent(entity2.key)
1633
- assert.doesNotThrow(() => entity2.addParent(entity3.key))
1634
- assert.deepEqual(entity2.parents, [entity3.key])
1635
- })
1636
-
1637
- test('does not throw an error when entity1 has entity3 as a parent and entity 2 has entity3 as parent', ({
1638
- assert,
1639
- }) => {
1640
- entity1.addParent(entity3.key)
1641
- assert.doesNotThrow(() => entity2.addParent(entity3.key))
1642
- assert.deepEqual(entity2.parents, [entity3.key])
1643
- })
1644
-
1645
- test('throws an error when adding the same parent twice', ({ assert }) => {
1646
- entity2.addParent(entity1.key)
1647
- assert.throws(
1648
- () => entity2.addParent(entity1.key),
1649
- ValidationError as unknown as ErrorConstructor,
1650
- `Parent ${entity1.key} already exists.`
1651
- )
1652
- })
1653
-
1654
- test('adds multiple parents', ({ assert }) => {
1655
- entity3.addParent(entity1.key)
1656
- entity3.addParent(entity2.key)
1657
- assert.deepEqual(entity3.parents.sort(), [entity1.key, entity2.key].sort())
1658
- })
1659
- })
1660
-
1661
- test.group('getParentInstance()', (group) => {
1662
- let root: DataNamespace
1663
- let model: DataModel
1664
- let entity1: DataEntity
1665
-
1666
- group.each.setup(() => {
1667
- root = new DataNamespace()
1668
- model = root.addDataModel('model')
1669
- entity1 = model.addEntity('entity1')
1670
- })
1671
-
1672
- test('returns undefined when the entity is not in a model', ({ assert }) => {
1673
- const result = new DataEntity(root).getParentInstance()
1674
- assert.isUndefined(result)
1675
- })
1676
-
1677
- test('returns the parent data model', ({ assert }) => {
1678
- const result = entity1.getParentInstance()
1679
- assert.instanceOf(result, DataModel)
1680
- })
1681
- })
1682
-
1683
- test.group('hasCircularParent()', (group) => {
1684
- let root: DataNamespace
1685
- let model: DataModel
1686
- let entity1: DataEntity
1687
- let entity2: DataEntity
1688
- let entity3: DataEntity
1689
- let entity4: DataEntity
1690
-
1691
- group.each.setup(() => {
1692
- root = new DataNamespace()
1693
- model = root.addDataModel('model')
1694
- entity1 = model.addEntity('entity1')
1695
- entity2 = model.addEntity('entity2')
1696
- entity3 = model.addEntity('entity3')
1697
- entity4 = model.addEntity('entity4')
1698
- })
1699
-
1700
- test('returns false when no parents', ({ assert }) => {
1701
- assert.isFalse(entity1.hasCircularParent(entity2.key))
1702
- })
1703
-
1704
- test('returns false when not a circular dependency', ({ assert }) => {
1705
- entity2.addParent(entity1.key)
1706
- assert.isFalse(entity1.hasCircularParent(entity3.key))
1707
- })
1708
-
1709
- test('returns true when direct circular dependency', ({ assert }) => {
1710
- entity1.addParent(entity2.key)
1711
- assert.isTrue(entity2.hasCircularParent(entity1.key))
1712
- })
1713
-
1714
- test('returns true when indirect circular dependency', ({ assert }) => {
1715
- entity1.addParent(entity2.key)
1716
- entity2.addParent(entity3.key)
1717
- assert.isTrue(entity3.hasCircularParent(entity1.key))
1718
- })
1719
-
1720
- test('returns true when indirect circular dependency - longer chain', ({ assert }) => {
1721
- entity1.addParent(entity2.key)
1722
- entity2.addParent(entity3.key)
1723
- entity3.addParent(entity4.key)
1724
- assert.isTrue(entity4.hasCircularParent(entity1.key))
1725
- })
1726
-
1727
- test('returns true when adding one of children as parent', ({ assert }) => {
1728
- entity1.addParent(entity2.key)
1729
- entity2.addParent(entity3.key)
1730
- assert.isTrue(entity2.hasCircularParent(entity1.key))
1731
- assert.isTrue(entity3.hasCircularParent(entity1.key))
1732
- })
1733
-
1734
- test('returns true when indirect circular dependency - multiple parents', ({ assert }) => {
1735
- entity1.addParent(entity2.key)
1736
- entity1.addParent(entity3.key)
1737
- entity2.addParent(entity4.key)
1738
- assert.isTrue(entity4.hasCircularParent(entity1.key))
1739
- })
1740
- })
1741
-
1742
- test.group('associationPath()', (group) => {
1743
- let root: DataNamespace
1744
- let model: DataModel
1745
- let entityA: DataEntity
1746
- let entityB: DataEntity
1747
- let entityC: DataEntity
1748
- let entityD: DataEntity
1749
-
1750
- group.each.setup(() => {
1751
- root = new DataNamespace()
1752
- model = root.addDataModel('model')
1753
- entityA = model.addEntity('entityA')
1754
- entityB = model.addEntity('entityB')
1755
- entityC = model.addEntity('entityC')
1756
- entityD = model.addEntity('entityD')
1757
- })
1758
-
1759
- test('returns empty generator when no associations', ({ assert }) => {
1760
- const result = [...entityA.associationPath(entityB.key)]
1761
- assert.deepEqual(result, [])
1762
- })
1763
-
1764
- test('returns the path when direct association', ({ assert }) => {
1765
- entityA.addTargetAssociation(entityB.key)
1766
- const result = [...entityA.associationPath(entityB.key)]
1767
- assert.deepEqual(result, [[entityA.key, entityB.key]])
1768
- })
1769
-
1770
- test('returns the path when indirect association', ({ assert }) => {
1771
- entityA.addTargetAssociation(entityB.key)
1772
- entityB.addTargetAssociation(entityC.key)
1773
- const result = [...entityA.associationPath(entityC.key)]
1774
- assert.deepEqual(result, [[entityA.key, entityB.key, entityC.key]])
1775
- })
1776
-
1777
- test('returns multiple paths when multiple indirect associations', ({ assert }) => {
1778
- entityA.addTargetAssociation(entityB.key)
1779
- entityA.addTargetAssociation(entityC.key)
1780
- entityB.addTargetAssociation(entityD.key)
1781
- entityC.addTargetAssociation(entityD.key)
1782
- const result = [...entityA.associationPath(entityD.key)]
1783
- assert.deepEqual(result, [
1784
- [entityA.key, entityC.key, entityD.key],
1785
- [entityA.key, entityB.key, entityD.key],
1786
- ])
1787
- })
1788
-
1789
- test('returns empty array when not associated', ({ assert }) => {
1790
- entityA.addTargetAssociation(entityB.key)
1791
- const result = [...entityA.associationPath(entityC.key)]
1792
- assert.deepEqual(result, [])
1793
- })
1794
-
1795
- test('returns empty array when no associations in foreign namespaces', ({ assert }) => {
1796
- const f1 = new DataNamespace()
1797
- const fm1 = f1.addDataModel('fm1')
1798
- const fe1 = fm1.addEntity('fe1')
1799
- root.foreign.push(f1)
1800
- entityA.addForeignAssociation(fe1.key, f1.key)
1801
- const result = [...entityA.associationPath(entityB.key)]
1802
- assert.deepEqual(result, [])
1803
- })
1804
- })
1805
-
1806
- test.group('getRelatedEntities()', (group) => {
1807
- let root: DataNamespace
1808
- let model: DataModel
1809
- let entityA: DataEntity
1810
- let entityB: DataEntity
1811
- let entityC: DataEntity
1812
- let entityD: DataEntity
1813
- let foreignRoot: DataNamespace
1814
-
1815
- group.each.setup(() => {
1816
- root = new DataNamespace()
1817
- model = root.addDataModel('model')
1818
- entityA = model.addEntity('entityA')
1819
- entityB = model.addEntity('entityB')
1820
- entityC = model.addEntity('entityC')
1821
- entityD = model.addEntity('entityD')
1822
-
1823
- foreignRoot = new DataNamespace()
1824
- root.addForeign(foreignRoot)
1825
- })
1826
-
1827
- test('returns empty array when no related entities', ({ assert }) => {
1828
- const result = entityA.getRelatedEntities()
1829
- assert.deepEqual(result, [])
1830
- })
1831
-
1832
- test('returns related entities when direct association', ({ assert }) => {
1833
- entityA.addTargetAssociation(entityB.key)
1834
- const result = entityB.getRelatedEntities()
1835
- assert.deepEqual(result, [entityA])
1836
- })
1837
-
1838
- test('returns related entities when indirect association', ({ assert }) => {
1839
- entityA.addTargetAssociation(entityB)
1840
- entityB.addTargetAssociation(entityC)
1841
- const result = entityC.getRelatedEntities()
1842
- assert.deepEqual(result, [entityB])
1843
- })
1844
-
1845
- test('returns multiple related entities', ({ assert }) => {
1846
- entityA.addTargetAssociation(entityC)
1847
- entityD.addTargetAssociation(entityC)
1848
- const result = entityC.getRelatedEntities()
1849
- assert.deepEqual(result, [entityA, entityD])
1850
- })
1851
- })
1852
-
1853
- test.group('listProperties()', (group) => {
1854
- let root: DataNamespace
1855
- let m1: DataModel
1856
- let e1: DataEntity
1857
- let p1: DataProperty
1858
- let p2: DataProperty
1859
-
1860
- group.each.setup(() => {
1861
- root = new DataNamespace()
1862
- m1 = root.addDataModel('m1')
1863
- e1 = m1.addEntity('e1')
1864
- p1 = e1.addNamedProperty('p1')
1865
- p2 = e1.addNamedProperty('p2')
1866
- })
1867
-
1868
- test('lists all properties', ({ assert }) => {
1869
- const result = e1.listProperties()
1870
- assert.deepEqual(result, [p1, p2])
1871
- })
1872
-
1873
- test('returns a copy of the array', ({ assert }) => {
1874
- const result = e1.listProperties()
1875
- result.pop()
1876
- assert.lengthOf(e1.properties, 2)
1877
- })
1878
- })
1879
-
1880
- test.group('listAssociations()', (group) => {
1881
- let root: DataNamespace
1882
- let m1: DataModel
1883
- let e1: DataEntity
1884
- let a1: DataAssociation
1885
- let a2: DataAssociation
1886
-
1887
- group.each.setup(() => {
1888
- root = new DataNamespace()
1889
- m1 = root.addDataModel('m1')
1890
- e1 = m1.addEntity('e1')
1891
- a1 = e1.addNamedAssociation('a1')
1892
- a2 = e1.addNamedAssociation('a2')
1893
- })
1894
-
1895
- test('lists all associations', ({ assert }) => {
1896
- const result = e1.listAssociations()
1897
- assert.deepEqual(result, [a1, a2])
1898
- })
1899
-
1900
- test('returns a copy of the array', ({ assert }) => {
1901
- const result = e1.listAssociations()
1902
- result.pop()
1903
- assert.lengthOf(e1.associations, 2)
1904
- })
1905
- })
1906
-
1907
- test.group('listFields()', (group) => {
1908
- let root: DataNamespace
1909
- let m1: DataModel
1910
- let e1: DataEntity
1911
- let p1: DataProperty
1912
- let p2: DataProperty
1913
- let a1: DataAssociation
1914
- let a2: DataAssociation
1915
-
1916
- group.each.setup(() => {
1917
- root = new DataNamespace()
1918
- m1 = root.addDataModel('m1')
1919
- e1 = m1.addEntity('e1')
1920
- p1 = e1.addNamedProperty('p1')
1921
- p2 = e1.addNamedProperty('p2')
1922
- a1 = e1.addNamedAssociation('a1')
1923
- a2 = e1.addNamedAssociation('a2')
1924
- })
1925
-
1926
- test('lists all fields in order', ({ assert }) => {
1927
- const result = e1.listFields()
1928
- assert.deepEqual(result, [p1, p2, a1, a2])
1929
- })
1930
-
1931
- test('returns a copy of the array', ({ assert }) => {
1932
- const result = e1.listFields()
1933
- result.pop()
1934
- assert.lengthOf(e1.fields, 4)
1935
- })
1936
-
1937
- test('returns fields in the order of the fields array', ({ assert }) => {
1938
- e1.moveField(p1.key, 3)
1939
- const result = e1.listFields()
1940
- assert.deepEqual(result, [p2, a1, a2, p1])
1941
- })
1942
- })
1943
-
1944
- test.group('moveField()', (group) => {
1945
- let root: DataNamespace
1946
- let m1: DataModel
1947
- let e1: DataEntity
1948
- let p1: DataProperty
1949
- let p2: DataProperty
1950
- let a1: DataAssociation
1951
- let a2: DataAssociation
1952
-
1953
- group.each.setup(() => {
1954
- root = new DataNamespace()
1955
- m1 = root.addDataModel('m1')
1956
- e1 = m1.addEntity('e1')
1957
- p1 = e1.addNamedProperty('p1')
1958
- p2 = e1.addNamedProperty('p2')
1959
- a1 = e1.addNamedAssociation('a1')
1960
- a2 = e1.addNamedAssociation('a2')
1961
- })
1962
-
1963
- test('moves the field to a new index', ({ assert }) => {
1964
- e1.moveField(p1.key, 3)
1965
- assert.deepEqual(
1966
- e1.fields.map((i) => i.key),
1967
- [p2.key, a1.key, a2.key, p1.key]
1968
- )
1969
- })
1970
-
1971
- test('Moving a field to the same index', ({ assert }) => {
1972
- e1.moveField(p1.key, 0)
1973
- assert.deepEqual(
1974
- e1.fields.map((i) => i.key),
1975
- [p1.key, p2.key, a1.key, a2.key]
1976
- )
1977
- })
1978
-
1979
- test('throws when the field does not exist', ({ assert }) => {
1980
- assert.throws(
1981
- () => e1.moveField('unknown', 0),
1982
- ValidationError as unknown as ErrorConstructor,
1983
- 'Validation failure'
1984
- )
1985
- })
1986
-
1987
- test('throws when the index is out of bounds', ({ assert }) => {
1988
- assert.throws(() => e1.moveField(p1.key, -1), ValidationError as unknown as ErrorConstructor, 'Validation failure')
1989
- assert.throws(() => e1.moveField(p1.key, 4), ValidationError as unknown as ErrorConstructor, 'Validation failure')
1990
- })
1991
- })
1992
-
1993
- test.group('DataEntity.isChildOf()', (group) => {
1994
- let root: DataNamespace
1995
- let n1: DataNamespace
1996
- let n2: DataNamespace
1997
- let m1: DataModel
1998
- let m2: DataModel
1999
- let e1: DataEntity
2000
- let e2: DataEntity
2001
- let e3: DataEntity
2002
-
2003
- group.each.setup(() => {
2004
- root = new DataNamespace()
2005
- n1 = root.addNamespace('n1')
2006
- n2 = n1.addNamespace('n2')
2007
- m1 = root.addDataModel('m1')
2008
- m2 = n1.addDataModel('m2')
2009
- e1 = m1.addEntity('e1')
2010
- e2 = m2.addEntity('e2')
2011
- e3 = n2.addDataModel('m3').addEntity('e3')
2012
- })
2013
-
2014
- test('returns false when called on an entity not in a data model', ({ assert }) => {
2015
- const e4 = new DataEntity(root)
2016
- const result = e4.isChildOf('some-key')
2017
- assert.isFalse(result)
2018
- })
2019
-
2020
- test('returns false when called on self', ({ assert }) => {
2021
- const result = e2.isChildOf(e2.key)
2022
- assert.isFalse(result)
2023
- })
2024
-
2025
- test('returns true when called on a direct parent', ({ assert }) => {
2026
- const result = e2.isChildOf(m2.key)
2027
- assert.isTrue(result)
2028
- })
2029
-
2030
- test('returns true when called on a grandparent', ({ assert }) => {
2031
- const result = e3.isChildOf(root.key)
2032
- assert.isTrue(result)
2033
- })
2034
-
2035
- test('returns false when called on a sibling', ({ assert }) => {
2036
- const e4 = m1.addEntity('e4')
2037
- const result = e1.isChildOf(e4.key)
2038
- assert.isFalse(result)
2039
- })
2040
-
2041
- test('returns false when called on a child', ({ assert }) => {
2042
- const p1 = e2.addNamedProperty('p1')
2043
- const result = e2.isChildOf(p1.key)
2044
- assert.isFalse(result)
2045
- })
2046
-
2047
- test('returns false when called on a non-existent namespace', ({ assert }) => {
2048
- const result = e2.isChildOf('non-existent-key')
2049
- assert.isFalse(result)
2050
- })
2051
-
2052
- test('returns true when called on a grandparent', ({ assert }) => {
2053
- const result = e3.isChildOf(n1.key)
2054
- assert.isTrue(result)
2055
- })
2056
-
2057
- test('returns true when called on a data model in the same namespace', ({ assert }) => {
2058
- const result = e1.isChildOf(m1.key)
2059
- assert.isTrue(result)
2060
- })
2061
- })