@usebruno/js 0.51.0 → 0.52.0
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/package.json +6 -6
- package/src/bru.js +15 -23
- package/src/bruno-request.js +4 -0
- package/src/grpc/bruno-grpc-request.js +52 -0
- package/src/grpc/bruno-grpc-response.js +43 -0
- package/src/grpc/grpc-message-list.js +74 -0
- package/src/grpc/grpc-message.js +20 -0
- package/src/grpc/grpc-metadata-list.js +214 -0
- package/src/grpc/grpc-metadata.js +21 -0
- package/src/grpc/grpc-script-runtime.js +302 -0
- package/src/index.js +2 -0
- package/src/interpolate-string.js +2 -1
- package/src/runtime/assert-runtime.js +1 -0
- package/src/runtime/script-runtime.js +18 -2
- package/src/runtime/test-runtime.js +12 -7
- package/src/sandbox/bundle-browser-rollup.js +32 -32
- package/src/sandbox/node-vm/cjs-loader.js +390 -39
- package/src/sandbox/node-vm/index.js +96 -65
- package/src/sandbox/node-vm/index.spec.js +616 -0
- package/src/sandbox/quickjs/index.js +101 -17
- package/src/sandbox/quickjs/shims/bruno-grpc.js +29 -0
- package/src/sandbox/quickjs/shims/grpc/bruno-grpc-request.js +47 -0
- package/src/sandbox/quickjs/shims/grpc/bruno-grpc-response.js +40 -0
- package/src/sandbox/quickjs/shims/grpc/grpc-message-list.js +29 -0
- package/src/sandbox/quickjs/shims/grpc/grpc-metadata-list.js +31 -0
- package/src/sandbox/quickjs/utils/index.js +42 -23
- package/src/utils/error-formatter.js +13 -9
- package/src/utils/error-formatter.spec.js +97 -2
- package/src/utils/results.js +30 -3
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
const chai = require('chai');
|
|
2
|
+
const Bru = require('../bru');
|
|
3
|
+
const BrunoGrpcRequest = require('./bruno-grpc-request');
|
|
4
|
+
const BrunoGrpcResponse = require('./bruno-grpc-response');
|
|
5
|
+
const { cleanJson } = require('../utils');
|
|
6
|
+
const { createBruTestResultMethods } = require('../utils/results');
|
|
7
|
+
const { runScriptInNodeVm } = require('../sandbox/node-vm');
|
|
8
|
+
const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
|
|
9
|
+
const { SANDBOX } = require('../utils/sandbox');
|
|
10
|
+
const { createScopeSetter } = require('../runtime/scripted-entries');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Runs the gRPC lifecycle hooks
|
|
14
|
+
*
|
|
15
|
+
* All four hooks share one body (`#runHook`) and differ only in what they put on `bru.grpc` and
|
|
16
|
+
* what their result object carries — `buildGrpc` and `baseResult` below.
|
|
17
|
+
*
|
|
18
|
+
* The shared body mirrors `ScriptRuntime`'s `runRequestScript` / `runResponseScript` step for step,
|
|
19
|
+
* substituting the gRPC request/response models. Two intentional differences, not oversights:
|
|
20
|
+
* - `bru.runRequest` rejects instead of running anything.
|
|
21
|
+
* - The models live under `bru.grpc` rather than as the `req` / `res` globals HTTP scripts get.
|
|
22
|
+
*/
|
|
23
|
+
class GrpcScriptRuntime {
|
|
24
|
+
constructor(props) {
|
|
25
|
+
this.runtime = props?.runtime || 'quickjs';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {object} params
|
|
30
|
+
* @param {string} params.script - The hook body, already decommented by the caller
|
|
31
|
+
* @param {object} params.request - The prepared gRPC request
|
|
32
|
+
* @param {Function} params.buildGrpc - Returns the `bru.grpc` object for this hook
|
|
33
|
+
* @param {object} [params.baseResult] - Hook-specific fields the shared result is built on top of
|
|
34
|
+
*/
|
|
35
|
+
async #runHook({
|
|
36
|
+
script,
|
|
37
|
+
request,
|
|
38
|
+
buildGrpc,
|
|
39
|
+
baseResult = {},
|
|
40
|
+
envVariables,
|
|
41
|
+
runtimeVariables,
|
|
42
|
+
secretVariables,
|
|
43
|
+
collectionPath,
|
|
44
|
+
onConsoleLog,
|
|
45
|
+
processEnvVars,
|
|
46
|
+
scriptingConfig,
|
|
47
|
+
collectionName
|
|
48
|
+
}) {
|
|
49
|
+
const globalEnvironmentVariables = request?.globalEnvironmentVariables || {};
|
|
50
|
+
const oauth2CredentialVariables = request?.oauth2CredentialVariables || {};
|
|
51
|
+
const collectionVariables = request?.collectionVariables || {};
|
|
52
|
+
const folderVariables = request?.folderVariables || {};
|
|
53
|
+
const requestVariables = request?.requestVariables || {};
|
|
54
|
+
const promptVariables = request?.promptVariables || {};
|
|
55
|
+
const assertionResults = request?.assertionResults || [];
|
|
56
|
+
const certsAndProxyConfig = request?.certsAndProxyConfig;
|
|
57
|
+
const scriptPath = request?.pathname;
|
|
58
|
+
const bru = new Bru({
|
|
59
|
+
runtime: this.runtime,
|
|
60
|
+
envVariables,
|
|
61
|
+
runtimeVariables,
|
|
62
|
+
processEnvVars,
|
|
63
|
+
secretVariables,
|
|
64
|
+
collectionPath,
|
|
65
|
+
collectionVariables,
|
|
66
|
+
folderVariables,
|
|
67
|
+
requestVariables,
|
|
68
|
+
globalEnvironmentVariables,
|
|
69
|
+
oauth2CredentialVariables,
|
|
70
|
+
collectionName,
|
|
71
|
+
promptVariables,
|
|
72
|
+
certsAndProxyConfig,
|
|
73
|
+
requestUrl: request?.url
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
bru.grpc = buildGrpc();
|
|
77
|
+
|
|
78
|
+
// extend bru with result getter methods
|
|
79
|
+
const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
80
|
+
|
|
81
|
+
const context = {
|
|
82
|
+
bru,
|
|
83
|
+
test,
|
|
84
|
+
expect: chai.expect,
|
|
85
|
+
assert: chai.assert,
|
|
86
|
+
__brunoTestResults: __brunoTestResults,
|
|
87
|
+
__bruSetScope: createScopeSetter(bru)
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
if (onConsoleLog && typeof onConsoleLog === 'function') {
|
|
91
|
+
const customLogger = (type) => {
|
|
92
|
+
return (...args) => {
|
|
93
|
+
onConsoleLog(type, cleanJson(args));
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
context.console = {
|
|
97
|
+
log: customLogger('log'),
|
|
98
|
+
debug: customLogger('debug'),
|
|
99
|
+
info: customLogger('info'),
|
|
100
|
+
warn: customLogger('warn'),
|
|
101
|
+
error: customLogger('error')
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// A gRPC request can't run another request yet, so there is no `runRequestByItemPathname` to bind.
|
|
106
|
+
bru.runRequest = () => Promise.reject(new Error('bru.runRequest is not supported in gRPC scripts'));
|
|
107
|
+
|
|
108
|
+
const buildScriptResult = () => ({
|
|
109
|
+
...baseResult,
|
|
110
|
+
envVariables: bru._envDirty ? cleanJson(envVariables) : null,
|
|
111
|
+
runtimeVariables: bru._runtimeVarsDirty ? cleanJson(runtimeVariables) : null,
|
|
112
|
+
collectionVariables: bru._collVarsDirty ? cleanJson(collectionVariables) : null,
|
|
113
|
+
globalEnvironmentVariables: bru._globalEnvDirty ? cleanJson(globalEnvironmentVariables) : null,
|
|
114
|
+
oauth2CredentialsToReset: bru.oauth2CredentialsToReset,
|
|
115
|
+
results: cleanJson(__brunoTestResults.getResults()),
|
|
116
|
+
nextRequestName: bru.nextRequest,
|
|
117
|
+
skipRequest: bru.skipRequest,
|
|
118
|
+
stopExecution: bru.stopExecution,
|
|
119
|
+
scriptedRequestEntries: cleanJson(bru.scriptedRequestEntries || [])
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Track script errors to attach partial results before re-throwing, so the variables the hook
|
|
123
|
+
// set before it threw still reach the caller
|
|
124
|
+
let scriptError = null;
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
if (this.runtime === SANDBOX.NODEVM) {
|
|
128
|
+
await runScriptInNodeVm({
|
|
129
|
+
script,
|
|
130
|
+
context,
|
|
131
|
+
collectionPath,
|
|
132
|
+
scriptingConfig,
|
|
133
|
+
scriptPath
|
|
134
|
+
});
|
|
135
|
+
} else {
|
|
136
|
+
// default runtime is `quickjs`
|
|
137
|
+
await executeQuickJsVmAsync({
|
|
138
|
+
script,
|
|
139
|
+
context,
|
|
140
|
+
collectionPath,
|
|
141
|
+
scriptPath
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
} catch (error) {
|
|
145
|
+
scriptError = error;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (scriptError) {
|
|
149
|
+
scriptError.partialResults = buildScriptResult();
|
|
150
|
+
throw scriptError;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return buildScriptResult();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async runGrpcRequestScript({
|
|
157
|
+
script,
|
|
158
|
+
request,
|
|
159
|
+
envVariables,
|
|
160
|
+
runtimeVariables,
|
|
161
|
+
secretVariables,
|
|
162
|
+
collectionPath,
|
|
163
|
+
onConsoleLog,
|
|
164
|
+
processEnvVars,
|
|
165
|
+
scriptingConfig,
|
|
166
|
+
collectionName
|
|
167
|
+
}) {
|
|
168
|
+
return this.#runHook({
|
|
169
|
+
script,
|
|
170
|
+
request,
|
|
171
|
+
// Initial scope - `request.messages` reports what the call sent, so it is still empty here.
|
|
172
|
+
buildGrpc: () => ({ request: new BrunoGrpcRequest(request, { metadataWritable: true }) }),
|
|
173
|
+
baseResult: { request },
|
|
174
|
+
envVariables,
|
|
175
|
+
runtimeVariables,
|
|
176
|
+
secretVariables,
|
|
177
|
+
collectionPath,
|
|
178
|
+
onConsoleLog,
|
|
179
|
+
processEnvVars,
|
|
180
|
+
scriptingConfig,
|
|
181
|
+
collectionName
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async runGrpcResponseScript({
|
|
186
|
+
script,
|
|
187
|
+
request,
|
|
188
|
+
response,
|
|
189
|
+
envVariables,
|
|
190
|
+
runtimeVariables,
|
|
191
|
+
secretVariables,
|
|
192
|
+
collectionPath,
|
|
193
|
+
onConsoleLog,
|
|
194
|
+
processEnvVars,
|
|
195
|
+
scriptingConfig,
|
|
196
|
+
collectionName,
|
|
197
|
+
sentMessages = []
|
|
198
|
+
}) {
|
|
199
|
+
return this.#runHook({
|
|
200
|
+
script,
|
|
201
|
+
request,
|
|
202
|
+
// Passing sentMessages so only messages sent by client is accessible
|
|
203
|
+
buildGrpc: () => ({
|
|
204
|
+
request: new BrunoGrpcRequest(request, { sentMessages, metadataWritable: false }),
|
|
205
|
+
response: new BrunoGrpcResponse(response)
|
|
206
|
+
}),
|
|
207
|
+
baseResult: { response },
|
|
208
|
+
envVariables,
|
|
209
|
+
runtimeVariables,
|
|
210
|
+
secretVariables,
|
|
211
|
+
collectionPath,
|
|
212
|
+
onConsoleLog,
|
|
213
|
+
processEnvVars,
|
|
214
|
+
scriptingConfig,
|
|
215
|
+
collectionName
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* `before-message-send`. `message` is the message about to be transmitted; it joins
|
|
221
|
+
* `request.messages` only once the send succeeds, so the two never overlap.
|
|
222
|
+
*
|
|
223
|
+
* `bru.grpc.response` is deliberately absent, matching `beforeCallStart` — even on a bidi stream
|
|
224
|
+
* where messages have already been received.
|
|
225
|
+
*/
|
|
226
|
+
async runGrpcBeforeMessageSendScript({
|
|
227
|
+
script,
|
|
228
|
+
request,
|
|
229
|
+
message,
|
|
230
|
+
envVariables,
|
|
231
|
+
runtimeVariables,
|
|
232
|
+
secretVariables,
|
|
233
|
+
collectionPath,
|
|
234
|
+
onConsoleLog,
|
|
235
|
+
processEnvVars,
|
|
236
|
+
scriptingConfig,
|
|
237
|
+
collectionName,
|
|
238
|
+
sentMessages = []
|
|
239
|
+
}) {
|
|
240
|
+
return this.#runHook({
|
|
241
|
+
script,
|
|
242
|
+
request,
|
|
243
|
+
buildGrpc: () => ({
|
|
244
|
+
request: new BrunoGrpcRequest(request, { metadataWritable: false, sentMessages, message })
|
|
245
|
+
}),
|
|
246
|
+
// `message` is carried on the result for the planned `message.set`; discarded by callers today.
|
|
247
|
+
baseResult: { request, message },
|
|
248
|
+
envVariables,
|
|
249
|
+
runtimeVariables,
|
|
250
|
+
secretVariables,
|
|
251
|
+
collectionPath,
|
|
252
|
+
onConsoleLog,
|
|
253
|
+
processEnvVars,
|
|
254
|
+
scriptingConfig,
|
|
255
|
+
collectionName
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* `after-message-receive`. `message` is the message just received, and is also the last entry of
|
|
261
|
+
* `response.messages` — the call folds it in before the hook runs.
|
|
262
|
+
*
|
|
263
|
+
* The `response` here is *partial*: the call is still open, so `statusCode`, `statusText`,
|
|
264
|
+
* `duration` and `trailers` are not yet known and read as `undefined` / empty. `metadata` is
|
|
265
|
+
* usually populated, since headers precede the first message.
|
|
266
|
+
*/
|
|
267
|
+
async runGrpcAfterMessageReceiveScript({
|
|
268
|
+
script,
|
|
269
|
+
request,
|
|
270
|
+
response,
|
|
271
|
+
message,
|
|
272
|
+
envVariables,
|
|
273
|
+
runtimeVariables,
|
|
274
|
+
secretVariables,
|
|
275
|
+
collectionPath,
|
|
276
|
+
onConsoleLog,
|
|
277
|
+
processEnvVars,
|
|
278
|
+
scriptingConfig,
|
|
279
|
+
collectionName,
|
|
280
|
+
sentMessages = []
|
|
281
|
+
}) {
|
|
282
|
+
return this.#runHook({
|
|
283
|
+
script,
|
|
284
|
+
request,
|
|
285
|
+
buildGrpc: () => ({
|
|
286
|
+
request: new BrunoGrpcRequest(request, { metadataWritable: false, sentMessages }),
|
|
287
|
+
response: new BrunoGrpcResponse(response, { message })
|
|
288
|
+
}),
|
|
289
|
+
baseResult: { response, message },
|
|
290
|
+
envVariables,
|
|
291
|
+
runtimeVariables,
|
|
292
|
+
secretVariables,
|
|
293
|
+
collectionPath,
|
|
294
|
+
onConsoleLog,
|
|
295
|
+
processEnvVars,
|
|
296
|
+
scriptingConfig,
|
|
297
|
+
collectionName
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
module.exports = GrpcScriptRuntime;
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const ScriptRuntime = require('./runtime/script-runtime');
|
|
2
|
+
const GrpcScriptRuntime = require('./grpc/grpc-script-runtime');
|
|
2
3
|
const TestRuntime = require('./runtime/test-runtime');
|
|
3
4
|
const VarsRuntime = require('./runtime/vars-runtime');
|
|
4
5
|
const AssertRuntime = require('./runtime/assert-runtime');
|
|
@@ -21,6 +22,7 @@ const {
|
|
|
21
22
|
|
|
22
23
|
module.exports = {
|
|
23
24
|
ScriptRuntime,
|
|
25
|
+
GrpcScriptRuntime,
|
|
24
26
|
TestRuntime,
|
|
25
27
|
VarsRuntime,
|
|
26
28
|
AssertRuntime,
|
|
@@ -2,7 +2,7 @@ const { interpolate } = require('@usebruno/common');
|
|
|
2
2
|
|
|
3
3
|
const interpolateString = (
|
|
4
4
|
str,
|
|
5
|
-
{ envVariables = {}, runtimeVariables = {}, processEnvVars = {}, collectionVariables = {}, folderVariables = {}, requestVariables = {}, globalEnvironmentVariables = {} }
|
|
5
|
+
{ envVariables = {}, runtimeVariables = {}, iterationData = {}, processEnvVars = {}, collectionVariables = {}, folderVariables = {}, requestVariables = {}, globalEnvironmentVariables = {} }
|
|
6
6
|
) => {
|
|
7
7
|
if (!str || !str.length || typeof str !== 'string') {
|
|
8
8
|
return str;
|
|
@@ -15,6 +15,7 @@ const interpolateString = (
|
|
|
15
15
|
...folderVariables,
|
|
16
16
|
...requestVariables,
|
|
17
17
|
...runtimeVariables,
|
|
18
|
+
...iterationData,
|
|
18
19
|
process: {
|
|
19
20
|
env: {
|
|
20
21
|
...processEnvVars
|
|
@@ -362,6 +362,7 @@ const evaluateRhsOperand = (rhsOperand, operator, context, runtime) => {
|
|
|
362
362
|
folderVariables: context.bru.folderVariables,
|
|
363
363
|
requestVariables: context.bru.requestVariables,
|
|
364
364
|
runtimeVariables: context.bru.runtimeVariables,
|
|
365
|
+
iterationData: context.bru.runner.iterationData.get(),
|
|
365
366
|
envVariables: context.bru.envVariables,
|
|
366
367
|
processEnvVars: context.bru.processEnvVars
|
|
367
368
|
};
|
|
@@ -73,7 +73,7 @@ class ScriptRuntime {
|
|
|
73
73
|
const req = new BrunoRequest(request, historyLogger);
|
|
74
74
|
|
|
75
75
|
// extend bru with result getter methods
|
|
76
|
-
const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
76
|
+
const { __brunoTestResults, test, waitForPendingTests } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
77
77
|
|
|
78
78
|
const context = {
|
|
79
79
|
bru,
|
|
@@ -119,6 +119,18 @@ class ScriptRuntime {
|
|
|
119
119
|
scriptedRequestEntries: cleanJson(bru.scriptedRequestEntries || [])
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
+
const attachScriptResultToOnFailHandler = () => {
|
|
123
|
+
if (typeof request.onFailHandler !== 'function') {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const onFailHandler = request.onFailHandler;
|
|
128
|
+
request.onFailHandler = async (error) => {
|
|
129
|
+
await onFailHandler(error);
|
|
130
|
+
return buildRequestScriptResult();
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
|
|
122
134
|
// Track script errors to attach partial results before re-throwing
|
|
123
135
|
// This ensures that any test() calls that passed before the error are preserved
|
|
124
136
|
// Similar pattern to test-runtime.js which already handles this correctly
|
|
@@ -136,6 +148,7 @@ class ScriptRuntime {
|
|
|
136
148
|
} catch (error) {
|
|
137
149
|
scriptError = error;
|
|
138
150
|
}
|
|
151
|
+
await waitForPendingTests();
|
|
139
152
|
|
|
140
153
|
// If script errored, attach partial results so callers can display passed tests
|
|
141
154
|
// before the error occurred (e.g., 2 tests pass, then script throws)
|
|
@@ -144,6 +157,7 @@ class ScriptRuntime {
|
|
|
144
157
|
throw scriptError;
|
|
145
158
|
}
|
|
146
159
|
|
|
160
|
+
attachScriptResultToOnFailHandler();
|
|
147
161
|
return buildRequestScriptResult();
|
|
148
162
|
}
|
|
149
163
|
|
|
@@ -164,6 +178,7 @@ class ScriptRuntime {
|
|
|
164
178
|
throw scriptError;
|
|
165
179
|
}
|
|
166
180
|
|
|
181
|
+
attachScriptResultToOnFailHandler();
|
|
167
182
|
return buildRequestScriptResult();
|
|
168
183
|
}
|
|
169
184
|
|
|
@@ -225,7 +240,7 @@ class ScriptRuntime {
|
|
|
225
240
|
const res = new BrunoResponse(response);
|
|
226
241
|
|
|
227
242
|
// extend bru with result getter methods
|
|
228
|
-
const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
243
|
+
const { __brunoTestResults, test, waitForPendingTests } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
229
244
|
|
|
230
245
|
const context = {
|
|
231
246
|
bru,
|
|
@@ -289,6 +304,7 @@ class ScriptRuntime {
|
|
|
289
304
|
} catch (error) {
|
|
290
305
|
scriptError = error;
|
|
291
306
|
}
|
|
307
|
+
await waitForPendingTests();
|
|
292
308
|
|
|
293
309
|
// If script errored, attach partial results so callers can display passed tests
|
|
294
310
|
// before the error occurred (e.g., 2 tests pass, then script throws)
|
|
@@ -64,7 +64,7 @@ class TestRuntime {
|
|
|
64
64
|
const res = new BrunoResponse(response);
|
|
65
65
|
|
|
66
66
|
// extend bru with result getter methods
|
|
67
|
-
const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
67
|
+
const { __brunoTestResults, test, waitForPendingTests } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
68
68
|
|
|
69
69
|
if (!testsFile || !testsFile.length) {
|
|
70
70
|
return {
|
|
@@ -110,8 +110,8 @@ class TestRuntime {
|
|
|
110
110
|
|
|
111
111
|
let scriptError = null;
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
if (this.runtime === SANDBOX.NODEVM) {
|
|
114
|
+
try {
|
|
115
115
|
await runScriptInNodeVm({
|
|
116
116
|
script: testsFile,
|
|
117
117
|
context,
|
|
@@ -119,17 +119,22 @@ class TestRuntime {
|
|
|
119
119
|
scriptingConfig,
|
|
120
120
|
scriptPath
|
|
121
121
|
});
|
|
122
|
-
}
|
|
123
|
-
|
|
122
|
+
} catch (error) {
|
|
123
|
+
scriptError = error;
|
|
124
|
+
}
|
|
125
|
+
await waitForPendingTests();
|
|
126
|
+
} else {
|
|
127
|
+
// default runtime is `quickjs`
|
|
128
|
+
try {
|
|
124
129
|
await executeQuickJsVmAsync({
|
|
125
130
|
script: testsFile,
|
|
126
131
|
context: context,
|
|
127
132
|
collectionPath,
|
|
128
133
|
scriptPath
|
|
129
134
|
});
|
|
135
|
+
} catch (error) {
|
|
136
|
+
scriptError = error;
|
|
130
137
|
}
|
|
131
|
-
} catch (error) {
|
|
132
|
-
scriptError = error;
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
if (historyLogger) {
|