@usebruno/js 0.31.0 → 0.33.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 +4 -3
- package/src/bru.js +2 -0
- package/src/runtime/script-runtime.js +25 -2
- package/src/runtime/test-runtime.js +65 -100
- package/src/sandbox/quickjs/index.js +1 -1
- package/src/sandbox/quickjs/shims/bru.js +45 -3
- package/src/utils/results.js +80 -0
- package/src/utils.js +28 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebruno/js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"test": "node --experimental-vm-modules $(npx which jest) --testPathIgnorePatterns test.js",
|
|
15
|
-
"sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js"
|
|
15
|
+
"sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js",
|
|
16
|
+
"prepack": "npm run test"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@usebruno/common": "0.
|
|
19
|
+
"@usebruno/common": "0.7.0",
|
|
19
20
|
"@usebruno/crypto-js": "^3.1.9",
|
|
20
21
|
"@usebruno/query": "0.1.0",
|
|
21
22
|
"ajv": "^8.12.0",
|
package/src/bru.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { cloneDeep } = require('lodash');
|
|
2
2
|
const { uuid } = require('./utils');
|
|
3
3
|
const { interpolate: _interpolate } = require('@usebruno/common');
|
|
4
|
+
const { sendRequest } = require('@usebruno/requests').scripting;
|
|
4
5
|
|
|
5
6
|
const variableNameRegex = /^[\w-.]*$/;
|
|
6
7
|
|
|
@@ -19,6 +20,7 @@ class Bru {
|
|
|
19
20
|
this.historyLogger = historyLogger;
|
|
20
21
|
this.setVisualizations = setVisualizations;
|
|
21
22
|
this.collectionName = collectionName;
|
|
23
|
+
this.sendRequest = sendRequest;
|
|
22
24
|
this.runner = {
|
|
23
25
|
skipRequest: () => {
|
|
24
26
|
this.skipRequest = true;
|
|
@@ -12,7 +12,10 @@ const { get } = require('lodash');
|
|
|
12
12
|
const Bru = require('../bru');
|
|
13
13
|
const BrunoRequest = require('../bruno-request');
|
|
14
14
|
const BrunoResponse = require('../bruno-response');
|
|
15
|
+
const Test = require('../test');
|
|
16
|
+
const TestResults = require('../test-results');
|
|
15
17
|
const { cleanJson } = require('../utils');
|
|
18
|
+
const { createBruTestResultMethods } = require('../utils/results');
|
|
16
19
|
|
|
17
20
|
// Inbuilt Library Support
|
|
18
21
|
const ajv = require('ajv');
|
|
@@ -64,6 +67,7 @@ class ScriptRuntime {
|
|
|
64
67
|
const folderVariables = request?.folderVariables || {};
|
|
65
68
|
const requestVariables = request?.requestVariables || {};
|
|
66
69
|
const iterationDetails = request?.runnerIterationDetails || {};
|
|
70
|
+
const assertionResults = request?.assertionResults || [];
|
|
67
71
|
// TODO please clean this up
|
|
68
72
|
const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName);
|
|
69
73
|
const req = new BrunoRequest(request);
|
|
@@ -86,9 +90,16 @@ class ScriptRuntime {
|
|
|
86
90
|
}
|
|
87
91
|
}
|
|
88
92
|
|
|
93
|
+
// extend bru with result getter methods
|
|
94
|
+
const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
95
|
+
|
|
89
96
|
const context = {
|
|
90
97
|
bru,
|
|
91
|
-
req
|
|
98
|
+
req,
|
|
99
|
+
test,
|
|
100
|
+
expect: chai.expect,
|
|
101
|
+
assert: chai.assert,
|
|
102
|
+
__brunoTestResults: __brunoTestResults
|
|
92
103
|
};
|
|
93
104
|
|
|
94
105
|
if (onConsoleLog && typeof onConsoleLog === 'function') {
|
|
@@ -123,6 +134,7 @@ class ScriptRuntime {
|
|
|
123
134
|
runtimeVariables: cleanJson(runtimeVariables),
|
|
124
135
|
visualizations,
|
|
125
136
|
globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
|
|
137
|
+
results: cleanJson(__brunoTestResults.getResults()),
|
|
126
138
|
nextRequestName: bru.nextRequest,
|
|
127
139
|
skipRequest: bru.skipRequest,
|
|
128
140
|
stopExecution: bru.stopExecution
|
|
@@ -178,6 +190,7 @@ class ScriptRuntime {
|
|
|
178
190
|
runtimeVariables: cleanJson(runtimeVariables),
|
|
179
191
|
visualizations,
|
|
180
192
|
globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
|
|
193
|
+
results: cleanJson(__brunoTestResults.getResults()),
|
|
181
194
|
nextRequestName: bru.nextRequest,
|
|
182
195
|
skipRequest: bru.skipRequest,
|
|
183
196
|
stopExecution: bru.stopExecution
|
|
@@ -209,6 +222,7 @@ class ScriptRuntime {
|
|
|
209
222
|
const folderVariables = request?.folderVariables || {};
|
|
210
223
|
const requestVariables = request?.requestVariables || {};
|
|
211
224
|
const iterationDetails = request?.runnerIterationDetails || {};
|
|
225
|
+
const assertionResults = request?.assertionResults || [];
|
|
212
226
|
const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName);
|
|
213
227
|
const req = new BrunoRequest(request);
|
|
214
228
|
const res = new BrunoResponse(response);
|
|
@@ -231,10 +245,17 @@ class ScriptRuntime {
|
|
|
231
245
|
}
|
|
232
246
|
}
|
|
233
247
|
|
|
248
|
+
// extend bru with result getter methods
|
|
249
|
+
const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
250
|
+
|
|
234
251
|
const context = {
|
|
235
252
|
bru,
|
|
236
253
|
req,
|
|
237
|
-
res
|
|
254
|
+
res,
|
|
255
|
+
test,
|
|
256
|
+
expect: chai.expect,
|
|
257
|
+
assert: chai.assert,
|
|
258
|
+
__brunoTestResults: __brunoTestResults
|
|
238
259
|
};
|
|
239
260
|
|
|
240
261
|
if (onConsoleLog && typeof onConsoleLog === 'function') {
|
|
@@ -269,6 +290,7 @@ class ScriptRuntime {
|
|
|
269
290
|
runtimeVariables: cleanJson(runtimeVariables),
|
|
270
291
|
visualizations,
|
|
271
292
|
globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
|
|
293
|
+
results: cleanJson(__brunoTestResults.getResults()),
|
|
272
294
|
nextRequestName: bru.nextRequest,
|
|
273
295
|
skipRequest: bru.skipRequest,
|
|
274
296
|
stopExecution: bru.stopExecution
|
|
@@ -324,6 +346,7 @@ class ScriptRuntime {
|
|
|
324
346
|
runtimeVariables: cleanJson(runtimeVariables),
|
|
325
347
|
visualizations,
|
|
326
348
|
globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
|
|
349
|
+
results: cleanJson(__brunoTestResults.getResults()),
|
|
327
350
|
nextRequestName: bru.nextRequest,
|
|
328
351
|
skipRequest: bru.skipRequest,
|
|
329
352
|
stopExecution: bru.stopExecution
|
|
@@ -15,7 +15,8 @@ const BrunoRequest = require('../bruno-request');
|
|
|
15
15
|
const BrunoResponse = require('../bruno-response');
|
|
16
16
|
const Test = require('../test');
|
|
17
17
|
const TestResults = require('../test-results');
|
|
18
|
-
const { cleanJson
|
|
18
|
+
const { cleanJson } = require('../utils');
|
|
19
|
+
const { createBruTestResultMethods } = require('../utils/results');
|
|
19
20
|
|
|
20
21
|
// Inbuilt Library Support
|
|
21
22
|
const ajv = require('ajv');
|
|
@@ -35,25 +36,6 @@ const cheerio = require('cheerio');
|
|
|
35
36
|
const tv4 = require('tv4');
|
|
36
37
|
const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
|
|
37
38
|
|
|
38
|
-
const getResultsSummary = (results) => {
|
|
39
|
-
const summary = {
|
|
40
|
-
total: results.length,
|
|
41
|
-
passed: 0,
|
|
42
|
-
failed: 0,
|
|
43
|
-
skipped: 0,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
results.forEach((r) => {
|
|
47
|
-
const passed = r.status === "pass";
|
|
48
|
-
if (passed) summary.passed += 1;
|
|
49
|
-
else if (r.status === "fail") summary.failed += 1;
|
|
50
|
-
else summary.skipped += 1;
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
return summary;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
39
|
class TestRuntime {
|
|
58
40
|
constructor(props) {
|
|
59
41
|
this.runtime = props?.runtime || 'vm2';
|
|
@@ -103,9 +85,8 @@ class TestRuntime {
|
|
|
103
85
|
}
|
|
104
86
|
}
|
|
105
87
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const test = Test(__brunoTestResults, chai);
|
|
88
|
+
// extend bru with result getter methods
|
|
89
|
+
const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
|
|
109
90
|
|
|
110
91
|
if (!testsFile || !testsFile.length) {
|
|
111
92
|
return {
|
|
@@ -118,36 +99,6 @@ class TestRuntime {
|
|
|
118
99
|
};
|
|
119
100
|
}
|
|
120
101
|
|
|
121
|
-
bru.getTestResults = async () => {
|
|
122
|
-
let results = await __brunoTestResults.getResults();
|
|
123
|
-
const summary = getResultsSummary(results);
|
|
124
|
-
return {
|
|
125
|
-
summary,
|
|
126
|
-
results: results?.map?.(r => ({
|
|
127
|
-
status: r?.status,
|
|
128
|
-
description: r?.description,
|
|
129
|
-
expected: r?.expected,
|
|
130
|
-
actual: r?.actual,
|
|
131
|
-
error: r?.error
|
|
132
|
-
}))
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
bru.getAssertionResults = async () => {
|
|
136
|
-
let results = assertionResults;
|
|
137
|
-
const summary = getResultsSummary(results);
|
|
138
|
-
return {
|
|
139
|
-
summary,
|
|
140
|
-
results: results?.map?.(r => ({
|
|
141
|
-
status: r?.status,
|
|
142
|
-
lhsExpr: r?.lhsExpr,
|
|
143
|
-
rhsExpr: r?.rhsExpr,
|
|
144
|
-
operator: r?.operator,
|
|
145
|
-
rhsOperand: r?.rhsOperand,
|
|
146
|
-
error: r?.error
|
|
147
|
-
}))
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
102
|
const context = {
|
|
152
103
|
test,
|
|
153
104
|
bru,
|
|
@@ -177,53 +128,60 @@ class TestRuntime {
|
|
|
177
128
|
context.bru.runRequest = runRequestByItemPathname;
|
|
178
129
|
}
|
|
179
130
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
131
|
+
let scriptError = null;
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
if (this.runtime === 'quickjs') {
|
|
135
|
+
await executeQuickJsVmAsync({
|
|
136
|
+
script: testsFile,
|
|
137
|
+
context: context
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
// default runtime is vm2
|
|
141
|
+
const vm = new NodeVM({
|
|
142
|
+
sandbox: context,
|
|
143
|
+
require: {
|
|
144
|
+
context: 'sandbox',
|
|
145
|
+
external: true,
|
|
146
|
+
root: [collectionPath, ...additionalContextRootsAbsolute],
|
|
147
|
+
mock: {
|
|
148
|
+
// node libs
|
|
149
|
+
path,
|
|
150
|
+
stream,
|
|
151
|
+
util,
|
|
152
|
+
url,
|
|
153
|
+
http,
|
|
154
|
+
https,
|
|
155
|
+
punycode,
|
|
156
|
+
zlib,
|
|
157
|
+
// 3rd party libs
|
|
158
|
+
ajv,
|
|
159
|
+
'ajv-formats': addFormats,
|
|
160
|
+
btoa,
|
|
161
|
+
atob,
|
|
162
|
+
lodash,
|
|
163
|
+
moment,
|
|
164
|
+
uuid,
|
|
165
|
+
nanoid,
|
|
166
|
+
axios,
|
|
167
|
+
chai,
|
|
168
|
+
'node-fetch': fetch,
|
|
169
|
+
'crypto-js': CryptoJS,
|
|
170
|
+
'xml2js': xml2js,
|
|
171
|
+
cheerio,
|
|
172
|
+
tv4,
|
|
173
|
+
...whitelistedModules,
|
|
174
|
+
fs: allowScriptFilesystemAccess ? fs : undefined,
|
|
175
|
+
'node-vault': NodeVault
|
|
176
|
+
}
|
|
222
177
|
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
178
|
+
});
|
|
179
|
+
const asyncVM = vm.run(`module.exports = async () => { ${testsFile}}`, path.join(collectionPath, 'vm.js'));
|
|
180
|
+
await asyncVM();
|
|
181
|
+
}
|
|
182
|
+
} catch (error) {
|
|
183
|
+
scriptError = error;
|
|
184
|
+
console.error('Test script execution error:', error);
|
|
227
185
|
}
|
|
228
186
|
|
|
229
187
|
if (historyLogger) {
|
|
@@ -235,7 +193,7 @@ class TestRuntime {
|
|
|
235
193
|
});
|
|
236
194
|
}
|
|
237
195
|
|
|
238
|
-
|
|
196
|
+
const result = {
|
|
239
197
|
request,
|
|
240
198
|
envVariables: cleanJson(envVariables),
|
|
241
199
|
runtimeVariables: cleanJson(runtimeVariables),
|
|
@@ -243,6 +201,13 @@ class TestRuntime {
|
|
|
243
201
|
results: cleanJson(__brunoTestResults.getResults()),
|
|
244
202
|
nextRequestName: bru.nextRequest
|
|
245
203
|
};
|
|
204
|
+
|
|
205
|
+
if (scriptError) {
|
|
206
|
+
scriptError.partialResults = result;
|
|
207
|
+
throw scriptError;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return result;
|
|
246
211
|
}
|
|
247
212
|
}
|
|
248
213
|
|
|
@@ -142,10 +142,10 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
|
|
|
142
142
|
|
|
143
143
|
const { bru, req, res, test, __brunoTestResults, console: consoleFn } = externalContext;
|
|
144
144
|
|
|
145
|
+
consoleFn && addConsoleShimToContext(vm, consoleFn);
|
|
145
146
|
bru && addBruShimToContext(vm, bru);
|
|
146
147
|
req && addBrunoRequestShimToContext(vm, req);
|
|
147
148
|
res && addBrunoResponseShimToContext(vm, res);
|
|
148
|
-
consoleFn && addConsoleShimToContext(vm, consoleFn);
|
|
149
149
|
addLocalModuleLoaderShimToContext(vm, collectionPath);
|
|
150
150
|
addPathShimToContext(vm);
|
|
151
151
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { cleanJson } = require('../../../utils');
|
|
1
|
+
const { cleanJson, cleanCircularJson } = require('../../../utils');
|
|
2
2
|
const { marshallToVm } = require('../utils');
|
|
3
3
|
|
|
4
4
|
const addBruShimToContext = (vm, bru) => {
|
|
@@ -252,8 +252,7 @@ const addBruShimToContext = (vm, bru) => {
|
|
|
252
252
|
bru
|
|
253
253
|
.runRequest(vm.dump(args))
|
|
254
254
|
.then((response) => {
|
|
255
|
-
|
|
256
|
-
promise.resolve(marshallToVm(cleanJson({ status, statusText, headers, data, dataBuffer, size }), vm));
|
|
255
|
+
promise.resolve(marshallToVm(cleanCircularJson(response), vm));
|
|
257
256
|
})
|
|
258
257
|
.catch((err) => {
|
|
259
258
|
promise.resolve(
|
|
@@ -270,6 +269,26 @@ const addBruShimToContext = (vm, bru) => {
|
|
|
270
269
|
});
|
|
271
270
|
runRequestHandle.consume((handle) => vm.setProp(bruObject, 'runRequest', handle));
|
|
272
271
|
|
|
272
|
+
let sendRequestHandle = vm.newFunction('_sendRequest', (args) => {
|
|
273
|
+
const promise = vm.newPromise();
|
|
274
|
+
bru
|
|
275
|
+
.sendRequest(vm.dump(args))
|
|
276
|
+
.then((response) => {
|
|
277
|
+
promise.resolve(marshallToVm(cleanCircularJson(response), vm));
|
|
278
|
+
})
|
|
279
|
+
.catch((err) => {
|
|
280
|
+
promise.reject(
|
|
281
|
+
marshallToVm(
|
|
282
|
+
cleanJson(err),
|
|
283
|
+
vm
|
|
284
|
+
)
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
promise.settled.then(vm.runtime.executePendingJobs);
|
|
288
|
+
return promise.handle;
|
|
289
|
+
});
|
|
290
|
+
sendRequestHandle.consume((handle) => vm.setProp(bruObject, '_sendRequest', handle));
|
|
291
|
+
|
|
273
292
|
const sleep = vm.newFunction('sleep', (timer) => {
|
|
274
293
|
const t = vm.getString(timer);
|
|
275
294
|
const promise = vm.newPromise();
|
|
@@ -285,6 +304,29 @@ const addBruShimToContext = (vm, bru) => {
|
|
|
285
304
|
vm.setProp(bruObject, 'runner', bruRunnerObject);
|
|
286
305
|
vm.setProp(vm.global, 'bru', bruObject);
|
|
287
306
|
bruObject.dispose();
|
|
307
|
+
|
|
308
|
+
vm.evalCode(`
|
|
309
|
+
globalThis.bru.sendRequest = async (requestConfig, callback) => {
|
|
310
|
+
if (!callback) return await globalThis.bru._sendRequest(requestConfig);
|
|
311
|
+
try {
|
|
312
|
+
const response = await globalThis.bru._sendRequest(requestConfig);
|
|
313
|
+
try {
|
|
314
|
+
await callback(null, response);
|
|
315
|
+
}
|
|
316
|
+
catch(error) {
|
|
317
|
+
return Promise.reject(error);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
catch(error) {
|
|
321
|
+
try {
|
|
322
|
+
await callback(JSON.parse(JSON.stringify(error)), null);
|
|
323
|
+
}
|
|
324
|
+
catch(err) {
|
|
325
|
+
return Promise.reject(err);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
`);
|
|
288
330
|
};
|
|
289
331
|
|
|
290
332
|
module.exports = addBruShimToContext;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const TestResults = require('../test-results');
|
|
2
|
+
const Test = require('../test');
|
|
3
|
+
|
|
4
|
+
// Calculate summary statistics for test results
|
|
5
|
+
const getResultsSummary = (results) => {
|
|
6
|
+
const summary = {
|
|
7
|
+
total: results.length,
|
|
8
|
+
passed: 0,
|
|
9
|
+
failed: 0,
|
|
10
|
+
skipped: 0,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
results.forEach((r) => {
|
|
14
|
+
const passed = r.status === 'pass';
|
|
15
|
+
if (passed) summary.passed += 1;
|
|
16
|
+
else if (r.status === 'fail') summary.failed += 1;
|
|
17
|
+
else summary.skipped += 1;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return summary;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const createBruTestResultMethods = (bru, assertionResults, chai) => {
|
|
24
|
+
const __brunoTestResults = new TestResults();
|
|
25
|
+
const test = Test(__brunoTestResults, chai);
|
|
26
|
+
setupBruTestMethods(bru, __brunoTestResults, assertionResults);
|
|
27
|
+
|
|
28
|
+
return { __brunoTestResults, test };
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const setupBruTestMethods = (bru, __brunoTestResults, assertionResults) => {
|
|
32
|
+
const getTestResults = async () => {
|
|
33
|
+
let results = await __brunoTestResults.getResults();
|
|
34
|
+
const summary = getResultsSummary(results);
|
|
35
|
+
return {
|
|
36
|
+
summary,
|
|
37
|
+
results: results.map(r => ({
|
|
38
|
+
status: r.status,
|
|
39
|
+
description: r.description,
|
|
40
|
+
expected: r.expected,
|
|
41
|
+
actual: r.actual,
|
|
42
|
+
error: r.error
|
|
43
|
+
}))
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const getAssertionResults = async () => {
|
|
48
|
+
let results = assertionResults;
|
|
49
|
+
const summary = getResultsSummary(results);
|
|
50
|
+
return {
|
|
51
|
+
summary,
|
|
52
|
+
results: results.map(r => ({
|
|
53
|
+
status: r.status,
|
|
54
|
+
lhsExpr: r.lhsExpr,
|
|
55
|
+
rhsExpr: r.rhsExpr,
|
|
56
|
+
operator: r.operator,
|
|
57
|
+
rhsOperand: r.rhsOperand,
|
|
58
|
+
error: r.error
|
|
59
|
+
}))
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Set methods on bru object if provided
|
|
64
|
+
if (bru) {
|
|
65
|
+
bru.getTestResults = getTestResults;
|
|
66
|
+
bru.getAssertionResults = getAssertionResults;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Also return the methods for direct use
|
|
70
|
+
return {
|
|
71
|
+
getTestResults,
|
|
72
|
+
getAssertionResults
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
getResultsSummary,
|
|
78
|
+
createBruTestResultMethods,
|
|
79
|
+
setupBruTestMethods
|
|
80
|
+
};
|
package/src/utils.js
CHANGED
|
@@ -158,6 +158,32 @@ const appendAwaitToTestFunc = (str) => {
|
|
|
158
158
|
return str.replace(/(?<!\.\s*)(?<!await\s)(test\()/g, 'await $1');
|
|
159
159
|
};
|
|
160
160
|
|
|
161
|
+
const cleanCircularJson = (data) => {
|
|
162
|
+
try {
|
|
163
|
+
// Handle circular references by keeping track of seen objects
|
|
164
|
+
const seen = new WeakSet();
|
|
165
|
+
|
|
166
|
+
const replacer = (key, value) => {
|
|
167
|
+
// Skip non-objects and null
|
|
168
|
+
if (typeof value !== 'object' || value === null) {
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Detect circular reference
|
|
173
|
+
if (seen.has(value)) {
|
|
174
|
+
return '[Circular Reference]';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
seen.add(value);
|
|
178
|
+
return value;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return JSON.parse(JSON.stringify(data, replacer));
|
|
182
|
+
} catch (e) {
|
|
183
|
+
return data;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
161
187
|
module.exports = {
|
|
162
188
|
evaluateJsExpression,
|
|
163
189
|
evaluateJsTemplateLiteral,
|
|
@@ -165,5 +191,6 @@ module.exports = {
|
|
|
165
191
|
internalExpressionCache,
|
|
166
192
|
cleanJson,
|
|
167
193
|
uuid,
|
|
168
|
-
appendAwaitToTestFunc
|
|
194
|
+
appendAwaitToTestFunc,
|
|
195
|
+
cleanCircularJson
|
|
169
196
|
};
|