diff --git a/packages/bruno-lang/v1/src/index.js b/packages/bruno-lang/v1/src/index.js
index 877e8ce3..ccd90a24 100644
--- a/packages/bruno-lang/v1/src/index.js
+++ b/packages/bruno-lang/v1/src/index.js
@@ -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);
diff --git a/packages/bruno-lang/v1/src/utils.js b/packages/bruno-lang/v1/src/utils.js
index fed6fdf4..7a0ebb55 100644
--- a/packages/bruno-lang/v1/src/utils.js
+++ b/packages/bruno-lang/v1/src/utils.js
@@ -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
diff --git a/packages/bruno-lang/v1/tests/utils.spec.js b/packages/bruno-lang/v1/tests/utils.spec.js
index 1d0a32b1..d8103648 100644
--- a/packages/bruno-lang/v1/tests/utils.spec.js
+++ b/packages/bruno-lang/v1/tests/utils.spec.js
@@ -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);
- });
- });
});
\ No newline at end of file
diff --git a/packages/bruno-lang/v2/src/bruToJson.js b/packages/bruno-lang/v2/src/bruToJson.js
index b21459cc..289e9b5b 100644
--- a/packages/bruno-lang/v2/src/bruToJson.js
+++ b/packages/bruno-lang/v2/src/bruToJson.js
@@ -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) {
diff --git a/packages/bruno-lang/v2/src/jsonToBru.js b/packages/bruno-lang/v2/src/jsonToBru.js
new file mode 100644
index 00000000..71387e30
--- /dev/null
+++ b/packages/bruno-lang/v2/src/jsonToBru.js
@@ -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;
diff --git a/packages/bruno-lang/v2/tests/fixtures/request.bru b/packages/bruno-lang/v2/tests/fixtures/request.bru
index 9db94d4d..103a44f7 100644
--- a/packages/bruno-lang/v2/tests/fixtures/request.bru
+++ b/packages/bruno-lang/v2/tests/fixtures/request.bru
@@ -27,6 +27,23 @@ headers:disabled {
transaction-id: {{transactionId}}
}
+body:json {
+ {
+ "hello": "world"
+ }
+}
+
+body:text {
+ This is a text body
+}
+
+body:xml {
+
+ John
+ 30
+
+}
+
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 {
-
- John
- 30
-
-}
-
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.
-}
\ No newline at end of file
+}
diff --git a/packages/bruno-lang/v2/tests/fixtures/request.json b/packages/bruno-lang/v2/tests/fixtures/request.json
index 167af5f6..d5f7672d 100644
--- a/packages/bruno-lang/v2/tests/fixtures/request.json
+++ b/packages/bruno-lang/v2/tests/fixtures/request.json
@@ -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": " \n John\n 30\n ",
+ "json": "{\n \"hello\": \"world\"\n}",
+ "text": "This is a text body",
+ "xml": "\n John\n 30\n",
"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."
}
\ No newline at end of file
diff --git a/packages/bruno-lang/v2/tests/index.spec.js b/packages/bruno-lang/v2/tests/index.spec.js
index 764a95da..02c88fe1 100644
--- a/packages/bruno-lang/v2/tests/index.spec.js
+++ b/packages/bruno-lang/v2/tests/index.spec.js
@@ -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);
});
});
diff --git a/packages/bruno-lang/v2/tests/text.spec.js b/packages/bruno-lang/v2/tests/text.spec.js
index 4eeb87ce..50959dc3 100644
--- a/packages/bruno-lang/v2/tests/text.spec.js
+++ b/packages/bruno-lang/v2/tests/text.spec.js
@@ -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);
});
});