diff --git a/packages/bruno-lang/v2/src/index.js b/packages/bruno-lang/v2/src/index.js index d4fb543b4..53ba9d452 100644 --- a/packages/bruno-lang/v2/src/index.js +++ b/packages/bruno-lang/v2/src/index.js @@ -1,4 +1,5 @@ const ohm = require("ohm-js"); +const _ = require('lodash'); const grammar = ohm.grammar(`Bru { BruFile = (script | test | headers)* @@ -6,26 +7,51 @@ const grammar = ohm.grammar(`Bru { st = " " | "\\t" tagend = nl "}" - headers = "headers" st* "{" nl* pairlist tagend + headers = "headers" st* "{" pairlist? tagend - pairlist = pair (~tagend nl pair)* (~tagend space)* + pairlist = nl* pair (~tagend nl pair)* (~tagend space)* pair = st* key st* ":" st* val st* - key = alnum* - val = letter* + key = ~tagend alnum* + val = ~tagend letter* - script = "script" st* "{" codeblock tagend + script = "script" st* "{" nl* codeblock tagend test = "test" st* "{" codeblock tagend codeblock = codeline (~tagend nl codeline)* codeline = codechar* - codechar = ~nl any + codechar = ~nl any }`); +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 sem = grammar.createSemantics().addAttribute('ast', { - headers(_1, _2, _3, _4, pairlist, _5) { - return pairlist.ast; + BruFile(tags) { + if(!tags || !tags.ast || !tags.ast.length) { + return {}; + } + + return _.reduce(tags.ast, (result, item) => { + return _.assign(result, item); + }, {}); }, - pairlist(pair, _1, rest, _2) { + headers(_1, _2, _3, pairlist, _4) { + return { + headers: mapPairListToKeyValPairs(pairlist.ast) + }; + }, + pairlist(_1, pair, _2, rest, _3) { return [pair.ast, ...rest.ast]; }, pair(_1, key, _2, _3, _4, val, _5) { @@ -39,11 +65,15 @@ const sem = grammar.createSemantics().addAttribute('ast', { val(chars) { return chars.sourceString; }, - script(_1, _2, _3, codeblock, _4) { - return codeblock.sourceString; + script(_1, _2, _3, _4, codeblock, _5) { + return { + script: codeblock.sourceString + }; }, test(_1, _2, _3, codeblock, _4) { - return codeblock.sourceString; + return { + test: codeblock.sourceString + };; }, codeblock(line, _1, rest) { return [line.ast, ...rest.ast].join('\n'); @@ -74,8 +104,6 @@ const parser = (input) => { if(match.succeeded()) { return sem(match).ast; } else { - console.log('match.message========='); - console.log(match.message); throw new Error(match.message); } } diff --git a/packages/bruno-lang/v2/tests/headers.spec.js b/packages/bruno-lang/v2/tests/headers.spec.js new file mode 100644 index 000000000..d1c998277 --- /dev/null +++ b/packages/bruno-lang/v2/tests/headers.spec.js @@ -0,0 +1,100 @@ +const bruToJsonV2 = require("../src/index"); + +const assertSingleHeader = (input) => { + const output = bruToJsonV2(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 = bruToJsonV2(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 multi headers", () => { + const input = ` +headers { + hello: world + foo: bar +}`; + + const output = bruToJsonV2(input); + const expected = { + "headers": [{ + "name": "hello", + "value": "world", + "enabled": true + }, { + "name": "foo", + "value": "bar", + "enabled": true + }] + }; + expect(output).toEqual(expected); + }); + + it("should throw error on invalid header", () => { + const input = ` +headers { + hello: world + foo +}`; + + expect(() => bruToJsonV2(input)).toThrow(); + }); + + it("should throw error on invalid header", () => { + const input = ` +headers { + hello: world + foo: bar}`; + + expect(() => bruToJsonV2(input)).toThrow(); + }); +}); + diff --git a/packages/bruno-lang/v2/tests/index.spec.js b/packages/bruno-lang/v2/tests/index.spec.js index 1effaa772..2ad905ed6 100644 --- a/packages/bruno-lang/v2/tests/index.spec.js +++ b/packages/bruno-lang/v2/tests/index.spec.js @@ -1,19 +1,13 @@ const parser = require("../src/index"); describe("parser", () => { - it("should parse headers", () => { + it("should parse the bru file", () => { const input = ` headers { hello: world foo: bar -}`; +} - const output = parser(input); - console.log(output); - }); - - it("should parse script body", () => { - const input = ` script { function onResponse(request, response) { expect(response.status).to.equal(200); @@ -22,6 +16,21 @@ script { `; const output = parser(input); - console.log(output); + const expected = { + "headers": [ + { + "name": "hello", + "value": "world", + "enabled": true + }, + { + "name": "foo", + "value": "bar", + "enabled": true + } + ], + "script": " function onResponse(request, response) {\n expect(response.status).to.equal(200);\n }" + } + expect(output).toEqual(expected); }); }); diff --git a/packages/bruno-lang/v2/tests/script.spec.js b/packages/bruno-lang/v2/tests/script.spec.js new file mode 100644 index 000000000..4adf12a9f --- /dev/null +++ b/packages/bruno-lang/v2/tests/script.spec.js @@ -0,0 +1,17 @@ +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); + }); +});