@reventlessdev/reventless-gwt 1.0.0-alpha.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +698 -0
- package/LICENSE +202 -0
- package/bin/reventless-dev.mjs +21 -0
- package/package.json +54 -0
- package/rescript.json +36 -0
- package/src/.gwtignore +10 -0
- package/src/Automation_GWT.res +207 -0
- package/src/Automation_GWT.res.mjs +160 -0
- package/src/Behavior_GWT.res +603 -0
- package/src/Behavior_GWT.res.mjs +426 -0
- package/src/Bind.res +29 -0
- package/src/Bind.res.mjs +22 -0
- package/src/BuildClassifier.res +137 -0
- package/src/BuildClassifier.res.mjs +136 -0
- package/src/Cancellation.res +31 -0
- package/src/Cancellation.res.mjs +45 -0
- package/src/ChildProcess.res +84 -0
- package/src/ChildProcess.res.mjs +92 -0
- package/src/Cli.res +671 -0
- package/src/Cli.res.mjs +754 -0
- package/src/Collector.res +201 -0
- package/src/Collector.res.mjs +215 -0
- package/src/ComponentMeta.res +104 -0
- package/src/ComponentMeta.res.mjs +120 -0
- package/src/ComponentScan.res +103 -0
- package/src/ComponentScan.res.mjs +105 -0
- package/src/Delegate_GWT.res +303 -0
- package/src/Delegate_GWT.res.mjs +372 -0
- package/src/Diff.res +91 -0
- package/src/Diff.res.mjs +98 -0
- package/src/Discovery.res +105 -0
- package/src/Discovery.res.mjs +103 -0
- package/src/DomainDeadCode.res +93 -0
- package/src/DomainDeadCode.res.mjs +69 -0
- package/src/DomainGraph.res +0 -0
- package/src/DomainGraph.res.mjs +0 -0
- package/src/EventMapping_GWT.res +29 -0
- package/src/EventMapping_GWT.res.mjs +44 -0
- package/src/Filter.res +36 -0
- package/src/Filter.res.mjs +40 -0
- package/src/Flow_GWT.res +664 -0
- package/src/Flow_GWT.res.mjs +604 -0
- package/src/FormatterHuman.res +138 -0
- package/src/FormatterHuman.res.mjs +122 -0
- package/src/FormatterJson.res +257 -0
- package/src/FormatterJson.res.mjs +320 -0
- package/src/FormatterJunit.res +93 -0
- package/src/FormatterJunit.res.mjs +90 -0
- package/src/FormatterTap.res +139 -0
- package/src/FormatterTap.res.mjs +149 -0
- package/src/FormatterVsCode.res +362 -0
- package/src/FormatterVsCode.res.mjs +564 -0
- package/src/Hint.res +119 -0
- package/src/Hint.res.mjs +124 -0
- package/src/InboundTranslation_GWT.res +83 -0
- package/src/InboundTranslation_GWT.res.mjs +94 -0
- package/src/JestBind.res +70 -0
- package/src/JestBind.res.mjs +63 -0
- package/src/Loader.res +24 -0
- package/src/Loader.res.mjs +23 -0
- package/src/LocalHost.res +135 -0
- package/src/LocalHost.res.mjs +127 -0
- package/src/Mapping_GWT.res +474 -0
- package/src/Mapping_GWT.res.mjs +322 -0
- package/src/MultiSourceProjection_GWT.res +316 -0
- package/src/MultiSourceProjection_GWT.res.mjs +354 -0
- package/src/OutboundTranslation_GWT.res +238 -0
- package/src/OutboundTranslation_GWT.res.mjs +186 -0
- package/src/Outcome.res +161 -0
- package/src/Outcome.res.mjs +140 -0
- package/src/PackageScan.res +80 -0
- package/src/PackageScan.res.mjs +81 -0
- package/src/PlatformRunner.res +160 -0
- package/src/PlatformRunner.res.mjs +155 -0
- package/src/PlatformScan.res +138 -0
- package/src/PlatformScan.res.mjs +131 -0
- package/src/ProcessManager.res +91 -0
- package/src/ProcessManager.res.mjs +80 -0
- package/src/Projection_GWT.res +312 -0
- package/src/Projection_GWT.res.mjs +332 -0
- package/src/Query_GWT.res +379 -0
- package/src/Query_GWT.res.mjs +367 -0
- package/src/RenderRescript.res +125 -0
- package/src/RenderRescript.res.mjs +141 -0
- package/src/RunnerTypes.res +68 -0
- package/src/RunnerTypes.res.mjs +60 -0
- package/src/SideEffect_GWT.res +157 -0
- package/src/SideEffect_GWT.res.mjs +113 -0
- package/src/StateChange/ExternalAddCategorySlice.res +25 -0
- package/src/StateChange/ExternalAddCategorySlice.res.mjs +34 -0
- package/src/StateChange/ExternalAddCategorySlice_Behavior.res +19 -0
- package/src/StateChange/ExternalAddCategorySlice_Behavior.res.mjs +46 -0
- package/src/StateChange/WithFixtures.res +22 -0
- package/src/StateChange/WithFixtures.res.mjs +31 -0
- package/src/StateChange/WithFixtures_Behavior.res +17 -0
- package/src/StateChange/WithFixtures_Behavior.res.mjs +37 -0
- package/src/StateChange/WithManualOpen.res +23 -0
- package/src/StateChange/WithManualOpen.res.mjs +31 -0
- package/src/StateChange/WithManualOpen_Behavior.res +17 -0
- package/src/StateChange/WithManualOpen_Behavior.res.mjs +37 -0
- package/src/StubRuntime.res +53 -0
- package/src/StubRuntime.res.mjs +54 -0
- package/src/TestFixtures.res +16 -0
- package/src/TestFixtures.res.mjs +34 -0
- package/src/Watch.res +92 -0
- package/src/Watch.res.mjs +83 -0
- package/src/WatcherProbe.res +48 -0
- package/src/WatcherProbe.res.mjs +46 -0
- package/tests/AutomationGwtTest.res +71 -0
- package/tests/AutomationGwtTest.res.mjs +189 -0
- package/tests/BuildClassifierTest.res +94 -0
- package/tests/BuildClassifierTest.res.mjs +132 -0
- package/tests/ComponentMetaTest.res +52 -0
- package/tests/ComponentMetaTest.res.mjs +57 -0
- package/tests/DelegateGwtTest.res +487 -0
- package/tests/DelegateGwtTest.res.mjs +891 -0
- package/tests/DiscoveryTest.res +42 -0
- package/tests/DiscoveryTest.res.mjs +43 -0
- package/tests/DomainDeadCodeTest.res +116 -0
- package/tests/DomainDeadCodeTest.res.mjs +155 -0
- package/tests/DomainGraphTest.res +365 -0
- package/tests/DomainGraphTest.res.mjs +413 -0
- package/tests/FlowAggregateGwtTest.res +169 -0
- package/tests/FlowAggregateGwtTest.res.mjs +269 -0
- package/tests/FlowCrossPluginGwtTest.res +340 -0
- package/tests/FlowCrossPluginGwtTest.res.mjs +798 -0
- package/tests/FlowGwtTest.res +222 -0
- package/tests/FlowGwtTest.res.mjs +432 -0
- package/tests/FormatterVsCodeMessageTest.res +41 -0
- package/tests/FormatterVsCodeMessageTest.res.mjs +42 -0
- package/tests/InboundTranslationGwtTest.res +34 -0
- package/tests/InboundTranslationGwtTest.res.mjs +98 -0
- package/tests/LocalHostIntegration.res +70 -0
- package/tests/LocalHostIntegration.res.mjs +64 -0
- package/tests/LocalHostTest.res +71 -0
- package/tests/LocalHostTest.res.mjs +63 -0
- package/tests/MappingGwtTest.res +348 -0
- package/tests/MappingGwtTest.res.mjs +592 -0
- package/tests/OutboundTranslationGwtTest.res +59 -0
- package/tests/OutboundTranslationGwtTest.res.mjs +138 -0
- package/tests/PlatformRunnerTest.res +66 -0
- package/tests/PlatformRunnerTest.res.mjs +85 -0
- package/tests/PlatformScanTest.res +61 -0
- package/tests/PlatformScanTest.res.mjs +56 -0
- package/tests/QueryGwtTest.res +161 -0
- package/tests/QueryGwtTest.res.mjs +314 -0
- package/tests/QueryResolverGwtTest.res +71 -0
- package/tests/QueryResolverGwtTest.res.mjs +136 -0
- package/tests/RunnerUnitTest.res +219 -0
- package/tests/RunnerUnitTest.res.mjs +244 -0
- package/tests/SideEffect/FakeOrderNotification.res +23 -0
- package/tests/SideEffect/FakeOrderNotification.res.mjs +36 -0
- package/tests/SideEffect/FakeOrderNotificationGwtTest.res +35 -0
- package/tests/SideEffect/FakeOrderNotificationGwtTest.res.mjs +73 -0
- package/tests/SideEffect/MockEmail.res +18 -0
- package/tests/SideEffect/MockEmail.res.mjs +47 -0
- package/tests/StateChange/ExternalAddCategorySlice_GWT.res +27 -0
- package/tests/StateChange/ExternalAddCategorySlice_GWT.res.mjs +70 -0
- package/tests/StateChange/WithFixtures_Fixtures.res +9 -0
- package/tests/StateChange/WithFixtures_Fixtures.res.mjs +20 -0
- package/tests/StateChange/WithFixtures_GWT.res +23 -0
- package/tests/StateChange/WithFixtures_GWT.res.mjs +56 -0
- package/tests/StateChange/WithManualOpen_Fixtures.res +7 -0
- package/tests/StateChange/WithManualOpen_Fixtures.res.mjs +20 -0
- package/tests/StateChange/WithManualOpen_GWT.res +17 -0
- package/tests/StateChange/WithManualOpen_GWT.res.mjs +56 -0
- package/tests/StateChangeSliceGwtTest.res +160 -0
- package/tests/StateChangeSliceGwtTest.res.mjs +280 -0
- package/tests/StateViewSliceGwtTest.res +64 -0
- package/tests/StateViewSliceGwtTest.res.mjs +161 -0
- package/tests/WatchDebounceTest.res +78 -0
- package/tests/WatchDebounceTest.res.mjs +97 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// Module-level collector used by the CLI runner.
|
|
2
|
+
//
|
|
3
|
+
// When the CLI loads a test file via dynamic import, each `describe`/`test`
|
|
4
|
+
// call routes through `Bind` or `JestBind` and pushes an entry into this
|
|
5
|
+
// collector. After the import resolves (all registrations complete), the CLI
|
|
6
|
+
// drains the entries, executes each body asynchronously, and feeds the results
|
|
7
|
+
// into a formatter.
|
|
8
|
+
//
|
|
9
|
+
// Activation is toggled by the CLI — when inactive, `JestBind` falls back to
|
|
10
|
+
// Jest globals, so existing Jest test runs are unaffected.
|
|
11
|
+
|
|
12
|
+
type status = Skipped | Runnable | Only
|
|
13
|
+
|
|
14
|
+
type location = {
|
|
15
|
+
file: string,
|
|
16
|
+
line: int,
|
|
17
|
+
column: int,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type entry = {
|
|
21
|
+
id: string,
|
|
22
|
+
name: string,
|
|
23
|
+
describePath: array<string>,
|
|
24
|
+
slice: option<string>,
|
|
25
|
+
body: unit => promise<Outcome.outcome>,
|
|
26
|
+
status: status,
|
|
27
|
+
location: option<location>,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let active = ref(false)
|
|
31
|
+
let describeStack: ref<array<string>> = ref([])
|
|
32
|
+
let entries: ref<array<entry>> = ref([])
|
|
33
|
+
let hasOnly = ref(false)
|
|
34
|
+
let skipNext = ref(false)
|
|
35
|
+
let onlyNext = ref(false)
|
|
36
|
+
let skipDepth = ref(0)
|
|
37
|
+
let currentFile: ref<option<string>> = ref(None)
|
|
38
|
+
|
|
39
|
+
let activate = () => {
|
|
40
|
+
active := true
|
|
41
|
+
describeStack := []
|
|
42
|
+
entries := []
|
|
43
|
+
hasOnly := false
|
|
44
|
+
skipNext := false
|
|
45
|
+
onlyNext := false
|
|
46
|
+
currentFile := None
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let deactivate = () => active := false
|
|
50
|
+
let isActive = () => active.contents
|
|
51
|
+
|
|
52
|
+
let setCurrentFile = path => currentFile := Some(path)
|
|
53
|
+
let getCurrentFile = () => currentFile.contents
|
|
54
|
+
|
|
55
|
+
let markSkipNext = () => skipNext := true
|
|
56
|
+
let markOnlyNext = () => {
|
|
57
|
+
onlyNext := true
|
|
58
|
+
hasOnly := true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let pushDescribe = (label: string, body: unit => unit) => {
|
|
62
|
+
describeStack := Array.concat(describeStack.contents, [label])
|
|
63
|
+
body()
|
|
64
|
+
let ds = describeStack.contents
|
|
65
|
+
describeStack := ds->Array.slice(~start=0, ~end=ds->Array.length - 1)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let buildId = (describePath, name) => {
|
|
69
|
+
let prefix = describePath->Array.join("::")
|
|
70
|
+
prefix == "" ? name : prefix ++ "::" ++ name
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let push = (
|
|
74
|
+
~slice=?,
|
|
75
|
+
~location=?,
|
|
76
|
+
name: string,
|
|
77
|
+
body: unit => promise<Outcome.outcome>,
|
|
78
|
+
) => {
|
|
79
|
+
let status = if skipDepth.contents > 0 {
|
|
80
|
+
Skipped
|
|
81
|
+
} else if skipNext.contents {
|
|
82
|
+
skipNext := false
|
|
83
|
+
Skipped
|
|
84
|
+
} else if onlyNext.contents {
|
|
85
|
+
onlyNext := false
|
|
86
|
+
Only
|
|
87
|
+
} else {
|
|
88
|
+
Runnable
|
|
89
|
+
}
|
|
90
|
+
let describePath = describeStack.contents
|
|
91
|
+
let id = buildId(describePath, name)
|
|
92
|
+
let entry = {
|
|
93
|
+
id,
|
|
94
|
+
name,
|
|
95
|
+
describePath,
|
|
96
|
+
slice,
|
|
97
|
+
body,
|
|
98
|
+
status,
|
|
99
|
+
location,
|
|
100
|
+
}
|
|
101
|
+
entries := Array.concat(entries.contents, [entry])
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// A `todo` placeholder: a spec-less slice still ships a discoverable, compiling
|
|
105
|
+
// `_GWT.res`. Register it as a Skipped entry with a no-op passing body so the
|
|
106
|
+
// CLI runner lists it without executing or failing.
|
|
107
|
+
let pushTodo = (name: string) => {
|
|
108
|
+
let describePath = describeStack.contents
|
|
109
|
+
let id = buildId(describePath, name)
|
|
110
|
+
let entry = {
|
|
111
|
+
id,
|
|
112
|
+
name,
|
|
113
|
+
describePath,
|
|
114
|
+
slice: None,
|
|
115
|
+
body: () => Promise.resolve(Outcome.pass),
|
|
116
|
+
status: Skipped,
|
|
117
|
+
location: None,
|
|
118
|
+
}
|
|
119
|
+
entries := Array.concat(entries.contents, [entry])
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let drain = () => {
|
|
123
|
+
let result = entries.contents
|
|
124
|
+
entries := []
|
|
125
|
+
describeStack := []
|
|
126
|
+
result
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Parse a single V8 stack frame line like:
|
|
130
|
+
// " at body (/abs/path/File.res.mjs:42:13)"
|
|
131
|
+
// " at /abs/path/File.res.mjs:42:13"
|
|
132
|
+
// Returns (file, line, column) if the frame belongs to a non-internal user file.
|
|
133
|
+
let parseFrame = (frame: string): option<location> => {
|
|
134
|
+
let trimmed = frame->String.trim
|
|
135
|
+
let body = if String.startsWith(trimmed, "at ") {
|
|
136
|
+
String.slice(trimmed, ~start=3, ~end=String.length(trimmed))
|
|
137
|
+
} else {
|
|
138
|
+
trimmed
|
|
139
|
+
}
|
|
140
|
+
let withLoc = switch String.lastIndexOf(body, "(") {
|
|
141
|
+
| -1 => body
|
|
142
|
+
| i =>
|
|
143
|
+
let rest = String.slice(body, ~start=i + 1, ~end=String.length(body))
|
|
144
|
+
switch String.lastIndexOf(rest, ")") {
|
|
145
|
+
| -1 => rest
|
|
146
|
+
| j => String.slice(rest, ~start=0, ~end=j)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
let parts = withLoc->String.split(":")
|
|
150
|
+
let n = parts->Array.length
|
|
151
|
+
if n < 3 {
|
|
152
|
+
None
|
|
153
|
+
} else {
|
|
154
|
+
let col = parts->Array.getUnsafe(n - 1)->Int.fromString
|
|
155
|
+
let line = parts->Array.getUnsafe(n - 2)->Int.fromString
|
|
156
|
+
let file =
|
|
157
|
+
parts->Array.slice(~start=0, ~end=n - 2)->Array.join(":")
|
|
158
|
+
let file = if String.startsWith(file, "file://") {
|
|
159
|
+
String.slice(file, ~start=7, ~end=String.length(file))
|
|
160
|
+
} else {
|
|
161
|
+
file
|
|
162
|
+
}
|
|
163
|
+
// Strip the Loader's `?t=N` cache-busting query so locations point at the
|
|
164
|
+
// real file path.
|
|
165
|
+
let file = switch String.indexOf(file, "?") {
|
|
166
|
+
| -1 => file
|
|
167
|
+
| q => String.slice(file, ~start=0, ~end=q)
|
|
168
|
+
}
|
|
169
|
+
switch (line, col) {
|
|
170
|
+
| (Some(l), Some(c)) => Some({file, line: l, column: c})
|
|
171
|
+
| _ => None
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Walk a captured stack and return the first frame that lives in a test
|
|
177
|
+
// file outside the reventless-gwt package itself.
|
|
178
|
+
let captureLocation = (skip: int): option<location> => {
|
|
179
|
+
let stack: option<string> = %raw(`(new Error()).stack`)
|
|
180
|
+
switch stack {
|
|
181
|
+
| None => None
|
|
182
|
+
| Some(s) =>
|
|
183
|
+
let lines = s->String.split("\n")
|
|
184
|
+
let total = lines->Array.length
|
|
185
|
+
// Skip the "Error" header, plus `skip` internal frames.
|
|
186
|
+
let rec find = i =>
|
|
187
|
+
if i >= total {
|
|
188
|
+
None
|
|
189
|
+
} else {
|
|
190
|
+
let frame = lines->Array.getUnsafe(i)
|
|
191
|
+
switch parseFrame(frame) {
|
|
192
|
+
| Some(loc)
|
|
193
|
+
if !(loc.file->String.includes("reventless-gwt/src/")) &&
|
|
194
|
+
!(loc.file->String.includes("node_modules/")) =>
|
|
195
|
+
Some(loc)
|
|
196
|
+
| _ => find(i + 1)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
find(skip + 1)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
4
|
+
import * as Outcome$ReventlessGwt from "./Outcome.res.mjs";
|
|
5
|
+
|
|
6
|
+
let active = {
|
|
7
|
+
contents: false
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
let describeStack = {
|
|
11
|
+
contents: []
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
let entries = {
|
|
15
|
+
contents: []
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
let hasOnly = {
|
|
19
|
+
contents: false
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
let skipNext = {
|
|
23
|
+
contents: false
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
let onlyNext = {
|
|
27
|
+
contents: false
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
let skipDepth = {
|
|
31
|
+
contents: 0
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
let currentFile = {
|
|
35
|
+
contents: undefined
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function activate() {
|
|
39
|
+
active.contents = true;
|
|
40
|
+
describeStack.contents = [];
|
|
41
|
+
entries.contents = [];
|
|
42
|
+
hasOnly.contents = false;
|
|
43
|
+
skipNext.contents = false;
|
|
44
|
+
onlyNext.contents = false;
|
|
45
|
+
currentFile.contents = undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function deactivate() {
|
|
49
|
+
active.contents = false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function isActive() {
|
|
53
|
+
return active.contents;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function setCurrentFile(path) {
|
|
57
|
+
currentFile.contents = path;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getCurrentFile() {
|
|
61
|
+
return currentFile.contents;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function markSkipNext() {
|
|
65
|
+
skipNext.contents = true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function markOnlyNext() {
|
|
69
|
+
onlyNext.contents = true;
|
|
70
|
+
hasOnly.contents = true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function pushDescribe(label, body) {
|
|
74
|
+
describeStack.contents = describeStack.contents.concat([label]);
|
|
75
|
+
body();
|
|
76
|
+
let ds = describeStack.contents;
|
|
77
|
+
describeStack.contents = ds.slice(0, ds.length - 1 | 0);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function buildId(describePath, name) {
|
|
81
|
+
let prefix = describePath.join("::");
|
|
82
|
+
if (prefix === "") {
|
|
83
|
+
return name;
|
|
84
|
+
} else {
|
|
85
|
+
return prefix + "::" + name;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function push(slice, location, name, body) {
|
|
90
|
+
let status = skipDepth.contents > 0 ? "Skipped" : (
|
|
91
|
+
skipNext.contents ? (skipNext.contents = false, "Skipped") : (
|
|
92
|
+
onlyNext.contents ? (onlyNext.contents = false, "Only") : "Runnable"
|
|
93
|
+
)
|
|
94
|
+
);
|
|
95
|
+
let describePath = describeStack.contents;
|
|
96
|
+
let id = buildId(describePath, name);
|
|
97
|
+
let entry = {
|
|
98
|
+
id: id,
|
|
99
|
+
name: name,
|
|
100
|
+
describePath: describePath,
|
|
101
|
+
slice: slice,
|
|
102
|
+
body: body,
|
|
103
|
+
status: status,
|
|
104
|
+
location: location
|
|
105
|
+
};
|
|
106
|
+
entries.contents = entries.contents.concat([entry]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function pushTodo(name) {
|
|
110
|
+
let describePath = describeStack.contents;
|
|
111
|
+
let id = buildId(describePath, name);
|
|
112
|
+
let entry_body = () => Promise.resolve(Outcome$ReventlessGwt.pass);
|
|
113
|
+
let entry = {
|
|
114
|
+
id: id,
|
|
115
|
+
name: name,
|
|
116
|
+
describePath: describePath,
|
|
117
|
+
slice: undefined,
|
|
118
|
+
body: entry_body,
|
|
119
|
+
status: "Skipped",
|
|
120
|
+
location: undefined
|
|
121
|
+
};
|
|
122
|
+
entries.contents = entries.contents.concat([entry]);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function drain() {
|
|
126
|
+
let result = entries.contents;
|
|
127
|
+
entries.contents = [];
|
|
128
|
+
describeStack.contents = [];
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function parseFrame(frame) {
|
|
133
|
+
let trimmed = frame.trim();
|
|
134
|
+
let body = trimmed.startsWith("at ") ? trimmed.slice(3, trimmed.length) : trimmed;
|
|
135
|
+
let i = body.lastIndexOf("(");
|
|
136
|
+
let withLoc;
|
|
137
|
+
if (i !== -1) {
|
|
138
|
+
let rest = body.slice(i + 1 | 0, body.length);
|
|
139
|
+
let j = rest.lastIndexOf(")");
|
|
140
|
+
withLoc = j !== -1 ? rest.slice(0, j) : rest;
|
|
141
|
+
} else {
|
|
142
|
+
withLoc = body;
|
|
143
|
+
}
|
|
144
|
+
let parts = withLoc.split(":");
|
|
145
|
+
let n = parts.length;
|
|
146
|
+
if (n < 3) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
let col = Stdlib_Int.fromString(parts[n - 1 | 0], undefined);
|
|
150
|
+
let line = Stdlib_Int.fromString(parts[n - 2 | 0], undefined);
|
|
151
|
+
let file = parts.slice(0, n - 2 | 0).join(":");
|
|
152
|
+
let file$1 = file.startsWith("file://") ? file.slice(7, file.length) : file;
|
|
153
|
+
let q = file$1.indexOf("?");
|
|
154
|
+
let file$2 = q !== -1 ? file$1.slice(0, q) : file$1;
|
|
155
|
+
if (line !== undefined && col !== undefined) {
|
|
156
|
+
return {
|
|
157
|
+
file: file$2,
|
|
158
|
+
line: line,
|
|
159
|
+
column: col
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function captureLocation(skip) {
|
|
165
|
+
let stack = ((new Error()).stack);
|
|
166
|
+
if (stack === undefined) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
let lines = stack.split("\n");
|
|
170
|
+
let total = lines.length;
|
|
171
|
+
let _i = skip + 1 | 0;
|
|
172
|
+
while (true) {
|
|
173
|
+
let i = _i;
|
|
174
|
+
if (i >= total) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
let frame = lines[i];
|
|
178
|
+
let loc = parseFrame(frame);
|
|
179
|
+
if (loc !== undefined) {
|
|
180
|
+
if (!loc.file.includes("reventless-gwt/src/") && !loc.file.includes("node_modules/")) {
|
|
181
|
+
return loc;
|
|
182
|
+
}
|
|
183
|
+
_i = i + 1 | 0;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
_i = i + 1 | 0;
|
|
187
|
+
continue;
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export {
|
|
192
|
+
active,
|
|
193
|
+
describeStack,
|
|
194
|
+
entries,
|
|
195
|
+
hasOnly,
|
|
196
|
+
skipNext,
|
|
197
|
+
onlyNext,
|
|
198
|
+
skipDepth,
|
|
199
|
+
currentFile,
|
|
200
|
+
activate,
|
|
201
|
+
deactivate,
|
|
202
|
+
isActive,
|
|
203
|
+
setCurrentFile,
|
|
204
|
+
getCurrentFile,
|
|
205
|
+
markSkipNext,
|
|
206
|
+
markOnlyNext,
|
|
207
|
+
pushDescribe,
|
|
208
|
+
buildId,
|
|
209
|
+
push,
|
|
210
|
+
pushTodo,
|
|
211
|
+
drain,
|
|
212
|
+
parseFrame,
|
|
213
|
+
captureLocation,
|
|
214
|
+
}
|
|
215
|
+
/* No side effect */
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Pure helpers mapping a file path to its Reventless component {kind, name}
|
|
2
|
+
// using the folder-name convention (the same vocabulary the plugin generator
|
|
3
|
+
// classifies by). Shared by the discovery `item` annotation (FormatterVsCode)
|
|
4
|
+
// and the src/ component inventory (ComponentScan). No I/O — path strings only.
|
|
5
|
+
|
|
6
|
+
type component = {kind: string, name: string}
|
|
7
|
+
|
|
8
|
+
// Folder names that denote a component kind. A file counts as a component when
|
|
9
|
+
// its immediate parent folder is one of these.
|
|
10
|
+
let kindFolders = [
|
|
11
|
+
"Aggregate",
|
|
12
|
+
"StateChangeSlice",
|
|
13
|
+
"StateViewSlice",
|
|
14
|
+
"StateViewSliceStream",
|
|
15
|
+
"ReadModel",
|
|
16
|
+
"ReadModelStream",
|
|
17
|
+
"AutomationSlice",
|
|
18
|
+
"InboundTranslationSlice",
|
|
19
|
+
"OutboundTranslationSlice",
|
|
20
|
+
"Extension",
|
|
21
|
+
"ExtensionPoint",
|
|
22
|
+
"Task",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
let isKindFolder = (segment: string) => kindFolders->Array.includes(segment)
|
|
26
|
+
|
|
27
|
+
// Body-file suffixes stripped to recover the spec stem (longest first so
|
|
28
|
+
// `_ExtensionPointMapping` is removed before `_ExtensionPoint`). Spec and body
|
|
29
|
+
// files in one folder collapse to the same component name.
|
|
30
|
+
let bodySuffixes = [
|
|
31
|
+
"_ExtensionPointMapping",
|
|
32
|
+
"_ExtensionPoint",
|
|
33
|
+
"_Extension",
|
|
34
|
+
"_Projections",
|
|
35
|
+
"_Projection",
|
|
36
|
+
"_Mappings",
|
|
37
|
+
"_Behavior",
|
|
38
|
+
"_Automation",
|
|
39
|
+
"_Translation",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
let stripBody = (stem: string) =>
|
|
43
|
+
switch bodySuffixes->Array.find(suf => String.endsWith(stem, suf)) {
|
|
44
|
+
| Some(suf) => String.slice(stem, ~start=0, ~end=String.length(stem) - String.length(suf))
|
|
45
|
+
| None => stem
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Strip the GWT test marker (`_GWT` / `GwtTest` / `Gwt`) — the three shapes
|
|
49
|
+
// `Discovery.isGwtTestFile` recognises.
|
|
50
|
+
let stripGwt = (stem: string) =>
|
|
51
|
+
if String.endsWith(stem, "_GWT") {
|
|
52
|
+
String.slice(stem, ~start=0, ~end=String.length(stem) - 4)
|
|
53
|
+
} else if String.endsWith(stem, "GwtTest") {
|
|
54
|
+
String.slice(stem, ~start=0, ~end=String.length(stem) - 7)
|
|
55
|
+
} else if String.endsWith(stem, "Gwt") {
|
|
56
|
+
String.slice(stem, ~start=0, ~end=String.length(stem) - 3)
|
|
57
|
+
} else {
|
|
58
|
+
stem
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Last path segment (POSIX paths — the monorepo's tooling normalises to `/`).
|
|
62
|
+
let basename = (path: string) =>
|
|
63
|
+
switch path->String.split("/")->Array.last {
|
|
64
|
+
| Some(s) => s
|
|
65
|
+
| None => path
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Parent folder name (the segment before the filename), if any.
|
|
69
|
+
let parentFolder = (path: string) => {
|
|
70
|
+
let segs = path->String.split("/")
|
|
71
|
+
let n = segs->Array.length
|
|
72
|
+
n >= 2 ? segs->Array.get(n - 2) : None
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Strip the compiled / source extension from a filename.
|
|
76
|
+
let stem = (filename: string) =>
|
|
77
|
+
if String.endsWith(filename, ".res.mjs") {
|
|
78
|
+
String.slice(filename, ~start=0, ~end=String.length(filename) - 8)
|
|
79
|
+
} else if String.endsWith(filename, ".res.js") {
|
|
80
|
+
String.slice(filename, ~start=0, ~end=String.length(filename) - 7)
|
|
81
|
+
} else if String.endsWith(filename, ".resi") {
|
|
82
|
+
String.slice(filename, ~start=0, ~end=String.length(filename) - 5)
|
|
83
|
+
} else if String.endsWith(filename, ".res") {
|
|
84
|
+
String.slice(filename, ~start=0, ~end=String.length(filename) - 4)
|
|
85
|
+
} else {
|
|
86
|
+
filename
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// {kind, name} for a discovered GWT test file, or None if it isn't inside a
|
|
90
|
+
// recognised kind folder.
|
|
91
|
+
let componentOfTestFile = (path: string): option<component> =>
|
|
92
|
+
switch parentFolder(path) {
|
|
93
|
+
| Some(folder) if isKindFolder(folder) =>
|
|
94
|
+
Some({kind: folder, name: path->basename->stem->stripGwt->stripBody})
|
|
95
|
+
| _ => None
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// {kind, name} for a src/ component file (spec or body), or None.
|
|
99
|
+
let componentOfSrcFile = (path: string): option<component> =>
|
|
100
|
+
switch parentFolder(path) {
|
|
101
|
+
| Some(folder) if isKindFolder(folder) =>
|
|
102
|
+
Some({kind: folder, name: path->basename->stem->stripBody})
|
|
103
|
+
| _ => None
|
|
104
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
4
|
+
|
|
5
|
+
let kindFolders = [
|
|
6
|
+
"Aggregate",
|
|
7
|
+
"StateChangeSlice",
|
|
8
|
+
"StateViewSlice",
|
|
9
|
+
"StateViewSliceStream",
|
|
10
|
+
"ReadModel",
|
|
11
|
+
"ReadModelStream",
|
|
12
|
+
"AutomationSlice",
|
|
13
|
+
"InboundTranslationSlice",
|
|
14
|
+
"OutboundTranslationSlice",
|
|
15
|
+
"Extension",
|
|
16
|
+
"ExtensionPoint",
|
|
17
|
+
"Task"
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
function isKindFolder(segment) {
|
|
21
|
+
return kindFolders.includes(segment);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let bodySuffixes = [
|
|
25
|
+
"_ExtensionPointMapping",
|
|
26
|
+
"_ExtensionPoint",
|
|
27
|
+
"_Extension",
|
|
28
|
+
"_Projections",
|
|
29
|
+
"_Projection",
|
|
30
|
+
"_Mappings",
|
|
31
|
+
"_Behavior",
|
|
32
|
+
"_Automation",
|
|
33
|
+
"_Translation"
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
function stripBody(stem) {
|
|
37
|
+
let suf = bodySuffixes.find(suf => stem.endsWith(suf));
|
|
38
|
+
if (suf !== undefined) {
|
|
39
|
+
return stem.slice(0, stem.length - suf.length | 0);
|
|
40
|
+
} else {
|
|
41
|
+
return stem;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function stripGwt(stem) {
|
|
46
|
+
if (stem.endsWith("_GWT")) {
|
|
47
|
+
return stem.slice(0, stem.length - 4 | 0);
|
|
48
|
+
} else if (stem.endsWith("GwtTest")) {
|
|
49
|
+
return stem.slice(0, stem.length - 7 | 0);
|
|
50
|
+
} else if (stem.endsWith("Gwt")) {
|
|
51
|
+
return stem.slice(0, stem.length - 3 | 0);
|
|
52
|
+
} else {
|
|
53
|
+
return stem;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function basename(path) {
|
|
58
|
+
let s = Stdlib_Array.last(path.split("/"));
|
|
59
|
+
if (s !== undefined) {
|
|
60
|
+
return s;
|
|
61
|
+
} else {
|
|
62
|
+
return path;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function parentFolder(path) {
|
|
67
|
+
let segs = path.split("/");
|
|
68
|
+
let n = segs.length;
|
|
69
|
+
if (n >= 2) {
|
|
70
|
+
return segs[n - 2 | 0];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function stem(filename) {
|
|
75
|
+
if (filename.endsWith(".res.mjs")) {
|
|
76
|
+
return filename.slice(0, filename.length - 8 | 0);
|
|
77
|
+
} else if (filename.endsWith(".res.js")) {
|
|
78
|
+
return filename.slice(0, filename.length - 7 | 0);
|
|
79
|
+
} else if (filename.endsWith(".resi")) {
|
|
80
|
+
return filename.slice(0, filename.length - 5 | 0);
|
|
81
|
+
} else if (filename.endsWith(".res")) {
|
|
82
|
+
return filename.slice(0, filename.length - 4 | 0);
|
|
83
|
+
} else {
|
|
84
|
+
return filename;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function componentOfTestFile(path) {
|
|
89
|
+
let folder = parentFolder(path);
|
|
90
|
+
if (folder !== undefined && kindFolders.includes(folder)) {
|
|
91
|
+
return {
|
|
92
|
+
kind: folder,
|
|
93
|
+
name: stripBody(stripGwt(stem(basename(path))))
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function componentOfSrcFile(path) {
|
|
99
|
+
let folder = parentFolder(path);
|
|
100
|
+
if (folder !== undefined && kindFolders.includes(folder)) {
|
|
101
|
+
return {
|
|
102
|
+
kind: folder,
|
|
103
|
+
name: stripBody(stem(basename(path)))
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
kindFolders,
|
|
110
|
+
isKindFolder,
|
|
111
|
+
bodySuffixes,
|
|
112
|
+
stripBody,
|
|
113
|
+
stripGwt,
|
|
114
|
+
basename,
|
|
115
|
+
parentFolder,
|
|
116
|
+
stem,
|
|
117
|
+
componentOfTestFile,
|
|
118
|
+
componentOfSrcFile,
|
|
119
|
+
}
|
|
120
|
+
/* No side effect */
|