forked from extern/bruno
feat: bru lang - jsonToBru functionality
This commit is contained in:
parent
d24f1a1054
commit
4a4208f272
@ -6,8 +6,7 @@ const {
|
||||
const _ = require('lodash');
|
||||
const {
|
||||
indentString,
|
||||
outdentString,
|
||||
get
|
||||
outdentString
|
||||
} = require('./utils');
|
||||
|
||||
const inlineTag = require('./inline-tag');
|
||||
@ -64,7 +63,7 @@ const bruToJson = (fileContents) => {
|
||||
}
|
||||
};
|
||||
|
||||
const body = get(json, 'request.body');
|
||||
const body = _.get(json, 'request.body');
|
||||
|
||||
if(body && body.text) {
|
||||
body.text = outdentString(body.text);
|
||||
|
@ -23,21 +23,7 @@ const outdentString = (str) => {
|
||||
return str.split("\n").map(line => line.replace(/^ /, '')).join("\n");
|
||||
};
|
||||
|
||||
// implement lodash _.get functionality
|
||||
const get = (obj, path, defaultValue) => {
|
||||
const pathParts = path.split('.');
|
||||
let current = obj;
|
||||
for(let i = 0; i < pathParts.length; i++) {
|
||||
if(current[pathParts[i]] === undefined) {
|
||||
return defaultValue;
|
||||
}
|
||||
current = current[pathParts[i]];
|
||||
}
|
||||
return current;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
get,
|
||||
safeParseJson,
|
||||
indentString,
|
||||
outdentString
|
||||
|
@ -35,16 +35,4 @@ describe('utils', () => {
|
||||
expect(outdentString(input)).toBe(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
it('returns the value at the given path', () => {
|
||||
const input = { a: { b: { c: 1 } } };
|
||||
expect(get(input, 'a.b.c')).toBe(1);
|
||||
});
|
||||
|
||||
it('returns the defaultValue if the path does not exist', () => {
|
||||
const input = { a: { b: { c: 1 } } };
|
||||
expect(get(input, 'a.b.d', 2)).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,5 +1,8 @@
|
||||
const ohm = require("ohm-js");
|
||||
const _ = require('lodash');
|
||||
const {
|
||||
outdentString
|
||||
} = require('../../v1/src/utils');
|
||||
|
||||
/**
|
||||
* A Bru file is made up of blocks.
|
||||
@ -21,7 +24,7 @@ const _ = require('lodash');
|
||||
*
|
||||
*/
|
||||
const grammar = ohm.grammar(`Bru {
|
||||
BruFile = (meta | http | querydisabled | query | headersdisabled | headers | bodies | varsandassert | script | test | docs)*
|
||||
BruFile = (meta | http | querydisabled | query | headersdisabled | headers | bodies | varsandassert | script | tests | docs)*
|
||||
bodies = bodyjson | bodytext | bodyxml | bodygraphql | bodygraphqlvars | bodyforms
|
||||
bodyforms = bodyformurlencodeddisabled | bodyformurlencoded | bodymultipartdisabled | bodymultipart
|
||||
|
||||
@ -81,7 +84,7 @@ const grammar = ohm.grammar(`Bru {
|
||||
bodymultipartdisabled = "body:multipart-form:disabled" dictionary
|
||||
|
||||
script = "script" st* "{" nl* textblock tagend
|
||||
test = "test" st* "{" nl* textblock tagend
|
||||
tests = "tests" st* "{" nl* textblock tagend
|
||||
docs = "docs" st* "{" nl* textblock tagend
|
||||
}`);
|
||||
|
||||
@ -148,7 +151,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
get(_1, dictionary) {
|
||||
return {
|
||||
http: {
|
||||
method: 'GET',
|
||||
method: 'get',
|
||||
...mapPairListToKeyValPair(dictionary.ast)
|
||||
}
|
||||
};
|
||||
@ -156,7 +159,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
post(_1, dictionary) {
|
||||
return {
|
||||
http: {
|
||||
method: 'POST',
|
||||
method: 'post',
|
||||
...mapPairListToKeyValPair(dictionary.ast)
|
||||
}
|
||||
};
|
||||
@ -164,7 +167,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
put(_1, dictionary) {
|
||||
return {
|
||||
http: {
|
||||
method: 'PUT',
|
||||
method: 'put',
|
||||
...mapPairListToKeyValPair(dictionary.ast)
|
||||
}
|
||||
};
|
||||
@ -172,7 +175,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
delete(_1, dictionary) {
|
||||
return {
|
||||
http: {
|
||||
method: 'DELETE',
|
||||
method: 'delete',
|
||||
...mapPairListToKeyValPair(dictionary.ast)
|
||||
}
|
||||
};
|
||||
@ -180,7 +183,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
options(_1, dictionary) {
|
||||
return {
|
||||
http: {
|
||||
method: 'OPTIONS',
|
||||
method: 'options',
|
||||
...mapPairListToKeyValPair(dictionary.ast)
|
||||
}
|
||||
};
|
||||
@ -188,7 +191,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
head(_1, dictionary) {
|
||||
return {
|
||||
http: {
|
||||
method: 'HEAD',
|
||||
method: 'head',
|
||||
...mapPairListToKeyValPair(dictionary.ast)
|
||||
}
|
||||
};
|
||||
@ -196,7 +199,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
connect(_1, dictionary) {
|
||||
return {
|
||||
http: {
|
||||
method: 'CONNECT',
|
||||
method: 'connect',
|
||||
...mapPairListToKeyValPair(dictionary.ast)
|
||||
}
|
||||
};
|
||||
@ -252,21 +255,21 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
bodyjson(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
body: {
|
||||
json: textblock.sourceString
|
||||
json: outdentString(textblock.sourceString)
|
||||
}
|
||||
};
|
||||
},
|
||||
bodytext(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
body: {
|
||||
text: textblock.sourceString
|
||||
text: outdentString(textblock.sourceString)
|
||||
}
|
||||
};
|
||||
},
|
||||
bodyxml(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
body: {
|
||||
xml: textblock.sourceString
|
||||
xml: outdentString(textblock.sourceString)
|
||||
}
|
||||
};
|
||||
},
|
||||
@ -274,7 +277,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
return {
|
||||
body: {
|
||||
graphql: {
|
||||
query: textblock.sourceString
|
||||
query: outdentString(textblock.sourceString)
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -283,29 +286,37 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
return {
|
||||
body: {
|
||||
graphql: {
|
||||
variables: textblock.sourceString
|
||||
variables: outdentString(textblock.sourceString)
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
vars(_1, dictionary) {
|
||||
const vars = mapPairListToKeyValPairs(dictionary.ast);
|
||||
_.each(vars, (val) => { val.local = false; });
|
||||
return {
|
||||
vars: mapPairListToKeyValPairs(dictionary.ast)
|
||||
vars
|
||||
};
|
||||
},
|
||||
varsdisabled(_1, dictionary) {
|
||||
const vars = mapPairListToKeyValPairs(dictionary.ast, false);
|
||||
_.each(vars, (val) => { val.local = false; });
|
||||
return {
|
||||
vars: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||
vars
|
||||
};
|
||||
},
|
||||
varslocal(_1, dictionary) {
|
||||
const varsLocal = mapPairListToKeyValPairs(dictionary.ast);
|
||||
_.each(varsLocal, (val) => { val.local = true; });
|
||||
return {
|
||||
varsLocal: mapPairListToKeyValPairs(dictionary.ast)
|
||||
vars: varsLocal
|
||||
};
|
||||
},
|
||||
varslocaldisabled(_1, dictionary) {
|
||||
const varsLocal = mapPairListToKeyValPairs(dictionary.ast, false);
|
||||
_.each(varsLocal, (val) => { val.local = true; });
|
||||
return {
|
||||
varsLocal: mapPairListToKeyValPairs(dictionary.ast, false)
|
||||
vars: varsLocal
|
||||
};
|
||||
},
|
||||
assert(_1, dictionary) {
|
||||
@ -320,17 +331,17 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
},
|
||||
script(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
script: textblock.sourceString
|
||||
script: outdentString(textblock.sourceString)
|
||||
};
|
||||
},
|
||||
test(_1, _2, _3, _4, textblock, _5) {
|
||||
tests(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
test: textblock.sourceString
|
||||
tests: outdentString(textblock.sourceString)
|
||||
};;
|
||||
},
|
||||
docs(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
docs: textblock.sourceString
|
||||
docs: outdentString(textblock.sourceString)
|
||||
};
|
||||
},
|
||||
textblock(line, _1, rest) {
|
||||
|
243
packages/bruno-lang/v2/src/jsonToBru.js
Normal file
243
packages/bruno-lang/v2/src/jsonToBru.js
Normal file
@ -0,0 +1,243 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
const {
|
||||
indentString,
|
||||
} = require('../../v1/src/utils');
|
||||
|
||||
const enabled = (items = []) => items.filter(item => item.enabled);
|
||||
const disabled = (items = []) => items.filter(item => !item.enabled);
|
||||
|
||||
// remove the last line if two new lines are found
|
||||
const stripLastLine = (text) => {
|
||||
if(!text || !text.length) return text;
|
||||
|
||||
return text.replace(/(\r?\n)$/, '');
|
||||
};
|
||||
|
||||
const jsonToBru = (json) => {
|
||||
const {
|
||||
meta,
|
||||
http,
|
||||
query,
|
||||
headers,
|
||||
body,
|
||||
script,
|
||||
tests,
|
||||
vars,
|
||||
assert,
|
||||
docs
|
||||
} = json;
|
||||
|
||||
let bru = '';
|
||||
|
||||
if(meta) {
|
||||
bru += 'meta {\n';
|
||||
for (const key in meta) {
|
||||
bru += ` ${key}: ${meta[key]}\n`;
|
||||
}
|
||||
bru += '}\n\n';
|
||||
}
|
||||
|
||||
if(http && http.method) {
|
||||
bru += `${http.method} {
|
||||
url: ${http.url}`;
|
||||
|
||||
if(http.body && http.body.length) {
|
||||
bru += `
|
||||
body: ${http.body}`;
|
||||
}
|
||||
|
||||
bru += `
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(query && query.length && enabled(query).length) {
|
||||
bru += `query {
|
||||
${indentString(enabled(query).map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(query && query.length && disabled(query).length) {
|
||||
bru += `query:disabled {
|
||||
${indentString(disabled(query).map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(headers && headers.length && enabled(headers).length) {
|
||||
bru += `headers {
|
||||
${indentString(enabled(headers).map(header => `${header.name}: ${header.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(headers && headers.length && disabled(headers).length) {
|
||||
bru += `headers:disabled {
|
||||
${indentString(disabled(headers).map(header => `${header.name}: ${header.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.json && body.json.length) {
|
||||
bru += `body:json {
|
||||
${indentString(body.json)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.text && body.text.length) {
|
||||
bru += `body:text {
|
||||
${indentString(body.text)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.xml && body.xml.length) {
|
||||
bru += `body:xml {
|
||||
${indentString(body.xml)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.formUrlEncoded && enabled(body.formUrlEncoded).length) {
|
||||
bru += `body:form-urlencoded {
|
||||
${indentString(enabled(body.formUrlEncoded).map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.formUrlEncoded && disabled(body.formUrlEncoded).length) {
|
||||
bru += `body:form-urlencoded:disabled {
|
||||
${indentString(disabled(body.formUrlEncoded).map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.multipartForm && enabled(body.multipartForm).length) {
|
||||
bru += `body:multipart-form {
|
||||
${indentString(enabled(body.multipartForm).map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.multipartForm && disabled(body.multipartForm).length) {
|
||||
bru += `body:multipart-form:disabled {
|
||||
${indentString(disabled(body.multipartForm).map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.graphql && body.graphql.query) {
|
||||
bru += `body:graphql {
|
||||
${indentString(body.graphql.query)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(body && body.graphql && body.graphql.variables) {
|
||||
bru += `body:graphql:vars {
|
||||
${indentString(body.graphql.variables)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(vars && vars.length) {
|
||||
const varsEnabled = _.filter(vars, (v) => v.enabled && !v.local);
|
||||
const varsDisabled = _.filter(vars, (v) => !v.enabled && !v.local);
|
||||
const varsLocalEnabled = _.filter(vars, (v) => v.enabled && v.local);
|
||||
const varsLocalDisabled = _.filter(vars, (v) => !v.enabled && v.local);
|
||||
|
||||
if(varsEnabled.length) {
|
||||
bru += `vars {
|
||||
${indentString(varsEnabled.map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(varsDisabled.length) {
|
||||
bru += `vars:disabled {
|
||||
${indentString(varsDisabled.map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(varsLocalEnabled.length) {
|
||||
bru += `vars:local {
|
||||
${indentString(varsLocalEnabled.map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(varsLocalDisabled.length) {
|
||||
bru += `vars:local:disabled {
|
||||
${indentString(varsLocalDisabled.map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
if(assert && enabled(assert).length) {
|
||||
bru += `assert {
|
||||
${indentString(enabled(assert).map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(assert && disabled(assert).length) {
|
||||
bru += `assert:disabled {
|
||||
${indentString(disabled(assert).map(item => `${item.name}: ${item.value}`).join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(script && script.length) {
|
||||
bru += `script {
|
||||
${indentString(script)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(tests && tests.length) {
|
||||
bru += `tests {
|
||||
${indentString(tests)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if(docs && docs.length) {
|
||||
bru += `docs {
|
||||
${indentString(docs)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
return stripLastLine(bru);
|
||||
};
|
||||
|
||||
module.exports = jsonToBru;
|
@ -27,6 +27,23 @@ headers:disabled {
|
||||
transaction-id: {{transactionId}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"hello": "world"
|
||||
}
|
||||
}
|
||||
|
||||
body:text {
|
||||
This is a text body
|
||||
}
|
||||
|
||||
body:xml {
|
||||
<xml>
|
||||
<name>John</name>
|
||||
<age>30</age>
|
||||
</xml>
|
||||
}
|
||||
|
||||
body:form-urlencoded {
|
||||
apikey: secret
|
||||
numbers: +91998877665
|
||||
@ -45,23 +62,6 @@ 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 {
|
||||
@ -103,7 +103,11 @@ assert:disabled {
|
||||
$res.body.message: success
|
||||
}
|
||||
|
||||
test {
|
||||
script {
|
||||
const foo = 'bar';
|
||||
}
|
||||
|
||||
tests {
|
||||
function onResponse(request, response) {
|
||||
expect(response.status).to.equal(200);
|
||||
}
|
||||
@ -111,4 +115,4 @@ test {
|
||||
|
||||
docs {
|
||||
This request needs auth token to be set in the headers.
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
"seq": "1"
|
||||
},
|
||||
"http": {
|
||||
"method": "GET",
|
||||
"method": "get",
|
||||
"url": "https://api.textlocal.in/send/",
|
||||
"body": "json"
|
||||
},
|
||||
@ -40,12 +40,12 @@
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"json": " {\n \"hello\": \"world\"\n }",
|
||||
"text": " This is a text body",
|
||||
"xml": " <xml>\n <name>John</name>\n <age>30</age>\n </xml>",
|
||||
"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 }"
|
||||
"query": "{\n launchesPast {\n launch_site {\n site_name\n }\n launch_success\n }\n}",
|
||||
"variables": "{\n \"limit\": 5\n}"
|
||||
},
|
||||
"formUrlEncoded": [
|
||||
{
|
||||
@ -86,23 +86,25 @@
|
||||
{
|
||||
"name": "token",
|
||||
"value": "$res.body.token",
|
||||
"local": false,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "petId",
|
||||
"value": "$res.body.id",
|
||||
"local": false,
|
||||
"enabled": false
|
||||
}
|
||||
],
|
||||
"varsLocal": [
|
||||
},
|
||||
{
|
||||
"name": "orderNumber",
|
||||
"value": "$res.body.orderNumber",
|
||||
"local": true,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "transactionId",
|
||||
"value": "$res.body.transactionId",
|
||||
"local": true,
|
||||
"enabled": false
|
||||
}
|
||||
],
|
||||
@ -118,6 +120,7 @@
|
||||
"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."
|
||||
"script": "const foo = 'bar';",
|
||||
"tests": "function onResponse(request, response) {\n expect(response.status).to.equal(200);\n}",
|
||||
"docs": "This request needs auth token to be set in the headers."
|
||||
}
|
@ -1,14 +1,24 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const parser = require("../src/bruToJson");
|
||||
const bruToJson = require("../src/bruToJson");
|
||||
const jsonToBru = require("../src/jsonToBru");
|
||||
|
||||
describe("parser", () => {
|
||||
describe("bruToJson", () => {
|
||||
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);
|
||||
const output = bruToJson(input);
|
||||
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("jsonToBru", () => {
|
||||
it("should parse the bru file", () => {
|
||||
const input = require("./fixtures/request.json");
|
||||
const expected = fs.readFileSync(path.join(__dirname, 'fixtures', 'request.bru'), 'utf8');
|
||||
const output = jsonToBru(input);
|
||||
|
||||
// console.log(JSON.stringify(output, null, 2));
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ script {
|
||||
`;
|
||||
|
||||
const output = parser(input);
|
||||
const expected = " function onResponse(request, response) {\n expect(response.status).to.equal(200);\n }";
|
||||
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