@usebruno/js
Advanced tools
Comparing version 0.2.0 to 0.3.0
{ | ||
"name": "@usebruno/js", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"main": "src/index.js", | ||
@@ -17,4 +17,4 @@ "files": [ | ||
"@usebruno/query": "0.1.0", | ||
"ajv": "^8.12.0", | ||
"atob": "^2.1.2", | ||
"ajv": "^8.12.0", | ||
"btoa": "^1.2.1", | ||
@@ -28,2 +28,2 @@ "crypto-js": "^4.1.1", | ||
} | ||
} | ||
} |
const _ = require('lodash'); | ||
const chai = require('chai'); | ||
const chai = require('chai'); | ||
const { nanoid } = require('nanoid'); | ||
const Bru = require('../bru'); | ||
const BrunoRequest = require('../bruno-request'); | ||
const { evaluateJsExpression, createResponseParser } = require('../utils'); | ||
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils'); | ||
const { expect } = chai; | ||
chai.use(function (chai, utils) { | ||
// Custom assertion for checking if a variable is JSON | ||
chai.Assertion.addProperty('json', function () { | ||
const obj = this._obj; | ||
const isJson = typeof obj === 'object' && obj !== null && !Array.isArray(obj) && obj.constructor === Object; | ||
this.assert( | ||
isJson, | ||
`expected ${utils.inspect(obj)} to be JSON`, | ||
`expected ${utils.inspect(obj)} not to be JSON` | ||
); | ||
}); | ||
}); | ||
// Custom assertion for matching regex | ||
chai.use(function (chai, utils) { | ||
chai.Assertion.addMethod('match', function (regex) { | ||
const obj = this._obj; | ||
let match = false; | ||
if(obj === undefined) { | ||
match = false; | ||
} else { | ||
match = regex.test(obj); | ||
} | ||
this.assert( | ||
match, | ||
`expected ${utils.inspect(obj)} to match ${regex}`, | ||
`expected ${utils.inspect(obj)} not to match ${regex}` | ||
); | ||
}); | ||
}); | ||
/** | ||
@@ -14,3 +47,2 @@ * Assertion operators | ||
* neq : not equal to | ||
* like : like | ||
* gt : greater than | ||
@@ -24,3 +56,2 @@ * gte : greater than or equal to | ||
* notContains : not contains | ||
* count : count | ||
* length : length | ||
@@ -52,4 +83,4 @@ * matches : matches | ||
const operators = [ | ||
'eq', 'neq', 'like', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn', | ||
'contains', 'notContains', 'count', 'length', 'matches', 'notMatches', | ||
'eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn', | ||
'contains', 'notContains', 'length', 'matches', 'notMatches', | ||
'startsWith', 'endsWith', 'between', 'isEmpty', 'isNull', 'isUndefined', | ||
@@ -59,5 +90,16 @@ 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean' | ||
const unaryOperators = [ | ||
'isEmpty', 'isNull', 'isUndefined', 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean' | ||
]; | ||
const [operator, ...rest] = str.trim().split(' '); | ||
const value = rest.join(' '); | ||
if(unaryOperators.includes(operator)) { | ||
return { | ||
operator, | ||
value: '' | ||
}; | ||
} | ||
if(operators.includes(operator)) { | ||
@@ -76,2 +118,41 @@ return { | ||
const isUnaryOperator = (operator) => { | ||
const unaryOperators = [ | ||
'isEmpty', 'isNull', 'isUndefined', 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean' | ||
]; | ||
return unaryOperators.includes(operator); | ||
}; | ||
const evaluateRhsOperand = (rhsOperand, operator, context) => { | ||
if(isUnaryOperator(operator)) { | ||
return; | ||
} | ||
// gracefully allow both a,b as well as [a, b] | ||
if(operator === 'in' || operator === 'notIn') { | ||
if(rhsOperand.startsWith('[') && rhsOperand.endsWith(']')) { | ||
rhsOperand = rhsOperand.substring(1, rhsOperand.length - 1); | ||
} | ||
return rhsOperand.split(',').map((v) => evaluateJsTemplateLiteral(v.trim(), context)); | ||
} | ||
if(operator === 'between') { | ||
const [lhs, rhs] = rhsOperand.split(',').map((v) => evaluateJsTemplateLiteral(v.trim(), context)); | ||
return [lhs, rhs]; | ||
} | ||
// gracefully allow both ^[a-Z] as well as /^[a-Z]/ | ||
if(operator === 'matches' || operator === 'notMatches') { | ||
if(rhsOperand.startsWith('/') && rhsOperand.endsWith('/')) { | ||
rhsOperand = rhsOperand.substring(1, rhsOperand.length - 1); | ||
} | ||
return rhsOperand; | ||
} | ||
return evaluateJsTemplateLiteral(rhsOperand, context); | ||
}; | ||
class AssertRuntime { | ||
@@ -113,3 +194,3 @@ runAssertions(assertions, request, response, envVariables, collectionVariables, collectionPath) { | ||
const lhs = evaluateJsExpression(lhsExpr, context); | ||
const rhs = evaluateJsExpression(rhsOperand, context); | ||
const rhs = evaluateRhsOperand(rhsOperand, operator, context); | ||
@@ -123,5 +204,2 @@ switch(operator) { | ||
break; | ||
case 'like': | ||
expect(lhs).to.match(new RegExp(rhs)); | ||
break; | ||
case 'gt': | ||
@@ -151,5 +229,2 @@ expect(lhs).to.be.greaterThan(rhs); | ||
break; | ||
case 'count': | ||
expect(lhs).to.have.lengthOf(rhs); | ||
break; | ||
case 'length': | ||
@@ -171,3 +246,3 @@ expect(lhs).to.have.lengthOf(rhs); | ||
case 'between': | ||
const [min, max] = value.split(' '); | ||
const [min, max] = value.split(','); | ||
expect(lhs).to.be.within(min, max); | ||
@@ -211,2 +286,3 @@ break; | ||
assertionResults.push({ | ||
uid: nanoid(), | ||
lhsExpr, | ||
@@ -221,2 +297,3 @@ rhsExpr, | ||
assertionResults.push({ | ||
uid: nanoid(), | ||
lhsExpr, | ||
@@ -236,2 +313,2 @@ rhsExpr, | ||
module.exports = AssertRuntime; | ||
module.exports = AssertRuntime; |
@@ -20,4 +20,4 @@ const { NodeVM } = require('vm2'); | ||
runRequestScript(script, request, environment, collectionVariables, collectionPath) { | ||
const bru = new Bru(environment, collectionVariables); | ||
runRequestScript(script, request, envVariables, collectionVariables, collectionPath) { | ||
const bru = new Bru(envVariables, collectionVariables); | ||
const req = new BrunoRequest(request); | ||
@@ -51,3 +51,3 @@ | ||
request, | ||
environment, | ||
envVariables, | ||
collectionVariables | ||
@@ -57,4 +57,4 @@ }; | ||
runResponseScript(script, request, response, environment, collectionVariables, collectionPath) { | ||
const bru = new Bru(environment, collectionVariables); | ||
runResponseScript(script, request, response, envVariables, collectionVariables, collectionPath) { | ||
const bru = new Bru(envVariables, collectionVariables); | ||
const req = new BrunoRequest(request); | ||
@@ -90,3 +90,3 @@ const res = new BrunoResponse(response); | ||
response, | ||
environment, | ||
envVariables, | ||
collectionVariables | ||
@@ -93,0 +93,0 @@ }; |
@@ -23,4 +23,4 @@ const { NodeVM } = require('vm2'); | ||
runTests(testsFile, request, response, environment, collectionVariables, collectionPath) { | ||
const bru = new Bru(environment, collectionVariables); | ||
runTests(testsFile, request, response, envVariables, collectionVariables, collectionPath) { | ||
const bru = new Bru(envVariables, collectionVariables); | ||
const req = new BrunoRequest(request); | ||
@@ -32,2 +32,11 @@ const res = new BrunoResponse(response); | ||
if(!testsFile || !testsFile.length) { | ||
return { | ||
request, | ||
envVariables, | ||
collectionVariables, | ||
results: __brunoTestResults.getResults() | ||
}; | ||
} | ||
const context = { | ||
@@ -65,3 +74,3 @@ test, | ||
request, | ||
environment, | ||
envVariables, | ||
collectionVariables, | ||
@@ -68,0 +77,0 @@ results: __brunoTestResults.getResults() |
const _ = require('lodash'); | ||
const Bru = require('../bru'); | ||
const BrunoRequest = require('../bruno-request'); | ||
const { evaluateJsExpression, createResponseParser } = require('../utils'); | ||
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils'); | ||
@@ -28,5 +28,9 @@ class VarsRuntime { | ||
_.each(enabledVars, (v) => { | ||
const value = evaluateJsExpression(v.value, context); | ||
const value = evaluateJsTemplateLiteral(v.value, context); | ||
bru.setVar(v.name, value); | ||
}); | ||
return { | ||
collectionVariables | ||
}; | ||
} | ||
@@ -60,2 +64,7 @@ | ||
}); | ||
return { | ||
envVariables, | ||
collectionVariables | ||
}; | ||
} | ||
@@ -62,0 +71,0 @@ } |
@@ -63,2 +63,42 @@ const jsonQuery = require('json-query'); | ||
const evaluateJsTemplateLiteral = (templateLiteral, context) => { | ||
if(!templateLiteral || !templateLiteral.length || typeof templateLiteral !== 'string') { | ||
return templateLiteral; | ||
} | ||
templateLiteral = templateLiteral.trim(); | ||
if(templateLiteral === 'true') { | ||
return true; | ||
} | ||
if(templateLiteral === 'false') { | ||
return false; | ||
} | ||
if(templateLiteral === 'null') { | ||
return null; | ||
} | ||
if(templateLiteral === 'undefined') { | ||
return undefined; | ||
} | ||
if(templateLiteral.startsWith('"') && templateLiteral.endsWith('"')) { | ||
return templateLiteral.slice(1, -1); | ||
} | ||
if(templateLiteral.startsWith("'") && templateLiteral.endsWith("'")) { | ||
return templateLiteral.slice(1, -1); | ||
} | ||
if(!isNaN(templateLiteral)) { | ||
return Number(templateLiteral); | ||
} | ||
templateLiteral = "`" + templateLiteral + "`"; | ||
return evaluateJsExpression(templateLiteral, context); | ||
}; | ||
const createResponseParser = (response = {}) => { | ||
@@ -84,4 +124,5 @@ const res = (expr, ...fns) => { | ||
evaluateJsExpression, | ||
evaluateJsTemplateLiteral, | ||
createResponseParser, | ||
internalExpressionCache | ||
}; |
20825
718