forked from extern/bruno
feat: bru lang - support for body type parsing
This commit is contained in:
parent
7a8e5198ff
commit
689d886e74
@ -2,7 +2,9 @@ const ohm = require("ohm-js");
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
const grammar = ohm.grammar(`Bru {
|
const grammar = ohm.grammar(`Bru {
|
||||||
BruFile = (script | test | headersdisabled | headers)*
|
BruFile = (script | test | querydisabled | query | headersdisabled | headers | bodies )*
|
||||||
|
bodies = bodyjson | bodytext | bodyxml | bodygraphql | bodygraphqlvars | bodyforms
|
||||||
|
bodyforms = bodyformurlencodeddisabled | bodyformurlencoded | bodymultipartdisabled | bodymultipart
|
||||||
nl = "\\r"? "\\n"
|
nl = "\\r"? "\\n"
|
||||||
st = " " | "\\t"
|
st = " " | "\\t"
|
||||||
tagend = nl "}"
|
tagend = nl "}"
|
||||||
@ -12,12 +14,26 @@ const grammar = ohm.grammar(`Bru {
|
|||||||
headers = "headers" pairblock
|
headers = "headers" pairblock
|
||||||
headersdisabled = "headers:disabled" pairblock
|
headersdisabled = "headers:disabled" pairblock
|
||||||
|
|
||||||
|
query = "query" pairblock
|
||||||
|
querydisabled = "query:disabled" pairblock
|
||||||
|
|
||||||
pairblock = st* "{" pairlist? tagend
|
pairblock = st* "{" pairlist? tagend
|
||||||
pairlist = nl* pair (~tagend nl pair)* (~tagend space)*
|
pairlist = nl* pair (~tagend nl pair)* (~tagend space)*
|
||||||
pair = st* key st* ":" st* value? st*
|
pair = st* key st* ":" st* value? st*
|
||||||
key = ~tagend validkey*
|
key = ~tagend validkey*
|
||||||
value = ~tagend validvalue*
|
value = ~tagend validvalue*
|
||||||
|
|
||||||
|
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" pairblock
|
||||||
|
bodyformurlencodeddisabled = "body:form-urlencoded:disabled" pairblock
|
||||||
|
bodymultipart = "body:multipart-form" pairblock
|
||||||
|
bodymultipartdisabled = "body:multipart-form:disabled" pairblock
|
||||||
|
|
||||||
script = "script" st* "{" nl* textblock tagend
|
script = "script" st* "{" nl* textblock tagend
|
||||||
test = "test" st* "{" textblock tagend
|
test = "test" st* "{" textblock tagend
|
||||||
|
|
||||||
@ -56,6 +72,16 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
return _.mergeWith(result, item, concatArrays);
|
return _.mergeWith(result, item, concatArrays);
|
||||||
}, {});
|
}, {});
|
||||||
},
|
},
|
||||||
|
query(_1, pairblock) {
|
||||||
|
return {
|
||||||
|
query: mapPairListToKeyValPairs(pairblock.ast)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
querydisabled(_1, pairblock) {
|
||||||
|
return {
|
||||||
|
query: mapPairListToKeyValPairs(pairblock.ast, false)
|
||||||
|
};
|
||||||
|
},
|
||||||
headers(_1, pairblock) {
|
headers(_1, pairblock) {
|
||||||
return {
|
return {
|
||||||
headers: mapPairListToKeyValPairs(pairblock.ast)
|
headers: mapPairListToKeyValPairs(pairblock.ast)
|
||||||
@ -83,6 +109,73 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
value(chars) {
|
value(chars) {
|
||||||
return chars.sourceString ? chars.sourceString.trim() : '';
|
return chars.sourceString ? chars.sourceString.trim() : '';
|
||||||
},
|
},
|
||||||
|
bodyformurlencoded(_1, pairblock) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
formUrlEncoded: mapPairListToKeyValPairs(pairblock.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodyformurlencodeddisabled(_1, pairblock) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
formUrlEncoded: mapPairListToKeyValPairs(pairblock.ast, false)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodymultipart(_1, pairblock) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
multipartForm: mapPairListToKeyValPairs(pairblock.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bodymultipartdisabled(_1, pairblock) {
|
||||||
|
return {
|
||||||
|
body: {
|
||||||
|
multipartForm: mapPairListToKeyValPairs(pairblock.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
script(_1, _2, _3, _4, textblock, _5) {
|
script(_1, _2, _3, _4, textblock, _5) {
|
||||||
return {
|
return {
|
||||||
script: textblock.sourceString
|
script: textblock.sourceString
|
||||||
|
@ -3,6 +3,15 @@ const parser = require("../src/index");
|
|||||||
describe("parser", () => {
|
describe("parser", () => {
|
||||||
it("should parse the bru file", () => {
|
it("should parse the bru file", () => {
|
||||||
const input = `
|
const input = `
|
||||||
|
query {
|
||||||
|
apiKey: secret
|
||||||
|
numbers: 998877665
|
||||||
|
}
|
||||||
|
|
||||||
|
query:disabled {
|
||||||
|
message: hello
|
||||||
|
}
|
||||||
|
|
||||||
headers {
|
headers {
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
Authorization: Bearer 123
|
Authorization: Bearer 123
|
||||||
@ -12,6 +21,58 @@ headers:disabled {
|
|||||||
transaction-id: {{transactionId}}
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
script {
|
script {
|
||||||
function onResponse(request, response) {
|
function onResponse(request, response) {
|
||||||
expect(response.status).to.equal(200);
|
expect(response.status).to.equal(200);
|
||||||
@ -21,6 +82,19 @@ script {
|
|||||||
|
|
||||||
const output = parser(input);
|
const output = parser(input);
|
||||||
const expected = {
|
const expected = {
|
||||||
|
"query": [{
|
||||||
|
"name": "apiKey",
|
||||||
|
"value": "secret",
|
||||||
|
"enabled": true
|
||||||
|
}, {
|
||||||
|
"name": "numbers",
|
||||||
|
"value": "998877665",
|
||||||
|
"enabled": true
|
||||||
|
}, {
|
||||||
|
"name": "message",
|
||||||
|
"value": "hello",
|
||||||
|
"enabled": false
|
||||||
|
}],
|
||||||
"headers": [
|
"headers": [
|
||||||
{
|
{
|
||||||
"name": "content-type",
|
"name": "content-type",
|
||||||
@ -38,9 +112,53 @@ script {
|
|||||||
"enabled": false
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"script": " function onResponse(request, response) {\n expect(response.status).to.equal(200);\n }"
|
"script": " function onResponse(request, response) {\n expect(response.status).to.equal(200);\n }"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log(JSON.stringify(output, null, 2));
|
||||||
expect(output).toEqual(expected);
|
expect(output).toEqual(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user