@reventlessdev/reventless-gwt 1.0.0-alpha.207 → 1.0.0-alpha.209
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.
- package/CHANGELOG.md +16 -0
- package/package.json +6 -6
- package/src/Automation_GWT.res +7 -17
- package/src/Behavior_GWT.res +16 -35
- package/src/Delegate_GWT.res +51 -50
- package/src/Diff.res +14 -27
- package/src/EventMapping_GWT.res +1 -3
- package/src/Flow_GWT.res +53 -57
- package/src/Hint.res +1 -4
- package/src/InboundTranslation_GWT.res +4 -10
- package/src/LocalHost.res +13 -9
- package/src/Mapping_GWT.res +6 -23
- package/src/MismatchRender.res +8 -2
- package/src/MultiSourceProjection_GWT.res +6 -15
- package/src/OutboundTranslation_GWT.res +12 -28
- package/src/Outcome.res +15 -15
- package/src/Projection_GWT.res +9 -17
- package/src/Query_GWT.res +28 -19
- package/src/RenderRescript.res +1 -2
- package/src/SideEffect_GWT.res +0 -1
- package/src/StateChange/ExternalAddCategorySlice.res +2 -4
- package/src/StateChange/WithFixtures.res +3 -6
- package/src/StateChange/WithManualOpen.res +3 -6
- package/tests/AutomationGwtTest.res +9 -7
- package/tests/DelegateGwtTest.res +0 -1
- package/tests/FlowAggregateGwtTest.res +2 -5
- package/tests/FlowCrossPluginGwtTest.res +65 -40
- package/tests/FlowGwtTest.res +0 -1
- package/tests/InboundTranslationGwtTest.res +7 -4
- package/tests/LocalHostIntegration.res +29 -12
- package/tests/LocalHostTest.res +15 -8
- package/tests/MappingGwtTest.res +5 -20
- package/tests/OutboundTranslationGwtTest.res +7 -4
- package/tests/QueryGwtTest.res +10 -12
- package/tests/QueryResolverGwtTest.res +4 -4
- package/tests/SideEffect/FakeOrderNotification.res +1 -2
- package/tests/SideEffect/FakeOrderNotificationGwtTest.res +6 -10
- package/tests/StateChange/WithFixtures_GWT.res +0 -1
- package/tests/StateChangeSliceGwtTest.res +22 -21
- package/tests/StateViewSliceGwtTest.res +5 -17
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 1.0.0-alpha.209 (2026-09-11)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @reventlessdev/reventless-gwt
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# 1.0.0-alpha.208 (2026-09-09)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @reventlessdev/reventless-gwt
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
# 1.0.0-alpha.207 (2026-09-08)
|
|
7
23
|
|
|
8
24
|
**Note:** Version bump only for package @reventlessdev/reventless-gwt
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-gwt",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.209",
|
|
4
4
|
"description": "Given-When-Then DSLs and test harness for Reventless slice testing",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"jest": {
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"sury": "11.0.0-rc.2",
|
|
17
|
+
"@reventlessdev/rescript-effect": "0.1.0-alpha.33",
|
|
17
18
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
18
|
-
"@reventlessdev/rescript-
|
|
19
|
-
"@reventlessdev/reventless-
|
|
20
|
-
"@reventlessdev/reventless-
|
|
21
|
-
"@reventlessdev/
|
|
22
|
-
"@reventlessdev/reventless-spec": "3.0.0-alpha.133"
|
|
19
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.11",
|
|
20
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.262",
|
|
21
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.163",
|
|
22
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.135"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"rescript": "12.3.0",
|
package/src/Automation_GWT.res
CHANGED
|
@@ -36,10 +36,7 @@ module type T = {
|
|
|
36
36
|
// Unit combinators — collect
|
|
37
37
|
let givenEvent: Spec.consumedEvent => Spec.consumedEvent
|
|
38
38
|
let whenCollect: Spec.consumedEvent => array<(string, Spec.todoItem)>
|
|
39
|
-
let thenTodos: (
|
|
40
|
-
array<(string, Spec.todoItem)>,
|
|
41
|
-
array<(string, Spec.todoItem)>,
|
|
42
|
-
) => Outcome.outcome
|
|
39
|
+
let thenTodos: (array<(string, Spec.todoItem)>, array<(string, Spec.todoItem)>) => Outcome.outcome
|
|
43
40
|
|
|
44
41
|
// Unit combinators — resolve
|
|
45
42
|
let whenResolve: Spec.consumedEvent => option<string>
|
|
@@ -62,7 +59,6 @@ module type T = {
|
|
|
62
59
|
module Make = (Spec: SliceSpec): (T with module Spec = Spec) => {
|
|
63
60
|
module Spec = Spec
|
|
64
61
|
|
|
65
|
-
|
|
66
62
|
let describe = JestBind.describe
|
|
67
63
|
let test = (name, body) => JestBind.test(~slice=Spec.name, name, body)
|
|
68
64
|
|
|
@@ -161,16 +157,12 @@ module Make = (Spec: SliceSpec): (T with module Spec = Spec) => {
|
|
|
161
157
|
let whenSweep = events => {
|
|
162
158
|
// Build the todo list by running collect, then drain any items that are
|
|
163
159
|
// completed by resolve in the same input stream.
|
|
164
|
-
let collected =
|
|
165
|
-
|
|
166
|
-
let resolvedIds
|
|
167
|
-
events->Array.filterMap(e => e->Spec.resolve)
|
|
168
|
-
let pending =
|
|
169
|
-
collected->Array.filter(((id, _)) => !Array.includes(resolvedIds, id))
|
|
160
|
+
let collected = events->Array.map(e => e->Spec.collect)->Array.flat
|
|
161
|
+
let resolvedIds = events->Array.filterMap(e => e->Spec.resolve)
|
|
162
|
+
let pending = collected->Array.filter(((id, _)) => !Array.includes(resolvedIds, id))
|
|
170
163
|
|
|
171
164
|
// Process each pending todo to produce commands.
|
|
172
|
-
let commands =
|
|
173
|
-
pending->Array.filterMap(((id, todo)) => Spec.process(id, todo))
|
|
165
|
+
let commands = pending->Array.filterMap(((id, todo)) => Spec.process(id, todo))
|
|
174
166
|
|
|
175
167
|
{todos: pending, commands}
|
|
176
168
|
}
|
|
@@ -195,10 +187,8 @@ module Make = (Spec: SliceSpec): (T with module Spec = Spec) => {
|
|
|
195
187
|
}
|
|
196
188
|
|
|
197
189
|
let andThenEvents = (scenario, events) => {
|
|
198
|
-
let resolvedIds =
|
|
199
|
-
|
|
200
|
-
let remaining =
|
|
201
|
-
scenario.todos->Array.filter(((id, _)) => !Array.includes(resolvedIds, id))
|
|
190
|
+
let resolvedIds = events->Array.filterMap(e => e->Spec.resolve)
|
|
191
|
+
let remaining = scenario.todos->Array.filter(((id, _)) => !Array.includes(resolvedIds, id))
|
|
202
192
|
{...scenario, todos: remaining}
|
|
203
193
|
}
|
|
204
194
|
|
package/src/Behavior_GWT.res
CHANGED
|
@@ -70,10 +70,7 @@ module type T = {
|
|
|
70
70
|
let thenError: (array<Spec.event>, Spec.error) => Outcome.outcome
|
|
71
71
|
|
|
72
72
|
// DCB optimistic-concurrency assertions.
|
|
73
|
-
let thenAppendsConditionedOn: (
|
|
74
|
-
array<Spec.event>,
|
|
75
|
-
Reventless.DcbTag.query,
|
|
76
|
-
) => Outcome.outcome
|
|
73
|
+
let thenAppendsConditionedOn: (array<Spec.event>, Reventless.DcbTag.query) => Outcome.outcome
|
|
77
74
|
let thenAppendsConditionedOnExactly: (
|
|
78
75
|
array<Spec.event>,
|
|
79
76
|
Reventless.DcbTag.appendCondition,
|
|
@@ -171,9 +168,7 @@ module AssertionCore = (Spec: CoreSpec) => {
|
|
|
171
168
|
} else if events->encEvents == expectedEvents->encEvents {
|
|
172
169
|
Outcome.pass
|
|
173
170
|
} else {
|
|
174
|
-
Outcome.fail(
|
|
175
|
-
EventsMismatch({expected: expectedEvents->encEvents, actual: events->encEvents}),
|
|
176
|
-
)
|
|
171
|
+
Outcome.fail(EventsMismatch({expected: expectedEvents->encEvents, actual: events->encEvents}))
|
|
177
172
|
}
|
|
178
173
|
|
|
179
174
|
let compareEventsWith = (events, expectedEvents, cmp) =>
|
|
@@ -185,9 +180,7 @@ module AssertionCore = (Spec: CoreSpec) => {
|
|
|
185
180
|
) {
|
|
186
181
|
Outcome.pass
|
|
187
182
|
} else {
|
|
188
|
-
Outcome.fail(
|
|
189
|
-
EventsMismatch({expected: expectedEvents->encEvents, actual: events->encEvents}),
|
|
190
|
-
)
|
|
183
|
+
Outcome.fail(EventsMismatch({expected: expectedEvents->encEvents, actual: events->encEvents}))
|
|
191
184
|
}
|
|
192
185
|
|
|
193
186
|
let compareNoEvent = events =>
|
|
@@ -235,19 +228,16 @@ module AssertionCore = (Spec: CoreSpec) => {
|
|
|
235
228
|
}
|
|
236
229
|
}
|
|
237
230
|
|
|
238
|
-
module Make = (
|
|
239
|
-
Spec
|
|
240
|
-
|
|
241
|
-
): (T with module Spec = Spec) => {
|
|
231
|
+
module Make = (Spec: BehaviorSpec, Behavior: Behavior with module Spec := Spec): (
|
|
232
|
+
T with module Spec = Spec
|
|
233
|
+
) => {
|
|
242
234
|
module Spec = Spec
|
|
243
235
|
|
|
244
|
-
|
|
245
236
|
let describe = JestBind.describe
|
|
246
237
|
let todo = JestBind.todo
|
|
247
238
|
let test = (name, body) => JestBind.test(~slice=Spec.name, name, body)
|
|
248
239
|
|
|
249
|
-
let currentState = consumed =>
|
|
250
|
-
consumed->Array.reduce(Behavior.initialState, Behavior.evolve)
|
|
240
|
+
let currentState = consumed => consumed->Array.reduce(Behavior.initialState, Behavior.evolve)
|
|
251
241
|
|
|
252
242
|
module Core = AssertionCore(Spec)
|
|
253
243
|
let errors = Core.errors
|
|
@@ -262,8 +252,7 @@ module Make = (
|
|
|
262
252
|
// their own checks; [thenAppends*] bypass it.
|
|
263
253
|
let appendConditionFailure: ref<option<Outcome.mismatch>> = ref(None)
|
|
264
254
|
|
|
265
|
-
let consumedEventTypes =
|
|
266
|
-
Reventless.DcbDecode.makeDecoder(Spec.consumedEventSchema).eventTypes
|
|
255
|
+
let consumedEventTypes = Reventless.DcbDecode.makeDecoder(Spec.consumedEventSchema).eventTypes
|
|
267
256
|
|
|
268
257
|
// Scope derived from this slice's schemas, mirroring the StateChangeSlice runtime.
|
|
269
258
|
let scopeShape = Reventless.DcbTag.sliceShapeFromSchemas(
|
|
@@ -290,8 +279,7 @@ module Make = (
|
|
|
290
279
|
// Per-event indexed-tag map so a foreign reference key on this slice's *own*
|
|
291
280
|
// emitted event (payload, not a read key) is narrowed out of a cross-partition
|
|
292
281
|
// clause — the same dead-clause removal the runtime threads.
|
|
293
|
-
let tagKeysByEventType =
|
|
294
|
-
Reventless.DcbScopeInference.infer([scopeShape]).tagKeysByEventType
|
|
282
|
+
let tagKeysByEventType = Reventless.DcbScopeInference.infer([scopeShape]).tagKeysByEventType
|
|
295
283
|
|
|
296
284
|
// Reachability guard inputs. The event types this slice *emits* are its own
|
|
297
285
|
// history — read with composite AND clauses, which is fine. A *foreign* event
|
|
@@ -305,10 +293,8 @@ module Make = (
|
|
|
305
293
|
// carries its productIds over to the cancel event). Flow_GWT catches this
|
|
306
294
|
// because it threads a real tagged log; this lets the per-slice GWT catch it
|
|
307
295
|
// too, rather than folding an unreachable event straight through.
|
|
308
|
-
let emittedEventTypes =
|
|
309
|
-
|
|
310
|
-
let consumedTagKeysByType =
|
|
311
|
-
Reventless.DcbTag.extractTagKeysByEventType(Spec.consumedEventSchema)
|
|
296
|
+
let emittedEventTypes = Reventless.DcbDecode.makeDecoder(Spec.eventSchema).eventTypes
|
|
297
|
+
let consumedTagKeysByType = Reventless.DcbTag.extractTagKeysByEventType(Spec.consumedEventSchema)
|
|
312
298
|
|
|
313
299
|
let queryTagKeys = (query: Reventless.DcbTag.query): array<string> =>
|
|
314
300
|
query->Array.flatMap(qi => qi.tags->Option.mapOr([], tags => tags->Array.map(t => t.key)))
|
|
@@ -340,9 +326,7 @@ module Make = (
|
|
|
340
326
|
}
|
|
341
327
|
|
|
342
328
|
let queryTagsTotal = (q: Reventless.DcbTag.query): int =>
|
|
343
|
-
q->Array.reduce(0, (acc, qi) =>
|
|
344
|
-
acc + qi.tags->Option.mapOr(0, t => t->Array.length)
|
|
345
|
-
)
|
|
329
|
+
q->Array.reduce(0, (acc, qi) => acc + qi.tags->Option.mapOr(0, t => t->Array.length))
|
|
346
330
|
|
|
347
331
|
let exec = (history, command): array<Spec.event> => {
|
|
348
332
|
errors := []
|
|
@@ -530,18 +514,15 @@ module type AggregateT = {
|
|
|
530
514
|
let thenError: (array<Spec.event>, Spec.error) => Outcome.outcome
|
|
531
515
|
}
|
|
532
516
|
|
|
533
|
-
module MakeFromAggregate = (
|
|
534
|
-
Spec
|
|
535
|
-
|
|
536
|
-
): (AggregateT with module Spec = Spec) => {
|
|
517
|
+
module MakeFromAggregate = (Spec: AggregateSpec, Behavior: Behavior.T with module Spec = Spec): (
|
|
518
|
+
AggregateT with module Spec = Spec
|
|
519
|
+
) => {
|
|
537
520
|
module Spec = Spec
|
|
538
521
|
|
|
539
|
-
|
|
540
522
|
let describe = JestBind.describe
|
|
541
523
|
let test = (name, body) => JestBind.test(~slice=Spec.name, name, body)
|
|
542
524
|
|
|
543
|
-
let currentState = events =>
|
|
544
|
-
events->Array.reduce(Behavior.initialState, Behavior.evolve)
|
|
525
|
+
let currentState = events => events->Array.reduce(Behavior.initialState, Behavior.evolve)
|
|
545
526
|
|
|
546
527
|
module Core = AssertionCore(Spec)
|
|
547
528
|
let errors = Core.errors
|
package/src/Delegate_GWT.res
CHANGED
|
@@ -72,10 +72,8 @@ module type T = {
|
|
|
72
72
|
module Make = (D: Delegate): (T with type inbound = D.inbound) => {
|
|
73
73
|
type inbound = D.inbound
|
|
74
74
|
|
|
75
|
-
|
|
76
75
|
let describe = JestBind.describe
|
|
77
|
-
let test = (name, ~timeout=?, body) =>
|
|
78
|
-
JestBind.testPromise(~slice=D.name, name, ~timeout?, body)
|
|
76
|
+
let test = (name, ~timeout=?, body) => JestBind.testPromise(~slice=D.name, name, ~timeout?, body)
|
|
79
77
|
|
|
80
78
|
let whenInput = ev => D.run(ev)
|
|
81
79
|
|
|
@@ -134,18 +132,17 @@ module FromExtensionPoint = (M: EPMapping.Mapping) => {
|
|
|
134
132
|
switch M.mapOutgoingEvent {
|
|
135
133
|
| None => []
|
|
136
134
|
| Some(f) =>
|
|
137
|
-
let nested =
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
->Promise.all
|
|
135
|
+
let nested = await f("gwt-id", event, StubRuntime.meta, StubRuntime.queryEngine)
|
|
136
|
+
->Array.map(async action =>
|
|
137
|
+
switch action {
|
|
138
|
+
| EPMapping.PublishEvent(id, ev) => [encPublished(~target=id, encEvent(ev))]
|
|
139
|
+
| EPMapping.PublishEventAsync(p) =>
|
|
140
|
+
let (id, ev) = await p
|
|
141
|
+
[encPublished(~target=id, encEvent(ev))]
|
|
142
|
+
| EPMapping.HandleDirective(_, dir) => [encDirective(dir)]
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
->Promise.all
|
|
149
146
|
nested->Array.flat
|
|
150
147
|
}
|
|
151
148
|
})
|
|
@@ -212,40 +209,39 @@ module FromExtension = (M: ExtMapping.Mapping) => {
|
|
|
212
209
|
let name = M.Delegate.name
|
|
213
210
|
type inbound = M.ExtensionPoint.event
|
|
214
211
|
let run = async (event: M.ExtensionPoint.event) => {
|
|
215
|
-
let nested =
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
->Promise.all
|
|
212
|
+
let nested = await M.mapIncomingEvent(
|
|
213
|
+
"gwt-id",
|
|
214
|
+
event,
|
|
215
|
+
StubRuntime.meta,
|
|
216
|
+
StubRuntime.pluginDefinition,
|
|
217
|
+
StubRuntime.queryEngine,
|
|
218
|
+
)
|
|
219
|
+
->Array.map(async action =>
|
|
220
|
+
switch action {
|
|
221
|
+
| ExtMapping.PublishStateChangeSliceCommand(cmd) => [
|
|
222
|
+
encPublished(~target=M.Delegate.name, encCmd(cmd)),
|
|
223
|
+
]
|
|
224
|
+
| ExtMapping.PublishStateChangeSliceCommandAsync(p) =>
|
|
225
|
+
let cmd = await p
|
|
226
|
+
[encPublished(~target=M.Delegate.name, encCmd(cmd))]
|
|
227
|
+
| ExtMapping.PublishStateChangeSliceCommandsAsync(p) =>
|
|
228
|
+
(await p)->Array.map(cmd => encPublished(~target=M.Delegate.name, encCmd(cmd)))
|
|
229
|
+
| ExtMapping.PublishAggregateCommand(id, cmd) => [encPublished(~target=id, encCmd(cmd))]
|
|
230
|
+
| ExtMapping.PublishAggregateCommandAsync(p) =>
|
|
231
|
+
let (id, cmd) = await p
|
|
232
|
+
[encPublished(~target=id, encCmd(cmd))]
|
|
233
|
+
| ExtMapping.PublishAggregateCommandsAsync(p) =>
|
|
234
|
+
(await p)->Array.map(((id, cmd)) => encPublished(~target=id, encCmd(cmd)))
|
|
235
|
+
| ExtMapping.PublishExtensionPointCommand(id, cmd) => [
|
|
236
|
+
encPublished(~target=id, encEpCmd(cmd)),
|
|
237
|
+
]
|
|
238
|
+
| ExtMapping.ForwardCommand({extensionPointName, id, commandJson}) => [
|
|
239
|
+
encPublished(~target=`${extensionPointName}:${id}`, commandJson),
|
|
240
|
+
]
|
|
241
|
+
| ExtMapping.HandleDirective(_, dir) => [encDirective(dir)]
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
->Promise.all
|
|
249
245
|
nested->Array.flat
|
|
250
246
|
}
|
|
251
247
|
})
|
|
@@ -258,7 +254,12 @@ module FromExtension = (M: ExtMapping.Mapping) => {
|
|
|
258
254
|
switch M.mapOutgoingEvent {
|
|
259
255
|
| None => []
|
|
260
256
|
| Some(f) =>
|
|
261
|
-
f(
|
|
257
|
+
f(
|
|
258
|
+
"gwt-id",
|
|
259
|
+
event,
|
|
260
|
+
StubRuntime.meta,
|
|
261
|
+
StubRuntime.pluginDefinition,
|
|
262
|
+
)->Array.filterMap(action =>
|
|
262
263
|
switch action {
|
|
263
264
|
| ExtMapping.PublishExtensionPointCommand(id, cmd) =>
|
|
264
265
|
Some(encPublished(~target=id, encEpCmd(cmd)))
|
package/src/Diff.res
CHANGED
|
@@ -19,20 +19,16 @@ let joinPath = (prefix, segment) =>
|
|
|
19
19
|
let rec walk = (~path="", expected: JSON.t, actual: JSON.t, acc: array<entry>) =>
|
|
20
20
|
switch (expected, actual) {
|
|
21
21
|
| (Object(e), Object(a)) =>
|
|
22
|
-
let keys =
|
|
23
|
-
Array.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
)
|
|
22
|
+
let keys = Array.concat(e->Dict.keysToArray, a->Dict.keysToArray)->Array.reduce([], (uniq, k) =>
|
|
23
|
+
if Array.includes(uniq, k) {
|
|
24
|
+
uniq
|
|
25
|
+
} else {
|
|
26
|
+
Array.concat(uniq, [k])
|
|
27
|
+
}
|
|
28
|
+
)
|
|
31
29
|
keys->Array.reduce(acc, (acc, k) => {
|
|
32
|
-
let childExpected =
|
|
33
|
-
|
|
34
|
-
let childActual =
|
|
35
|
-
a->Dict.get(k)->Option.getOr(JSON.Encode.null)
|
|
30
|
+
let childExpected = e->Dict.get(k)->Option.getOr(JSON.Encode.null)
|
|
31
|
+
let childActual = a->Dict.get(k)->Option.getOr(JSON.Encode.null)
|
|
36
32
|
walk(~path=joinPath(path, k), childExpected, childActual, acc)
|
|
37
33
|
})
|
|
38
34
|
| (Array(e), Array(a)) =>
|
|
@@ -43,16 +39,9 @@ let rec walk = (~path="", expected: JSON.t, actual: JSON.t, acc: array<entry>) =
|
|
|
43
39
|
if i >= len {
|
|
44
40
|
acc
|
|
45
41
|
} else {
|
|
46
|
-
let childExpected =
|
|
47
|
-
|
|
48
|
-
let childActual
|
|
49
|
-
a->Array.get(i)->Option.getOr(JSON.Encode.null)
|
|
50
|
-
let acc = walk(
|
|
51
|
-
~path=joinPath(path, Int.toString(i)),
|
|
52
|
-
childExpected,
|
|
53
|
-
childActual,
|
|
54
|
-
acc,
|
|
55
|
-
)
|
|
42
|
+
let childExpected = e->Array.get(i)->Option.getOr(JSON.Encode.null)
|
|
43
|
+
let childActual = a->Array.get(i)->Option.getOr(JSON.Encode.null)
|
|
44
|
+
let acc = walk(~path=joinPath(path, Int.toString(i)), childExpected, childActual, acc)
|
|
56
45
|
loop(i + 1, acc)
|
|
57
46
|
}
|
|
58
47
|
loop(0, acc)
|
|
@@ -73,8 +62,7 @@ let rec walk = (~path="", expected: JSON.t, actual: JSON.t, acc: array<entry>) =
|
|
|
73
62
|
}
|
|
74
63
|
}
|
|
75
64
|
|
|
76
|
-
let diff = (expected: JSON.t, actual: JSON.t): array<entry> =>
|
|
77
|
-
walk(expected, actual, [])
|
|
65
|
+
let diff = (expected: JSON.t, actual: JSON.t): array<entry> => walk(expected, actual, [])
|
|
78
66
|
|
|
79
67
|
let diffArrays = (expected: array<JSON.t>, actual: array<JSON.t>): array<entry> =>
|
|
80
68
|
walk(JSON.Encode.array(expected), JSON.Encode.array(actual), [])
|
|
@@ -87,5 +75,4 @@ let toJson = (e: entry): JSON.t => {
|
|
|
87
75
|
JSON.Encode.object(obj)
|
|
88
76
|
}
|
|
89
77
|
|
|
90
|
-
let toJsonArray = (entries: array<entry>): JSON.t =>
|
|
91
|
-
entries->Array.map(toJson)->JSON.Encode.array
|
|
78
|
+
let toJsonArray = (entries: array<entry>): JSON.t => entries->Array.map(toJson)->JSON.Encode.array
|
package/src/EventMapping_GWT.res
CHANGED
|
@@ -12,9 +12,7 @@ module Make = (
|
|
|
12
12
|
SourceBehavior: Behavior.T with module Spec = Source,
|
|
13
13
|
Target: Reventless.Aggregate.Spec,
|
|
14
14
|
TargetBehavior: Behavior.T with module Spec = Target,
|
|
15
|
-
EventMapping: Reventless.EventMapping.T
|
|
16
|
-
with module Source = Source
|
|
17
|
-
and module Target = Target,
|
|
15
|
+
EventMapping: Reventless.EventMapping.T with module Source = Source and module Target = Target,
|
|
18
16
|
) => {
|
|
19
17
|
module AdaptedSource = Mapping_GWT.FromBehavior(Source, SourceBehavior)
|
|
20
18
|
module AdaptedTarget = Mapping_GWT.FromBehavior(Target, TargetBehavior)
|
package/src/Flow_GWT.res
CHANGED
|
@@ -81,7 +81,6 @@ type flowState = {
|
|
|
81
81
|
|
|
82
82
|
type flow = promise<flowState>
|
|
83
83
|
|
|
84
|
-
|
|
85
84
|
let emptyState = {
|
|
86
85
|
log: [],
|
|
87
86
|
outcome: Outcome.pass,
|
|
@@ -295,8 +294,7 @@ module CommandStep = (
|
|
|
295
294
|
)
|
|
296
295
|
Array.fromIterator(set->Set.values)->Array.toSorted((a, b) => String.compare(a, b))
|
|
297
296
|
}
|
|
298
|
-
let tagKeysByEventType =
|
|
299
|
-
Reventless.DcbScopeInference.infer([scopeShape]).tagKeysByEventType
|
|
297
|
+
let tagKeysByEventType = Reventless.DcbScopeInference.infer([scopeShape]).tagKeysByEventType
|
|
300
298
|
|
|
301
299
|
let whenCommand = async (flowP: flow, command: Spec.command) => {
|
|
302
300
|
let s = await flowP
|
|
@@ -477,7 +475,10 @@ module AutomationStep = (Spec: Automation_GWT.SliceSpec) => {
|
|
|
477
475
|
let resolvedIds = events->Array.filterMap(e => e->Spec.resolve)
|
|
478
476
|
let pending = collected->Array.filter(((id, _)) => !(resolvedIds->Array.includes(id)))
|
|
479
477
|
let commands = pending->Array.filterMap(((id, todo)) => Spec.process(id, todo))
|
|
480
|
-
{
|
|
478
|
+
{
|
|
479
|
+
...s,
|
|
480
|
+
lastCommands: commands->Array.map(((_id, cmd)) => cmd->Message.encode(Spec.commandSchema)),
|
|
481
|
+
}
|
|
481
482
|
}
|
|
482
483
|
|
|
483
484
|
let thenIssuesCommands = async (flowP: flow, expected: array<Spec.command>) => {
|
|
@@ -579,10 +580,9 @@ module ExtensionPointStep = (M: EPMapping.Mapping) => {
|
|
|
579
580
|
// the first arg (e.g. catalog Product → ProductBecameAvailable uses it as
|
|
580
581
|
// `productId`). DCB upstreams don't set `lastAggregateId` and fall back to
|
|
581
582
|
// the synthetic `gwt-id` so existing DCB Flow tests keep their behaviour.
|
|
582
|
-
let runMapping = async (
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
): array<M.ExtensionPoint.event> =>
|
|
583
|
+
let runMapping = async (sourceId: string, events: array<M.Delegate.event>): array<
|
|
584
|
+
M.ExtensionPoint.event,
|
|
585
|
+
> =>
|
|
586
586
|
switch M.mapOutgoingEvent {
|
|
587
587
|
| None => []
|
|
588
588
|
| Some(f) =>
|
|
@@ -590,31 +590,29 @@ module ExtensionPointStep = (M: EPMapping.Mapping) => {
|
|
|
590
590
|
events
|
|
591
591
|
->Array.map(ev => f(sourceId, ev, StubRuntime.meta, StubRuntime.queryEngine))
|
|
592
592
|
->Array.flat
|
|
593
|
-
let nested =
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
->Promise.all
|
|
593
|
+
let nested = await actions
|
|
594
|
+
->Array.map(async action =>
|
|
595
|
+
switch action {
|
|
596
|
+
| EPMapping.PublishEvent(_id, e) => [e]
|
|
597
|
+
| EPMapping.PublishEventAsync(p) =>
|
|
598
|
+
let (_id, e) = await p
|
|
599
|
+
[e]
|
|
600
|
+
| EPMapping.HandleDirective(_, _) => []
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
->Promise.all
|
|
605
604
|
nested->Array.flat
|
|
606
605
|
}
|
|
607
606
|
|
|
608
607
|
let whenPublishedThrough = async (flowP: flow) => {
|
|
609
608
|
let s = await flowP
|
|
610
|
-
let delegateEvents =
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
})
|
|
609
|
+
let delegateEvents = s.lastEvents->Array.filterMap(json => {
|
|
610
|
+
let data = switch json {
|
|
611
|
+
| Object(d) => d
|
|
612
|
+
| _ => Dict.make()
|
|
613
|
+
}
|
|
614
|
+
delegateDecoder.decode(~eventType=json->Reventless.Message.variantNameOfJson, ~data)
|
|
615
|
+
})
|
|
618
616
|
let sourceId = s.lastAggregateId->Option.getOr("gwt-id")
|
|
619
617
|
let publicEvents = await runMapping(sourceId, delegateEvents)
|
|
620
618
|
{
|
|
@@ -647,14 +645,13 @@ module ExtensionStep = (M: ExtMapping.Mapping) => {
|
|
|
647
645
|
|
|
648
646
|
let whenExtensionReacts = async (flowP: flow) => {
|
|
649
647
|
let s = await flowP
|
|
650
|
-
let epEvents =
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
})
|
|
648
|
+
let epEvents = s.lastPublic->Array.filterMap(json => {
|
|
649
|
+
let data = switch json {
|
|
650
|
+
| Object(d) => d
|
|
651
|
+
| _ => Dict.make()
|
|
652
|
+
}
|
|
653
|
+
epDecoder.decode(~eventType=json->Reventless.Message.variantNameOfJson, ~data)
|
|
654
|
+
})
|
|
658
655
|
let actions =
|
|
659
656
|
epEvents
|
|
660
657
|
->Array.map(ev =>
|
|
@@ -667,27 +664,26 @@ module ExtensionStep = (M: ExtMapping.Mapping) => {
|
|
|
667
664
|
)
|
|
668
665
|
)
|
|
669
666
|
->Array.flat
|
|
670
|
-
let nested =
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
->Promise.all
|
|
667
|
+
let nested = await actions
|
|
668
|
+
->Array.map(async action =>
|
|
669
|
+
switch action {
|
|
670
|
+
| ExtMapping.PublishStateChangeSliceCommand(cmd) => [encCmd(cmd)]
|
|
671
|
+
| ExtMapping.PublishStateChangeSliceCommandAsync(p) =>
|
|
672
|
+
let cmd = await p
|
|
673
|
+
[encCmd(cmd)]
|
|
674
|
+
| ExtMapping.PublishStateChangeSliceCommandsAsync(p) => (await p)->Array.map(encCmd)
|
|
675
|
+
| ExtMapping.PublishAggregateCommand(_id, cmd) => [encCmd(cmd)]
|
|
676
|
+
| ExtMapping.PublishAggregateCommandAsync(p) =>
|
|
677
|
+
let (_id, cmd) = await p
|
|
678
|
+
[encCmd(cmd)]
|
|
679
|
+
| ExtMapping.PublishAggregateCommandsAsync(p) =>
|
|
680
|
+
(await p)->Array.map(((_id, cmd)) => encCmd(cmd))
|
|
681
|
+
| ExtMapping.PublishExtensionPointCommand(_, _)
|
|
682
|
+
| ExtMapping.ForwardCommand(_)
|
|
683
|
+
| ExtMapping.HandleDirective(_, _) => []
|
|
684
|
+
}
|
|
685
|
+
)
|
|
686
|
+
->Promise.all
|
|
691
687
|
{...s, lastCommands: nested->Array.flat}
|
|
692
688
|
}
|
|
693
689
|
|
package/src/Hint.res
CHANGED
|
@@ -111,10 +111,7 @@ let forMismatch = (~slice="<slice>", m: Outcome.mismatch): t =>
|
|
|
111
111
|
let toJson = (h: t): JSON.t => {
|
|
112
112
|
let obj = Dict.make()
|
|
113
113
|
obj->Dict.set("locus", JSON.Encode.string(h.locus))
|
|
114
|
-
obj->Dict.set(
|
|
115
|
-
"branch",
|
|
116
|
-
h.branch->Option.mapOr(JSON.Encode.null, JSON.Encode.string),
|
|
117
|
-
)
|
|
114
|
+
obj->Dict.set("branch", h.branch->Option.mapOr(JSON.Encode.null, JSON.Encode.string))
|
|
118
115
|
obj->Dict.set("message", JSON.Encode.string(h.message))
|
|
119
116
|
JSON.Encode.object(obj)
|
|
120
117
|
}
|
|
@@ -33,7 +33,6 @@ module type T = {
|
|
|
33
33
|
module Make = (Spec: SliceSpec): (T with module Spec = Spec) => {
|
|
34
34
|
module Spec = Spec
|
|
35
35
|
|
|
36
|
-
|
|
37
36
|
let describe = JestBind.describe
|
|
38
37
|
let test = (name, body) => JestBind.test(~slice=Spec.name, name, body)
|
|
39
38
|
|
|
@@ -54,11 +53,8 @@ module Make = (Spec: SliceSpec): (T with module Spec = Spec) => {
|
|
|
54
53
|
switch result {
|
|
55
54
|
| Ok(actual) if actual == expected => Outcome.pass
|
|
56
55
|
| Ok(actual) =>
|
|
57
|
-
Outcome.fail(
|
|
58
|
-
|
|
59
|
-
)
|
|
60
|
-
| Error(msg) =>
|
|
61
|
-
Outcome.fail(TranslateError({expected: "(commands)", actual: Some(msg)}))
|
|
56
|
+
Outcome.fail(EventsMismatch({expected: encPairs(expected), actual: encPairs(actual)}))
|
|
57
|
+
| Error(msg) => Outcome.fail(TranslateError({expected: "(commands)", actual: Some(msg)}))
|
|
62
58
|
}
|
|
63
59
|
|
|
64
60
|
let thenCommand = (result, expectedId, expectedCmd) =>
|
|
@@ -68,15 +64,13 @@ module Make = (Spec: SliceSpec): (T with module Spec = Spec) => {
|
|
|
68
64
|
switch result {
|
|
69
65
|
| Ok([]) => Outcome.pass
|
|
70
66
|
| Ok(actual) => Outcome.fail(NoEventExpected({actual: encPairs(actual)}))
|
|
71
|
-
| Error(msg) =>
|
|
72
|
-
Outcome.fail(TranslateError({expected: "(no commands)", actual: Some(msg)}))
|
|
67
|
+
| Error(msg) => Outcome.fail(TranslateError({expected: "(no commands)", actual: Some(msg)}))
|
|
73
68
|
}
|
|
74
69
|
|
|
75
70
|
let thenTranslateError = (result, expectedMsg) =>
|
|
76
71
|
switch result {
|
|
77
72
|
| Error(actual) if actual == expectedMsg => Outcome.pass
|
|
78
|
-
| Error(actual) =>
|
|
79
|
-
Outcome.fail(TranslateError({expected: expectedMsg, actual: Some(actual)}))
|
|
73
|
+
| Error(actual) => Outcome.fail(TranslateError({expected: expectedMsg, actual: Some(actual)}))
|
|
80
74
|
| Ok(_) => Outcome.fail(TranslateError({expected: expectedMsg, actual: None}))
|
|
81
75
|
}
|
|
82
76
|
}
|