@usebruno/js 0.30.0 → 0.32.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usebruno/js",
3
- "version": "0.30.0",
3
+ "version": "0.32.0",
4
4
  "license": "MIT",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -15,7 +15,7 @@
15
15
  "sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js"
16
16
  },
17
17
  "dependencies": {
18
- "@usebruno/common": "0.5.0",
18
+ "@usebruno/common": "0.7.0",
19
19
  "@usebruno/crypto-js": "^3.1.9",
20
20
  "@usebruno/query": "0.1.0",
21
21
  "ajv": "^8.12.0",
package/src/bru.js CHANGED
@@ -1,12 +1,11 @@
1
1
  const { cloneDeep } = require('lodash');
2
2
  const { uuid } = require('./utils');
3
- const { interpolate } = require('@usebruno/common');
3
+ const { interpolate: _interpolate } = require('@usebruno/common');
4
4
 
5
5
  const variableNameRegex = /^[\w-.]*$/;
6
6
 
7
7
  class Bru {
8
- constructor(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails) {
9
-
8
+ constructor(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName) {
10
9
  this.envVariables = envVariables || {};
11
10
  this.runtimeVariables = runtimeVariables || {};
12
11
  this.processEnvVars = cloneDeep(processEnvVars || {});
@@ -19,7 +18,7 @@ class Bru {
19
18
  this.collectionPath = collectionPath;
20
19
  this.historyLogger = historyLogger;
21
20
  this.setVisualizations = setVisualizations;
22
-
21
+ this.collectionName = collectionName;
23
22
  this.runner = {
24
23
  skipRequest: () => {
25
24
  this.skipRequest = true;
@@ -38,10 +37,10 @@ class Bru {
38
37
  }
39
38
 
40
39
 
41
- _interpolate = (str) => {
42
- if (!str || !str.length || typeof str !== 'string') {
43
- return str;
44
- }
40
+ interpolate = (strOrObj) => {
41
+ if (!strOrObj) return strOrObj;
42
+ const isObj = typeof strOrObj === 'object';
43
+ const strToInterpolate = isObj ? JSON.stringify(strOrObj) : strOrObj;
45
44
 
46
45
  const combinedVars = {
47
46
  ...this.globalEnvironmentVariables,
@@ -58,7 +57,8 @@ class Bru {
58
57
  }
59
58
  };
60
59
 
61
- return interpolate(str, combinedVars);
60
+ const interpolatedStr = _interpolate(strToInterpolate, combinedVars);
61
+ return isObj ? JSON.parse(interpolatedStr) : interpolatedStr;
62
62
  };
63
63
 
64
64
  cwd() {
@@ -78,7 +78,7 @@ class Bru {
78
78
  }
79
79
 
80
80
  getEnvVar(key) {
81
- return this._interpolate(this.envVariables[key]);
81
+ return this.interpolate(this.envVariables[key]);
82
82
  }
83
83
 
84
84
  setEnvVar(key, value) {
@@ -103,7 +103,7 @@ class Bru {
103
103
  }
104
104
 
105
105
  getGlobalEnvVar(key) {
106
- return this._interpolate(this.globalEnvironmentVariables[key]);
106
+ return this.interpolate(this.globalEnvironmentVariables[key]);
107
107
  }
108
108
 
109
109
  setGlobalEnvVar(key, value) {
@@ -115,7 +115,7 @@ class Bru {
115
115
  }
116
116
 
117
117
  getOauth2CredentialVar(key) {
118
- return this._interpolate(this.oauth2CredentialVariables[key]);
118
+ return this.interpolate(this.oauth2CredentialVariables[key]);
119
119
  }
120
120
 
121
121
  hasVar(key) {
@@ -130,7 +130,7 @@ class Bru {
130
130
  if (variableNameRegex.test(key) === false) {
131
131
  throw new Error(
132
132
  `Variable name: "${key}" contains invalid characters!` +
133
- ' Names must only contain alpha-numeric characters, "-", "_", "."'
133
+ ' Names must only contain alpha-numeric characters, "-", "_", "."'
134
134
  );
135
135
  }
136
136
 
@@ -150,11 +150,11 @@ class Bru {
150
150
  if (variableNameRegex.test(key) === false) {
151
151
  throw new Error(
152
152
  `Variable name: "${key}" contains invalid characters!` +
153
- ' Names must only contain alpha-numeric characters, "-", "_", "."'
153
+ ' Names must only contain alpha-numeric characters, "-", "_", "."'
154
154
  );
155
155
  }
156
156
 
157
- return this._interpolate(this.runtimeVariables[key]);
157
+ return this.interpolate(this.runtimeVariables[key]);
158
158
  }
159
159
 
160
160
  deleteVar(key) {
@@ -170,15 +170,15 @@ class Bru {
170
170
  }
171
171
 
172
172
  getCollectionVar(key) {
173
- return this._interpolate(this.collectionVariables[key]);
173
+ return this.interpolate(this.collectionVariables[key]);
174
174
  }
175
175
 
176
176
  getFolderVar(key) {
177
- return this._interpolate(this.folderVariables[key]);
177
+ return this.interpolate(this.folderVariables[key]);
178
178
  }
179
179
 
180
180
  getRequestVar(key) {
181
- return this._interpolate(this.requestVariables[key]);
181
+ return this.interpolate(this.requestVariables[key]);
182
182
  }
183
183
 
184
184
  setNextRequest(nextRequest) {
@@ -215,6 +215,10 @@ class Bru {
215
215
  sleep(ms) {
216
216
  return new Promise((resolve) => setTimeout(resolve, ms));
217
217
  }
218
+
219
+ getCollectionName() {
220
+ return this.collectionName;
221
+ }
218
222
  }
219
223
 
220
224
  class IterationDataManager {
@@ -21,7 +21,7 @@ class BrunoRequest {
21
21
  this.headers = req.headers;
22
22
  this.timeout = req.timeout;
23
23
  this.historyLogger = historyLogger;
24
-
24
+ this.name = req.name;
25
25
  /**
26
26
  * We automatically parse the JSON body if the content type is JSON
27
27
  * This is to make it easier for the user to access the body directly
@@ -198,6 +198,10 @@ class BrunoRequest {
198
198
  getExecutionMode() {
199
199
  return this.req.__bruno__executionMode;
200
200
  }
201
+
202
+ getName() {
203
+ return this.req.name;
204
+ }
201
205
  }
202
206
 
203
207
  module.exports = BrunoRequest;
@@ -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');
@@ -51,7 +54,8 @@ class ScriptRuntime {
51
54
  scriptingConfig,
52
55
  historyLogger,
53
56
  secretVariables,
54
- runRequestByItemPathname
57
+ runRequestByItemPathname,
58
+ collectionName
55
59
  ) {
56
60
  let visualizations = [];
57
61
  let setVisualizations = (data) => {
@@ -63,8 +67,9 @@ class ScriptRuntime {
63
67
  const folderVariables = request?.folderVariables || {};
64
68
  const requestVariables = request?.requestVariables || {};
65
69
  const iterationDetails = request?.runnerIterationDetails || {};
70
+ const assertionResults = request?.assertionResults || [];
66
71
  // TODO please clean this up
67
- const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails);
72
+ const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName);
68
73
  const req = new BrunoRequest(request);
69
74
  const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
70
75
  const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []);
@@ -85,9 +90,16 @@ class ScriptRuntime {
85
90
  }
86
91
  }
87
92
 
93
+ // extend bru with result getter methods
94
+ const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
95
+
88
96
  const context = {
89
97
  bru,
90
- req
98
+ req,
99
+ test,
100
+ expect: chai.expect,
101
+ assert: chai.assert,
102
+ __brunoTestResults: __brunoTestResults
91
103
  };
92
104
 
93
105
  if (onConsoleLog && typeof onConsoleLog === 'function') {
@@ -105,7 +117,7 @@ class ScriptRuntime {
105
117
  };
106
118
  }
107
119
 
108
- if(runRequestByItemPathname) {
120
+ if (runRequestByItemPathname) {
109
121
  context.bru.runRequest = runRequestByItemPathname;
110
122
  }
111
123
 
@@ -122,6 +134,7 @@ class ScriptRuntime {
122
134
  runtimeVariables: cleanJson(runtimeVariables),
123
135
  visualizations,
124
136
  globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
137
+ results: cleanJson(__brunoTestResults.getResults()),
125
138
  nextRequestName: bru.nextRequest,
126
139
  skipRequest: bru.skipRequest,
127
140
  stopExecution: bru.stopExecution
@@ -159,7 +172,7 @@ class ScriptRuntime {
159
172
  chai,
160
173
  'node-fetch': fetch,
161
174
  'crypto-js': CryptoJS,
162
- 'xml2js': xml2js,
175
+ xml2js: xml2js,
163
176
  cheerio,
164
177
  tv4,
165
178
  ...whitelistedModules,
@@ -177,6 +190,7 @@ class ScriptRuntime {
177
190
  runtimeVariables: cleanJson(runtimeVariables),
178
191
  visualizations,
179
192
  globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
193
+ results: cleanJson(__brunoTestResults.getResults()),
180
194
  nextRequestName: bru.nextRequest,
181
195
  skipRequest: bru.skipRequest,
182
196
  stopExecution: bru.stopExecution
@@ -195,7 +209,8 @@ class ScriptRuntime {
195
209
  scriptingConfig,
196
210
  historyLogger,
197
211
  secretVariables,
198
- runRequestByItemPathname
212
+ runRequestByItemPathname,
213
+ collectionName
199
214
  ) {
200
215
  let visualizations = [];
201
216
  let setVisualizations = (data) => {
@@ -207,7 +222,8 @@ class ScriptRuntime {
207
222
  const folderVariables = request?.folderVariables || {};
208
223
  const requestVariables = request?.requestVariables || {};
209
224
  const iterationDetails = request?.runnerIterationDetails || {};
210
- const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails);
225
+ const assertionResults = request?.assertionResults || [];
226
+ const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName);
211
227
  const req = new BrunoRequest(request);
212
228
  const res = new BrunoResponse(response);
213
229
  const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
@@ -229,10 +245,17 @@ class ScriptRuntime {
229
245
  }
230
246
  }
231
247
 
248
+ // extend bru with result getter methods
249
+ const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
250
+
232
251
  const context = {
233
252
  bru,
234
253
  req,
235
- res
254
+ res,
255
+ test,
256
+ expect: chai.expect,
257
+ assert: chai.assert,
258
+ __brunoTestResults: __brunoTestResults
236
259
  };
237
260
 
238
261
  if (onConsoleLog && typeof onConsoleLog === 'function') {
@@ -250,7 +273,7 @@ class ScriptRuntime {
250
273
  };
251
274
  }
252
275
 
253
- if(runRequestByItemPathname) {
276
+ if (runRequestByItemPathname) {
254
277
  context.bru.runRequest = runRequestByItemPathname;
255
278
  }
256
279
 
@@ -267,6 +290,7 @@ class ScriptRuntime {
267
290
  runtimeVariables: cleanJson(runtimeVariables),
268
291
  visualizations,
269
292
  globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
293
+ results: cleanJson(__brunoTestResults.getResults()),
270
294
  nextRequestName: bru.nextRequest,
271
295
  skipRequest: bru.skipRequest,
272
296
  stopExecution: bru.stopExecution
@@ -322,6 +346,7 @@ class ScriptRuntime {
322
346
  runtimeVariables: cleanJson(runtimeVariables),
323
347
  visualizations,
324
348
  globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
349
+ results: cleanJson(__brunoTestResults.getResults()),
325
350
  nextRequestName: bru.nextRequest,
326
351
  skipRequest: bru.skipRequest,
327
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, appendAwaitToTestFunc } = require('../utils');
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';
@@ -71,7 +53,8 @@ class TestRuntime {
71
53
  scriptingConfig,
72
54
  historyLogger,
73
55
  secretVariables,
74
- runRequestByItemPathname
56
+ runRequestByItemPathname,
57
+ collectionName
75
58
  ) {
76
59
  const globalEnvironmentVariables = request?.globalEnvironmentVariables || {};
77
60
  const oauth2CredentialVariables = request?.oauth2CredentialVariables || {};
@@ -80,7 +63,7 @@ class TestRuntime {
80
63
  const requestVariables = request?.requestVariables || {};
81
64
  const iterationDetails = request?.runnerIterationDetails || {};
82
65
  const assertionResults = request?.assertionResults || [];
83
- const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, undefined, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails);
66
+ const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, undefined, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName);
84
67
  const req = new BrunoRequest(request, historyLogger);
85
68
  const res = new BrunoResponse(response);
86
69
  const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
@@ -102,9 +85,8 @@ class TestRuntime {
102
85
  }
103
86
  }
104
87
 
105
- const __brunoTestResults = new TestResults();
106
-
107
- const test = Test(__brunoTestResults, chai);
88
+ // extend bru with result getter methods
89
+ const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
108
90
 
109
91
  if (!testsFile || !testsFile.length) {
110
92
  return {
@@ -117,36 +99,6 @@ class TestRuntime {
117
99
  };
118
100
  }
119
101
 
120
- bru.getTestResults = async () => {
121
- let results = await __brunoTestResults.getResults();
122
- const summary = getResultsSummary(results);
123
- return {
124
- summary,
125
- results: results?.map?.(r => ({
126
- status: r?.status,
127
- description: r?.description,
128
- expected: r?.expected,
129
- actual: r?.actual,
130
- error: r?.error
131
- }))
132
- };
133
- }
134
- bru.getAssertionResults = async () => {
135
- let results = assertionResults;
136
- const summary = getResultsSummary(results);
137
- return {
138
- summary,
139
- results: results?.map?.(r => ({
140
- status: r?.status,
141
- lhsExpr: r?.lhsExpr,
142
- rhsExpr: r?.rhsExpr,
143
- operator: r?.operator,
144
- rhsOperand: r?.rhsOperand,
145
- error: r?.error
146
- }))
147
- };
148
- }
149
-
150
102
  const context = {
151
103
  test,
152
104
  bru,
@@ -18,12 +18,24 @@ const addBruShimToContext = (vm, bru) => {
18
18
  vm.setProp(bruObject, 'getEnvName', getEnvName);
19
19
  getEnvName.dispose();
20
20
 
21
+ let getCollectionName = vm.newFunction('getCollectionName', function () {
22
+ return marshallToVm(bru.getCollectionName(), vm);
23
+ });
24
+ vm.setProp(bruObject, 'getCollectionName', getCollectionName);
25
+ getCollectionName.dispose();
26
+
21
27
  let getProcessEnv = vm.newFunction('getProcessEnv', function (key) {
22
28
  return marshallToVm(bru.getProcessEnv(vm.dump(key)), vm);
23
29
  });
24
30
  vm.setProp(bruObject, 'getProcessEnv', getProcessEnv);
25
31
  getProcessEnv.dispose();
26
32
 
33
+ let interpolate = vm.newFunction('interpolate', function (str) {
34
+ return marshallToVm(bru.interpolate(vm.dump(str)), vm);
35
+ });
36
+ vm.setProp(bruObject, 'interpolate', interpolate);
37
+ interpolate.dispose();
38
+
27
39
  let hasEnvVar = vm.newFunction('hasEnvVar', function (key) {
28
40
  return marshallToVm(bru.hasEnvVar(vm.dump(key)), vm);
29
41
  });
@@ -193,7 +205,8 @@ const addBruShimToContext = (vm, bru) => {
193
205
 
194
206
  let getTestResults = vm.newFunction('getTestResults', () => {
195
207
  const promise = vm.newPromise();
196
- bru.getTestResults()
208
+ bru
209
+ .getTestResults()
197
210
  .then((results) => {
198
211
  promise.resolve(marshallToVm(cleanJson(results), vm));
199
212
  })
@@ -214,7 +227,8 @@ const addBruShimToContext = (vm, bru) => {
214
227
 
215
228
  let getAssertionResults = vm.newFunction('getAssertionResults', () => {
216
229
  const promise = vm.newPromise();
217
- bru.getAssertionResults()
230
+ bru
231
+ .getAssertionResults()
218
232
  .then((results) => {
219
233
  promise.resolve(marshallToVm(cleanJson(results), vm));
220
234
  })
@@ -235,7 +249,8 @@ const addBruShimToContext = (vm, bru) => {
235
249
 
236
250
  let runRequestHandle = vm.newFunction('runRequest', (args) => {
237
251
  const promise = vm.newPromise();
238
- bru.runRequest(vm.dump(args))
252
+ bru
253
+ .runRequest(vm.dump(args))
239
254
  .then((response) => {
240
255
  const { status, headers, data, dataBuffer, size, statusText } = response || {};
241
256
  promise.resolve(marshallToVm(cleanJson({ status, statusText, headers, data, dataBuffer, size }), vm));
@@ -8,18 +8,21 @@ const addBrunoRequestShimToContext = (vm, req) => {
8
8
  const headers = marshallToVm(req.getHeaders(), vm);
9
9
  const body = marshallToVm(req.getBody(), vm);
10
10
  const timeout = marshallToVm(req.getTimeout(), vm);
11
+ const name = marshallToVm(req.getName(), vm);
11
12
 
12
13
  vm.setProp(reqObject, 'url', url);
13
14
  vm.setProp(reqObject, 'method', method);
14
15
  vm.setProp(reqObject, 'headers', headers);
15
16
  vm.setProp(reqObject, 'body', body);
16
17
  vm.setProp(reqObject, 'timeout', timeout);
18
+ vm.setProp(reqObject, 'name', name);
17
19
 
18
20
  url.dispose();
19
21
  method.dispose();
20
22
  headers.dispose();
21
23
  body.dispose();
22
24
  timeout.dispose();
25
+ name.dispose();
23
26
 
24
27
  let getUrl = vm.newFunction('getUrl', function () {
25
28
  return marshallToVm(req.getUrl(), vm);
@@ -45,6 +48,12 @@ const addBrunoRequestShimToContext = (vm, req) => {
45
48
  vm.setProp(reqObject, 'getAuthMode', getAuthMode);
46
49
  getAuthMode.dispose();
47
50
 
51
+ let getName = vm.newFunction('getName', function () {
52
+ return marshallToVm(req.getName(), vm);
53
+ });
54
+ vm.setProp(reqObject, 'getName', getName);
55
+ getName.dispose();
56
+
48
57
  let setMethod = vm.newFunction('setMethod', function (method) {
49
58
  req.setMethod(vm.dump(method));
50
59
  });
@@ -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
+ };