@api-client/core 0.14.9 → 0.15.0

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 (110) hide show
  1. package/RELEASE.md +163 -0
  2. package/RELEASE_SETUP.md +235 -0
  3. package/build/src/events/authorization/AuthorizationEvents.d.ts +1 -1
  4. package/build/src/events/authorization/AuthorizationEvents.d.ts.map +1 -1
  5. package/build/src/events/authorization/AuthorizationEvents.js +1 -1
  6. package/build/src/events/authorization/AuthorizationEvents.js.map +1 -1
  7. package/build/src/events/cookies/CookieEvents.d.ts +1 -1
  8. package/build/src/events/cookies/CookieEvents.d.ts.map +1 -1
  9. package/build/src/events/cookies/CookieEvents.js +1 -1
  10. package/build/src/events/cookies/CookieEvents.js.map +1 -1
  11. package/build/src/modeling/DataDomain.d.ts +45 -3
  12. package/build/src/modeling/DataDomain.d.ts.map +1 -1
  13. package/build/src/modeling/DataDomain.js +81 -3
  14. package/build/src/modeling/DataDomain.js.map +1 -1
  15. package/build/src/modeling/DomainElement.d.ts +7 -0
  16. package/build/src/modeling/DomainElement.d.ts.map +1 -1
  17. package/build/src/modeling/DomainElement.js +14 -0
  18. package/build/src/modeling/DomainElement.js.map +1 -1
  19. package/build/src/modeling/DomainImpactAnalysis.d.ts +22 -119
  20. package/build/src/modeling/DomainImpactAnalysis.d.ts.map +1 -1
  21. package/build/src/modeling/DomainImpactAnalysis.js +49 -155
  22. package/build/src/modeling/DomainImpactAnalysis.js.map +1 -1
  23. package/build/src/modeling/DomainValidation.d.ts +8 -0
  24. package/build/src/modeling/DomainValidation.d.ts.map +1 -0
  25. package/build/src/modeling/DomainValidation.js +99 -0
  26. package/build/src/modeling/DomainValidation.js.map +1 -0
  27. package/build/src/modeling/types.d.ts +70 -0
  28. package/build/src/modeling/types.d.ts.map +1 -1
  29. package/build/src/modeling/types.js.map +1 -1
  30. package/build/src/modeling/validation/entity_validation.js +1 -1
  31. package/build/src/modeling/validation/entity_validation.js.map +1 -1
  32. package/build/src/modeling/validation/rules.d.ts +2 -3
  33. package/build/src/modeling/validation/rules.d.ts.map +1 -1
  34. package/build/src/modeling/validation/rules.js.map +1 -1
  35. package/build/src/modeling/validation/semantic_validation.d.ts +31 -0
  36. package/build/src/modeling/validation/semantic_validation.d.ts.map +1 -0
  37. package/build/src/modeling/validation/semantic_validation.js +126 -0
  38. package/build/src/modeling/validation/semantic_validation.js.map +1 -0
  39. package/build/tsconfig.tsbuildinfo +1 -1
  40. package/data/models/example-generator-api.json +12 -12
  41. package/noop.ts +3 -0
  42. package/package.json +9 -4
  43. package/src/events/authorization/AuthorizationEvents.ts +1 -1
  44. package/src/events/cookies/CookieEvents.ts +1 -1
  45. package/src/modeling/DataDomain.ts +84 -3
  46. package/src/modeling/DomainElement.ts +16 -0
  47. package/src/modeling/DomainImpactAnalysis.ts +54 -239
  48. package/src/modeling/DomainValidation.ts +105 -0
  49. package/src/modeling/types.ts +86 -0
  50. package/src/modeling/validation/entity_validation.ts +1 -1
  51. package/src/modeling/validation/rules.ts +2 -4
  52. package/src/modeling/validation/semantic_validation.ts +145 -0
  53. package/tests/unit/events/EventsTestHelpers.ts +16 -0
  54. package/tests/unit/events/amf.spec.ts +151 -0
  55. package/tests/unit/events/authorization.spec.ts +150 -0
  56. package/tests/unit/events/cookie.spec.ts +274 -0
  57. package/tests/unit/events/encryption.spec.ts +108 -0
  58. package/tests/unit/events/events_polyfills.ts +77 -0
  59. package/tests/unit/events/process.spec.ts +120 -0
  60. package/tests/unit/events/reporting.spec.ts +82 -0
  61. package/tests/unit/events/telemetry.spec.ts +224 -0
  62. package/tests/unit/events/transport.spec.ts +139 -0
  63. package/tests/unit/modeling/data_domain_foreign.spec.ts +244 -0
  64. package/tests/unit/modeling/domain_impact_analysis.spec.ts +0 -110
  65. package/tests/unit/modeling/domain_validation.spec.ts +94 -0
  66. package/tests/unit/modeling/validation/semantic_validation.spec.ts +91 -0
  67. package/tests/unit/models/environment.spec.ts +574 -0
  68. package/tests/unit/models/error_response.spec.ts +183 -0
  69. package/tests/unit/models/headers_array.spec.ts +86 -0
  70. package/tests/unit/models/http-actions/assertion/equal_assertion.spec.ts +103 -0
  71. package/tests/unit/models/http-actions/assertion/greater_than_assertion.spec.ts +91 -0
  72. package/tests/unit/models/http-actions/assertion/includes_assertion.spec.ts +71 -0
  73. package/tests/unit/models/http-actions/assertion/less_than_assertion.spec.ts +91 -0
  74. package/tests/unit/models/http-actions/assertion/matches_assertion.spec.ts +71 -0
  75. package/tests/unit/models/http-actions/assertion/matches_schema_assertion.spec.ts +117 -0
  76. package/tests/unit/models/http-actions/assertion/not_equal_assertion.spec.ts +103 -0
  77. package/tests/unit/models/http-actions/assertion/not_includes_assertion.spec.ts +71 -0
  78. package/tests/unit/models/http-actions/assertion/not_ok_assertion.spec.ts +47 -0
  79. package/tests/unit/models/http-actions/assertion/not_to_be_assertion.spec.ts +72 -0
  80. package/tests/unit/models/http-actions/assertion/ok_assertion.spec.ts +44 -0
  81. package/tests/unit/models/http-actions/assertion/to_be_assertion.spec.ts +71 -0
  82. package/tests/unit/models/http-actions/transformation/as_lower_case_step.spec.ts +47 -0
  83. package/tests/unit/models/http-actions/transformation/as_number_step.spec.ts +47 -0
  84. package/tests/unit/models/http-actions/transformation/as_upper_case_step.spec.ts +47 -0
  85. package/tests/unit/models/http-actions/transformation/round_step.spec.ts +69 -0
  86. package/tests/unit/models/http-actions/transformation/substring_step.spec.ts +85 -0
  87. package/tests/unit/models/http-actions/transformation/trim_step.spec.ts +44 -0
  88. package/tests/unit/models/http_cookie.spec.ts +516 -0
  89. package/tests/unit/models/http_history.spec.ts +443 -0
  90. package/tests/unit/models/project_folder.spec.ts +926 -0
  91. package/tests/unit/models/project_item.spec.ts +137 -0
  92. package/tests/unit/models/project_request.spec.ts +1047 -0
  93. package/tests/unit/models/project_schema.spec.ts +236 -0
  94. package/tests/unit/models/property.spec.ts +625 -0
  95. package/tests/unit/models/provider.spec.ts +102 -0
  96. package/tests/unit/models/request.spec.ts +1206 -0
  97. package/tests/unit/models/request_log.spec.ts +308 -0
  98. package/tests/unit/models/request_time.spec.ts +138 -0
  99. package/tests/unit/models/response_redirect.spec.ts +303 -0
  100. package/tests/unit/models/sent_request.spec.ts +206 -0
  101. package/tests/unit/models/server.spec.ts +195 -0
  102. package/tests/unit/models/thing.spec.ts +154 -0
  103. package/build/oauth-popup.html +0 -33
  104. /package/tests/unit/models/{Certificate.spec.ts → certificate.spec.ts} +0 -0
  105. /package/tests/unit/models/{HostRule.spec.ts → host_rule.spec.ts} +0 -0
  106. /package/tests/unit/models/{HttpProject.spec.ts → http_project.spec.ts} +0 -0
  107. /package/tests/unit/models/{HttpRequest.spec.ts → http_request.spec.ts} +0 -0
  108. /package/tests/unit/models/{HttpResponse.spec.ts → http_response.spec.ts} +0 -0
  109. /package/tests/unit/models/{License.spec.ts → license.spec.ts} +0 -0
  110. /package/tests/unit/models/{Response.spec.ts → response.spec.ts} +0 -0
@@ -0,0 +1,224 @@
1
+ import { test } from '@japa/runner'
2
+ import sinon from 'sinon'
3
+ import { EventTypes } from '../../../src/events/EventTypes.js'
4
+ import { Events } from '../../../src/events/Events.js'
5
+ import { ensureUnique } from './EventsTestHelpers.js'
6
+ import './events_polyfills.js'
7
+
8
+ test.group('Events > Telemetry > EventTypes.Telemetry', () => {
9
+ test('has the namespace', ({ assert }) => {
10
+ assert.typeOf(EventTypes.Telemetry, 'object')
11
+ })
12
+
13
+ test('has "{prop}" property')
14
+ .with([
15
+ { prop: 'view', value: 'telemetryscreenview' },
16
+ { prop: 'event', value: 'telemetryevent' },
17
+ { prop: 'exception', value: 'telemetryexception' },
18
+ { prop: 'social', value: 'telemetrysocial' },
19
+ { prop: 'timing', value: 'telemetrytiming' },
20
+ ])
21
+ .run(({ assert }, { prop, value }) => {
22
+ // @ts-expect-error Used in testing
23
+ assert.equal(EventTypes.Telemetry[prop], value)
24
+ })
25
+
26
+ test('has unique events for the namespace', () => {
27
+ ensureUnique('EventTypes.Telemetry', EventTypes.Telemetry)
28
+ })
29
+ })
30
+
31
+ test.group('Events > Telemetry > Events.Telemetry > view()', () => {
32
+ const screenName = 'test-screen'
33
+
34
+ test('dispatches the event', async ({ assert }) => {
35
+ const spy = sinon.spy()
36
+ globalThis.addEventListener(EventTypes.Telemetry.view, spy)
37
+ Events.Telemetry.view(screenName)
38
+ globalThis.removeEventListener(EventTypes.Telemetry.view, spy)
39
+ assert.isTrue(spy.calledOnce)
40
+ })
41
+
42
+ test('the event has screen name on the detail', async ({ assert }) => {
43
+ const spy = sinon.spy()
44
+ globalThis.addEventListener(EventTypes.Telemetry.view, spy)
45
+ Events.Telemetry.view(screenName)
46
+ globalThis.removeEventListener(EventTypes.Telemetry.view, spy)
47
+ const e = spy.args[0][0] as CustomEvent
48
+ assert.equal(e.detail.screenName, screenName)
49
+ })
50
+
51
+ test('the event has the custom configuration', async ({ assert }) => {
52
+ const spy = sinon.spy()
53
+ const custom = {
54
+ customMetrics: [{ index: 1, value: 1 }],
55
+ customDimensions: [{ index: 1, value: 'test' }],
56
+ }
57
+ globalThis.addEventListener(EventTypes.Telemetry.view, spy)
58
+ Events.Telemetry.view(screenName, undefined, custom)
59
+ globalThis.removeEventListener(EventTypes.Telemetry.view, spy)
60
+ const e = spy.args[0][0] as CustomEvent
61
+ assert.deepEqual(e.detail.customMetrics, custom.customMetrics, 'has customMetrics')
62
+ assert.deepEqual(e.detail.customDimensions, custom.customDimensions, 'has customDimensions')
63
+ })
64
+ })
65
+
66
+ test.group('Events > Telemetry > Events.Telemetry > event()', () => {
67
+ const init = {
68
+ category: 'e-cat',
69
+ action: 'e-act',
70
+ label: 'e-label',
71
+ value: 1,
72
+ }
73
+
74
+ test('dispatches the event', async ({ assert }) => {
75
+ const spy = sinon.spy()
76
+ globalThis.addEventListener(EventTypes.Telemetry.event, spy)
77
+ Events.Telemetry.event(init)
78
+ globalThis.removeEventListener(EventTypes.Telemetry.event, spy)
79
+ assert.isTrue(spy.calledOnce)
80
+ })
81
+
82
+ test('the event has the detail object', async ({ assert }) => {
83
+ const spy = sinon.spy()
84
+ globalThis.addEventListener(EventTypes.Telemetry.event, spy)
85
+ Events.Telemetry.event(init)
86
+ globalThis.removeEventListener(EventTypes.Telemetry.event, spy)
87
+ const e = spy.args[0][0] as CustomEvent
88
+ assert.deepEqual(e.detail, init)
89
+ })
90
+ })
91
+
92
+ test.group('Events > Telemetry > Events.Telemetry > exception()', () => {
93
+ const description = 'event-exception'
94
+ const fatal = true
95
+
96
+ test('dispatches the event', async ({ assert }) => {
97
+ const spy = sinon.spy()
98
+ globalThis.addEventListener(EventTypes.Telemetry.exception, spy)
99
+ Events.Telemetry.exception(description)
100
+ globalThis.removeEventListener(EventTypes.Telemetry.exception, spy)
101
+ assert.isTrue(spy.calledOnce)
102
+ })
103
+
104
+ test('the event has the description', async ({ assert }) => {
105
+ const spy = sinon.spy()
106
+ globalThis.addEventListener(EventTypes.Telemetry.exception, spy)
107
+ Events.Telemetry.exception(description)
108
+ globalThis.removeEventListener(EventTypes.Telemetry.exception, spy)
109
+ const e = spy.args[0][0] as CustomEvent
110
+ assert.equal(e.detail.description, description)
111
+ })
112
+
113
+ test('the event has the fatal', async ({ assert }) => {
114
+ const spy = sinon.spy()
115
+ globalThis.addEventListener(EventTypes.Telemetry.exception, spy)
116
+ Events.Telemetry.exception(description, fatal)
117
+ globalThis.removeEventListener(EventTypes.Telemetry.exception, spy)
118
+ const e = spy.args[0][0] as CustomEvent
119
+ assert.equal(e.detail.fatal, fatal)
120
+ })
121
+
122
+ test('the event has custom configuration', async ({ assert }) => {
123
+ const spy = sinon.spy()
124
+ const custom = {
125
+ customMetrics: [{ index: 1, value: 1 }],
126
+ customDimensions: [{ index: 1, value: 'test' }],
127
+ }
128
+ globalThis.addEventListener(EventTypes.Telemetry.exception, spy)
129
+ Events.Telemetry.exception(description, fatal, undefined, custom)
130
+ globalThis.removeEventListener(EventTypes.Telemetry.exception, spy)
131
+ const e = spy.args[0][0] as CustomEvent
132
+ assert.deepEqual(e.detail.customMetrics, custom.customMetrics, 'has customMetrics')
133
+ assert.deepEqual(e.detail.customDimensions, custom.customDimensions, 'has customDimensions')
134
+ })
135
+ })
136
+
137
+ test.group('Events > Telemetry > Events.Telemetry > social()', () => {
138
+ const init = {
139
+ network: 'e-network',
140
+ action: 'e-action',
141
+ target: 'e-target',
142
+ }
143
+
144
+ test('dispatches the event', async ({ assert }) => {
145
+ const spy = sinon.spy()
146
+ globalThis.addEventListener(EventTypes.Telemetry.social, spy)
147
+ Events.Telemetry.social(init.network, init.action, init.target)
148
+ globalThis.removeEventListener(EventTypes.Telemetry.social, spy)
149
+ assert.isTrue(spy.calledOnce)
150
+ })
151
+
152
+ test('the event has the detail object', async ({ assert }) => {
153
+ const spy = sinon.spy()
154
+ globalThis.addEventListener(EventTypes.Telemetry.social, spy)
155
+ Events.Telemetry.social(init.network, init.action, init.target)
156
+ globalThis.removeEventListener(EventTypes.Telemetry.social, spy)
157
+ const e = spy.args[0][0] as CustomEvent
158
+ assert.deepEqual(e.detail, init)
159
+ })
160
+
161
+ test('the event has custom configuration', async ({ assert }) => {
162
+ const spy = sinon.spy()
163
+ const custom = {
164
+ customMetrics: [{ index: 1, value: 1 }],
165
+ customDimensions: [{ index: 1, value: 'test' }],
166
+ }
167
+ globalThis.addEventListener(EventTypes.Telemetry.social, spy)
168
+ Events.Telemetry.social(init.network, init.action, init.target, undefined, custom)
169
+ globalThis.removeEventListener(EventTypes.Telemetry.social, spy)
170
+ const e = spy.args[0][0] as CustomEvent
171
+ assert.deepEqual(e.detail.customMetrics, custom.customMetrics, 'has customMetrics')
172
+ assert.deepEqual(e.detail.customDimensions, custom.customDimensions, 'has customDimensions')
173
+ })
174
+ })
175
+
176
+ test.group('Events > Telemetry > Events.Telemetry > timing()', () => {
177
+ const init = {
178
+ category: 'e-category',
179
+ variable: 'e-variable',
180
+ value: 100,
181
+ label: 'e-label',
182
+ }
183
+
184
+ test('dispatches the event', async ({ assert }) => {
185
+ const spy = sinon.spy()
186
+ globalThis.addEventListener(EventTypes.Telemetry.timing, spy)
187
+ Events.Telemetry.timing(init.category, init.variable, init.value, init.label)
188
+ globalThis.removeEventListener(EventTypes.Telemetry.timing, spy)
189
+ assert.isTrue(spy.calledOnce)
190
+ })
191
+
192
+ test('the event has the detail object', async ({ assert }) => {
193
+ const spy = sinon.spy()
194
+ globalThis.addEventListener(EventTypes.Telemetry.timing, spy)
195
+ Events.Telemetry.timing(init.category, init.variable, init.value, init.label)
196
+ globalThis.removeEventListener(EventTypes.Telemetry.timing, spy)
197
+ const e = spy.args[0][0] as CustomEvent
198
+ assert.deepEqual(e.detail, init)
199
+ })
200
+
201
+ test('the event has custom configuration', async ({ assert }) => {
202
+ const spy = sinon.spy()
203
+ const custom = {
204
+ customMetrics: [{ index: 1, value: 1 }],
205
+ customDimensions: [{ index: 1, value: 'test' }],
206
+ }
207
+ globalThis.addEventListener(EventTypes.Telemetry.timing, spy)
208
+ Events.Telemetry.timing(init.category, init.variable, init.value, init.label, undefined, custom)
209
+ globalThis.removeEventListener(EventTypes.Telemetry.timing, spy)
210
+ const e = spy.args[0][0] as CustomEvent
211
+ assert.deepEqual(e.detail.customMetrics, custom.customMetrics, 'has customMetrics')
212
+ assert.deepEqual(e.detail.customDimensions, custom.customDimensions, 'has customDimensions')
213
+ })
214
+ })
215
+
216
+ test.group('Events > Telemetry > Events.Telemetry > State', () => {
217
+ test('set()', async ({ assert }) => {
218
+ const spy = sinon.spy()
219
+ globalThis.addEventListener(EventTypes.Telemetry.State.set, spy)
220
+ Events.Telemetry.State.set()
221
+ globalThis.removeEventListener(EventTypes.Telemetry.State.set, spy)
222
+ assert.isTrue(spy.calledOnce)
223
+ })
224
+ })
@@ -0,0 +1,139 @@
1
+ import { test } from '@japa/runner'
2
+ import sinon from 'sinon'
3
+ import { EventTypes } from '../../../src/events/EventTypes.js'
4
+ import { Events } from '../../../src/events/Events.js'
5
+ import { ensureUnique } from './EventsTestHelpers.js'
6
+ import { IHttpRequest, HttpRequest, Kind as HttpRequestKind } from '../../../src/models/HttpRequest.js'
7
+ import { Kind as HttpProjectKind } from '../../../src/models/HttpProject.js'
8
+ import { IHttpRequestDetail } from '../../../src/events/transport/TransportEvents.js'
9
+ import { IRequestProxyInit } from '../../../src/proxy/RequestProxy.js'
10
+ import { ContextEventDetailWithResult } from '../../../src/events/BaseEvents.js'
11
+ import { IHttpProjectProxyInit, IHttpProjectStoreProxyInit } from '../../../src/proxy/HttpProjectProxy.js'
12
+ import './events_polyfills.js'
13
+
14
+ test.group('Events > Transport > EventTypes.Transport.Core', () => {
15
+ test('has "{prop}" property')
16
+ .with([
17
+ ['request', 'transportcorerequest'],
18
+ ['httpProject', 'transportcorehttpproject'],
19
+ ])
20
+ .run(({ assert }, [prop, value]) => {
21
+ // @ts-expect-error Used in testing
22
+ assert.equal(EventTypes.Transport.Core[prop], value)
23
+ })
24
+
25
+ test('has unique events for the namespace', () => {
26
+ ensureUnique('EventTypes.Transport.Core', EventTypes.Transport.Core)
27
+ })
28
+ })
29
+
30
+ test.group('Events > Transport > EventTypes.Transport.Http', () => {
31
+ test('has "{prop}" property')
32
+ .with([['send', 'httptransportsend']])
33
+ .run(({ assert }, [prop, value]) => {
34
+ // @ts-expect-error Used in testing
35
+ assert.equal(EventTypes.Transport.Http[prop], value)
36
+ })
37
+
38
+ test('has unique events for the namespace', () => {
39
+ ensureUnique('EventTypes.Transport.Http', EventTypes.Transport.Http)
40
+ })
41
+ })
42
+
43
+ test.group('Events > Transport > EventTypes.Transport.Ws', () => {
44
+ test('has "{prop}" property')
45
+ .with([
46
+ ['connect', 'wstransportconnect'],
47
+ ['disconnect', 'wstransportdisconnect'],
48
+ ['send', 'wstransportsend'],
49
+ ])
50
+ .run(({ assert }, [prop, value]) => {
51
+ // @ts-expect-error Used in testing
52
+ assert.equal(EventTypes.Transport.Ws[prop], value)
53
+ })
54
+
55
+ test('has unique events for the namespace', () => {
56
+ ensureUnique('EventTypes.Transport.Ws', EventTypes.Transport.Ws)
57
+ })
58
+ })
59
+
60
+ test.group('Events > Transport > Events.Transport.Core > request()', () => {
61
+ const init: IRequestProxyInit = {
62
+ kind: HttpRequestKind,
63
+ request: new HttpRequest().toJSON(),
64
+ }
65
+
66
+ test('dispatches the event', async ({ assert }) => {
67
+ const spy = sinon.spy()
68
+ globalThis.addEventListener(EventTypes.Transport.Core.request, spy)
69
+ await Events.Transport.Core.request(init)
70
+ globalThis.removeEventListener(EventTypes.Transport.Core.request, spy)
71
+ assert.isTrue(spy.calledOnce)
72
+ })
73
+
74
+ test('has the detail object', async ({ assert }) => {
75
+ const spy = sinon.spy()
76
+ globalThis.addEventListener(EventTypes.Transport.Core.request, spy)
77
+ await Events.Transport.Core.request(init)
78
+ globalThis.removeEventListener(EventTypes.Transport.Core.request, spy)
79
+ const e = spy.args[0][0] as CustomEvent<ContextEventDetailWithResult<IRequestProxyInit>>
80
+ assert.deepEqual(e.detail, { ...init, result: undefined })
81
+ })
82
+ })
83
+
84
+ test.group('Events > Transport > Events.Transport.Core > httpProject()', () => {
85
+ const init: IHttpProjectStoreProxyInit = {
86
+ kind: HttpProjectKind,
87
+ pid: 'test-id',
88
+ options: { parallel: true },
89
+ organization: 'test-organization',
90
+ }
91
+
92
+ test('dispatches the event', async ({ assert }) => {
93
+ const spy = sinon.spy()
94
+ globalThis.addEventListener(EventTypes.Transport.Core.httpProject, spy)
95
+ await Events.Transport.Core.httpProject(init)
96
+ globalThis.removeEventListener(EventTypes.Transport.Core.httpProject, spy)
97
+ assert.isTrue(spy.calledOnce)
98
+ })
99
+
100
+ test('has the detail object', async ({ assert }) => {
101
+ const spy = sinon.spy()
102
+ globalThis.addEventListener(EventTypes.Transport.Core.httpProject, spy)
103
+ await Events.Transport.Core.httpProject(init)
104
+ globalThis.removeEventListener(EventTypes.Transport.Core.httpProject, spy)
105
+ const e = spy.args[0][0] as CustomEvent<ContextEventDetailWithResult<IHttpProjectProxyInit>>
106
+ assert.deepEqual(e.detail, { ...init, result: undefined })
107
+ })
108
+ })
109
+
110
+ test.group('Events > Transport > Events.Transport.Http > send()', () => {
111
+ const request: IHttpRequest = new HttpRequest().toJSON()
112
+ const init: RequestInit = { method: 'POST' }
113
+
114
+ test('dispatches the event', async ({ assert }) => {
115
+ const spy = sinon.spy()
116
+ globalThis.addEventListener(EventTypes.Transport.Http.send, spy)
117
+ await Events.Transport.Http.send(request)
118
+ globalThis.removeEventListener(EventTypes.Transport.Http.send, spy)
119
+ assert.isTrue(spy.calledOnce)
120
+ })
121
+
122
+ test('has the request on the detail', async ({ assert }) => {
123
+ const spy = sinon.spy()
124
+ globalThis.addEventListener(EventTypes.Transport.Http.send, spy)
125
+ await Events.Transport.Http.send(request)
126
+ globalThis.removeEventListener(EventTypes.Transport.Http.send, spy)
127
+ const e = spy.args[0][0] as CustomEvent<IHttpRequestDetail>
128
+ assert.equal(e.detail.request, request)
129
+ })
130
+
131
+ test('has the optional init on the detail', async ({ assert }) => {
132
+ const spy = sinon.spy()
133
+ globalThis.addEventListener(EventTypes.Transport.Http.send, spy)
134
+ await Events.Transport.Http.send(request, init)
135
+ globalThis.removeEventListener(EventTypes.Transport.Http.send, spy)
136
+ const e = spy.args[0][0] as CustomEvent<IHttpRequestDetail>
137
+ assert.deepEqual(e.detail.init, init)
138
+ })
139
+ })
@@ -1,5 +1,6 @@
1
1
  import { test } from '@japa/runner'
2
2
  import { DataDomain } from '../../../src/modeling/DataDomain.js'
3
+ import type { DomainEntity } from '../../../src/modeling/DomainEntity.js'
3
4
 
4
5
  test.group('DataDomain.registerForeignDomain()', () => {
5
6
  test('registers a foreign domain', ({ assert }) => {
@@ -424,6 +425,180 @@ test.group('DataDomain.findEntity()', () => {
424
425
  })
425
426
  })
426
427
 
428
+ test.group('DataDomain.listForeignNamespaces()', () => {
429
+ test('lists all namespaces from a registered foreign domain', ({ assert }) => {
430
+ const localDomain = new DataDomain()
431
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
432
+ foreignDomain.info.version = '1.0.0'
433
+
434
+ const ns1Foreign = foreignDomain.addNamespace({ key: 'ns1' })
435
+ const ns2Foreign = foreignDomain.addNamespace({ key: 'ns2' })
436
+
437
+ localDomain.registerForeignDomain(foreignDomain)
438
+
439
+ const namespaces = [...localDomain.listForeignNamespaces(foreignDomain.key)]
440
+ assert.lengthOf(namespaces, 2)
441
+ assert.deepInclude(namespaces, ns1Foreign)
442
+ assert.deepInclude(namespaces, ns2Foreign)
443
+ })
444
+
445
+ test('returns an empty generator if the foreign domain has no namespaces', ({ assert }) => {
446
+ const localDomain = new DataDomain()
447
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
448
+ foreignDomain.info.version = '1.0.0'
449
+ localDomain.registerForeignDomain(foreignDomain)
450
+
451
+ const namespaces = [...localDomain.listForeignNamespaces(foreignDomain.key)]
452
+ assert.lengthOf(namespaces, 0)
453
+ })
454
+
455
+ test('returns an empty generator if foreign namespaces are not in the local graph', ({ assert }) => {
456
+ const localDomain = new DataDomain()
457
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
458
+ foreignDomain.info.version = '1.0.0'
459
+ foreignDomain.addNamespace({ key: 'ns1' })
460
+ localDomain.registerForeignDomain(foreignDomain)
461
+
462
+ // Simulate that the foreign namespaces are not in the local graph
463
+ localDomain.graph.removeNode(`${foreignDomain.key}:ns1`)
464
+
465
+ const namespacesAfterRemoval = [...localDomain.listForeignNamespaces(foreignDomain.key)]
466
+ assert.lengthOf(namespacesAfterRemoval, 0)
467
+ })
468
+
469
+ test('throws an error if the foreign domain key is not registered', ({ assert }) => {
470
+ const localDomain = new DataDomain()
471
+ assert.throws(
472
+ () => [...localDomain.listForeignNamespaces('nonExistentKey')],
473
+ 'Foreign domain nonExistentKey not found'
474
+ )
475
+ })
476
+ })
477
+
478
+ test.group('DataDomain.listForeignModels()', () => {
479
+ test('lists all models from a registered foreign domain', ({ assert }) => {
480
+ const localDomain = new DataDomain()
481
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
482
+ foreignDomain.info.version = '1.0.0'
483
+
484
+ const model1Foreign = foreignDomain.addModel({ key: 'model1' })
485
+ const model2Foreign = foreignDomain.addModel({ key: 'model2' })
486
+
487
+ localDomain.registerForeignDomain(foreignDomain)
488
+
489
+ // Ensure the foreign nodes are in the local graph (simulating mergeGraph)
490
+ localDomain.graph.setNode(`${foreignDomain.key}:${model1Foreign.key}`, model1Foreign)
491
+ localDomain.graph.setNode(`${foreignDomain.key}:${model2Foreign.key}`, model2Foreign)
492
+
493
+ const models = [...localDomain.listForeignModels(foreignDomain.key)]
494
+ assert.lengthOf(models, 2)
495
+ assert.deepInclude(models, model1Foreign)
496
+ assert.deepInclude(models, model2Foreign)
497
+ })
498
+
499
+ test('returns an empty generator if the foreign domain has no models', ({ assert }) => {
500
+ const localDomain = new DataDomain()
501
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
502
+ foreignDomain.info.version = '1.0.0'
503
+ localDomain.registerForeignDomain(foreignDomain)
504
+
505
+ const models = [...localDomain.listForeignModels(foreignDomain.key)]
506
+ assert.lengthOf(models, 0)
507
+ })
508
+
509
+ test('returns an empty generator if foreign models are not in the local graph', ({ assert }) => {
510
+ const localDomain = new DataDomain()
511
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
512
+ foreignDomain.info.version = '1.0.0'
513
+ foreignDomain.addModel({ key: 'model1' })
514
+ localDomain.registerForeignDomain(foreignDomain)
515
+
516
+ // Simulate that the foreign models are not in the local graph
517
+ localDomain.graph.removeNode(`${foreignDomain.key}:model1`)
518
+
519
+ const modelsAfterRemoval = [...localDomain.listForeignModels(foreignDomain.key)]
520
+ assert.lengthOf(modelsAfterRemoval, 0)
521
+ })
522
+
523
+ test('throws an error if the foreign domain key is not registered', ({ assert }) => {
524
+ const localDomain = new DataDomain()
525
+ assert.throws(() => [...localDomain.listForeignModels('nonExistentKey')], 'Foreign domain nonExistentKey not found')
526
+ })
527
+ })
528
+
529
+ test.group('DataDomain.listForeignEntities()', () => {
530
+ test('lists all entities from a registered foreign domain', ({ assert }) => {
531
+ const localDomain = new DataDomain()
532
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
533
+ foreignDomain.info.version = '1.0.0'
534
+
535
+ const modelForeign = foreignDomain.addModel({ key: 'modelF' })
536
+ const entity1Foreign = foreignDomain.addEntity(modelForeign.key, { key: 'entity1' })
537
+ const entity2Foreign = foreignDomain.addEntity(modelForeign.key, { key: 'entity2' })
538
+
539
+ localDomain.registerForeignDomain(foreignDomain)
540
+
541
+ // Ensure the foreign nodes are in the local graph (simulating mergeGraph)
542
+ localDomain.graph.setNode(`${foreignDomain.key}:${entity1Foreign.key}`, entity1Foreign)
543
+ localDomain.graph.setNode(`${foreignDomain.key}:${entity2Foreign.key}`, entity2Foreign)
544
+
545
+ const entities = [...localDomain.listForeignEntities(foreignDomain.key)]
546
+ assert.lengthOf(entities, 2)
547
+ assert.deepInclude(entities, entity1Foreign)
548
+ assert.deepInclude(entities, entity2Foreign)
549
+ })
550
+
551
+ test('returns an empty generator if the foreign domain has no entities', ({ assert }) => {
552
+ const localDomain = new DataDomain()
553
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
554
+ foreignDomain.info.version = '1.0.0'
555
+ localDomain.registerForeignDomain(foreignDomain)
556
+
557
+ const entities = [...localDomain.listForeignEntities(foreignDomain.key)]
558
+ assert.lengthOf(entities, 0)
559
+ })
560
+
561
+ test('returns an empty generator if foreign entities are not in the local graph', ({ assert }) => {
562
+ const localDomain = new DataDomain()
563
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
564
+ foreignDomain.info.version = '1.0.0'
565
+ const modelForeign = foreignDomain.addModel({ key: 'modelF' })
566
+ foreignDomain.addEntity(modelForeign.key, { key: 'entity1' })
567
+ localDomain.registerForeignDomain(foreignDomain)
568
+
569
+ // Simulate that the foreign entities are not in the local graph
570
+ localDomain.graph.removeNode(`${foreignDomain.key}:entity1`)
571
+
572
+ const entitiesAfterRemoval = [...localDomain.listForeignEntities(foreignDomain.key)]
573
+ assert.lengthOf(entitiesAfterRemoval, 0)
574
+ })
575
+
576
+ test('throws an error if the foreign domain key is not registered', ({ assert }) => {
577
+ const localDomain = new DataDomain()
578
+ assert.throws(
579
+ () => [...localDomain.listForeignEntities('nonExistentKey')],
580
+ 'Foreign domain nonExistentKey not found'
581
+ )
582
+ })
583
+
584
+ test('lists entities from a foreign domain even if local domain has entities', ({ assert }) => {
585
+ const localDomain = new DataDomain()
586
+ const modelLocal = localDomain.addModel({ key: 'modelL' })
587
+ localDomain.addEntity(modelLocal.key, { key: 'entityL' })
588
+
589
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
590
+ foreignDomain.info.version = '1.0.0'
591
+ const modelForeign = foreignDomain.addModel({ key: 'modelF' })
592
+ const entityForeign = foreignDomain.addEntity(modelForeign.key, { key: 'entityF' })
593
+ localDomain.registerForeignDomain(foreignDomain)
594
+
595
+ const entities = [...localDomain.listForeignEntities(foreignDomain.key)]
596
+ assert.lengthOf(entities, 1)
597
+ assert.deepInclude(entities, entityForeign)
598
+ assert.notDeepInclude(entities, localDomain.findEntity('entityL') as DomainEntity)
599
+ })
600
+ })
601
+
427
602
  test.group('DataDomain.findAssociation()', () => {
428
603
  test('finds a foreign association by its key and domain key', ({ assert }) => {
429
604
  const domain = new DataDomain()
@@ -486,3 +661,72 @@ test.group('DataDomain.findProperty()', () => {
486
661
  }, `Foreign domain non-existent-domain not found`)
487
662
  })
488
663
  })
664
+
665
+ test.group('DataDomain foreign elements namespace property', () => {
666
+ test('DomainNamespace retains its original namespace key after foreign registration', ({ assert }) => {
667
+ const localDomain = new DataDomain({ key: 'localKey' })
668
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
669
+ foreignDomain.addNamespace({ key: 'nsInForeign' })
670
+ foreignDomain.info.version = '1.0.0'
671
+ localDomain.registerForeignDomain(foreignDomain)
672
+
673
+ const retrievedNs = localDomain.findNamespace('nsInForeign', 'foreignKey')
674
+ assert.ok(retrievedNs, 'Foreign namespace should be found in local domain')
675
+ assert.equal(retrievedNs!.namespace, 'foreignKey', 'Namespace property should point to foreign domain key')
676
+ assert.equal(retrievedNs!.domain.key, 'foreignKey', 'Domain property should point to local domain key')
677
+ })
678
+
679
+ test('DomainModel retains its original namespace key after foreign registration', ({ assert }) => {
680
+ const localDomain = new DataDomain({ key: 'localKey' })
681
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
682
+ foreignDomain.info.version = '1.0.0'
683
+
684
+ foreignDomain.addModel({ key: 'modelInForeign' })
685
+ localDomain.registerForeignDomain(foreignDomain)
686
+
687
+ const retrievedModel = localDomain.findModel('modelInForeign', 'foreignKey')
688
+ assert.ok(retrievedModel, 'Foreign model should be found in local domain')
689
+ assert.equal(retrievedModel!.namespace, 'foreignKey', 'Namespace property should point to foreign domain key')
690
+ assert.equal(retrievedModel!.domain.key, 'foreignKey', 'Domain property should point to local domain key')
691
+ })
692
+
693
+ test('DomainEntity retains its original namespace key after foreign registration', ({ assert }) => {
694
+ const localDomain = new DataDomain({ key: 'localKey' })
695
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
696
+ foreignDomain.info.version = '1.0.0'
697
+
698
+ const parentForeignModel = foreignDomain.addModel({ key: 'parentModelInForeign' })
699
+ foreignDomain.addEntity(parentForeignModel.key, { key: 'entityInForeign' })
700
+ localDomain.registerForeignDomain(foreignDomain)
701
+
702
+ const retrievedEntity = localDomain.findEntity('entityInForeign', 'foreignKey')
703
+ assert.ok(retrievedEntity, 'Foreign entity should be found in local domain')
704
+ assert.equal(retrievedEntity!.namespace, 'foreignKey', 'Namespace property should point to foreign domain key')
705
+ assert.equal(retrievedEntity!.domain.key, 'foreignKey', 'Domain property should point to local domain key')
706
+ })
707
+
708
+ test('DomainProperty retains its original namespace key after foreign registration', ({ assert }) => {
709
+ const localDomain = new DataDomain({ key: 'localKey' })
710
+ const foreignDomain = new DataDomain({ key: 'foreignKey' })
711
+ foreignDomain.info.version = '1.0.0'
712
+
713
+ const parentForeignModel = foreignDomain.addModel({ key: 'parentModelInForeign' })
714
+ const parentForeignEntity = foreignDomain.addEntity(parentForeignModel.key, { key: 'parentEntityInForeign' })
715
+ foreignDomain.addProperty(parentForeignEntity.key, { key: 'propertyInForeign' })
716
+ localDomain.registerForeignDomain(foreignDomain)
717
+
718
+ const retrievedProperty = localDomain.findProperty('propertyInForeign', 'foreignKey')
719
+ assert.ok(retrievedProperty, 'Foreign property should be found in local domain')
720
+ assert.equal(retrievedProperty!.namespace, 'foreignKey', 'Namespace property should point to foreign domain key')
721
+ assert.equal(retrievedProperty!.domain.key, 'foreignKey', 'Domain property should point to local domain key')
722
+ })
723
+
724
+ test('DomainElement.namespace is the key of the domain it was created in', ({ assert }) => {
725
+ const domain = new DataDomain({ key: 'originalDomainKey' })
726
+ const model = domain.addModel({ key: 'myModel' })
727
+ const entity = model.addEntity({ key: 'myEntity' })
728
+
729
+ assert.equal(model.namespace, 'originalDomainKey')
730
+ assert.equal(entity.namespace, 'originalDomainKey')
731
+ })
732
+ })