mirror of
https://github.com/usebruno/bruno.git
synced 2024-12-23 15:19:01 +01:00
Merge pull request #85 from usebruno/feature/bru-lang-parser
Bru Lang Parser
This commit is contained in:
commit
86200a8f11
@ -10,6 +10,7 @@
|
|||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"arcsecond": "^5.0.0"
|
"arcsecond": "^5.0.0",
|
||||||
|
"ohm-js": "^16.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
369
packages/bruno-lang/v2/src/index.js
Normal file
369
packages/bruno-lang/v2/src/index.js
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
const ohm = require("ohm-js");
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Bru file is made up of blocks.
|
||||||
|
* There are two types of blocks
|
||||||
|
*
|
||||||
|
* 1. Dictionary Blocks - These are blocks that have key value pairs
|
||||||
|
* ex:
|
||||||
|
* headers {
|
||||||
|
* content-type: application/json
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* 2. Text Blocks - These are blocks that have text
|
||||||
|
* ex:
|
||||||
|
* body:json {
|
||||||
|
* {
|
||||||
|
* "username": "John Nash",
|
||||||
|
* "password": "governingdynamics
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const grammar = ohm.grammar(`Bru {
|
||||||
|
BruFile = (meta | http | querydisabled | query | headersdisabled | headers | bodies | varsandassert | script | test | docs)*
|
||||||
|
bodies = bodyjson | bodytext | bodyxml | bodygraphql | bodygraphqlvars | bodyforms
|
||||||
|
bodyforms = bodyformurlencodeddisabled | bodyformurlencoded | bodymultipartdisabled | bodymultipart
|
||||||
|
|
||||||
|
nl = "\\r"? "\\n"
|
||||||
|
st = " " | "\\t"
|
||||||
|
tagend = nl "}"
|
||||||
|
validkey = ~(st | ":") any
|
||||||
|
validvalue = ~nl any
|
||||||
|
|
||||||
|
// Dictionary Blocks
|
||||||
|
dictionary = st* "{" pairlist? tagend
|
||||||
|
pairlist = nl* pair (~tagend nl pair)* (~tagend space)*
|
||||||
|
pair = st* key st* ":" st* value? st*
|
||||||
|
key = ~tagend validkey*
|
||||||
|
value = ~tagend validvalue*
|
||||||
|
|
||||||
|
// Text Blocks
|
||||||
|
textblock = textline (~tagend nl textline)*
|
||||||
|
textline = textchar*
|
||||||
|
textchar = ~nl any
|
||||||
|
|
||||||
|
meta = "meta" dictionary
|
||||||
|
|
||||||
|
http = get | post | put | delete | options | head | connect | trace
|
||||||
|
get = "get" dictionary
|
||||||
|
post = "post" dictionary
|
||||||
|
put = "put" dictionary
|
||||||
|
delete = "delete" dictionary
|
||||||
|
options = "options" dictionary
|
||||||
|
head = "head" dictionary
|
||||||
|
connect = "connect" dictionary
|
||||||
|
trace = "trace" dictionary
|
||||||
|
|
||||||
|
headers = "headers" dictionary
|
||||||
|
headersdisabled = "headers:disabled" dictionary
|
||||||
|
|
||||||
|
query = "query" dictionary
|
||||||
|
querydisabled = "query:disabled" dictionary
|
||||||
|
|
||||||
|
varsandassert = vars | varsdisabled | varslocal | varslocaldisabled | assert | assertdisabled
|
||||||
|
vars = "vars" dictionary
|
||||||
|
varsdisabled = "vars:disabled" dictionary
|
||||||
|
varslocal = "vars:local" dictionary
|
||||||
|
varslocaldisabled = "vars:local:disabled" dictionary
|
||||||
|
assert = "assert" dictionary
|
||||||
|
assertdisabled = "assert:disabled" dictionary
|
||||||
|
|
||||||
|
bodyjson = "body:json" st* "{" nl* textblock tagend
|
||||||
|
bodytext = "body:text" st* "{" nl* textblock tagend
|
||||||
|
bodyxml = "body:xml" st* "{" nl* textblock tagend
|
||||||
|
bodygraphql = "body:graphql" st* "{" nl* textblock tagend
|
||||||
|
bodygraphqlvars = "body:graphql:vars" st* "{" nl* textblock tagend
|
||||||
|
|
||||||
|
bodyformurlencoded = "body:form-urlencoded" dictionary
|
||||||
|
bodyformurlencodeddisabled = "body:form-urlencoded:disabled" dictionary
|
||||||
|
bodymultipart = "body:multipart-form" dictionary
|
||||||
|
bodymultipartdisabled = "body:multipart-form:disabled" dictionary
|
||||||
|
|
||||||
|
script = "script" st* "{" nl* textblock tagend
|
||||||
|
test = "test" st* "{" nl* textblock tagend
|
||||||
|
docs = "docs" st* "{" nl* textblock tagend
|
||||||
|
}`);
|
||||||
|
|
||||||
|
const mapPairListToKeyValPairs = (pairList = [], enabled = true) => {
|
||||||
|
if(!pairList.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return _.map(pairList[0], pair => {
|
||||||
|
const key = _.keys(pair)[0];
|
||||||
|
return {
|
||||||
|
name: key,
|
||||||
|
value: pair[key],
|
||||||
|
enabled: enabled
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const concatArrays = (objValue, srcValue) => {
|
||||||
|
if (_.isArray(objValue) && _.isArray(srcValue)) {
|
||||||
|
return objValue.concat(srcValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapPairListToKeyValPair = (pairList = []) => {
|
||||||
|
if(!pairList || !pairList.length) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return _.merge({}, ...pairList[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sem = grammar.createSemantics().addAttribute('ast', {
|
||||||
|
BruFile(tags) {
|
||||||
|
if(!tags || !tags.ast || !tags.ast.length) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return _.reduce(tags.ast, (result, item) => {
|
||||||
|
return _.mergeWith(result, item, concatArrays);
|
||||||
|
}, {});
|
||||||
|
},
|
||||||
|
dictionary(_1, _2, pairlist, _3) {
|
||||||
|
return pairlist.ast;
|
||||||
|
},
|
||||||
|
pairlist(_1, pair, _2, rest, _3) {
|
||||||
|
return [pair.ast, ...rest.ast];
|
||||||
|
},
|
||||||
|
pair(_1, key, _2, _3, _4, value, _5) {
|
||||||
|
let res = {};
|
||||||
|
res[key.ast] = _.get(value, 'ast[0]', '');
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
key(chars) {
|
||||||
|
return chars.sourceString;
|
||||||
|
},
|
||||||
|
value(chars) {
|
||||||
|
return chars.sourceString ? chars.sourceString.trim() : '';
|
||||||
|
},
|
||||||
|
meta(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
meta: mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
http: {
|
||||||
|
method: 'GET',
|
||||||
|
...mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
post(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
http: {
|
||||||
|
method: 'POST',
|
||||||
|
...mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
put(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
http: {
|
||||||
|
method: 'PUT',
|
||||||
|
...mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
delete(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
http: {
|
||||||
|
method: 'DELETE',
|
||||||
|
...mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
options(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
http: {
|
||||||
|
method: 'OPTIONS',
|
||||||
|
...mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
head(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
http: {
|
||||||
|
method: 'HEAD',
|
||||||
|
...mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
connect(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
http: {
|
||||||
|
method: 'CONNECT',
|
||||||
|
...mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
query(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
query: mapPairListToKeyValPairs(dictionary.ast)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
querydisabled(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
query: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
headers(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
headers: mapPairListToKeyValPairs(dictionary.ast)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
headersdisabled(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
headers: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodyformurlencoded(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
formUrlEncoded: mapPairListToKeyValPairs(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodyformurlencodeddisabled(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
formUrlEncoded: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodymultipart(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
multipartForm: mapPairListToKeyValPairs(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodymultipartdisabled(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
multipartForm: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodyjson(_1, _2, _3, _4, textblock, _5) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
json: textblock.sourceString
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodytext(_1, _2, _3, _4, textblock, _5) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
text: textblock.sourceString
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodyxml(_1, _2, _3, _4, textblock, _5) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
xml: textblock.sourceString
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodygraphql(_1, _2, _3, _4, textblock, _5) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
graphql: {
|
||||||
|
query: textblock.sourceString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodygraphqlvars(_1, _2, _3, _4, textblock, _5) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
graphql: {
|
||||||
|
variables: textblock.sourceString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
vars(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
vars: mapPairListToKeyValPairs(dictionary.ast)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
varsdisabled(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
vars: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
varslocal(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
varsLocal: mapPairListToKeyValPairs(dictionary.ast)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
varslocaldisabled(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
varsLocal: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
assert(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
assert: mapPairListToKeyValPairs(dictionary.ast)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
assertdisabled(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
assert: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
script(_1, _2, _3, _4, textblock, _5) {
|
||||||
|
return {
|
||||||
|
script: textblock.sourceString
|
||||||
|
};
|
||||||
|
},
|
||||||
|
test(_1, _2, _3, _4, textblock, _5) {
|
||||||
|
return {
|
||||||
|
test: textblock.sourceString
|
||||||
|
};;
|
||||||
|
},
|
||||||
|
docs(_1, _2, _3, _4, textblock, _5) {
|
||||||
|
return {
|
||||||
|
docs: textblock.sourceString
|
||||||
|
};
|
||||||
|
},
|
||||||
|
textblock(line, _1, rest) {
|
||||||
|
return [line.ast, ...rest.ast].join('\n');
|
||||||
|
},
|
||||||
|
textline(chars) {
|
||||||
|
return chars.sourceString;
|
||||||
|
},
|
||||||
|
textchar(char) {
|
||||||
|
return char.sourceString;
|
||||||
|
},
|
||||||
|
nl(_1, _2) {
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
st(_) {
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
tagend(_1 ,_2) {
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
_iter(...elements) {
|
||||||
|
return elements.map(e => e.ast);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const parser = (input) => {
|
||||||
|
const match = grammar.match(input);
|
||||||
|
|
||||||
|
if(match.succeeded()) {
|
||||||
|
return sem(match).ast;
|
||||||
|
} else {
|
||||||
|
throw new Error(match.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = parser;
|
138
packages/bruno-lang/v2/tests/dictionary.spec.js
Normal file
138
packages/bruno-lang/v2/tests/dictionary.spec.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* This test file is used to test the text parser.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const parser = require("../src/index");
|
||||||
|
|
||||||
|
const assertSingleHeader = (input) => {
|
||||||
|
const output = parser(input);
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
"headers": [{
|
||||||
|
"name": "hello",
|
||||||
|
"value": "world",
|
||||||
|
"enabled": true
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
expect(output).toEqual(expected);
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("headers parser", () => {
|
||||||
|
it("should parse empty header", () => {
|
||||||
|
const input = `
|
||||||
|
headers {
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const output = parser(input);
|
||||||
|
const expected = {
|
||||||
|
"headers": []
|
||||||
|
};
|
||||||
|
expect(output).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse single header", () => {
|
||||||
|
const input = `
|
||||||
|
headers {
|
||||||
|
hello: world
|
||||||
|
}`;
|
||||||
|
|
||||||
|
assertSingleHeader(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse single header with spaces", () => {
|
||||||
|
const input = `
|
||||||
|
headers {
|
||||||
|
hello: world
|
||||||
|
}`;
|
||||||
|
|
||||||
|
assertSingleHeader(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse single header with spaces and newlines", () => {
|
||||||
|
const input = `
|
||||||
|
headers {
|
||||||
|
|
||||||
|
hello: world
|
||||||
|
|
||||||
|
|
||||||
|
}`;
|
||||||
|
|
||||||
|
assertSingleHeader(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse single header with empty value", () => {
|
||||||
|
const input = `
|
||||||
|
headers {
|
||||||
|
hello:
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const output = parser(input);
|
||||||
|
const expected = {
|
||||||
|
"headers": [{
|
||||||
|
"name": "hello",
|
||||||
|
"value": "",
|
||||||
|
"enabled": true
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
expect(output).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse multi headers", () => {
|
||||||
|
const input = `
|
||||||
|
headers {
|
||||||
|
content-type: application/json
|
||||||
|
Authorization: JWT secret
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const output = parser(input);
|
||||||
|
const expected = {
|
||||||
|
"headers": [{
|
||||||
|
"name": "content-type",
|
||||||
|
"value": "application/json",
|
||||||
|
"enabled": true
|
||||||
|
}, {
|
||||||
|
"name": "Authorization",
|
||||||
|
"value": "JWT secret",
|
||||||
|
"enabled": true
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
expect(output).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse disabled headers", () => {
|
||||||
|
const input = `
|
||||||
|
headers:disabled {
|
||||||
|
content-type: application/json
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const output = parser(input);
|
||||||
|
const expected = {
|
||||||
|
"headers": [{
|
||||||
|
"name": "content-type",
|
||||||
|
"value": "application/json",
|
||||||
|
"enabled": false
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
expect(output).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw error on invalid header", () => {
|
||||||
|
const input = `
|
||||||
|
headers {
|
||||||
|
hello: world
|
||||||
|
foo
|
||||||
|
}`;
|
||||||
|
|
||||||
|
expect(() => parser(input)).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw error on invalid header", () => {
|
||||||
|
const input = `
|
||||||
|
headers {
|
||||||
|
hello: world
|
||||||
|
foo: bar}`;
|
||||||
|
|
||||||
|
expect(() => parser(input)).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
114
packages/bruno-lang/v2/tests/fixtures/request.bru
vendored
Normal file
114
packages/bruno-lang/v2/tests/fixtures/request.bru
vendored
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
meta {
|
||||||
|
name: Send Bulk SMS
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: https://api.textlocal.in/send/
|
||||||
|
body: json
|
||||||
|
}
|
||||||
|
|
||||||
|
query {
|
||||||
|
apiKey: secret
|
||||||
|
numbers: 998877665
|
||||||
|
}
|
||||||
|
|
||||||
|
query:disabled {
|
||||||
|
message: hello
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
content-type: application/json
|
||||||
|
Authorization: Bearer 123
|
||||||
|
}
|
||||||
|
|
||||||
|
headers:disabled {
|
||||||
|
transaction-id: {{transactionId}}
|
||||||
|
}
|
||||||
|
|
||||||
|
body:form-urlencoded {
|
||||||
|
apikey: secret
|
||||||
|
numbers: +91998877665
|
||||||
|
}
|
||||||
|
|
||||||
|
body:form-urlencoded:disabled {
|
||||||
|
message: hello
|
||||||
|
}
|
||||||
|
|
||||||
|
body:multipart-form {
|
||||||
|
apikey: secret
|
||||||
|
numbers: +91998877665
|
||||||
|
}
|
||||||
|
|
||||||
|
body:multipart-form:disabled {
|
||||||
|
message: hello
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"hello": "world"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body:text {
|
||||||
|
This is a text body
|
||||||
|
}
|
||||||
|
|
||||||
|
body:xml {
|
||||||
|
<xml>
|
||||||
|
<name>John</name>
|
||||||
|
<age>30</age>
|
||||||
|
</xml>
|
||||||
|
}
|
||||||
|
|
||||||
|
body:graphql {
|
||||||
|
{
|
||||||
|
launchesPast {
|
||||||
|
launch_site {
|
||||||
|
site_name
|
||||||
|
}
|
||||||
|
launch_success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body:graphql:vars {
|
||||||
|
{
|
||||||
|
"limit": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vars {
|
||||||
|
token: $res.body.token
|
||||||
|
}
|
||||||
|
|
||||||
|
vars:disabled {
|
||||||
|
petId: $res.body.id
|
||||||
|
}
|
||||||
|
|
||||||
|
vars:local {
|
||||||
|
orderNumber: $res.body.orderNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
vars:local:disabled {
|
||||||
|
transactionId: $res.body.transactionId
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
$res.status: 200
|
||||||
|
}
|
||||||
|
|
||||||
|
assert:disabled {
|
||||||
|
$res.body.message: success
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
function onResponse(request, response) {
|
||||||
|
expect(response.status).to.equal(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
docs {
|
||||||
|
This request needs auth token to be set in the headers.
|
||||||
|
}
|
123
packages/bruno-lang/v2/tests/fixtures/request.json
vendored
Normal file
123
packages/bruno-lang/v2/tests/fixtures/request.json
vendored
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"name": "Send Bulk SMS",
|
||||||
|
"type": "http",
|
||||||
|
"seq": "1"
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"method": "GET",
|
||||||
|
"url": "https://api.textlocal.in/send/",
|
||||||
|
"body": "json"
|
||||||
|
},
|
||||||
|
"query": [{
|
||||||
|
"name": "apiKey",
|
||||||
|
"value": "secret",
|
||||||
|
"enabled": true
|
||||||
|
}, {
|
||||||
|
"name": "numbers",
|
||||||
|
"value": "998877665",
|
||||||
|
"enabled": true
|
||||||
|
}, {
|
||||||
|
"name": "message",
|
||||||
|
"value": "hello",
|
||||||
|
"enabled": false
|
||||||
|
}],
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "content-type",
|
||||||
|
"value": "application/json",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Authorization",
|
||||||
|
"value": "Bearer 123",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "transaction-id",
|
||||||
|
"value": "{{transactionId}}",
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"json": " {\n \"hello\": \"world\"\n }",
|
||||||
|
"text": " This is a text body",
|
||||||
|
"xml": " <xml>\n <name>John</name>\n <age>30</age>\n </xml>",
|
||||||
|
"graphql": {
|
||||||
|
"query": " {\n launchesPast {\n launch_site {\n site_name\n }\n launch_success\n }\n }",
|
||||||
|
"variables": " {\n \"limit\": 5\n }"
|
||||||
|
},
|
||||||
|
"formUrlEncoded": [
|
||||||
|
{
|
||||||
|
"name": "apikey",
|
||||||
|
"value": "secret",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "numbers",
|
||||||
|
"value": "+91998877665",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "message",
|
||||||
|
"value": "hello",
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multipartForm": [
|
||||||
|
{
|
||||||
|
"name": "apikey",
|
||||||
|
"value": "secret",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "numbers",
|
||||||
|
"value": "+91998877665",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "message",
|
||||||
|
"value": "hello",
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"vars": [
|
||||||
|
{
|
||||||
|
"name": "token",
|
||||||
|
"value": "$res.body.token",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "petId",
|
||||||
|
"value": "$res.body.id",
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"varsLocal": [
|
||||||
|
{
|
||||||
|
"name": "orderNumber",
|
||||||
|
"value": "$res.body.orderNumber",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "transactionId",
|
||||||
|
"value": "$res.body.transactionId",
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"assert": [
|
||||||
|
{
|
||||||
|
"name": "$res.status",
|
||||||
|
"value": "200",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$res.body.message",
|
||||||
|
"value": "success",
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"test": " function onResponse(request, response) {\n expect(response.status).to.equal(200);\n }",
|
||||||
|
"docs": " This request needs auth token to be set in the headers."
|
||||||
|
}
|
14
packages/bruno-lang/v2/tests/index.spec.js
Normal file
14
packages/bruno-lang/v2/tests/index.spec.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const parser = require("../src/index");
|
||||||
|
|
||||||
|
describe("parser", () => {
|
||||||
|
it("should parse the bru file", () => {
|
||||||
|
const input = fs.readFileSync(path.join(__dirname, 'fixtures', 'request.bru'), 'utf8');
|
||||||
|
const expected = require("./fixtures/request.json");
|
||||||
|
const output = parser(input);
|
||||||
|
|
||||||
|
// console.log(JSON.stringify(output, null, 2));
|
||||||
|
expect(output).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
20
packages/bruno-lang/v2/tests/text.spec.js
Normal file
20
packages/bruno-lang/v2/tests/text.spec.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* This test file is used to test the text parser.
|
||||||
|
*/
|
||||||
|
const parser = require("../src/index");
|
||||||
|
|
||||||
|
describe("script parser", () => {
|
||||||
|
it("should parse script body", () => {
|
||||||
|
const input = `
|
||||||
|
script {
|
||||||
|
function onResponse(request, response) {
|
||||||
|
expect(response.status).to.equal(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const output = parser(input);
|
||||||
|
const expected = " function onResponse(request, response) {\n expect(response.status).to.equal(200);\n }";
|
||||||
|
expect(output.script).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user