@reventlessdev/reventless-gwt 1.0.0-alpha.115 → 1.0.0-alpha.116

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 (91) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/package.json +5 -12
  3. package/rescript.json +0 -1
  4. package/bin/reventless-dev.mjs +0 -21
  5. package/src/Bind.res +0 -29
  6. package/src/Bind.res.mjs +0 -22
  7. package/src/BuildClassifier.res +0 -147
  8. package/src/BuildClassifier.res.mjs +0 -136
  9. package/src/Cancellation.res +0 -37
  10. package/src/Cancellation.res.mjs +0 -46
  11. package/src/ChildProcess.res +0 -102
  12. package/src/ChildProcess.res.mjs +0 -107
  13. package/src/Cli.res +0 -889
  14. package/src/Cli.res.mjs +0 -944
  15. package/src/Collector.res +0 -222
  16. package/src/Collector.res.mjs +0 -228
  17. package/src/ComponentMeta.res +0 -77
  18. package/src/ComponentMeta.res.mjs +0 -91
  19. package/src/ComponentScan.res +0 -101
  20. package/src/ComponentScan.res.mjs +0 -92
  21. package/src/Discovery.res +0 -102
  22. package/src/Discovery.res.mjs +0 -86
  23. package/src/DomainDeadCode.res +0 -98
  24. package/src/DomainDeadCode.res.mjs +0 -72
  25. package/src/DomainGraph.res +0 -0
  26. package/src/DomainGraph.res.mjs +0 -0
  27. package/src/ExnMessage.res +0 -14
  28. package/src/ExnMessage.res.mjs +0 -17
  29. package/src/ExnReflect.mjs +0 -24
  30. package/src/Filter.res +0 -45
  31. package/src/Filter.res.mjs +0 -47
  32. package/src/FormatterHuman.res +0 -109
  33. package/src/FormatterHuman.res.mjs +0 -115
  34. package/src/FormatterJson.res +0 -264
  35. package/src/FormatterJson.res.mjs +0 -322
  36. package/src/FormatterJunit.res +0 -93
  37. package/src/FormatterJunit.res.mjs +0 -90
  38. package/src/FormatterTap.res +0 -100
  39. package/src/FormatterTap.res.mjs +0 -131
  40. package/src/FormatterVsCode.res +0 -352
  41. package/src/FormatterVsCode.res.mjs +0 -546
  42. package/src/Loader.res +0 -24
  43. package/src/Loader.res.mjs +0 -23
  44. package/src/PackageScan.res +0 -80
  45. package/src/PackageScan.res.mjs +0 -81
  46. package/src/PlatformRunner.res +0 -191
  47. package/src/PlatformRunner.res.mjs +0 -178
  48. package/src/PlatformScan.res +0 -141
  49. package/src/PlatformScan.res.mjs +0 -124
  50. package/src/ProcessManager.res +0 -135
  51. package/src/ProcessManager.res.mjs +0 -119
  52. package/src/RunWorker.res +0 -24
  53. package/src/RunWorker.res.mjs +0 -16
  54. package/src/RunnerTypes.res +0 -68
  55. package/src/RunnerTypes.res.mjs +0 -60
  56. package/src/ScanIgnore.res +0 -11
  57. package/src/ScanIgnore.res.mjs +0 -23
  58. package/src/Watch.res +0 -102
  59. package/src/Watch.res.mjs +0 -80
  60. package/src/WatcherProbe.res +0 -56
  61. package/src/WatcherProbe.res.mjs +0 -59
  62. package/src/Worker.res +0 -24
  63. package/src/Worker.res.mjs +0 -9
  64. package/tests/BuildClassifierTest.res +0 -133
  65. package/tests/BuildClassifierTest.res.mjs +0 -176
  66. package/tests/CliRunEntryTest.res +0 -57
  67. package/tests/CliRunEntryTest.res.mjs +0 -65
  68. package/tests/CliWatchScopeTest.res +0 -62
  69. package/tests/CliWatchScopeTest.res.mjs +0 -95
  70. package/tests/ComponentMetaTest.res +0 -67
  71. package/tests/ComponentMetaTest.res.mjs +0 -71
  72. package/tests/DiscoveryTest.res +0 -42
  73. package/tests/DiscoveryTest.res.mjs +0 -43
  74. package/tests/DomainDeadCodeTest.res +0 -119
  75. package/tests/DomainDeadCodeTest.res.mjs +0 -158
  76. package/tests/DomainGraphTest.res +0 -448
  77. package/tests/DomainGraphTest.res.mjs +0 -505
  78. package/tests/ExnMessageTest.res +0 -42
  79. package/tests/ExnMessageTest.res.mjs +0 -64
  80. package/tests/FormatterGoldenTest.res +0 -125
  81. package/tests/FormatterGoldenTest.res.mjs +0 -162
  82. package/tests/FormatterVsCodeMessageTest.res +0 -41
  83. package/tests/FormatterVsCodeMessageTest.res.mjs +0 -42
  84. package/tests/PlatformRunnerTest.res +0 -66
  85. package/tests/PlatformRunnerTest.res.mjs +0 -85
  86. package/tests/PlatformScanTest.res +0 -61
  87. package/tests/PlatformScanTest.res.mjs +0 -56
  88. package/tests/RunnerUnitTest.res +0 -219
  89. package/tests/RunnerUnitTest.res.mjs +0 -244
  90. package/tests/WatchDebounceTest.res +0 -106
  91. package/tests/WatchDebounceTest.res.mjs +0 -128
@@ -1,125 +0,0 @@
1
- // Golden-output tests pinning the per-mismatch rendering of the three
2
- // string-emitting formatters:
3
- // - `Outcome.format` (used by the JUnit `<failure>` body)
4
- // - `FormatterHuman.renderMismatch` (terminal output)
5
- // - `FormatterTap.renderMismatchYaml` (TAP YAML diagnostic block)
6
- //
7
- // These three functions are exactly what the deferred `Outcome.mismatch`
8
- // normalization (plan C4) will unify. Pinning their current output byte-for-byte
9
- // lets that refactor prove it preserved Human/TAP rendering — and makes the
10
- // deliberate JUnit change (it currently renders via raw `Outcome.format`, unlike
11
- // the RenderRescript-based Human/TAP) explicit and reviewable rather than silent.
12
- //
13
- // The fixtures cover all 10 mismatch kinds — the full structural variety the
14
- // normalization must preserve: array expected/actual (Events/QueryRows/
15
- // PublishedActions), the Error()/Ok() wrapping with a `None` actual
16
- // (ErrorMismatch), the `key` extra + option rendering (StateMismatch), a
17
- // single-sided actual (NoEventExpected), plain-string (non-JSON) sides
18
- // (TranslateError), the `(id, value)` pair rendering (TodoMismatch), a nested
19
- // JSON value (AppendConditionMismatch), and the `Throw` stack special case.
20
-
21
- open JestGlobals
22
-
23
- let evA = JSON.parseOrThrow(`{"TAG":"ProductAdded","_0":{"productId":"p1","name":"Widget"}}`)
24
- let evB = JSON.parseOrThrow(`{"TAG":"ProductRenamed","_0":{"productId":"p1","name":"Gadget"}}`)
25
- let stateActive = JSON.parseOrThrow(`{"status":"active"}`)
26
- let stateArchived = JSON.parseOrThrow(`{"status":"archived"}`)
27
- let appendExpected = JSON.parseOrThrow(`{"query":[]}`)
28
- let appendActual = JSON.parseOrThrow(`{"query":[{"eventTypes":["ProductAdded"]}]}`)
29
-
30
- type golden = {
31
- name: string,
32
- mismatch: Outcome.mismatch,
33
- format: string,
34
- human: string,
35
- tap: string,
36
- }
37
-
38
- let goldens: array<golden> = [
39
- {
40
- name: "EventsMismatch",
41
- mismatch: EventsMismatch({expected: [evA], actual: [evB]}),
42
- format: "EventsMismatch:\n expected: [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]\n actual: [{\n \"TAG\": \"ProductRenamed\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Gadget\"\n }\n}]",
43
- human: " expected: [ProductAdded({productId: \"p1\", name: \"Widget\"})]\n actual: [ProductRenamed({productId: \"p1\", name: \"Gadget\"})]",
44
- tap: " kind: \"EventsMismatch\"\n expected: \"[ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})]\"\n actual: \"[ProductRenamed({productId: \\\"p1\\\", name: \\\"Gadget\\\"})]\"",
45
- },
46
- {
47
- name: "ErrorMismatch",
48
- mismatch: ErrorMismatch({
49
- expected: JSON.String("CategoryAlreadyExists"),
50
- actual: None,
51
- actualEvents: [evA],
52
- }),
53
- format: "ErrorMismatch:\n expected error: \"CategoryAlreadyExists\"\n actual error: (none)\n actual events: [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]",
54
- human: " expected: Error(\"CategoryAlreadyExists\")\n actual: Ok([ProductAdded({productId: \"p1\", name: \"Widget\"})])",
55
- tap: " kind: \"ErrorMismatch\"\n expected: \"Error(\\\"CategoryAlreadyExists\\\")\"\n actual: \"Ok([ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})])\"",
56
- },
57
- {
58
- name: "StateMismatch",
59
- mismatch: StateMismatch({key: "p1", expected: Some(stateActive), actual: Some(stateArchived)}),
60
- format: "StateMismatch (key: p1):\n expected: {\n \"status\": \"active\"\n}\n actual: {\n \"status\": \"archived\"\n}",
61
- human: " key: \"p1\"\n expected: {status: \"active\"}\n actual: {status: \"archived\"}",
62
- tap: " kind: \"StateMismatch\"\n key: \"p1\"\n expected: \"{status: \\\"active\\\"}\"\n actual: \"{status: \\\"archived\\\"}\"",
63
- },
64
- {
65
- name: "NoEventExpected",
66
- mismatch: NoEventExpected({actual: [evA]}),
67
- format: "NoEventExpected: expected no events, got:\n [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]",
68
- human: " expected no events\n actual: [ProductAdded({productId: \"p1\", name: \"Widget\"})]",
69
- tap: " kind: \"NoEventExpected\"\n actual: \"[ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})]\"",
70
- },
71
- {
72
- name: "TranslateError",
73
- mismatch: TranslateError({expected: "boom", actual: Some("kaboom")}),
74
- format: "TranslateError:\n expected: boom\n actual: kaboom",
75
- human: " expected: boom\n actual: kaboom",
76
- tap: " kind: \"TranslateError\"\n expected: \"boom\"\n actual: \"kaboom\"",
77
- },
78
- {
79
- name: "Throw",
80
- mismatch: Throw({error: "unexpected", stack: "at foo"}),
81
- format: "Throw: unexpected\nat foo",
82
- human: " error: unexpected\nat foo",
83
- tap: " kind: \"Throw\"\n error: \"unexpected\"\n stack: \"at foo\"",
84
- },
85
- {
86
- name: "TodoMismatch",
87
- mismatch: TodoMismatch({expected: [("case-1", evA)], actual: [("case-2", evB)]}),
88
- format: "TodoMismatch:\n expected: [(case-1, {\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n})]\n actual: [(case-2, {\n \"TAG\": \"ProductRenamed\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Gadget\"\n }\n})]",
89
- human: " expected: [(case-1, ProductAdded({productId: \"p1\", name: \"Widget\"}))]\n actual: [(case-2, ProductRenamed({productId: \"p1\", name: \"Gadget\"}))]",
90
- tap: " kind: \"TodoMismatch\"\n expected: \"[(case-1, ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"}))]\"\n actual: \"[(case-2, ProductRenamed({productId: \\\"p1\\\", name: \\\"Gadget\\\"}))]\"",
91
- },
92
- {
93
- name: "AppendConditionMismatch",
94
- mismatch: AppendConditionMismatch({expected: appendExpected, actual: appendActual}),
95
- format: "AppendConditionMismatch:\n expected: {\n \"query\": []\n}\n actual: {\n \"query\": [\n {\n \"eventTypes\": [\n \"ProductAdded\"\n ]\n }\n ]\n}",
96
- human: " expected: {query: []}\n actual: {query: [{eventTypes: [\"ProductAdded\"]}]}",
97
- tap: " kind: \"AppendConditionMismatch\"\n expected: \"{query: []}\"\n actual: \"{query: [{eventTypes: [\\\"ProductAdded\\\"]}]}\"",
98
- },
99
- {
100
- name: "QueryRowsMismatch",
101
- mismatch: QueryRowsMismatch({expected: [evA], actual: [evB]}),
102
- format: "QueryRowsMismatch:\n expected: [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]\n actual: [{\n \"TAG\": \"ProductRenamed\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Gadget\"\n }\n}]",
103
- human: " expected: [ProductAdded({productId: \"p1\", name: \"Widget\"})]\n actual: [ProductRenamed({productId: \"p1\", name: \"Gadget\"})]",
104
- tap: " kind: \"QueryRowsMismatch\"\n expected: \"[ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})]\"\n actual: \"[ProductRenamed({productId: \\\"p1\\\", name: \\\"Gadget\\\"})]\"",
105
- },
106
- {
107
- name: "PublishedActionsMismatch",
108
- mismatch: PublishedActionsMismatch({expected: [evA], actual: [evB]}),
109
- format: "PublishedActionsMismatch:\n expected: [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]\n actual: [{\n \"TAG\": \"ProductRenamed\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Gadget\"\n }\n}]",
110
- human: " expected: [ProductAdded({productId: \"p1\", name: \"Widget\"})]\n actual: [ProductRenamed({productId: \"p1\", name: \"Gadget\"})]",
111
- tap: " kind: \"PublishedActionsMismatch\"\n expected: \"[ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})]\"\n actual: \"[ProductRenamed({productId: \\\"p1\\\", name: \\\"Gadget\\\"})]\"",
112
- },
113
- ]
114
-
115
- describe("Formatter golden outputs (per-mismatch rendering)", () => {
116
- goldens->Array.forEach(g => {
117
- testSync(`${g.name} — Outcome.format`, () => expect(Outcome.format(g.mismatch))->toEqual(g.format))
118
- testSync(`${g.name} — FormatterHuman.renderMismatch`, () =>
119
- expect(FormatterHuman.renderMismatch(g.mismatch))->toEqual(g.human)
120
- )
121
- testSync(`${g.name} — FormatterTap.renderMismatchYaml`, () =>
122
- expect(FormatterTap.renderMismatchYaml(g.mismatch))->toEqual(g.tap)
123
- )
124
- })
125
- })
@@ -1,162 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Outcome$ReventlessGwt from "../src/Outcome.res.mjs";
4
- import * as FormatterTap$ReventlessGwt from "../src/FormatterTap.res.mjs";
5
- import * as FormatterHuman$ReventlessGwt from "../src/FormatterHuman.res.mjs";
6
-
7
- let evA = JSON.parse(`{"TAG":"ProductAdded","_0":{"productId":"p1","name":"Widget"}}`);
8
-
9
- let evB = JSON.parse(`{"TAG":"ProductRenamed","_0":{"productId":"p1","name":"Gadget"}}`);
10
-
11
- let stateActive = JSON.parse(`{"status":"active"}`);
12
-
13
- let stateArchived = JSON.parse(`{"status":"archived"}`);
14
-
15
- let appendExpected = JSON.parse(`{"query":[]}`);
16
-
17
- let appendActual = JSON.parse(`{"query":[{"eventTypes":["ProductAdded"]}]}`);
18
-
19
- let goldens = [
20
- {
21
- name: "EventsMismatch",
22
- mismatch: {
23
- TAG: "EventsMismatch",
24
- expected: [evA],
25
- actual: [evB]
26
- },
27
- format: "EventsMismatch:\n expected: [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]\n actual: [{\n \"TAG\": \"ProductRenamed\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Gadget\"\n }\n}]",
28
- human: " expected: [ProductAdded({productId: \"p1\", name: \"Widget\"})]\n actual: [ProductRenamed({productId: \"p1\", name: \"Gadget\"})]",
29
- tap: " kind: \"EventsMismatch\"\n expected: \"[ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})]\"\n actual: \"[ProductRenamed({productId: \\\"p1\\\", name: \\\"Gadget\\\"})]\""
30
- },
31
- {
32
- name: "ErrorMismatch",
33
- mismatch: {
34
- TAG: "ErrorMismatch",
35
- expected: "CategoryAlreadyExists",
36
- actual: undefined,
37
- actualEvents: [evA]
38
- },
39
- format: "ErrorMismatch:\n expected error: \"CategoryAlreadyExists\"\n actual error: (none)\n actual events: [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]",
40
- human: " expected: Error(\"CategoryAlreadyExists\")\n actual: Ok([ProductAdded({productId: \"p1\", name: \"Widget\"})])",
41
- tap: " kind: \"ErrorMismatch\"\n expected: \"Error(\\\"CategoryAlreadyExists\\\")\"\n actual: \"Ok([ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})])\""
42
- },
43
- {
44
- name: "StateMismatch",
45
- mismatch: {
46
- TAG: "StateMismatch",
47
- key: "p1",
48
- expected: stateActive,
49
- actual: stateArchived
50
- },
51
- format: "StateMismatch (key: p1):\n expected: {\n \"status\": \"active\"\n}\n actual: {\n \"status\": \"archived\"\n}",
52
- human: " key: \"p1\"\n expected: {status: \"active\"}\n actual: {status: \"archived\"}",
53
- tap: " kind: \"StateMismatch\"\n key: \"p1\"\n expected: \"{status: \\\"active\\\"}\"\n actual: \"{status: \\\"archived\\\"}\""
54
- },
55
- {
56
- name: "NoEventExpected",
57
- mismatch: {
58
- TAG: "NoEventExpected",
59
- actual: [evA]
60
- },
61
- format: "NoEventExpected: expected no events, got:\n [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]",
62
- human: " expected no events\n actual: [ProductAdded({productId: \"p1\", name: \"Widget\"})]",
63
- tap: " kind: \"NoEventExpected\"\n actual: \"[ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})]\""
64
- },
65
- {
66
- name: "TranslateError",
67
- mismatch: {
68
- TAG: "TranslateError",
69
- expected: "boom",
70
- actual: "kaboom"
71
- },
72
- format: "TranslateError:\n expected: boom\n actual: kaboom",
73
- human: " expected: boom\n actual: kaboom",
74
- tap: " kind: \"TranslateError\"\n expected: \"boom\"\n actual: \"kaboom\""
75
- },
76
- {
77
- name: "Throw",
78
- mismatch: {
79
- TAG: "Throw",
80
- error: "unexpected",
81
- stack: "at foo"
82
- },
83
- format: "Throw: unexpected\nat foo",
84
- human: " error: unexpected\nat foo",
85
- tap: " kind: \"Throw\"\n error: \"unexpected\"\n stack: \"at foo\""
86
- },
87
- {
88
- name: "TodoMismatch",
89
- mismatch: {
90
- TAG: "TodoMismatch",
91
- expected: [[
92
- "case-1",
93
- evA
94
- ]],
95
- actual: [[
96
- "case-2",
97
- evB
98
- ]]
99
- },
100
- format: "TodoMismatch:\n expected: [(case-1, {\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n})]\n actual: [(case-2, {\n \"TAG\": \"ProductRenamed\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Gadget\"\n }\n})]",
101
- human: " expected: [(case-1, ProductAdded({productId: \"p1\", name: \"Widget\"}))]\n actual: [(case-2, ProductRenamed({productId: \"p1\", name: \"Gadget\"}))]",
102
- tap: " kind: \"TodoMismatch\"\n expected: \"[(case-1, ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"}))]\"\n actual: \"[(case-2, ProductRenamed({productId: \\\"p1\\\", name: \\\"Gadget\\\"}))]\""
103
- },
104
- {
105
- name: "AppendConditionMismatch",
106
- mismatch: {
107
- TAG: "AppendConditionMismatch",
108
- expected: appendExpected,
109
- actual: appendActual
110
- },
111
- format: "AppendConditionMismatch:\n expected: {\n \"query\": []\n}\n actual: {\n \"query\": [\n {\n \"eventTypes\": [\n \"ProductAdded\"\n ]\n }\n ]\n}",
112
- human: " expected: {query: []}\n actual: {query: [{eventTypes: [\"ProductAdded\"]}]}",
113
- tap: " kind: \"AppendConditionMismatch\"\n expected: \"{query: []}\"\n actual: \"{query: [{eventTypes: [\\\"ProductAdded\\\"]}]}\""
114
- },
115
- {
116
- name: "QueryRowsMismatch",
117
- mismatch: {
118
- TAG: "QueryRowsMismatch",
119
- expected: [evA],
120
- actual: [evB]
121
- },
122
- format: "QueryRowsMismatch:\n expected: [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]\n actual: [{\n \"TAG\": \"ProductRenamed\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Gadget\"\n }\n}]",
123
- human: " expected: [ProductAdded({productId: \"p1\", name: \"Widget\"})]\n actual: [ProductRenamed({productId: \"p1\", name: \"Gadget\"})]",
124
- tap: " kind: \"QueryRowsMismatch\"\n expected: \"[ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})]\"\n actual: \"[ProductRenamed({productId: \\\"p1\\\", name: \\\"Gadget\\\"})]\""
125
- },
126
- {
127
- name: "PublishedActionsMismatch",
128
- mismatch: {
129
- TAG: "PublishedActionsMismatch",
130
- expected: [evA],
131
- actual: [evB]
132
- },
133
- format: "PublishedActionsMismatch:\n expected: [{\n \"TAG\": \"ProductAdded\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Widget\"\n }\n}]\n actual: [{\n \"TAG\": \"ProductRenamed\",\n \"_0\": {\n \"productId\": \"p1\",\n \"name\": \"Gadget\"\n }\n}]",
134
- human: " expected: [ProductAdded({productId: \"p1\", name: \"Widget\"})]\n actual: [ProductRenamed({productId: \"p1\", name: \"Gadget\"})]",
135
- tap: " kind: \"PublishedActionsMismatch\"\n expected: \"[ProductAdded({productId: \\\"p1\\\", name: \\\"Widget\\\"})]\"\n actual: \"[ProductRenamed({productId: \\\"p1\\\", name: \\\"Gadget\\\"})]\""
136
- }
137
- ];
138
-
139
- globalThis.describe("Formatter golden outputs (per-mismatch rendering)", () => {
140
- goldens.forEach(g => {
141
- globalThis.test(g.name + ` — Outcome.format`, () => {
142
- globalThis.expect(Outcome$ReventlessGwt.format(g.mismatch)).toEqual(g.format);
143
- });
144
- globalThis.test(g.name + ` — FormatterHuman.renderMismatch`, () => {
145
- globalThis.expect(FormatterHuman$ReventlessGwt.renderMismatch(g.mismatch)).toEqual(g.human);
146
- });
147
- globalThis.test(g.name + ` — FormatterTap.renderMismatchYaml`, () => {
148
- globalThis.expect(FormatterTap$ReventlessGwt.renderMismatchYaml(g.mismatch)).toEqual(g.tap);
149
- });
150
- });
151
- });
152
-
153
- export {
154
- evA,
155
- evB,
156
- stateActive,
157
- stateArchived,
158
- appendExpected,
159
- appendActual,
160
- goldens,
161
- }
162
- /* evA Not a pure module */
@@ -1,41 +0,0 @@
1
- // Unit test for FormatterVsCode.messagePayload — the failure payload the
2
- // VS Code extension renders. Asserts the `kind` discriminator (the mismatch
3
- // family) is present so a client can gate the apply-expected quick-fix.
4
-
5
- open JestGlobals
6
-
7
- let failingResult = (~mismatch): RunnerTypes.testResult => {
8
- id: "t1",
9
- name: "rejects when category already exists",
10
- describePath: [],
11
- status: RunnerTypes.Fail,
12
- durationMs: 1.0,
13
- location: None,
14
- slice: None,
15
- mismatch,
16
- skipReason: None,
17
- }
18
-
19
- describe("FormatterVsCode.messagePayload", () => {
20
- testPromise("includes the mismatch kind for an EventsMismatch", async () => {
21
- let m = FormatterVsCode.messagePayload(
22
- failingResult(~mismatch=Some(Outcome.EventsMismatch({expected: [], actual: []}))),
23
- )
24
- expect(m.kind)->toEqual(Some("EventsMismatch"))
25
- })
26
-
27
- testPromise("includes the mismatch kind for an ErrorMismatch", async () => {
28
- let m = FormatterVsCode.messagePayload(
29
- failingResult(
30
- ~mismatch=Some(
31
- Outcome.ErrorMismatch({
32
- expected: JSON.String("CategoryAlreadyExists"),
33
- actual: None,
34
- actualEvents: [],
35
- }),
36
- ),
37
- ),
38
- )
39
- expect(m.kind)->toEqual(Some("ErrorMismatch"))
40
- })
41
- })
@@ -1,42 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as FormatterVsCode$ReventlessGwt from "../src/FormatterVsCode.res.mjs";
4
-
5
- function failingResult(mismatch) {
6
- return {
7
- id: "t1",
8
- name: "rejects when category already exists",
9
- describePath: [],
10
- status: "Fail",
11
- durationMs: 1.0,
12
- location: undefined,
13
- slice: undefined,
14
- mismatch: mismatch,
15
- skipReason: undefined
16
- };
17
- }
18
-
19
- globalThis.describe("FormatterVsCode.messagePayload", () => {
20
- globalThis.test("includes the mismatch kind for an EventsMismatch", async () => {
21
- let m = FormatterVsCode$ReventlessGwt.messagePayload(failingResult({
22
- TAG: "EventsMismatch",
23
- expected: [],
24
- actual: []
25
- }));
26
- globalThis.expect(m.kind).toEqual("EventsMismatch");
27
- });
28
- globalThis.test("includes the mismatch kind for an ErrorMismatch", async () => {
29
- let m = FormatterVsCode$ReventlessGwt.messagePayload(failingResult({
30
- TAG: "ErrorMismatch",
31
- expected: "CategoryAlreadyExists",
32
- actual: undefined,
33
- actualEvents: []
34
- }));
35
- globalThis.expect(m.kind).toEqual("ErrorMismatch");
36
- });
37
- });
38
-
39
- export {
40
- failingResult,
41
- }
42
- /* Not a pure module */
@@ -1,66 +0,0 @@
1
- // Unit tests for PlatformRunner.classifyLine — the pure line classifier that turns
2
- // the spawned reventless-local platform's stdout into structured runner events
3
- // (features plan Phase 9). The tap emits sentinel-prefixed JSON; the Domain
4
- // GraphQL "listening" line marks readiness; everything else is a passthrough log.
5
-
6
- open JestGlobals
7
-
8
- describe("PlatformRunner.classifyLine", () => {
9
- testPromise("classifies a tap line as Domain with the parsed payload", async () => {
10
- let line =
11
- `@@RVLESS_EVT@@ {"event":"domainEvent","seq":1,"topic":"CatalogEventTopic","service":"CatalogDcbEventLog","payload":{"event":{"TAG":"ProductAdded"}},"ts":"2026-06-07T00:00:00.000Z"}`
12
- switch PlatformRunner.classifyLine(line) {
13
- | Domain(json) =>
14
- let topic =
15
- json
16
- ->JSON.Decode.object
17
- ->Option.flatMap(d => d->Dict.get("topic"))
18
- ->Option.flatMap(JSON.Decode.string)
19
- expect(topic)->toEqual(Some("CatalogEventTopic"))
20
- | _ => expect("not Domain")->toEqual("Domain")
21
- }
22
- })
23
-
24
- testPromise("a malformed tap line falls back to Log (never throws)", async () => {
25
- switch PlatformRunner.classifyLine("@@RVLESS_EVT@@ {not json") {
26
- | Log(_) => expect(true)->toBe(true)
27
- | _ => expect("not Log")->toEqual("Log")
28
- }
29
- })
30
-
31
- testPromise("classifies the Domain GraphQL listening line as Ready", async () => {
32
- // Real platform output carries ANSI escapes around the [GraphQL:Domain] tag;
33
- // the substring checks see through them.
34
- let line = `12:00:00 I [GraphQL:Domain] listening on http://localhost:4100/graphql (SDL: /sdl)`
35
- switch PlatformRunner.classifyLine(line) {
36
- | Ready => expect(true)->toBe(true)
37
- | _ => expect("not Ready")->toEqual("Ready")
38
- }
39
- })
40
-
41
- testPromise("the Platform (not Domain) listening line is NOT Ready", async () => {
42
- let line = `12:00:00 I [GraphQL:Platform] listening on http://localhost:4101/graphql`
43
- switch PlatformRunner.classifyLine(line) {
44
- | Log(_) => expect(true)->toBe(true)
45
- | _ => expect("expected Log")->toEqual("Log")
46
- }
47
- })
48
-
49
- testPromise("an arbitrary log line is Log", async () => {
50
- switch PlatformRunner.classifyLine("12:00:00 I [Catalog][Aggregate(Product)] handling command") {
51
- | Log(_) => expect(true)->toBe(true)
52
- | _ => expect("expected Log")->toEqual("Log")
53
- }
54
- })
55
-
56
- testPromise("a Log line preserves its ANSI colour/bold escapes (rendered in the terminal)", async () => {
57
- // The child emits coloured logs; the Log payload keeps the ANSI so the
58
- // extension's Pseudoterminal renders colour/bold. Build real ESC (0x1b) bytes.
59
- let esc = String.fromCharCode(27)
60
- let line = `12:00:00 ${esc}[36mI${esc}[0m ${esc}[1m[Catalog]${esc}[0m handling command`
61
- switch PlatformRunner.classifyLine(line) {
62
- | Log(raw) => expect(raw)->toEqual(line)
63
- | _ => expect("expected Log")->toEqual("Log")
64
- }
65
- })
66
- })
@@ -1,85 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
4
- import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
- import * as PlatformRunner$ReventlessGwt from "../src/PlatformRunner.res.mjs";
6
-
7
- globalThis.describe("PlatformRunner.classifyLine", () => {
8
- globalThis.test("classifies a tap line as Domain with the parsed payload", async () => {
9
- let json = PlatformRunner$ReventlessGwt.classifyLine(`@@RVLESS_EVT@@ {"event":"domainEvent","seq":1,"topic":"CatalogEventTopic","service":"CatalogDcbEventLog","payload":{"event":{"TAG":"ProductAdded"}},"ts":"2026-06-07T00:00:00.000Z"}`);
10
- if (typeof json !== "object") {
11
- globalThis.expect("not Domain").toEqual("Domain");
12
- return;
13
- }
14
- if (json.TAG === "Domain") {
15
- let topic = Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(json._0), d => d["topic"]), Stdlib_JSON.Decode.string);
16
- globalThis.expect(topic).toEqual("CatalogEventTopic");
17
- return;
18
- }
19
- globalThis.expect("not Domain").toEqual("Domain");
20
- });
21
- globalThis.test("a malformed tap line falls back to Log (never throws)", async () => {
22
- let match = PlatformRunner$ReventlessGwt.classifyLine("@@RVLESS_EVT@@ {not json");
23
- if (typeof match !== "object") {
24
- globalThis.expect("not Log").toEqual("Log");
25
- return;
26
- }
27
- if (match.TAG === "Domain") {
28
- globalThis.expect("not Log").toEqual("Log");
29
- return;
30
- }
31
- globalThis.expect(true).toBe(true);
32
- });
33
- globalThis.test("classifies the Domain GraphQL listening line as Ready", async () => {
34
- let match = PlatformRunner$ReventlessGwt.classifyLine(`12:00:00 I [GraphQL:Domain] listening on http://localhost:4100/graphql (SDL: /sdl)`);
35
- if (typeof match !== "object") {
36
- globalThis.expect(true).toBe(true);
37
- return;
38
- }
39
- if (match.TAG === "Domain") {
40
- globalThis.expect("not Ready").toEqual("Ready");
41
- return;
42
- }
43
- globalThis.expect("not Ready").toEqual("Ready");
44
- });
45
- globalThis.test("the Platform (not Domain) listening line is NOT Ready", async () => {
46
- let match = PlatformRunner$ReventlessGwt.classifyLine(`12:00:00 I [GraphQL:Platform] listening on http://localhost:4101/graphql`);
47
- if (typeof match !== "object") {
48
- globalThis.expect("expected Log").toEqual("Log");
49
- return;
50
- }
51
- if (match.TAG === "Domain") {
52
- globalThis.expect("expected Log").toEqual("Log");
53
- return;
54
- }
55
- globalThis.expect(true).toBe(true);
56
- });
57
- globalThis.test("an arbitrary log line is Log", async () => {
58
- let match = PlatformRunner$ReventlessGwt.classifyLine("12:00:00 I [Catalog][Aggregate(Product)] handling command");
59
- if (typeof match !== "object") {
60
- globalThis.expect("expected Log").toEqual("Log");
61
- return;
62
- }
63
- if (match.TAG === "Domain") {
64
- globalThis.expect("expected Log").toEqual("Log");
65
- return;
66
- }
67
- globalThis.expect(true).toBe(true);
68
- });
69
- globalThis.test("a Log line preserves its ANSI colour/bold escapes (rendered in the terminal)", async () => {
70
- let esc = String.fromCharCode(27);
71
- let line = `12:00:00 ` + esc + `[36mI` + esc + `[0m ` + esc + `[1m[Catalog]` + esc + `[0m handling command`;
72
- let raw = PlatformRunner$ReventlessGwt.classifyLine(line);
73
- if (typeof raw !== "object") {
74
- globalThis.expect("expected Log").toEqual("Log");
75
- return;
76
- }
77
- if (raw.TAG === "Domain") {
78
- globalThis.expect("expected Log").toEqual("Log");
79
- return;
80
- }
81
- globalThis.expect(raw._0).toEqual(line);
82
- });
83
- });
84
-
85
- /* Not a pure module */
@@ -1,61 +0,0 @@
1
- // Unit tests for PlatformScan.matchPlatform — the pure predicate deciding whether
2
- // a package.json + presence of src/Main.res.mjs make a launchable reventless-local
3
- // platform package, and which serve script to prefer (features plan Phase 9).
4
-
5
- open JestGlobals
6
-
7
- let pkgJson = (~deps=`{}`, ~scripts=`{}`) =>
8
- `{"name":"@app/platform-local","dependencies":${deps},"scripts":${scripts}}`
9
-
10
- describe("PlatformScan.matchPlatform", () => {
11
- testPromise("matches when it depends on reventless-local and Main.res.mjs exists", async () => {
12
- let text = pkgJson(~deps=`{"@reventlessdev/reventless-local":"workspace:*"}`)
13
- switch PlatformScan.matchPlatform(~pkgJsonText=text, ~mainExists=true) {
14
- | Some((name, _)) => expect(name)->toEqual("@app/platform-local")
15
- | None => expect("None")->toEqual("Some")
16
- }
17
- })
18
-
19
- testPromise("no match when src/Main.res.mjs is absent", async () => {
20
- let text = pkgJson(~deps=`{"@reventlessdev/reventless-local":"workspace:*"}`)
21
- expect(PlatformScan.matchPlatform(~pkgJsonText=text, ~mainExists=false)->Option.isNone)->toBe(
22
- true,
23
- )
24
- })
25
-
26
- testPromise("no match without the reventless-local dependency", async () => {
27
- let text = pkgJson(~deps=`{"sury":"^11"}`)
28
- expect(PlatformScan.matchPlatform(~pkgJsonText=text, ~mainExists=true)->Option.isNone)->toBe(
29
- true,
30
- )
31
- })
32
-
33
- testPromise("prefers the serve:memory script over serve", async () => {
34
- let text = pkgJson(
35
- ~deps=`{"@reventlessdev/reventless-local":"workspace:*"}`,
36
- ~scripts=`{"serve":"tsx Main","serve:memory":"REVENTLESS_LOCAL_BACKEND=memory tsx Main"}`,
37
- )
38
- switch PlatformScan.matchPlatform(~pkgJsonText=text, ~mainExists=true) {
39
- | Some((_, serveScript)) => expect(serveScript)->toEqual(Some("serve:memory"))
40
- | None => expect("None")->toEqual("Some")
41
- }
42
- })
43
-
44
- testPromise("falls back to serve when serve:memory is absent", async () => {
45
- let text = pkgJson(
46
- ~deps=`{"@reventlessdev/reventless-local":"workspace:*"}`,
47
- ~scripts=`{"serve":"tsx Main"}`,
48
- )
49
- switch PlatformScan.matchPlatform(~pkgJsonText=text, ~mainExists=true) {
50
- | Some((_, serveScript)) => expect(serveScript)->toEqual(Some("serve"))
51
- | None => expect("None")->toEqual("Some")
52
- }
53
- })
54
-
55
- testPromise("matches via devDependencies too", async () => {
56
- let text = `{"name":"p","devDependencies":{"@reventlessdev/reventless-local":"*"}}`
57
- expect(PlatformScan.matchPlatform(~pkgJsonText=text, ~mainExists=true)->Option.isSome)->toBe(
58
- true,
59
- )
60
- })
61
- })
@@ -1,56 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
- import * as PlatformScan$ReventlessGwt from "../src/PlatformScan.res.mjs";
5
-
6
- function pkgJson(depsOpt, scriptsOpt) {
7
- let deps = depsOpt !== undefined ? depsOpt : `{}`;
8
- let scripts = scriptsOpt !== undefined ? scriptsOpt : `{}`;
9
- return `{"name":"@app/platform-local","dependencies":` + deps + `,"scripts":` + scripts + `}`;
10
- }
11
-
12
- globalThis.describe("PlatformScan.matchPlatform", () => {
13
- globalThis.test("matches when it depends on reventless-local and Main.res.mjs exists", async () => {
14
- let text = pkgJson(`{"@reventlessdev/reventless-local":"workspace:*"}`, undefined);
15
- let match = PlatformScan$ReventlessGwt.matchPlatform(text, true);
16
- if (match !== undefined) {
17
- globalThis.expect(match[0]).toEqual("@app/platform-local");
18
- } else {
19
- globalThis.expect("None").toEqual("Some");
20
- }
21
- });
22
- globalThis.test("no match when src/Main.res.mjs is absent", async () => {
23
- let text = pkgJson(`{"@reventlessdev/reventless-local":"workspace:*"}`, undefined);
24
- globalThis.expect(Stdlib_Option.isNone(PlatformScan$ReventlessGwt.matchPlatform(text, false))).toBe(true);
25
- });
26
- globalThis.test("no match without the reventless-local dependency", async () => {
27
- let text = pkgJson(`{"sury":"^11"}`, undefined);
28
- globalThis.expect(Stdlib_Option.isNone(PlatformScan$ReventlessGwt.matchPlatform(text, true))).toBe(true);
29
- });
30
- globalThis.test("prefers the serve:memory script over serve", async () => {
31
- let text = pkgJson(`{"@reventlessdev/reventless-local":"workspace:*"}`, `{"serve":"tsx Main","serve:memory":"REVENTLESS_LOCAL_BACKEND=memory tsx Main"}`);
32
- let match = PlatformScan$ReventlessGwt.matchPlatform(text, true);
33
- if (match !== undefined) {
34
- globalThis.expect(match[1]).toEqual("serve:memory");
35
- } else {
36
- globalThis.expect("None").toEqual("Some");
37
- }
38
- });
39
- globalThis.test("falls back to serve when serve:memory is absent", async () => {
40
- let text = pkgJson(`{"@reventlessdev/reventless-local":"workspace:*"}`, `{"serve":"tsx Main"}`);
41
- let match = PlatformScan$ReventlessGwt.matchPlatform(text, true);
42
- if (match !== undefined) {
43
- globalThis.expect(match[1]).toEqual("serve");
44
- } else {
45
- globalThis.expect("None").toEqual("Some");
46
- }
47
- });
48
- globalThis.test("matches via devDependencies too", async () => {
49
- globalThis.expect(Stdlib_Option.isSome(PlatformScan$ReventlessGwt.matchPlatform(`{"name":"p","devDependencies":{"@reventlessdev/reventless-local":"*"}}`, true))).toBe(true);
50
- });
51
- });
52
-
53
- export {
54
- pkgJson,
55
- }
56
- /* Not a pure module */