@reventlessdev/reventless-gwt 1.0.0-alpha.247 → 1.0.0-alpha.249

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 (50) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -1
  3. package/package.json +7 -7
  4. package/src/.gwtignore +1 -1
  5. package/src/{Behavior_GWT.res → Decision_GWT.res} +110 -40
  6. package/src/{Behavior_GWT.res.mjs → Decision_GWT.res.mjs} +92 -42
  7. package/src/Delegate_GWT.res +1 -1
  8. package/src/EventMapping_GWT.res +7 -7
  9. package/src/EventMapping_GWT.res.mjs +3 -3
  10. package/src/Flow_GWT.res +14 -14
  11. package/src/Flow_GWT.res.mjs +6 -6
  12. package/src/Hint.res +1 -1
  13. package/src/Mapping_GWT.res +8 -8
  14. package/src/Mapping_GWT.res.mjs +6 -6
  15. package/src/Outcome.res +1 -1
  16. package/src/Query_GWT.res +1 -1
  17. package/src/RunnerHook.res +1 -1
  18. package/src/ScenarioRecorder.res +182 -0
  19. package/src/ScenarioRecorder.res.mjs +287 -0
  20. package/src/StateChange/ExternalAddCategorySlice.res +1 -1
  21. package/src/StateChange/WithFixtures.res +1 -1
  22. package/src/StateChange/WithManualOpen.res +1 -1
  23. package/tests/CallerTest.res +7 -7
  24. package/tests/CallerTest.res.mjs +8 -8
  25. package/tests/FlowAggregateGwtTest.res +6 -6
  26. package/tests/FlowAggregateGwtTest.res.mjs +6 -6
  27. package/tests/FlowCrossPluginGwtTest.res +8 -8
  28. package/tests/FlowCrossPluginGwtTest.res.mjs +8 -8
  29. package/tests/FlowGwtTest.res +4 -4
  30. package/tests/FlowGwtTest.res.mjs +4 -4
  31. package/tests/HintTest.res +2 -2
  32. package/tests/HintTest.res.mjs +1 -1
  33. package/tests/MappingGwtTest.res +5 -5
  34. package/tests/MappingGwtTest.res.mjs +6 -6
  35. package/tests/ScenarioRecorderTest.res +101 -0
  36. package/tests/ScenarioRecorderTest.res.mjs +163 -0
  37. package/tests/StateChange/ExternalAddCategorySlice_GWT.res +3 -3
  38. package/tests/StateChange/ExternalAddCategorySlice_GWT.res.mjs +5 -5
  39. package/tests/StateChange/WithFixtures_GWT.res.mjs +5 -5
  40. package/tests/StateChange/WithManualOpen_GWT.res.mjs +5 -5
  41. package/tests/StateChangeSliceAuthorizeGwtTest.res +10 -10
  42. package/tests/StateChangeSliceAuthorizeGwtTest.res.mjs +14 -14
  43. package/tests/StateChangeSliceGwtTest.res +9 -9
  44. package/tests/StateChangeSliceGwtTest.res.mjs +12 -12
  45. /package/src/StateChange/{ExternalAddCategorySlice_Behavior.res → ExternalAddCategorySlice_Decision.res} +0 -0
  46. /package/src/StateChange/{ExternalAddCategorySlice_Behavior.res.mjs → ExternalAddCategorySlice_Decision.res.mjs} +0 -0
  47. /package/src/StateChange/{WithFixtures_Behavior.res → WithFixtures_Decision.res} +0 -0
  48. /package/src/StateChange/{WithFixtures_Behavior.res.mjs → WithFixtures_Decision.res.mjs} +0 -0
  49. /package/src/StateChange/{WithManualOpen_Behavior.res → WithManualOpen_Decision.res} +0 -0
  50. /package/src/StateChange/{WithManualOpen_Behavior.res.mjs → WithManualOpen_Decision.res.mjs} +0 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,27 @@
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.249 (2026-10-21)
7
+
8
+ * feat!: the write-side logic module is called the decision, and a codemod moves an app over ([cb573ff](https://github.com/ReventlessDev/reventless-core/commit/cb573ff5b928c7d7f3e75988dfaa65066f8c95eb))
9
+
10
+ ### BREAKING CHANGES
11
+
12
+ * <Spec>_Behavior.res, @@reventless.behavior,
13
+ Reventless.Behavior.T, StateChangeSlice.Behavior, Behavior_GWT and
14
+ thenRefused no longer exist. Run `npx reventless-rename-to-decision` at an
15
+ app's root, then rebuild; comments are not rewritten. The PPX must be the
16
+ matching release.
17
+
18
+
19
+
20
+ # 1.0.0-alpha.248 (2026-10-19)
21
+
22
+ ### Features
23
+
24
+ * **gwt:** record behaviour scenarios as they run, for suites whose source names none ([256b253](https://github.com/ReventlessDev/reventless-core/commit/256b253153ec043105c38ac742a1a3efbde48c87))
25
+
26
+
6
27
  # 1.0.0-alpha.247 (2026-10-17)
7
28
 
8
29
  **Note:** Version bump only for package @reventlessdev/reventless-gwt
package/README.md CHANGED
@@ -21,7 +21,7 @@ the `reventless-dev` CLI discovers and runs those tests across a workspace.
21
21
  Every component kind has a functor that produces the same
22
22
  `describe / test / given* / when* / then*` combinator surface:
23
23
 
24
- - **`Behavior_GWT`** — event-sourced behavior tests for aggregates and
24
+ - **`Decision_GWT`** — event-sourced decision tests for aggregates and
25
25
  StateChangeSlices (`givenEvents → whenCmd → thenEmits`), including DCB
26
26
  append-condition assertions.
27
27
  - **`Projection_GWT`** / **`MultiSourceProjection_GWT`** — single-source
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-gwt",
3
- "version": "1.0.0-alpha.247",
3
+ "version": "1.0.0-alpha.249",
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",
17
- "@reventlessdev/rescript-effect": "1.0.0-alpha.0",
18
- "@reventlessdev/rescript-node": "2.0.0-alpha.22",
19
- "@reventlessdev/reventless-core": "3.0.0-alpha.299",
20
- "@reventlessdev/reventless-infra": "3.0.0-alpha.196",
21
- "@reventlessdev/rescript-jest": "1.0.0-alpha.12",
22
- "@reventlessdev/reventless-spec": "3.0.0-alpha.168"
17
+ "@reventlessdev/rescript-effect": "1.0.0-alpha.1",
18
+ "@reventlessdev/rescript-jest": "1.0.0-alpha.13",
19
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.198",
20
+ "@reventlessdev/rescript-node": "2.0.0-alpha.23",
21
+ "@reventlessdev/reventless-core": "3.0.0-alpha.301",
22
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.170"
23
23
  },
24
24
  "devDependencies": {
25
25
  "rescript": "12.3.1",
package/src/.gwtignore CHANGED
@@ -1,6 +1,6 @@
1
1
  # Prunes this subtree from reventless-gwt discovery (test tree + component tree).
2
2
  #
3
- # These are the GWT DSL framework modules — `Automation_GWT`, `Behavior_GWT`,
3
+ # These are the GWT DSL framework modules — `Automation_GWT`, `Decision_GWT`,
4
4
  # `Mapping_GWT`, etc. — i.e. the `*_GWT.Make` functors the test runner is built
5
5
  # from. They are named with the same `_GWT` suffix that marks user test files, so
6
6
  # discovery would otherwise list each one as a test, even though loading the
@@ -1,15 +1,15 @@
1
1
  open ReventlessCore
2
2
 
3
- // Plan 02 Phase 6b — unified Behavior GWT DSL covering both Aggregate and
3
+ // Plan 02 Phase 6b — unified Decision GWT DSL covering both Aggregate and
4
4
  // StateChangeSlice. Two entry points:
5
5
  //
6
- // * [Make(Spec, Behavior)] — StateChangeSlice form. [Spec] carries
7
- // [consumedEvent]; [Behavior.evolve]
6
+ // * [Make(Spec, Decision)] — StateChangeSlice form. [Spec] carries
7
+ // [consumedEvent]; [Decision.evolve]
8
8
  // consumes it. DCB append-condition
9
9
  // checks are wired in.
10
- // * [MakeFromAggregate(Spec, Behavior)] — Aggregate adapter. [Spec] is
10
+ // * [MakeFromAggregate(Spec, Decision)] — Aggregate adapter. [Spec] is
11
11
  // [Reventless.Aggregate.Spec],
12
- // [Behavior] is [Reventless.Behavior.T].
12
+ // [Decision] is [Reventless.Decision.T].
13
13
  // No DCB semantics; the simpler
14
14
  // [AggregateT] surface is returned.
15
15
  //
@@ -19,7 +19,7 @@ open ReventlessCore
19
19
  // optimistic-concurrency assertions.
20
20
  //
21
21
  // Aggregate users *cannot* use [Make] (their Spec doesn't carry [consumedEvent])
22
- // and slice users *cannot* use [MakeFromAggregate] (their Spec/Behavior shape
22
+ // and slice users *cannot* use [MakeFromAggregate] (their Spec/Decision shape
23
23
  // differs). Pick the matching entry point.
24
24
 
25
25
  // ---------------------------------------------------------------------------
@@ -204,7 +204,7 @@ module Acting = (Spec: ActingSpec) => {
204
204
  )
205
205
  )
206
206
 
207
- let thenRefused = (~encEvents, ~decided: option<JSON.t>, events) =>
207
+ let thenForbidden = (~encEvents, ~decided: option<JSON.t>, events) =>
208
208
  switch refusal.contents {
209
209
  | Some(_) => Outcome.pass
210
210
  | None =>
@@ -224,7 +224,7 @@ module Acting = (Spec: ActingSpec) => {
224
224
  // Slice form — replaces the legacy `StateChangeSlice_GWT`.
225
225
  // ---------------------------------------------------------------------------
226
226
 
227
- module type BehaviorSpec = {
227
+ module type DecisionSpec = {
228
228
  let name: string
229
229
 
230
230
  @schema
@@ -243,8 +243,8 @@ module type BehaviorSpec = {
243
243
  let authorizationOf: string => Reventless.Authorization.rule<role>
244
244
  }
245
245
 
246
- module type Behavior = {
247
- module Spec: BehaviorSpec
246
+ module type Decision = {
247
+ module Spec: DecisionSpec
248
248
 
249
249
  type state
250
250
  let initialState: state
@@ -253,7 +253,7 @@ module type Behavior = {
253
253
  }
254
254
 
255
255
  module type T = {
256
- module Spec: BehaviorSpec
256
+ module Spec: DecisionSpec
257
257
 
258
258
  let describe: (string, unit => unit) => unit
259
259
  let todo: string => unit
@@ -275,7 +275,7 @@ module type T = {
275
275
  let thenError: (array<Spec.event>, Spec.error) => Outcome.outcome
276
276
  // Refused before `decide`: by the command's rule, or because the caller does not
277
277
  // own what it acts on.
278
- let thenRefused: array<Spec.event> => Outcome.outcome
278
+ let thenForbidden: array<Spec.event> => Outcome.outcome
279
279
 
280
280
  // DCB optimistic-concurrency assertions.
281
281
  let thenAppendsConditionedOn: (array<Spec.event>, Reventless.DcbTag.query) => Outcome.outcome
@@ -323,7 +323,7 @@ let encodeAppendCondition = (c: Reventless.DcbTag.appendCondition): JSON.t => {
323
323
  }
324
324
 
325
325
  // ---------------------------------------------------------------------------
326
- // Shared assertion core for both Behavior GWT flavours.
326
+ // Shared assertion core for both Decision GWT flavours.
327
327
  //
328
328
  // `Make` (slice/DCB) and `MakeFromAggregate` encode produced events / errors
329
329
  // identically and compare them against the expectation the same way — only the
@@ -436,16 +436,19 @@ module AssertionCore = (Spec: CoreSpec) => {
436
436
  }
437
437
  }
438
438
 
439
- module Make = (Spec: BehaviorSpec, Behavior: Behavior with module Spec := Spec): (
439
+ module Make = (Spec: DecisionSpec, Decision: Decision with module Spec := Spec): (
440
440
  T with module Spec = Spec
441
441
  ) => {
442
442
  module Spec = Spec
443
443
 
444
444
  let describe = JestBind.describe
445
445
  let todo = JestBind.todo
446
- let test = (name, body) => JestBind.test(~slice=Spec.name, name, body)
446
+ let test = (name, body) =>
447
+ JestBind.test(~slice=Spec.name, name, () =>
448
+ ScenarioRecorder.around(~spec=Spec.name, name, body)
449
+ )
447
450
 
448
- let currentState = consumed => consumed->Array.reduce(Behavior.initialState, Behavior.evolve)
451
+ let currentState = consumed => consumed->Array.reduce(Decision.initialState, Decision.evolve)
449
452
 
450
453
  module Core = AssertionCore(Spec)
451
454
  let errors = Core.errors
@@ -604,7 +607,7 @@ module Make = (Spec: BehaviorSpec, Behavior: Behavior with module Spec := Spec):
604
607
  if Guard.refuses(history, command) {
605
608
  []
606
609
  } else {
607
- switch Behavior.decide(currentState(history), command) {
610
+ switch Decision.decide(currentState(history), command) {
608
611
  | Ok(events) => events
609
612
  | Error(error) =>
610
613
  errors := [error]
@@ -614,7 +617,27 @@ module Make = (Spec: BehaviorSpec, Behavior: Behavior with module Spec := Spec):
614
617
  }
615
618
 
616
619
  let givenEvents = consumed => consumed
617
- let whenCmd = (history, cmd) => history->exec(cmd)
620
+ let whenCmd = (history, cmd) => {
621
+ if ScenarioRecorder.recording() {
622
+ ScenarioRecorder.given(
623
+ history->Array.map(e =>
624
+ e->Message.encode(Spec.consumedEventSchema)->Message.variantNameOfJson
625
+ ),
626
+ )
627
+ ScenarioRecorder.whenCommand(Guard.commandName(cmd))
628
+ }
629
+ history->exec(cmd)
630
+ }
631
+ // What a test expects, named for the recorded sidecar.
632
+ let expects = (~events=[], ~error=?) =>
633
+ if ScenarioRecorder.recording() {
634
+ ScenarioRecorder.thenEvents(
635
+ events->Array.map(e => e->Core.encEvent->Message.variantNameOfJson),
636
+ )
637
+ error->Option.forEach(err =>
638
+ ScenarioRecorder.thenError(err->Core.encError->Message.variantNameOfJson)
639
+ )
640
+ }
618
641
 
619
642
  let checkAppendCondition = (): option<Outcome.outcome> =>
620
643
  switch appendConditionFailure.contents {
@@ -622,8 +645,8 @@ module Make = (Spec: BehaviorSpec, Behavior: Behavior with module Spec := Spec):
622
645
  | None => Guard.unexpectedRefusal()
623
646
  }
624
647
 
625
- let thenRefused = events =>
626
- Guard.thenRefused(
648
+ let thenForbidden = events =>
649
+ Guard.thenForbidden(
627
650
  ~encEvents=Core.encEvents,
628
651
  ~decided=errors.contents->Array.get(0)->Option.map(Core.encError),
629
652
  events,
@@ -631,37 +654,49 @@ module Make = (Spec: BehaviorSpec, Behavior: Behavior with module Spec := Spec):
631
654
 
632
655
  // The append-condition footgun is surfaced before the shared comparison core
633
656
  // runs; `thenAppends*` below bypass it deliberately.
634
- let thenEvents = (events, expectedEvents) =>
657
+ let thenEvents = (events, expectedEvents) => {
658
+ expects(~events=expectedEvents)
635
659
  switch checkAppendCondition() {
636
660
  | Some(o) => o
637
661
  | None => Core.compareEvents(events, expectedEvents)
638
662
  }
663
+ }
639
664
 
640
665
  let thenEvent = (events, expectedEvent) => thenEvents(events, [expectedEvent])
641
666
 
642
- let thenNoEvent = events =>
667
+ let thenNoEvent = events => {
668
+ if ScenarioRecorder.recording() {
669
+ ScenarioRecorder.thenNoEvent()
670
+ }
643
671
  switch checkAppendCondition() {
644
672
  | Some(o) => o
645
673
  | None => Core.compareNoEvent(events)
646
674
  }
675
+ }
647
676
 
648
- let thenError = (events, expectedError) =>
677
+ let thenError = (events, expectedError) => {
678
+ expects(~error=expectedError)
649
679
  switch checkAppendCondition() {
650
680
  | Some(o) => o
651
681
  | None => Core.matchesError(events, [], expectedError)
652
682
  }
683
+ }
653
684
 
654
- let thenEventWithError = (events, expectedEvent, expectedError) =>
685
+ let thenEventWithError = (events, expectedEvent, expectedError) => {
686
+ expects(~events=[expectedEvent], ~error=expectedError)
655
687
  switch checkAppendCondition() {
656
688
  | Some(o) => o
657
689
  | None => Core.matchesError(events, [expectedEvent], expectedError)
658
690
  }
691
+ }
659
692
 
660
- let thenEventsWithError = (events, expectedEvents, expectedError) =>
693
+ let thenEventsWithError = (events, expectedEvents, expectedError) => {
694
+ expects(~events=expectedEvents, ~error=expectedError)
661
695
  switch checkAppendCondition() {
662
696
  | Some(o) => o
663
697
  | None => Core.matchesError(events, expectedEvents, expectedError)
664
698
  }
699
+ }
665
700
 
666
701
  let thenAppendsConditionedOn = (_events, expectedQuery: Reventless.DcbTag.query) =>
667
702
  switch derivedCondition.contents {
@@ -716,7 +751,7 @@ module Make = (Spec: BehaviorSpec, Behavior: Behavior with module Spec := Spec):
716
751
  // ---------------------------------------------------------------------------
717
752
 
718
753
  // Minimal aggregate spec the DSL requires. Declared inline (rather than
719
- // aliasing `Reventless.Behavior.T`'s inner Spec) because that inner Spec
754
+ // aliasing `Reventless.Decision.T`'s inner Spec) because that inner Spec
720
755
  // only carries the three @schema types — no `name` — and ReScript's
721
756
  // `with module Spec = X` can only equate the inner Spec to a concrete
722
757
  // module, not constrain it to a module type that adds `name`.
@@ -764,18 +799,21 @@ module type AggregateT = {
764
799
  let thenError: (array<Spec.event>, Spec.error) => Outcome.outcome
765
800
  // Refused before `decide`: by the command's rule, or because the caller does not
766
801
  // own what it acts on.
767
- let thenRefused: array<Spec.event> => Outcome.outcome
802
+ let thenForbidden: array<Spec.event> => Outcome.outcome
768
803
  }
769
804
 
770
- module MakeFromAggregate = (Spec: AggregateSpec, Behavior: Behavior.T with module Spec = Spec): (
805
+ module MakeFromAggregate = (Spec: AggregateSpec, Decision: Decision.T with module Spec = Spec): (
771
806
  AggregateT with module Spec = Spec
772
807
  ) => {
773
808
  module Spec = Spec
774
809
 
775
810
  let describe = JestBind.describe
776
- let test = (name, body) => JestBind.test(~slice=Spec.name, name, body)
811
+ let test = (name, body) =>
812
+ JestBind.test(~slice=Spec.name, name, () =>
813
+ ScenarioRecorder.around(~spec=Spec.name, name, body)
814
+ )
777
815
 
778
- let currentState = events => events->Array.reduce(Behavior.initialState, Behavior.evolve)
816
+ let currentState = events => events->Array.reduce(Decision.initialState, Decision.evolve)
779
817
 
780
818
  module Core = AssertionCore(Spec)
781
819
  let errors = Core.errors
@@ -799,7 +837,7 @@ module MakeFromAggregate = (Spec: AggregateSpec, Behavior: Behavior.T with modul
799
837
  if Guard.refuses(history, command) {
800
838
  []
801
839
  } else {
802
- switch Behavior.decide(currentState(history), command) {
840
+ switch Decision.decide(currentState(history), command) {
803
841
  | Ok(events) => events
804
842
  | Error(error) =>
805
843
  errors := [error]
@@ -809,7 +847,23 @@ module MakeFromAggregate = (Spec: AggregateSpec, Behavior: Behavior.T with modul
809
847
  }
810
848
 
811
849
  let givenEvents = events => events
812
- let whenCmd = (history, cmd) => history->exec(cmd)
850
+ let whenCmd = (history, cmd) => {
851
+ if ScenarioRecorder.recording() {
852
+ ScenarioRecorder.given(history->Array.map(e => e->Core.encEvent->Message.variantNameOfJson))
853
+ ScenarioRecorder.whenCommand(Guard.commandName(cmd))
854
+ }
855
+ history->exec(cmd)
856
+ }
857
+ // What a test expects, named for the recorded sidecar.
858
+ let expects = (~events=[], ~error=?) =>
859
+ if ScenarioRecorder.recording() {
860
+ ScenarioRecorder.thenEvents(
861
+ events->Array.map(e => e->Core.encEvent->Message.variantNameOfJson),
862
+ )
863
+ error->Option.forEach(err =>
864
+ ScenarioRecorder.thenError(err->Core.encError->Message.variantNameOfJson)
865
+ )
866
+ }
813
867
 
814
868
  // The aggregate flavour has no append-condition footgun, so the shared core's
815
869
  // comparisons are exposed directly once a refusal has been ruled out; only
@@ -819,25 +873,41 @@ module MakeFromAggregate = (Spec: AggregateSpec, Behavior: Behavior.T with modul
819
873
  | Some(o) => o
820
874
  | None => compare(events)
821
875
  }
822
- let thenEvents = (events, expected) => events->unlessRefused(Core.compareEvents(_, expected))
823
- let thenCompareEvents = (events, expected, cmp) =>
876
+ let thenEvents = (events, expected) => {
877
+ expects(~events=expected)
878
+ events->unlessRefused(Core.compareEvents(_, expected))
879
+ }
880
+ let thenCompareEvents = (events, expected, cmp) => {
881
+ expects(~events=expected)
824
882
  events->unlessRefused(Core.compareEventsWith(_, expected, cmp))
883
+ }
825
884
  let thenEvent = (events, expectedEvent) => thenEvents(events, [expectedEvent])
826
885
  let thenCompareEvent = (events, expectedEvent, cmp) =>
827
886
  thenCompareEvents(events, [expectedEvent], cmp)
828
- let thenNoEvent = events => events->unlessRefused(Core.compareNoEvent)
887
+ let thenNoEvent = events => {
888
+ if ScenarioRecorder.recording() {
889
+ ScenarioRecorder.thenNoEvent()
890
+ }
891
+ events->unlessRefused(Core.compareNoEvent)
892
+ }
829
893
 
830
- let thenError = (events, expectedError) =>
894
+ let thenError = (events, expectedError) => {
895
+ expects(~error=expectedError)
831
896
  events->unlessRefused(Core.matchesError(_, [], expectedError))
897
+ }
832
898
 
833
- let thenEventWithError = (events, expectedEvent, expectedError) =>
899
+ let thenEventWithError = (events, expectedEvent, expectedError) => {
900
+ expects(~events=[expectedEvent], ~error=expectedError)
834
901
  events->unlessRefused(Core.matchesError(_, [expectedEvent], expectedError))
902
+ }
835
903
 
836
- let thenEventsWithError = (events, expectedEvents, expectedError) =>
904
+ let thenEventsWithError = (events, expectedEvents, expectedError) => {
905
+ expects(~events=expectedEvents, ~error=expectedError)
837
906
  events->unlessRefused(Core.matchesError(_, expectedEvents, expectedError))
907
+ }
838
908
 
839
- let thenRefused = events =>
840
- Guard.thenRefused(
909
+ let thenForbidden = events =>
910
+ Guard.thenForbidden(
841
911
  ~encEvents=Core.encEvents,
842
912
  ~decided=errors.contents->Array.get(0)->Option.map(Core.encError),
843
913
  events,
@@ -15,6 +15,7 @@ import * as JestBind$ReventlessGwt from "./JestBind.res.mjs";
15
15
  import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Message.res.mjs";
16
16
  import * as Authorization$Reventless from "@reventlessdev/reventless-spec/src/types/Authorization.res.mjs";
17
17
  import * as DcbScopeInference$Reventless from "@reventlessdev/reventless-spec/src/components/DcbScopeInference.res.mjs";
18
+ import * as ScenarioRecorder$ReventlessGwt from "./ScenarioRecorder.res.mjs";
18
19
  import * as CommandTopic_Helpers$ReventlessCore from "@reventlessdev/reventless-core/src/components/CommandTopic/CommandTopic_Helpers.res.mjs";
19
20
 
20
21
  function roleNames(roles) {
@@ -155,7 +156,7 @@ function Acting(Spec) {
155
156
  actual: encRefusal(r),
156
157
  actualEvents: []
157
158
  }));
158
- let thenRefused = (encEvents, decided, events) => {
159
+ let thenForbidden = (encEvents, decided, events) => {
159
160
  let match = refusal.contents;
160
161
  if (match !== undefined) {
161
162
  return Outcome$ReventlessGwt.pass;
@@ -181,7 +182,7 @@ function Acting(Spec) {
181
182
  refuses: refuses,
182
183
  encRefusal: encRefusal,
183
184
  unexpectedRefusal: unexpectedRefusal,
184
- thenRefused: thenRefused
185
+ thenForbidden: thenForbidden
185
186
  };
186
187
  }
187
188
 
@@ -316,8 +317,8 @@ function AssertionCore(Spec) {
316
317
  }
317
318
 
318
319
  function Make(Spec) {
319
- return Behavior => {
320
- let test = (name, body) => JestBind$ReventlessGwt.test(Spec.name, name, body);
320
+ return Decision => {
321
+ let test = (name, body) => JestBind$ReventlessGwt.test(Spec.name, name, () => ScenarioRecorder$ReventlessGwt.around(Spec.name, name, body));
321
322
  let errors = {
322
323
  contents: []
323
324
  };
@@ -494,6 +495,10 @@ function Make(Spec) {
494
495
  let queryTagsTotal = q => Stdlib_Array.reduce(q, 0, (acc, qi) => acc + Stdlib_Option.mapOr(qi.tags, 0, t => t.length) | 0);
495
496
  let givenEvents = consumed => consumed;
496
497
  let whenCmd = (history, cmd) => {
498
+ if (ScenarioRecorder$ReventlessGwt.recording()) {
499
+ ScenarioRecorder$ReventlessGwt.given(history.map(e => Message$ReventlessCore.variantNameOfJson(Message$ReventlessCore.encode(e, Spec.consumedEventSchema))));
500
+ ScenarioRecorder$ReventlessGwt.whenCommand(Message$ReventlessCore.variantNameOfJson(Message$ReventlessCore.encode(cmd, commandSchema)));
501
+ }
497
502
  errors.contents = [];
498
503
  appendConditionFailure.contents = undefined;
499
504
  let query = DcbTag$Reventless.buildQueryFromCommand(consumedEventTypes, Spec.commandSchema, cmd, tagKeysByEventType, crossPartitionTagKeys, payloadTagKeys);
@@ -522,13 +527,20 @@ function Make(Spec) {
522
527
  if (refuses(history, cmd)) {
523
528
  return [];
524
529
  }
525
- let events = Behavior.decide(Stdlib_Array.reduce(history, Behavior.initialState, Behavior.evolve), cmd);
530
+ let events = Decision.decide(Stdlib_Array.reduce(history, Decision.initialState, Decision.evolve), cmd);
526
531
  if (events.TAG === "Ok") {
527
532
  return events._0;
528
533
  }
529
534
  errors.contents = [events._0];
530
535
  return [];
531
536
  };
537
+ let expects = (eventsOpt, error) => {
538
+ let events = eventsOpt !== undefined ? eventsOpt : [];
539
+ if (ScenarioRecorder$ReventlessGwt.recording()) {
540
+ ScenarioRecorder$ReventlessGwt.thenEvents(events.map(e => Message$ReventlessCore.variantNameOfJson(Message$ReventlessCore.encode(e, Spec.eventSchema))));
541
+ return Stdlib_Option.forEach(error, err => ScenarioRecorder$ReventlessGwt.thenError(Message$ReventlessCore.variantNameOfJson(Message$ReventlessCore.encode(err, Spec.errorSchema))));
542
+ }
543
+ };
532
544
  let checkAppendCondition = () => {
533
545
  let m = appendConditionFailure.contents;
534
546
  if (m !== undefined) {
@@ -537,7 +549,7 @@ function Make(Spec) {
537
549
  return unexpectedRefusal();
538
550
  }
539
551
  };
540
- let thenRefused = events => {
552
+ let thenForbidden = events => {
541
553
  let decided = Stdlib_Option.map(errors.contents[0], encError);
542
554
  let match = refusal.contents;
543
555
  if (match !== undefined) {
@@ -555,6 +567,7 @@ function Make(Spec) {
555
567
  }
556
568
  };
557
569
  let thenEvents = (events, expectedEvents) => {
570
+ expects(expectedEvents, undefined);
558
571
  let o = checkAppendCondition();
559
572
  if (o !== undefined) {
560
573
  return o;
@@ -572,6 +585,9 @@ function Make(Spec) {
572
585
  };
573
586
  let thenEvent = (events, expectedEvent) => thenEvents(events, [expectedEvent]);
574
587
  let thenNoEvent = events => {
588
+ if (ScenarioRecorder$ReventlessGwt.recording()) {
589
+ ScenarioRecorder$ReventlessGwt.thenNoEvent();
590
+ }
575
591
  let o = checkAppendCondition();
576
592
  if (o !== undefined) {
577
593
  return o;
@@ -587,6 +603,7 @@ function Make(Spec) {
587
603
  }
588
604
  };
589
605
  let thenError = (events, expectedError) => {
606
+ expects(undefined, Primitive_option.some(expectedError));
590
607
  let o = checkAppendCondition();
591
608
  if (o !== undefined) {
592
609
  return o;
@@ -595,6 +612,7 @@ function Make(Spec) {
595
612
  }
596
613
  };
597
614
  let thenEventWithError = (events, expectedEvent, expectedError) => {
615
+ expects([expectedEvent], Primitive_option.some(expectedError));
598
616
  let o = checkAppendCondition();
599
617
  if (o !== undefined) {
600
618
  return o;
@@ -603,6 +621,7 @@ function Make(Spec) {
603
621
  }
604
622
  };
605
623
  let thenEventsWithError = (events, expectedEvents, expectedError) => {
624
+ expects(expectedEvents, Primitive_option.some(expectedError));
606
625
  let o = checkAppendCondition();
607
626
  if (o !== undefined) {
608
627
  return o;
@@ -667,7 +686,7 @@ function Make(Spec) {
667
686
  thenEventWithError: thenEventWithError,
668
687
  thenEventsWithError: thenEventsWithError,
669
688
  thenError: thenError,
670
- thenRefused: thenRefused,
689
+ thenForbidden: thenForbidden,
671
690
  thenAppendsConditionedOn: thenAppendsConditionedOn,
672
691
  thenAppendsConditionedOnExactly: thenAppendsConditionedOnExactly
673
692
  };
@@ -675,8 +694,8 @@ function Make(Spec) {
675
694
  }
676
695
 
677
696
  function MakeFromAggregate(Spec) {
678
- return Behavior => {
679
- let test = (name, body) => JestBind$ReventlessGwt.test(Spec.name, name, body);
697
+ return Decision => {
698
+ let test = (name, body) => JestBind$ReventlessGwt.test(Spec.name, name, () => ScenarioRecorder$ReventlessGwt.around(Spec.name, name, body));
680
699
  let errors = {
681
700
  contents: []
682
701
  };
@@ -810,17 +829,28 @@ function MakeFromAggregate(Spec) {
810
829
  }));
811
830
  let givenEvents = events => events;
812
831
  let whenCmd = (history, cmd) => {
832
+ if (ScenarioRecorder$ReventlessGwt.recording()) {
833
+ ScenarioRecorder$ReventlessGwt.given(history.map(e => Message$ReventlessCore.variantNameOfJson(Message$ReventlessCore.encode(e, Spec.eventSchema))));
834
+ ScenarioRecorder$ReventlessGwt.whenCommand(Message$ReventlessCore.variantNameOfJson(Message$ReventlessCore.encode(cmd, commandSchema)));
835
+ }
813
836
  errors.contents = [];
814
837
  if (refuses(history, cmd)) {
815
838
  return [];
816
839
  }
817
- let events = Behavior.decide(Stdlib_Array.reduce(history, Behavior.initialState, Behavior.evolve), cmd);
840
+ let events = Decision.decide(Stdlib_Array.reduce(history, Decision.initialState, Decision.evolve), cmd);
818
841
  if (events.TAG === "Ok") {
819
842
  return events._0;
820
843
  }
821
844
  errors.contents = [events._0];
822
845
  return [];
823
846
  };
847
+ let expects = (eventsOpt, error) => {
848
+ let events = eventsOpt !== undefined ? eventsOpt : [];
849
+ if (ScenarioRecorder$ReventlessGwt.recording()) {
850
+ ScenarioRecorder$ReventlessGwt.thenEvents(events.map(e => Message$ReventlessCore.variantNameOfJson(Message$ReventlessCore.encode(e, Spec.eventSchema))));
851
+ return Stdlib_Option.forEach(error, err => ScenarioRecorder$ReventlessGwt.thenError(Message$ReventlessCore.variantNameOfJson(Message$ReventlessCore.encode(err, Spec.errorSchema))));
852
+ }
853
+ };
824
854
  let unlessRefused = (events, compare) => {
825
855
  let o = unexpectedRefusal();
826
856
  if (o !== undefined) {
@@ -829,39 +859,59 @@ function MakeFromAggregate(Spec) {
829
859
  return compare(events);
830
860
  }
831
861
  };
832
- let thenEvents = (events, expected) => unlessRefused(events, __x => {
833
- if (errors.contents.length !== 0) {
834
- return unexpectedError(__x);
835
- } else if (Primitive_object.equal(__x.map(encEvent), expected.map(encEvent))) {
836
- return Outcome$ReventlessGwt.pass;
837
- } else {
838
- return Outcome$ReventlessGwt.fail({
839
- TAG: "EventsMismatch",
840
- expected: expected.map(encEvent),
841
- actual: __x.map(encEvent)
842
- });
843
- }
844
- });
845
- let thenCompareEvents = (events, expected, cmp) => unlessRefused(events, __x => {
846
- if (errors.contents.length !== 0) {
847
- return unexpectedError(__x);
848
- } else if (__x.length === expected.length && Stdlib_Array.zip(__x, expected).every(param => cmp(param[0], param[1]))) {
849
- return Outcome$ReventlessGwt.pass;
850
- } else {
851
- return Outcome$ReventlessGwt.fail({
852
- TAG: "EventsMismatch",
853
- expected: expected.map(encEvent),
854
- actual: __x.map(encEvent)
855
- });
856
- }
857
- });
862
+ let thenEvents = (events, expected) => {
863
+ expects(expected, undefined);
864
+ return unlessRefused(events, __x => {
865
+ if (errors.contents.length !== 0) {
866
+ return unexpectedError(__x);
867
+ } else if (Primitive_object.equal(__x.map(encEvent), expected.map(encEvent))) {
868
+ return Outcome$ReventlessGwt.pass;
869
+ } else {
870
+ return Outcome$ReventlessGwt.fail({
871
+ TAG: "EventsMismatch",
872
+ expected: expected.map(encEvent),
873
+ actual: __x.map(encEvent)
874
+ });
875
+ }
876
+ });
877
+ };
878
+ let thenCompareEvents = (events, expected, cmp) => {
879
+ expects(expected, undefined);
880
+ return unlessRefused(events, __x => {
881
+ if (errors.contents.length !== 0) {
882
+ return unexpectedError(__x);
883
+ } else if (__x.length === expected.length && Stdlib_Array.zip(__x, expected).every(param => cmp(param[0], param[1]))) {
884
+ return Outcome$ReventlessGwt.pass;
885
+ } else {
886
+ return Outcome$ReventlessGwt.fail({
887
+ TAG: "EventsMismatch",
888
+ expected: expected.map(encEvent),
889
+ actual: __x.map(encEvent)
890
+ });
891
+ }
892
+ });
893
+ };
858
894
  let thenEvent = (events, expectedEvent) => thenEvents(events, [expectedEvent]);
859
895
  let thenCompareEvent = (events, expectedEvent, cmp) => thenCompareEvents(events, [expectedEvent], cmp);
860
- let thenNoEvent = events => unlessRefused(events, compareNoEvent);
861
- let thenError = (events, expectedError) => unlessRefused(events, __x => matchesError(__x, [], expectedError));
862
- let thenEventWithError = (events, expectedEvent, expectedError) => unlessRefused(events, __x => matchesError(__x, [expectedEvent], expectedError));
863
- let thenEventsWithError = (events, expectedEvents, expectedError) => unlessRefused(events, __x => matchesError(__x, expectedEvents, expectedError));
864
- let thenRefused = events => {
896
+ let thenNoEvent = events => {
897
+ if (ScenarioRecorder$ReventlessGwt.recording()) {
898
+ ScenarioRecorder$ReventlessGwt.thenNoEvent();
899
+ }
900
+ return unlessRefused(events, compareNoEvent);
901
+ };
902
+ let thenError = (events, expectedError) => {
903
+ expects(undefined, Primitive_option.some(expectedError));
904
+ return unlessRefused(events, __x => matchesError(__x, [], expectedError));
905
+ };
906
+ let thenEventWithError = (events, expectedEvent, expectedError) => {
907
+ expects([expectedEvent], Primitive_option.some(expectedError));
908
+ return unlessRefused(events, __x => matchesError(__x, [expectedEvent], expectedError));
909
+ };
910
+ let thenEventsWithError = (events, expectedEvents, expectedError) => {
911
+ expects(expectedEvents, Primitive_option.some(expectedError));
912
+ return unlessRefused(events, __x => matchesError(__x, expectedEvents, expectedError));
913
+ };
914
+ let thenForbidden = events => {
865
915
  let decided = Stdlib_Option.map(errors.contents[0], encError);
866
916
  let match = refusal.contents;
867
917
  if (match !== undefined) {
@@ -894,7 +944,7 @@ function MakeFromAggregate(Spec) {
894
944
  thenCompareEvents: thenCompareEvents,
895
945
  thenEventsWithError: thenEventsWithError,
896
946
  thenError: thenError,
897
- thenRefused: thenRefused
947
+ thenForbidden: thenForbidden
898
948
  };
899
949
  };
900
950
  }