@usebruno/js 0.7.0 → 0.9.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
package/src/bruno-request.js
CHANGED
|
@@ -5,6 +5,7 @@ class BrunoRequest {
|
|
|
5
5
|
this.method = req.method;
|
|
6
6
|
this.headers = req.headers;
|
|
7
7
|
this.body = req.data;
|
|
8
|
+
this.timeout = req.timeout;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
getUrl() {
|
|
@@ -50,6 +51,14 @@ class BrunoRequest {
|
|
|
50
51
|
setMaxRedirects(maxRedirects) {
|
|
51
52
|
this.req.maxRedirects = maxRedirects;
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
getTimeout() {
|
|
56
|
+
return this.req.timeout;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setTimeout(timeout) {
|
|
60
|
+
this.req.timeout = timeout;
|
|
61
|
+
}
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
module.exports = BrunoRequest;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const Handlebars = require('handlebars');
|
|
2
|
+
const { forOwn, cloneDeep } = require('lodash');
|
|
3
|
+
|
|
4
|
+
const interpolateEnvVars = (str, processEnvVars) => {
|
|
5
|
+
if (!str || !str.length || typeof str !== 'string') {
|
|
6
|
+
return str;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const template = Handlebars.compile(str, { noEscape: true });
|
|
10
|
+
|
|
11
|
+
return template({
|
|
12
|
+
process: {
|
|
13
|
+
env: {
|
|
14
|
+
...processEnvVars
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const interpolateString = (str, { envVariables, collectionVariables, processEnvVars }) => {
|
|
21
|
+
if (!str || !str.length || typeof str !== 'string') {
|
|
22
|
+
return str;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
processEnvVars = processEnvVars || {};
|
|
26
|
+
collectionVariables = collectionVariables || {};
|
|
27
|
+
|
|
28
|
+
// we clone envVariables because we don't want to modify the original object
|
|
29
|
+
envVariables = envVariables ? cloneDeep(envVariables) : {};
|
|
30
|
+
|
|
31
|
+
// envVariables can inturn have values as {{process.env.VAR_NAME}}
|
|
32
|
+
// so we need to interpolate envVariables first with processEnvVars
|
|
33
|
+
forOwn(envVariables, (value, key) => {
|
|
34
|
+
envVariables[key] = interpolateEnvVars(value, processEnvVars);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const template = Handlebars.compile(str, { noEscape: true });
|
|
38
|
+
|
|
39
|
+
// collectionVariables take precedence over envVariables
|
|
40
|
+
const combinedVars = {
|
|
41
|
+
...envVariables,
|
|
42
|
+
...collectionVariables,
|
|
43
|
+
process: {
|
|
44
|
+
env: {
|
|
45
|
+
...processEnvVars
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return template(combinedVars);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
module.exports = {
|
|
54
|
+
interpolateString
|
|
55
|
+
};
|
|
@@ -4,8 +4,10 @@ const { nanoid } = require('nanoid');
|
|
|
4
4
|
const Bru = require('../bru');
|
|
5
5
|
const BrunoRequest = require('../bruno-request');
|
|
6
6
|
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils');
|
|
7
|
+
const { interpolateString } = require('../interpolate-string');
|
|
7
8
|
|
|
8
9
|
const { expect } = chai;
|
|
10
|
+
chai.use(require('chai-string'));
|
|
9
11
|
chai.use(function (chai, utils) {
|
|
10
12
|
// Custom assertion for checking if a variable is JSON
|
|
11
13
|
chai.Assertion.addProperty('json', function () {
|
|
@@ -160,17 +162,27 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => {
|
|
|
160
162
|
return;
|
|
161
163
|
}
|
|
162
164
|
|
|
165
|
+
const interpolationContext = {
|
|
166
|
+
collectionVariables: context.bru.collectionVariables,
|
|
167
|
+
envVariables: context.bru.envVariables,
|
|
168
|
+
processEnvVars: context.bru.processEnvVars
|
|
169
|
+
};
|
|
170
|
+
|
|
163
171
|
// gracefully allow both a,b as well as [a, b]
|
|
164
172
|
if (operator === 'in' || operator === 'notIn') {
|
|
165
173
|
if (rhsOperand.startsWith('[') && rhsOperand.endsWith(']')) {
|
|
166
174
|
rhsOperand = rhsOperand.substring(1, rhsOperand.length - 1);
|
|
167
175
|
}
|
|
168
176
|
|
|
169
|
-
return rhsOperand
|
|
177
|
+
return rhsOperand
|
|
178
|
+
.split(',')
|
|
179
|
+
.map((v) => evaluateJsTemplateLiteral(interpolateString(v.trim(), interpolationContext), context));
|
|
170
180
|
}
|
|
171
181
|
|
|
172
182
|
if (operator === 'between') {
|
|
173
|
-
const [lhs, rhs] = rhsOperand
|
|
183
|
+
const [lhs, rhs] = rhsOperand
|
|
184
|
+
.split(',')
|
|
185
|
+
.map((v) => evaluateJsTemplateLiteral(interpolateString(v.trim(), interpolationContext), context));
|
|
174
186
|
return [lhs, rhs];
|
|
175
187
|
}
|
|
176
188
|
|
|
@@ -180,10 +192,10 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => {
|
|
|
180
192
|
rhsOperand = rhsOperand.substring(1, rhsOperand.length - 1);
|
|
181
193
|
}
|
|
182
194
|
|
|
183
|
-
return rhsOperand;
|
|
195
|
+
return interpolateString(rhsOperand, interpolationContext);
|
|
184
196
|
}
|
|
185
197
|
|
|
186
|
-
return evaluateJsTemplateLiteral(rhsOperand, context);
|
|
198
|
+
return evaluateJsTemplateLiteral(interpolateString(rhsOperand, interpolationContext), context);
|
|
187
199
|
};
|
|
188
200
|
|
|
189
201
|
class AssertRuntime {
|
|
@@ -268,7 +280,7 @@ class AssertRuntime {
|
|
|
268
280
|
expect(lhs).to.endWith(rhs);
|
|
269
281
|
break;
|
|
270
282
|
case 'between':
|
|
271
|
-
const [min, max] =
|
|
283
|
+
const [min, max] = rhs;
|
|
272
284
|
expect(lhs).to.be.within(min, max);
|
|
273
285
|
break;
|
|
274
286
|
case 'isEmpty':
|
|
@@ -8,12 +8,14 @@ const zlib = require('zlib');
|
|
|
8
8
|
const url = require('url');
|
|
9
9
|
const punycode = require('punycode');
|
|
10
10
|
const fs = require('fs');
|
|
11
|
+
const { get } = require('lodash');
|
|
11
12
|
const Bru = require('../bru');
|
|
12
13
|
const BrunoRequest = require('../bruno-request');
|
|
13
14
|
const BrunoResponse = require('../bruno-response');
|
|
14
15
|
const { cleanJson } = require('../utils');
|
|
15
16
|
|
|
16
17
|
// Inbuilt Library Support
|
|
18
|
+
const ajv = require('ajv');
|
|
17
19
|
const atob = require('atob');
|
|
18
20
|
const btoa = require('btoa');
|
|
19
21
|
const lodash = require('lodash');
|
|
@@ -38,10 +40,23 @@ class ScriptRuntime {
|
|
|
38
40
|
collectionPath,
|
|
39
41
|
onConsoleLog,
|
|
40
42
|
processEnvVars,
|
|
41
|
-
|
|
43
|
+
scriptingConfig
|
|
42
44
|
) {
|
|
43
45
|
const bru = new Bru(envVariables, collectionVariables, processEnvVars, collectionPath);
|
|
44
46
|
const req = new BrunoRequest(request);
|
|
47
|
+
const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
|
|
48
|
+
const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []);
|
|
49
|
+
|
|
50
|
+
const whitelistedModules = {};
|
|
51
|
+
|
|
52
|
+
for (let module of moduleWhitelist) {
|
|
53
|
+
try {
|
|
54
|
+
whitelistedModules[module] = require(module);
|
|
55
|
+
} catch (e) {
|
|
56
|
+
// Ignore
|
|
57
|
+
console.warn(e);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
45
60
|
|
|
46
61
|
const context = {
|
|
47
62
|
bru,
|
|
@@ -56,6 +71,7 @@ class ScriptRuntime {
|
|
|
56
71
|
};
|
|
57
72
|
context.console = {
|
|
58
73
|
log: customLogger('log'),
|
|
74
|
+
debug: customLogger('debug'),
|
|
59
75
|
info: customLogger('info'),
|
|
60
76
|
warn: customLogger('warn'),
|
|
61
77
|
error: customLogger('error')
|
|
@@ -79,6 +95,7 @@ class ScriptRuntime {
|
|
|
79
95
|
punycode,
|
|
80
96
|
zlib,
|
|
81
97
|
// 3rd party libs
|
|
98
|
+
ajv,
|
|
82
99
|
atob,
|
|
83
100
|
btoa,
|
|
84
101
|
lodash,
|
|
@@ -89,6 +106,7 @@ class ScriptRuntime {
|
|
|
89
106
|
chai,
|
|
90
107
|
'node-fetch': fetch,
|
|
91
108
|
'crypto-js': CryptoJS,
|
|
109
|
+
...whitelistedModules,
|
|
92
110
|
fs: allowScriptFilesystemAccess ? fs : undefined
|
|
93
111
|
}
|
|
94
112
|
}
|
|
@@ -111,11 +129,24 @@ class ScriptRuntime {
|
|
|
111
129
|
collectionPath,
|
|
112
130
|
onConsoleLog,
|
|
113
131
|
processEnvVars,
|
|
114
|
-
|
|
132
|
+
scriptingConfig
|
|
115
133
|
) {
|
|
116
134
|
const bru = new Bru(envVariables, collectionVariables, processEnvVars, collectionPath);
|
|
117
135
|
const req = new BrunoRequest(request);
|
|
118
136
|
const res = new BrunoResponse(response);
|
|
137
|
+
const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
|
|
138
|
+
const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []);
|
|
139
|
+
|
|
140
|
+
const whitelistedModules = {};
|
|
141
|
+
|
|
142
|
+
for (let module of moduleWhitelist) {
|
|
143
|
+
try {
|
|
144
|
+
whitelistedModules[module] = require(module);
|
|
145
|
+
} catch (e) {
|
|
146
|
+
// Ignore
|
|
147
|
+
console.warn(e);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
119
150
|
|
|
120
151
|
const context = {
|
|
121
152
|
bru,
|
|
@@ -154,6 +185,7 @@ class ScriptRuntime {
|
|
|
154
185
|
punycode,
|
|
155
186
|
zlib,
|
|
156
187
|
// 3rd party libs
|
|
188
|
+
ajv,
|
|
157
189
|
atob,
|
|
158
190
|
btoa,
|
|
159
191
|
lodash,
|
|
@@ -163,6 +195,7 @@ class ScriptRuntime {
|
|
|
163
195
|
axios,
|
|
164
196
|
'node-fetch': fetch,
|
|
165
197
|
'crypto-js': CryptoJS,
|
|
198
|
+
...whitelistedModules,
|
|
166
199
|
fs: allowScriptFilesystemAccess ? fs : undefined
|
|
167
200
|
}
|
|
168
201
|
}
|
|
@@ -9,6 +9,7 @@ const zlib = require('zlib');
|
|
|
9
9
|
const url = require('url');
|
|
10
10
|
const punycode = require('punycode');
|
|
11
11
|
const fs = require('fs');
|
|
12
|
+
const { get } = require('lodash');
|
|
12
13
|
const Bru = require('../bru');
|
|
13
14
|
const BrunoRequest = require('../bruno-request');
|
|
14
15
|
const BrunoResponse = require('../bruno-response');
|
|
@@ -17,13 +18,15 @@ const TestResults = require('../test-results');
|
|
|
17
18
|
const { cleanJson } = require('../utils');
|
|
18
19
|
|
|
19
20
|
// Inbuilt Library Support
|
|
21
|
+
const ajv = require('ajv');
|
|
20
22
|
const atob = require('atob');
|
|
21
|
-
const axios = require('axios');
|
|
22
23
|
const btoa = require('btoa');
|
|
23
24
|
const lodash = require('lodash');
|
|
24
25
|
const moment = require('moment');
|
|
25
26
|
const uuid = require('uuid');
|
|
26
27
|
const nanoid = require('nanoid');
|
|
28
|
+
const axios = require('axios');
|
|
29
|
+
const fetch = require('node-fetch');
|
|
27
30
|
const CryptoJS = require('crypto-js');
|
|
28
31
|
|
|
29
32
|
class TestRuntime {
|
|
@@ -38,11 +41,24 @@ class TestRuntime {
|
|
|
38
41
|
collectionPath,
|
|
39
42
|
onConsoleLog,
|
|
40
43
|
processEnvVars,
|
|
41
|
-
|
|
44
|
+
scriptingConfig
|
|
42
45
|
) {
|
|
43
46
|
const bru = new Bru(envVariables, collectionVariables, processEnvVars, collectionPath);
|
|
44
47
|
const req = new BrunoRequest(request);
|
|
45
48
|
const res = new BrunoResponse(response);
|
|
49
|
+
const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
|
|
50
|
+
const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []);
|
|
51
|
+
|
|
52
|
+
const whitelistedModules = {};
|
|
53
|
+
|
|
54
|
+
for (let module of moduleWhitelist) {
|
|
55
|
+
try {
|
|
56
|
+
whitelistedModules[module] = require(module);
|
|
57
|
+
} catch (e) {
|
|
58
|
+
// Ignore
|
|
59
|
+
console.warn(e);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
46
62
|
|
|
47
63
|
const __brunoTestResults = new TestResults();
|
|
48
64
|
const test = Test(__brunoTestResults, chai);
|
|
@@ -97,15 +113,18 @@ class TestRuntime {
|
|
|
97
113
|
punycode,
|
|
98
114
|
zlib,
|
|
99
115
|
// 3rd party libs
|
|
100
|
-
|
|
101
|
-
axios,
|
|
116
|
+
ajv,
|
|
102
117
|
btoa,
|
|
118
|
+
atob,
|
|
103
119
|
lodash,
|
|
104
120
|
moment,
|
|
105
121
|
uuid,
|
|
106
122
|
nanoid,
|
|
123
|
+
axios,
|
|
107
124
|
chai,
|
|
125
|
+
'node-fetch': fetch,
|
|
108
126
|
'crypto-js': CryptoJS,
|
|
127
|
+
...whitelistedModules,
|
|
109
128
|
fs: allowScriptFilesystemAccess ? fs : undefined
|
|
110
129
|
}
|
|
111
130
|
}
|