@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,47 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Outcome$ReventlessGwt from "./Outcome.res.mjs";
4
- import * as Collector$ReventlessGwt from "./Collector.res.mjs";
5
-
6
- function skip() {
7
- Collector$ReventlessGwt.markSkipNext();
8
- }
9
-
10
- function only() {
11
- Collector$ReventlessGwt.markOnlyNext();
12
- }
13
-
14
- function xtest(param, name, _body) {
15
- if (Collector$ReventlessGwt.isActive()) {
16
- Collector$ReventlessGwt.markSkipNext();
17
- return Collector$ReventlessGwt.push(undefined, undefined, undefined, name, () => Promise.resolve(Outcome$ReventlessGwt.pass));
18
- } else {
19
- globalThis.xtest(name, () => {});
20
- return;
21
- }
22
- }
23
-
24
- function xdescribe(label, body) {
25
- if (Collector$ReventlessGwt.isActive()) {
26
- Collector$ReventlessGwt.skipDepth.contents = Collector$ReventlessGwt.skipDepth.contents + 1 | 0;
27
- try {
28
- Collector$ReventlessGwt.pushDescribe(label, body);
29
- Collector$ReventlessGwt.skipDepth.contents = Collector$ReventlessGwt.skipDepth.contents - 1 | 0;
30
- return;
31
- } catch (e) {
32
- Collector$ReventlessGwt.skipDepth.contents = Collector$ReventlessGwt.skipDepth.contents - 1 | 0;
33
- throw e;
34
- }
35
- } else {
36
- globalThis.xdescribe(label, body);
37
- return;
38
- }
39
- }
40
-
41
- export {
42
- skip,
43
- only,
44
- xtest,
45
- xdescribe,
46
- }
47
- /* No side effect */
@@ -1,109 +0,0 @@
1
- // Terminal-coloured human formatter. Shipped as the default output for
2
- // `reventless-gwt run`. Uses picocolors for ANSI colours — it is a tiny
3
- // zero-dependency helper that transparently disables colour when stdout
4
- // is not a TTY.
5
-
6
- type colour = string => string
7
- type picocolors = {
8
- red: colour,
9
- green: colour,
10
- yellow: colour,
11
- cyan: colour,
12
- gray: colour,
13
- bold: colour,
14
- dim: colour,
15
- }
16
-
17
- @module("picocolors") external pc: picocolors = "default"
18
-
19
- @val external processStdout: {"write": string => unit} = "process.stdout"
20
- @val external processCwd: unit => string = "process.cwd"
21
- @module("node:path") external pathBasename: string => string = "basename"
22
- @module("node:path") external pathRelative: (string, string) => string = "relative"
23
-
24
- let write = (s: string) => processStdout["write"](s)
25
- let writeLine = (s: string) => write(s ++ "\n")
26
-
27
- let formatFilePath = (abs: string) => {
28
- let base = pathBasename(abs)
29
- let name = if String.endsWith(base, ".res.mjs") {
30
- String.slice(base, ~start=0, ~end=String.length(base) - 8)
31
- } else {
32
- base
33
- }
34
- let rel = pathRelative(processCwd(), abs)
35
- `${name} - ${rel}`
36
- }
37
-
38
- let formatLocation = (loc: option<Collector.location>) =>
39
- switch loc {
40
- | None => ""
41
- | Some(l) => `${l.file}:${Int.toString(l.line)}`
42
- }
43
-
44
- // Frames one normalized field as a terminal line. Labels are padded so values
45
- // align at column 12 (`key:`, `expected:`, `actual:`); `error:` is its own
46
- // shorter form and the `Throw` stack is dumped raw beneath it.
47
- let renderField = (f: MismatchRender.field) =>
48
- switch f {
49
- | Expected(v) => ` expected: ${v}`
50
- | Actual(v) => ` actual: ${v}`
51
- | Key(k) => ` key: "${k}"`
52
- | ExpectedNoEvents => " expected no events"
53
- | Error(e) => ` error: ${e}`
54
- | Stack(s) => s
55
- }
56
-
57
- let renderMismatch = (m: Outcome.mismatch) =>
58
- MismatchRender.normalize(m).fields->Array.map(renderField)->Array.join("\n")
59
-
60
- let emitTest = (t: RunnerTypes.testResult) => {
61
- let path = t.describePath->Array.join(" > ")
62
- let full = path == "" ? t.name : `${path} > ${t.name}`
63
- let loc = formatLocation(t.location)
64
- let locStr = loc == "" ? "" : ` ${pc.dim(loc)}`
65
- switch t.status {
66
- | Pass => writeLine(` ${pc.green("✓")} ${full}${locStr}`)
67
- | Skip =>
68
- writeLine(
69
- ` ${pc.yellow("○")} ${full}${locStr} ${pc.dim(
70
- t.skipReason->Option.getOr("skipped"),
71
- )}`,
72
- )
73
- | Fail => {
74
- writeLine(` ${pc.red("✗")} ${pc.bold(full)}${locStr}`)
75
- switch t.mismatch {
76
- | Some(m) => {
77
- writeLine("")
78
- writeLine(renderMismatch(m))
79
- let hint = Hint.forMismatch(~slice=?t.slice, m)
80
- writeLine("")
81
- writeLine(` ${pc.cyan(Hint.format(hint))}`)
82
- writeLine("")
83
- }
84
- | None => ()
85
- }
86
- }
87
- }
88
- }
89
-
90
- let emitFile = (f: RunnerTypes.fileResult) => {
91
- writeLine("")
92
- writeLine(pc.bold(formatFilePath(f.path)))
93
- f.tests->Array.forEach(emitTest)
94
- }
95
-
96
- let emitSummary = (s: RunnerTypes.summary) => {
97
- writeLine("")
98
- let line = `Tests: ${Int.toString(s.total)} ${pc.green(
99
- Int.toString(s.passed) ++ " passed",
100
- )} ${pc.red(Int.toString(s.failed) ++ " failed")} ${pc.yellow(
101
- Int.toString(s.skipped) ++ " skipped",
102
- )} (${Float.toString(s.durationMs)} ms)`
103
- writeLine(line)
104
- }
105
-
106
- let emit = (r: RunnerTypes.runResult) => {
107
- r.files->Array.forEach(emitFile)
108
- emitSummary(r.summary)
109
- }
@@ -1,115 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Nodepath from "node:path";
4
- import Picocolors from "picocolors";
5
- import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
- import * as Hint$ReventlessGwt from "./Hint.res.mjs";
7
- import * as MismatchRender$ReventlessGwt from "./MismatchRender.res.mjs";
8
-
9
- function write(s) {
10
- process.stdout.write(s);
11
- }
12
-
13
- function writeLine(s) {
14
- process.stdout.write(s + "\n");
15
- }
16
-
17
- function formatFilePath(abs) {
18
- let base = Nodepath.basename(abs);
19
- let name = base.endsWith(".res.mjs") ? base.slice(0, base.length - 8 | 0) : base;
20
- let rel = Nodepath.relative(process.cwd(), abs);
21
- return name + ` - ` + rel;
22
- }
23
-
24
- function formatLocation(loc) {
25
- if (loc !== undefined) {
26
- return loc.file + `:` + loc.line.toString();
27
- } else {
28
- return "";
29
- }
30
- }
31
-
32
- function renderField(f) {
33
- if (typeof f !== "object") {
34
- return " expected no events";
35
- }
36
- switch (f.TAG) {
37
- case "Expected" :
38
- return ` expected: ` + f._0;
39
- case "Actual" :
40
- return ` actual: ` + f._0;
41
- case "Key" :
42
- return ` key: "` + f._0 + `"`;
43
- case "Error" :
44
- return ` error: ` + f._0;
45
- case "Stack" :
46
- return f._0;
47
- }
48
- }
49
-
50
- function renderMismatch(m) {
51
- return MismatchRender$ReventlessGwt.normalize(m).fields.map(renderField).join("\n");
52
- }
53
-
54
- function emitTest(t) {
55
- let path = t.describePath.join(" > ");
56
- let full = path === "" ? t.name : path + ` > ` + t.name;
57
- let loc = formatLocation(t.location);
58
- let locStr = loc === "" ? "" : ` ` + Picocolors.dim(loc);
59
- let match = t.status;
60
- switch (match) {
61
- case "Pass" :
62
- let s = ` ` + Picocolors.green("✓") + ` ` + full + locStr;
63
- return process.stdout.write(s + "\n");
64
- case "Fail" :
65
- let s$1 = ` ` + Picocolors.red("✗") + ` ` + Picocolors.bold(full) + locStr;
66
- process.stdout.write(s$1 + "\n");
67
- let m = t.mismatch;
68
- if (m === undefined) {
69
- return;
70
- }
71
- process.stdout.write("\n");
72
- let s$2 = renderMismatch(m);
73
- process.stdout.write(s$2 + "\n");
74
- let hint = Hint$ReventlessGwt.forMismatch(t.slice, m);
75
- process.stdout.write("\n");
76
- let s$3 = ` ` + Picocolors.cyan(Hint$ReventlessGwt.format(hint));
77
- process.stdout.write(s$3 + "\n");
78
- return process.stdout.write("\n");
79
- case "Skip" :
80
- let s$4 = ` ` + Picocolors.yellow("○") + ` ` + full + locStr + ` ` + Picocolors.dim(Stdlib_Option.getOr(t.skipReason, "skipped"));
81
- return process.stdout.write(s$4 + "\n");
82
- }
83
- }
84
-
85
- function emitFile(f) {
86
- process.stdout.write("\n");
87
- let s = Picocolors.bold(formatFilePath(f.path));
88
- process.stdout.write(s + "\n");
89
- f.tests.forEach(emitTest);
90
- }
91
-
92
- function emitSummary(s) {
93
- process.stdout.write("\n");
94
- let s$1 = `Tests: ` + s.total.toString() + ` ` + Picocolors.green(s.passed.toString() + " passed") + ` ` + Picocolors.red(s.failed.toString() + " failed") + ` ` + Picocolors.yellow(s.skipped.toString() + " skipped") + ` (` + s.durationMs.toString() + ` ms)`;
95
- process.stdout.write(s$1 + "\n");
96
- }
97
-
98
- function emit(r) {
99
- r.files.forEach(emitFile);
100
- emitSummary(r.summary);
101
- }
102
-
103
- export {
104
- write,
105
- writeLine,
106
- formatFilePath,
107
- formatLocation,
108
- renderField,
109
- renderMismatch,
110
- emitTest,
111
- emitFile,
112
- emitSummary,
113
- emit,
114
- }
115
- /* node:path Not a pure module */
@@ -1,264 +0,0 @@
1
- // Structured JSON formatter — the AI loop's primary input and the substrate
2
- // for any programmatic consumer. Ships both a single-envelope mode and an
3
- // NDJSON streaming mode (`--stream`). Shape matches §3.3 of
4
- // `docs/analysis/given-when-then-specifications.md`.
5
-
6
- // 1.1.0 — additive: `PublishedActionsMismatch` mismatch kind for the
7
- // Delegate_GWT / cross-plugin Flow_GWT boundary steps.
8
- // The default the emitted envelope carries; the `--schema-version` CLI flag
9
- // overrides it (threaded through `emit` / `streamRunStart`) so a consumer can
10
- // pin the schema version its AI prompt was built against.
11
- let defaultSchemaVersion = "1.1.0"
12
-
13
- @val external processStdout: {"write": string => unit} = "process.stdout"
14
- let write = (s: string) => processStdout["write"](s)
15
- let writeLine = (s: string) => write(s ++ "\n")
16
-
17
- // Re-render a JSON value as a dual-rendered `{type, payload, rendered}` entry.
18
- let renderValue = (j: JSON.t): JSON.t => {
19
- let obj = Dict.make()
20
- switch j {
21
- | Object(dict) =>
22
- switch dict->Dict.get("TAG") {
23
- | Some(String(tag)) => {
24
- obj->Dict.set("type", JSON.Encode.string(tag))
25
- let payloadKeys =
26
- dict
27
- ->Dict.keysToArray
28
- ->Array.filter(k => k != "TAG" && String.startsWith(k, "_"))
29
- let payload = switch payloadKeys {
30
- | [] => JSON.Encode.null
31
- | ["_0"] =>
32
- dict->Dict.get("_0")->Option.getOr(JSON.Encode.null)
33
- | _ => {
34
- let payloadDict = Dict.make()
35
- payloadKeys->Array.forEach(k =>
36
- payloadDict->Dict.set(
37
- k,
38
- dict->Dict.get(k)->Option.getOr(JSON.Encode.null),
39
- )
40
- )
41
- JSON.Encode.object(payloadDict)
42
- }
43
- }
44
- obj->Dict.set("payload", payload)
45
- }
46
- | _ => {
47
- obj->Dict.set("type", JSON.Encode.null)
48
- obj->Dict.set("payload", j)
49
- }
50
- }
51
- | String(s) => {
52
- obj->Dict.set("type", JSON.Encode.string(s))
53
- obj->Dict.set("payload", JSON.Encode.null)
54
- }
55
- | _ => {
56
- obj->Dict.set("type", JSON.Encode.null)
57
- obj->Dict.set("payload", j)
58
- }
59
- }
60
- obj->Dict.set("rendered", JSON.Encode.string(RenderRescript.render(j)))
61
- JSON.Encode.object(obj)
62
- }
63
-
64
- let renderValues = (arr: array<JSON.t>): JSON.t =>
65
- arr->Array.map(renderValue)->JSON.Encode.array
66
-
67
- let mismatchJson = (m: Outcome.mismatch, slice: option<string>): JSON.t => {
68
- let obj = Dict.make()
69
- obj->Dict.set("kind", JSON.Encode.string(Outcome.kindName(m)))
70
- let optVal = o =>
71
- switch o {
72
- | Some(v) => renderValue(v)
73
- | None => JSON.Encode.null
74
- }
75
- switch m {
76
- | EventsMismatch({expected, actual}) => {
77
- obj->Dict.set("expected", renderValues(expected))
78
- obj->Dict.set("actual", renderValues(actual))
79
- obj->Dict.set("fieldDiff", Diff.toJsonArray(Diff.diffArrays(expected, actual)))
80
- }
81
- | ErrorMismatch({expected, actual, actualEvents}) => {
82
- obj->Dict.set("expected", renderValue(expected))
83
- obj->Dict.set("actual", optVal(actual))
84
- obj->Dict.set("actualEvents", renderValues(actualEvents))
85
- }
86
- | StateMismatch({key, expected, actual}) => {
87
- obj->Dict.set("key", JSON.Encode.string(key))
88
- obj->Dict.set("expected", optVal(expected))
89
- obj->Dict.set("actual", optVal(actual))
90
- let eJson = expected->Option.getOr(JSON.Encode.null)
91
- let aJson = actual->Option.getOr(JSON.Encode.null)
92
- obj->Dict.set("fieldDiff", Diff.toJsonArray(Diff.diff(eJson, aJson)))
93
- }
94
- | NoEventExpected({actual}) => obj->Dict.set("actual", renderValues(actual))
95
- | TodoMismatch({expected, actual}) => {
96
- let pairArr = pairs =>
97
- pairs
98
- ->Array.map(((id, v)) => {
99
- let d = Dict.make()
100
- d->Dict.set("id", JSON.Encode.string(id))
101
- d->Dict.set("value", renderValue(v))
102
- JSON.Encode.object(d)
103
- })
104
- ->JSON.Encode.array
105
- obj->Dict.set("expected", pairArr(expected))
106
- obj->Dict.set("actual", pairArr(actual))
107
- }
108
- | AppendConditionMismatch({expected, actual}) => {
109
- obj->Dict.set("expected", expected)
110
- obj->Dict.set("actual", actual)
111
- }
112
- | TranslateError({expected, actual}) => {
113
- obj->Dict.set("expected", JSON.Encode.string(expected))
114
- obj->Dict.set(
115
- "actual",
116
- actual->Option.mapOr(JSON.Encode.null, JSON.Encode.string),
117
- )
118
- }
119
- | QueryRowsMismatch({expected, actual}) => {
120
- obj->Dict.set("expected", renderValues(expected))
121
- obj->Dict.set("actual", renderValues(actual))
122
- obj->Dict.set("fieldDiff", Diff.toJsonArray(Diff.diffArrays(expected, actual)))
123
- }
124
- | PublishedActionsMismatch({expected, actual}) => {
125
- obj->Dict.set("expected", renderValues(expected))
126
- obj->Dict.set("actual", renderValues(actual))
127
- obj->Dict.set("fieldDiff", Diff.toJsonArray(Diff.diffArrays(expected, actual)))
128
- }
129
- | Throw({error, stack}) => {
130
- obj->Dict.set("error", JSON.Encode.string(error))
131
- obj->Dict.set("stack", JSON.Encode.string(stack))
132
- }
133
- }
134
- let hint = Hint.forMismatch(~slice?, m)
135
- obj->Dict.set("hint", Hint.toJson(hint))
136
- JSON.Encode.object(obj)
137
- }
138
-
139
- let locationJson = (loc: option<Collector.location>): JSON.t =>
140
- switch loc {
141
- | None => JSON.Encode.null
142
- | Some(l) => {
143
- let d = Dict.make()
144
- d->Dict.set("file", JSON.Encode.string(l.file))
145
- d->Dict.set("line", JSON.Encode.int(l.line))
146
- d->Dict.set("column", JSON.Encode.int(l.column))
147
- JSON.Encode.object(d)
148
- }
149
- }
150
-
151
- let testJson = (t: RunnerTypes.testResult): JSON.t => {
152
- let d = Dict.make()
153
- d->Dict.set("id", JSON.Encode.string(t.id))
154
- d->Dict.set("name", JSON.Encode.string(t.name))
155
- d->Dict.set(
156
- "describePath",
157
- t.describePath->Array.map(JSON.Encode.string)->JSON.Encode.array,
158
- )
159
- d->Dict.set("status", JSON.Encode.string(RunnerTypes.statusString(t.status)))
160
- d->Dict.set("durationMs", JSON.Encode.float(t.durationMs))
161
- d->Dict.set("location", locationJson(t.location))
162
- switch t.mismatch {
163
- | Some(m) => d->Dict.set("mismatch", mismatchJson(m, t.slice))
164
- | None => ()
165
- }
166
- switch t.skipReason {
167
- | Some(r) => d->Dict.set("skipReason", JSON.Encode.string(r))
168
- | None => ()
169
- }
170
- JSON.Encode.object(d)
171
- }
172
-
173
- let fileJson = (f: RunnerTypes.fileResult): JSON.t => {
174
- let d = Dict.make()
175
- d->Dict.set("path", JSON.Encode.string(f.path))
176
- d->Dict.set("tests", f.tests->Array.map(testJson)->JSON.Encode.array)
177
- JSON.Encode.object(d)
178
- }
179
-
180
- let summaryJson = (s: RunnerTypes.summary): JSON.t => {
181
- let d = Dict.make()
182
- d->Dict.set("total", JSON.Encode.int(s.total))
183
- d->Dict.set("passed", JSON.Encode.int(s.passed))
184
- d->Dict.set("failed", JSON.Encode.int(s.failed))
185
- d->Dict.set("skipped", JSON.Encode.int(s.skipped))
186
- d->Dict.set("files", JSON.Encode.int(s.files))
187
- JSON.Encode.object(d)
188
- }
189
-
190
- let envelope = (
191
- r: RunnerTypes.runResult,
192
- ~toolVersion: string,
193
- ~schemaVersion: string,
194
- ): JSON.t => {
195
- let d = Dict.make()
196
- d->Dict.set("schemaVersion", JSON.Encode.string(schemaVersion))
197
- d->Dict.set("tool", JSON.Encode.string("reventless-gwt"))
198
- d->Dict.set("toolVersion", JSON.Encode.string(toolVersion))
199
- d->Dict.set("startedAt", JSON.Encode.string(r.summary.startedAt))
200
- d->Dict.set("durationMs", JSON.Encode.float(r.summary.durationMs))
201
- d->Dict.set("summary", summaryJson(r.summary))
202
- d->Dict.set("files", r.files->Array.map(fileJson)->JSON.Encode.array)
203
- JSON.Encode.object(d)
204
- }
205
-
206
- let emit = (r: RunnerTypes.runResult, ~toolVersion: string, ~schemaVersion=defaultSchemaVersion) =>
207
- write(JSON.stringify(envelope(r, ~toolVersion, ~schemaVersion), ~space=2) ++ "\n")
208
-
209
- // Streaming variant — NDJSON events.
210
- let streamRunStart = (~toolVersion: string, ~startedAt: string, ~schemaVersion=defaultSchemaVersion) => {
211
- let d = Dict.make()
212
- d->Dict.set("type", JSON.Encode.string("runStarted"))
213
- d->Dict.set("schemaVersion", JSON.Encode.string(schemaVersion))
214
- d->Dict.set("toolVersion", JSON.Encode.string(toolVersion))
215
- d->Dict.set("at", JSON.Encode.string(startedAt))
216
- writeLine(JSON.stringify(JSON.Encode.object(d)))
217
- }
218
-
219
- let streamFileStart = (path: string) => {
220
- let d = Dict.make()
221
- d->Dict.set("type", JSON.Encode.string("fileStarted"))
222
- d->Dict.set("path", JSON.Encode.string(path))
223
- writeLine(JSON.stringify(JSON.Encode.object(d)))
224
- }
225
-
226
- let streamTest = (t: RunnerTypes.testResult) => {
227
- let d = Dict.make()
228
- d->Dict.set("type", JSON.Encode.string("testResult"))
229
- let tj = testJson(t)
230
- // Fold testJson's object keys into the envelope.
231
- switch tj {
232
- | Object(inner) =>
233
- inner->Dict.keysToArray->Array.forEach(k =>
234
- d->Dict.set(k, inner->Dict.getUnsafe(k))
235
- )
236
- | _ => ()
237
- }
238
- writeLine(JSON.stringify(JSON.Encode.object(d)))
239
- }
240
-
241
- let streamFileFinished = (f: RunnerTypes.fileResult) => {
242
- let passed = ref(0)
243
- let failed = ref(0)
244
- f.tests->Array.forEach(t =>
245
- switch t.status {
246
- | Pass => passed := passed.contents + 1
247
- | Fail => failed := failed.contents + 1
248
- | Skip => ()
249
- }
250
- )
251
- let d = Dict.make()
252
- d->Dict.set("type", JSON.Encode.string("fileFinished"))
253
- d->Dict.set("path", JSON.Encode.string(f.path))
254
- d->Dict.set("passed", JSON.Encode.int(passed.contents))
255
- d->Dict.set("failed", JSON.Encode.int(failed.contents))
256
- writeLine(JSON.stringify(JSON.Encode.object(d)))
257
- }
258
-
259
- let streamRunEnd = (r: RunnerTypes.runResult) => {
260
- let d = Dict.make()
261
- d->Dict.set("type", JSON.Encode.string("runFinished"))
262
- d->Dict.set("summary", summaryJson(r.summary))
263
- writeLine(JSON.stringify(JSON.Encode.object(d)))
264
- }