@usebruno/js 0.1.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 +23 -0
- package/readme.md +8 -0
- package/src/bru.js +38 -0
- package/src/bruno-request.js +51 -0
- package/src/bruno-response.js +27 -0
- package/src/index.js +11 -0
- package/src/runtime/assert-runtime.js +226 -0
- package/src/runtime/script-runtime.js +93 -0
- package/src/runtime/test-runtime.js +70 -0
- package/src/runtime/vars-runtime.js +62 -0
- package/src/test-results.js +18 -0
- package/src/test.js +27 -0
- package/src/utils.js +25 -0
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@usebruno/js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "src/index.js",
|
|
5
|
+
"files": [
|
|
6
|
+
"src",
|
|
7
|
+
"package.json"
|
|
8
|
+
],
|
|
9
|
+
"peerDependencies": {
|
|
10
|
+
"vm2": "^3.9.13"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"atob": "^2.1.2",
|
|
14
|
+
"ajv": "^8.12.0",
|
|
15
|
+
"btoa": "^1.2.1",
|
|
16
|
+
"crypto-js": "^4.1.1",
|
|
17
|
+
"json-query": "^2.2.2",
|
|
18
|
+
"lodash": "^4.17.21",
|
|
19
|
+
"moment": "^2.29.4",
|
|
20
|
+
"nanoid": "3.3.4",
|
|
21
|
+
"uuid": "^9.0.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/readme.md
ADDED
package/src/bru.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
class Bru {
|
|
3
|
+
constructor(envVariables, collectionVariables) {
|
|
4
|
+
this._envVariables = envVariables;
|
|
5
|
+
this._collectionVariables = collectionVariables;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
getEnvVar(key) {
|
|
9
|
+
return this._envVariables[key];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
setEnvVar(key, value) {
|
|
13
|
+
if(!key) {
|
|
14
|
+
throw new Error('Key is required');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// gracefully ignore if key is not present in environment
|
|
18
|
+
if(!this._envVariables.hasOwnProperty(key)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this._envVariables[key] = value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setVar(key, value) {
|
|
26
|
+
if(!key) {
|
|
27
|
+
throw new Error('Key is required');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this._collectionVariables[key] = value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getVar(key) {
|
|
34
|
+
return this._collectionVariables[key];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = Bru;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
class BrunoRequest {
|
|
2
|
+
constructor(req) {
|
|
3
|
+
this.req = req;
|
|
4
|
+
this.url = req.url;
|
|
5
|
+
this.method = req.method;
|
|
6
|
+
this.headers = req.headers;
|
|
7
|
+
this.body = req.data;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getUrl() {
|
|
11
|
+
return this.req.url;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
setUrl(url) {
|
|
15
|
+
this.req.url = url;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getMethod() {
|
|
19
|
+
return this.req.method;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setMethod(method) {
|
|
23
|
+
this.req.method = method;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getHeaders() {
|
|
27
|
+
return this.req.headers;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
setHeaders(headers) {
|
|
31
|
+
this.req.headers = headers;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getHeader(name) {
|
|
35
|
+
return this.req.headers[name];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
setHeader(name, value) {
|
|
39
|
+
this.req.headers[name] = value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getBody() {
|
|
43
|
+
return this.req.data;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
setBody(data) {
|
|
47
|
+
this.req.data = data;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = BrunoRequest;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class BrunoResponse {
|
|
2
|
+
constructor(res) {
|
|
3
|
+
this.res = res;
|
|
4
|
+
this.status = res.status;
|
|
5
|
+
this.statusText = res.statusText;
|
|
6
|
+
this.headers = res.headers;
|
|
7
|
+
this.body = res.data;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getStatus() {
|
|
11
|
+
return this.res.status;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
getHeader(name) {
|
|
15
|
+
return this.res.header[name];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getHeaders() {
|
|
19
|
+
return this.res.headers;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getBody() {
|
|
23
|
+
return this.res.data;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = BrunoResponse;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const ScriptRuntime = require('./runtime/script-runtime');
|
|
2
|
+
const TestRuntime = require('./runtime/test-runtime');
|
|
3
|
+
const VarsRuntime = require('./runtime/vars-runtime');
|
|
4
|
+
const AssertRuntime = require('./runtime/assert-runtime');
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
ScriptRuntime,
|
|
8
|
+
TestRuntime,
|
|
9
|
+
VarsRuntime,
|
|
10
|
+
AssertRuntime
|
|
11
|
+
};
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
const chai = require('chai');
|
|
3
|
+
const { nanoid } = require('nanoid');
|
|
4
|
+
const Bru = require('../bru');
|
|
5
|
+
const BrunoRequest = require('../bruno-request');
|
|
6
|
+
const { evaluateJsExpression, createResponseParser } = require('../utils');
|
|
7
|
+
|
|
8
|
+
const { expect } = chai;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Assertion operators
|
|
12
|
+
*
|
|
13
|
+
* eq : equal to
|
|
14
|
+
* neq : not equal to
|
|
15
|
+
* like : like
|
|
16
|
+
* gt : greater than
|
|
17
|
+
* gte : greater than or equal to
|
|
18
|
+
* lt : less than
|
|
19
|
+
* lte : less than or equal to
|
|
20
|
+
* in : in
|
|
21
|
+
* notIn : not in
|
|
22
|
+
* contains : contains
|
|
23
|
+
* notContains : not contains
|
|
24
|
+
* count : count
|
|
25
|
+
* length : length
|
|
26
|
+
* matches : matches
|
|
27
|
+
* notMatches : not matches
|
|
28
|
+
* startsWith : starts with
|
|
29
|
+
* endsWith : ends with
|
|
30
|
+
* between : between
|
|
31
|
+
* isEmpty : is empty
|
|
32
|
+
* isNull : is null
|
|
33
|
+
* isUndefined : is undefined
|
|
34
|
+
* isDefined : is defined
|
|
35
|
+
* isTruthy : is truthy
|
|
36
|
+
* isFalsy : is falsy
|
|
37
|
+
* isJson : is json
|
|
38
|
+
* isNumber : is number
|
|
39
|
+
* isString : is string
|
|
40
|
+
* isBoolean : is boolean
|
|
41
|
+
*/
|
|
42
|
+
const parseAssertionOperator = (str = '') => {
|
|
43
|
+
if(!str || typeof str !== 'string' || str.length) {
|
|
44
|
+
return {
|
|
45
|
+
operator: 'eq',
|
|
46
|
+
value: str
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const operators = [
|
|
51
|
+
'eq', 'neq', 'like', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn',
|
|
52
|
+
'contains', 'notContains', 'count', 'length', 'matches', 'notMatches',
|
|
53
|
+
'startsWith', 'endsWith', 'between', 'isEmpty', 'isNull', 'isUndefined',
|
|
54
|
+
'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean'
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const [operator, ...rest] = str.trim().split(' ');
|
|
58
|
+
const value = rest.join(' ');
|
|
59
|
+
|
|
60
|
+
if(operators.includes(operator)) {
|
|
61
|
+
return {
|
|
62
|
+
operator,
|
|
63
|
+
value
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
operator: 'eq',
|
|
69
|
+
value: str
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
class AssertRuntime {
|
|
74
|
+
runAssertions(assertions, request, response, envVariables, collectionVariables, collectionPath) {
|
|
75
|
+
const enabledAssertions = _.filter(assertions, (a) => a.enabled);
|
|
76
|
+
if(!enabledAssertions.length) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const bru = new Bru(envVariables, collectionVariables);
|
|
81
|
+
const req = new BrunoRequest(request);
|
|
82
|
+
const res = createResponseParser(response);
|
|
83
|
+
|
|
84
|
+
const bruContext = {
|
|
85
|
+
bru,
|
|
86
|
+
req,
|
|
87
|
+
res
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const context = {
|
|
91
|
+
...envVariables,
|
|
92
|
+
...collectionVariables,
|
|
93
|
+
...bruContext
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const assertionResults = [];
|
|
97
|
+
|
|
98
|
+
// parse assertion operators
|
|
99
|
+
for (const v of enabledAssertions) {
|
|
100
|
+
const lhsExpr = v.name;
|
|
101
|
+
const rhsExpr = v.value;
|
|
102
|
+
const {
|
|
103
|
+
operator,
|
|
104
|
+
value: rhsOperand
|
|
105
|
+
} = parseAssertionOperator(rhsExpr);
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const lhs = evaluateJsExpression(lhsExpr, context);
|
|
109
|
+
const rhs = evaluateJsExpression(rhsOperand, context);
|
|
110
|
+
|
|
111
|
+
switch(operator) {
|
|
112
|
+
case 'eq':
|
|
113
|
+
expect(lhs).to.equal(rhs);
|
|
114
|
+
break;
|
|
115
|
+
case 'neq':
|
|
116
|
+
expect(lhs).to.not.equal(rhs);
|
|
117
|
+
break;
|
|
118
|
+
case 'like':
|
|
119
|
+
expect(lhs).to.match(new RegExp(rhs));
|
|
120
|
+
break;
|
|
121
|
+
case 'gt':
|
|
122
|
+
expect(lhs).to.be.greaterThan(rhs);
|
|
123
|
+
break;
|
|
124
|
+
case 'gte':
|
|
125
|
+
expect(lhs).to.be.greaterThanOrEqual(rhs);
|
|
126
|
+
break;
|
|
127
|
+
case 'lt':
|
|
128
|
+
expect(lhs).to.be.lessThan(rhs);
|
|
129
|
+
break;
|
|
130
|
+
case 'lte':
|
|
131
|
+
expect(lhs).to.be.lessThanOrEqual(rhs);
|
|
132
|
+
break;
|
|
133
|
+
case 'in':
|
|
134
|
+
expect(lhs).to.be.oneOf(rhs);
|
|
135
|
+
break;
|
|
136
|
+
case 'notIn':
|
|
137
|
+
expect(lhs).to.not.be.oneOf(rhs);
|
|
138
|
+
break;
|
|
139
|
+
case 'contains':
|
|
140
|
+
expect(lhs).to.include(rhs);
|
|
141
|
+
break;
|
|
142
|
+
case 'notContains':
|
|
143
|
+
expect(lhs).to.not.include(rhs);
|
|
144
|
+
break;
|
|
145
|
+
case 'count':
|
|
146
|
+
expect(lhs).to.have.lengthOf(rhs);
|
|
147
|
+
break;
|
|
148
|
+
case 'length':
|
|
149
|
+
expect(lhs).to.have.lengthOf(rhs);
|
|
150
|
+
break;
|
|
151
|
+
case 'matches':
|
|
152
|
+
expect(lhs).to.match(new RegExp(rhs));
|
|
153
|
+
break;
|
|
154
|
+
case 'notMatches':
|
|
155
|
+
expect(lhs).to.not.match(new RegExp(rhs));
|
|
156
|
+
break;
|
|
157
|
+
case 'startsWith':
|
|
158
|
+
expect(lhs).to.startWith(rhs);
|
|
159
|
+
break;
|
|
160
|
+
case 'endsWith':
|
|
161
|
+
expect(lhs).to.endWith(rhs);
|
|
162
|
+
break;
|
|
163
|
+
case 'between':
|
|
164
|
+
const [min, max] = value.split(' ');
|
|
165
|
+
expect(lhs).to.be.within(min, max);
|
|
166
|
+
break;
|
|
167
|
+
case 'isEmpty':
|
|
168
|
+
expect(lhs).to.be.empty;
|
|
169
|
+
break;
|
|
170
|
+
case 'isNull':
|
|
171
|
+
expect(lhs).to.be.null;
|
|
172
|
+
break;
|
|
173
|
+
case 'isUndefined':
|
|
174
|
+
expect(lhs).to.be.undefined;
|
|
175
|
+
break;
|
|
176
|
+
case 'isDefined':
|
|
177
|
+
expect(lhs).to.not.be.undefined;
|
|
178
|
+
break;
|
|
179
|
+
case 'isTruthy':
|
|
180
|
+
expect(lhs).to.be.true;
|
|
181
|
+
break;
|
|
182
|
+
case 'isFalsy':
|
|
183
|
+
expect(lhs).to.be.false;
|
|
184
|
+
break;
|
|
185
|
+
case 'isJson':
|
|
186
|
+
expect(lhs).to.be.json;
|
|
187
|
+
break;
|
|
188
|
+
case 'isNumber':
|
|
189
|
+
expect(lhs).to.be.a('number');
|
|
190
|
+
break;
|
|
191
|
+
case 'isString':
|
|
192
|
+
expect(lhs).to.be.a('string');
|
|
193
|
+
break;
|
|
194
|
+
case 'isBoolean':
|
|
195
|
+
expect(lhs).to.be.a('boolean');
|
|
196
|
+
break;
|
|
197
|
+
default:
|
|
198
|
+
expect(lhs).to.equal(rhs);
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
assertionResults.push({
|
|
203
|
+
lhsExpr,
|
|
204
|
+
rhsExpr,
|
|
205
|
+
rhsOperand,
|
|
206
|
+
operator,
|
|
207
|
+
status: 'pass'
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
assertionResults.push({
|
|
212
|
+
lhsExpr,
|
|
213
|
+
rhsExpr,
|
|
214
|
+
rhsOperand,
|
|
215
|
+
operator,
|
|
216
|
+
status: 'fail',
|
|
217
|
+
error: err.message
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return assertionResults;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
module.exports = AssertRuntime;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const { NodeVM } = require('vm2');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const Bru = require('../bru');
|
|
4
|
+
const BrunoRequest = require('../bruno-request');
|
|
5
|
+
const BrunoResponse = require('../bruno-response');
|
|
6
|
+
|
|
7
|
+
// Inbuilt Library Support
|
|
8
|
+
const atob = require('atob');
|
|
9
|
+
const btoa = require('btoa');
|
|
10
|
+
const lodash = require('lodash');
|
|
11
|
+
const moment = require('moment');
|
|
12
|
+
const uuid = require('uuid');
|
|
13
|
+
const nanoid = require('nanoid');
|
|
14
|
+
const CryptoJS = require('crypto-js');
|
|
15
|
+
|
|
16
|
+
class ScriptRuntime {
|
|
17
|
+
constructor() {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
runRequestScript(script, request, environment, collectionVariables, collectionPath) {
|
|
21
|
+
const bru = new Bru(environment, collectionVariables);
|
|
22
|
+
const req = new BrunoRequest(request);
|
|
23
|
+
|
|
24
|
+
const context = {
|
|
25
|
+
bru,
|
|
26
|
+
req
|
|
27
|
+
};
|
|
28
|
+
const vm = new NodeVM({
|
|
29
|
+
sandbox: context,
|
|
30
|
+
require: {
|
|
31
|
+
context: 'sandbox',
|
|
32
|
+
external: true,
|
|
33
|
+
root: [collectionPath],
|
|
34
|
+
mock: {
|
|
35
|
+
atob,
|
|
36
|
+
btoa,
|
|
37
|
+
lodash,
|
|
38
|
+
moment,
|
|
39
|
+
uuid,
|
|
40
|
+
nanoid,
|
|
41
|
+
'crypto-js': CryptoJS
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
vm.run(script, path.join(collectionPath, 'vm.js'));
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
request,
|
|
50
|
+
environment,
|
|
51
|
+
collectionVariables
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
runResponseScript(script, request, response, environment, collectionVariables, collectionPath) {
|
|
56
|
+
const bru = new Bru(environment, collectionVariables);
|
|
57
|
+
const req = new BrunoRequest(request);
|
|
58
|
+
const res = new BrunoResponse(response);
|
|
59
|
+
|
|
60
|
+
const context = {
|
|
61
|
+
bru,
|
|
62
|
+
req,
|
|
63
|
+
res
|
|
64
|
+
};
|
|
65
|
+
const vm = new NodeVM({
|
|
66
|
+
sandbox: context,
|
|
67
|
+
require: {
|
|
68
|
+
context: 'sandbox',
|
|
69
|
+
external: true,
|
|
70
|
+
root: [collectionPath],
|
|
71
|
+
mock: {
|
|
72
|
+
atob,
|
|
73
|
+
btoa,
|
|
74
|
+
lodash,
|
|
75
|
+
moment,
|
|
76
|
+
uuid,
|
|
77
|
+
nanoid,
|
|
78
|
+
'crypto-js': CryptoJS
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
vm.run(script, path.join(collectionPath, 'vm.js'));
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
response,
|
|
87
|
+
environment,
|
|
88
|
+
collectionVariables
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = ScriptRuntime;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const { NodeVM } = require('vm2');
|
|
2
|
+
const chai = require('chai');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const Bru = require('../bru');
|
|
5
|
+
const BrunoRequest = require('../bruno-request');
|
|
6
|
+
const BrunoResponse = require('../bruno-response');
|
|
7
|
+
const Test = require('../test');
|
|
8
|
+
const TestResults = require('../test-results');
|
|
9
|
+
|
|
10
|
+
// Inbuilt Library Support
|
|
11
|
+
const atob = require('atob');
|
|
12
|
+
const btoa = require('btoa');
|
|
13
|
+
const lodash = require('lodash');
|
|
14
|
+
const moment = require('moment');
|
|
15
|
+
const uuid = require('uuid');
|
|
16
|
+
const nanoid = require('nanoid');
|
|
17
|
+
const CryptoJS = require('crypto-js');
|
|
18
|
+
|
|
19
|
+
class TestRuntime {
|
|
20
|
+
constructor() {
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
runTests(testsFile, request, response, environment, collectionVariables, collectionPath) {
|
|
24
|
+
const bru = new Bru(environment, collectionVariables);
|
|
25
|
+
const req = new BrunoRequest(request);
|
|
26
|
+
const res = new BrunoResponse(response);
|
|
27
|
+
|
|
28
|
+
const __brunoTestResults = new TestResults();
|
|
29
|
+
const test = Test(__brunoTestResults, chai);
|
|
30
|
+
|
|
31
|
+
const context = {
|
|
32
|
+
test,
|
|
33
|
+
bru,
|
|
34
|
+
req,
|
|
35
|
+
res,
|
|
36
|
+
expect: chai.expect,
|
|
37
|
+
assert: chai.assert,
|
|
38
|
+
__brunoTestResults: __brunoTestResults
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const vm = new NodeVM({
|
|
42
|
+
sandbox: context,
|
|
43
|
+
require: {
|
|
44
|
+
context: 'sandbox',
|
|
45
|
+
external: true,
|
|
46
|
+
root: [collectionPath],
|
|
47
|
+
mock: {
|
|
48
|
+
atob,
|
|
49
|
+
btoa,
|
|
50
|
+
lodash,
|
|
51
|
+
moment,
|
|
52
|
+
uuid,
|
|
53
|
+
nanoid,
|
|
54
|
+
'crypto-js': CryptoJS
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
vm.run(testsFile, path.join(collectionPath, 'vm.js'));
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
request,
|
|
63
|
+
environment,
|
|
64
|
+
collectionVariables,
|
|
65
|
+
results: __brunoTestResults.getResults()
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = TestRuntime;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
const Bru = require('../bru');
|
|
3
|
+
const BrunoRequest = require('../bruno-request');
|
|
4
|
+
const { evaluateJsExpression, createResponseParser } = require('../utils');
|
|
5
|
+
|
|
6
|
+
class VarsRuntime {
|
|
7
|
+
runPreRequestVars(vars, request, envVariables, collectionVariables, collectionPath) {
|
|
8
|
+
const enabledVars = _.filter(vars, (v) => v.enabled);
|
|
9
|
+
if(!enabledVars.length) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const bru = new Bru(envVariables, collectionVariables);
|
|
14
|
+
const req = new BrunoRequest(request);
|
|
15
|
+
|
|
16
|
+
const bruContext = {
|
|
17
|
+
bru,
|
|
18
|
+
req
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const context = {
|
|
22
|
+
...envVariables,
|
|
23
|
+
...collectionVariables,
|
|
24
|
+
...bruContext
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_.each(enabledVars, (v) => {
|
|
28
|
+
const value = evaluateJsExpression(v.value, context);
|
|
29
|
+
bru.setVar(v.name, value);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
runPostResponseVars(vars, request, response, envVariables, collectionVariables, collectionPath) {
|
|
34
|
+
const enabledVars = _.filter(vars, (v) => v.enabled);
|
|
35
|
+
if(!enabledVars.length) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const bru = new Bru(envVariables, collectionVariables);
|
|
40
|
+
const req = new BrunoRequest(request);
|
|
41
|
+
const res = createResponseParser(response);
|
|
42
|
+
|
|
43
|
+
const bruContext = {
|
|
44
|
+
bru,
|
|
45
|
+
req,
|
|
46
|
+
res
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const context = {
|
|
50
|
+
...envVariables,
|
|
51
|
+
...collectionVariables,
|
|
52
|
+
...bruContext
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_.each(enabledVars, (v) => {
|
|
56
|
+
const value = evaluateJsExpression(v.value, context);
|
|
57
|
+
bru.setVar(v.name, value);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = VarsRuntime;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const { nanoid } = require('nanoid');
|
|
2
|
+
|
|
3
|
+
class TestResults {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.results = [];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
addResult(result) {
|
|
9
|
+
result.uid = nanoid();
|
|
10
|
+
this.results.push(result);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getResults() {
|
|
14
|
+
return this.results;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = TestResults;
|
package/src/test.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const Test = (__brunoTestResults, chai) => (description, callback) => {
|
|
2
|
+
try {
|
|
3
|
+
callback();
|
|
4
|
+
__brunoTestResults.addResult({ description, status: "pass" });
|
|
5
|
+
} catch (error) {
|
|
6
|
+
console.log(chai.AssertionError);
|
|
7
|
+
if (error instanceof chai.AssertionError) {
|
|
8
|
+
const { message, actual, expected } = error;
|
|
9
|
+
__brunoTestResults.addResult({
|
|
10
|
+
description,
|
|
11
|
+
status: "fail",
|
|
12
|
+
error: message,
|
|
13
|
+
actual,
|
|
14
|
+
expected
|
|
15
|
+
});
|
|
16
|
+
} else {
|
|
17
|
+
__brunoTestResults.addResult({
|
|
18
|
+
description,
|
|
19
|
+
status: "fail",
|
|
20
|
+
error: error.message || 'An unexpected error occurred.'
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
console.log(error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = Test;
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const jsonQuery = require('json-query');
|
|
2
|
+
|
|
3
|
+
const evaluateJsExpression = (expression, context) => {
|
|
4
|
+
const fn = new Function(...Object.keys(context), `return ${expression}`);
|
|
5
|
+
return fn(...Object.values(context));
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const createResponseParser = (response = {}) => {
|
|
9
|
+
const res = (expr) => {
|
|
10
|
+
const output = jsonQuery(expr, { data: response.data });
|
|
11
|
+
return output ? output.value : null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
res.status = response.status;
|
|
15
|
+
res.statusText = response.statusText;
|
|
16
|
+
res.headers = response.headers;
|
|
17
|
+
res.body = response.data;
|
|
18
|
+
|
|
19
|
+
return res;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
evaluateJsExpression,
|
|
24
|
+
createResponseParser
|
|
25
|
+
};
|