Something went wrong. Try again.
Something went wrong. Try again.
14 kB · 405 lines
Lua
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406---@module 'luassert'
require("spec.minimal_init")
local parser = require("rest-nvim.parser")local utils = require("rest-nvim.utils")local context = require("rest-nvim.context").Contextlocal logger = require("rest-nvim.logger")
local spy = require("luassert.spy")
local function open(path) vim.cmd.edit(path) return 0end
---@diagnostic disable-next-line: duplicate-set-fieldvim.notify = function() end
describe("http parser", function() it("validate http parser", function() assert.same("http", vim.treesitter.language.get_lang("http")) end) it("parse from http string", function() local source = "GET https://github.com\n" local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) assert.same({ method = "GET", url = "https://github.com", headers = {}, cookies = {}, handlers = {}, }, parser.parse(req_node, source)) end) it("parse from http file", function() local source = open("spec/examples/basic_get.http") local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) assert.same({ name = "basic get statement", method = "GET", url = "https://api.github.com/users/boltlessengineer", headers = { ["user-agent"] = { "neovim" }, }, cookies = {}, handlers = {}, }, parser.parse(req_node, source)) end) it("capture all request names", function() local source = [[### first named requestGET http://localhost:80### request separator that isn't a request name#### @name=second named request# additional commentsGET http://localhost:80]] local names = parser.get_request_names(source) assert.same({ "first named request", "second named request" }, names) end) it("parse request with host header", function() local source = [[GET /some/pathHOST: localhost:8000]] local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) local req = assert(parser.parse(req_node, source)) assert.same("http://localhost:8000/some/path", req.url) end) it("parse request with headers", function() local source = [[http://example.com/apiX-Header1: value1X-Header2:X-Header1: value2]] local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) assert.same({ url = "http://example.com/api", method = "GET", headers = { ["x-header1"] = { "value1", "value2" }, ["x-header2"] = {}, }, handlers = {}, cookies = {}, }, parser.parse(req_node, source)) end)
describe("parse body", function() it("json body", function() local source = 'POST https://example.com\n\n{\n\t"blah": 1}\n' local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) assert.same({ method = "POST", url = "https://example.com", headers = {}, cookies = {}, handlers = {}, body = { __TYPE = "json", data = '{\n\t"blah": 1}', }, }, parser.parse(req_node, source)) end) it("invalid json body", function() local source = 'POST https://example.com\n\n{\n\t"blah": 1\n' local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) local spy_log_warn = spy.on(logger, "warn") parser.parse(req_node, source) ---@diagnostic disable-next-line: undefined-field assert.spy(spy_log_warn).called_with("invalid json: '{\n\t\"blah\": 1'") end) it("parse xml", function() local source = [[POST https://example.com
<?xml version="1.0" encoding="utf-8"?><Request> <Login>login</Login> <Password>password</Password></Request>]] local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) assert.same({ method = "POST", url = "https://example.com", headers = {}, cookies = {}, handlers = {}, body = { __TYPE = "xml", data = [[<?xml version="1.0" encoding="utf-8"?><Request> <Login>login</Login> <Password>password</Password></Request>]], }, }, parser.parse(req_node, source)) end) it("parse invalid xml", function() logger.info("hi") local source = "POST https://example.com\n\n<?xml\n" local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) local spy_log_warn = spy.on(logger, "warn") parser.parse(req_node, source) ---@diagnostic disable-next-line: undefined-field assert.spy(spy_log_warn).called_with("invalid xml: '<?xml'") end) it("parse form-urlencoded body", function() local source = [[POST https://ijhttp-examples.jetbrains.com/postContent-Type: application/x-www-form-urlencoded
key1 = value1 &key2 = value2 &key3 = value3 &key4 = value4 &key5 = value5]] local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) assert.same({ method = "POST", url = "https://ijhttp-examples.jetbrains.com/post", headers = { ["content-type"] = { "application/x-www-form-urlencoded" }, }, cookies = {}, handlers = {}, body = { __TYPE = "raw", data = "key1=value1&key2=value2&key3=value3&key4=value4&key5=value5", }, }, parser.parse(req_node, source)) end) it("parse external body", function() -- external body can be only sourced when local source = open("spec/examples/request_body/external_body.http") local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(1)) assert.same({ method = "POST", url = "https://example.com:8080/api/html/post", headers = {}, cookies = {}, handlers = {}, name = "External body", body = { __TYPE = "external", data = { path = "spec/examples/request_body/input.json", content = '{\n "foo": "baz"\n}\n', }, }, }, parser.parse(req_node, source)) end) it("parse external body (raw)", function() -- external body can be only sourced when local source = open("spec/examples/request_body/external_body.http") local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(2)) assert.same({ method = "POST", url = "https://example.com:8080/api/html/post", headers = {}, cookies = {}, handlers = {}, name = "External body (raw)", body = { __TYPE = "external", data = { path = "spec/examples/request_body/input.json", }, }, }, parser.parse(req_node, source)) end) it("parse graphql body without json variables", function() local source = open("spec/examples/request_body/graphql.http") local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(1)) local req = parser.parse(req_node, source) assert(req) assert.same("POST", req.method) assert.same("graphql", req.body.__TYPE) assert.same({ query = [[query { repository(name: "NativeVim", owner: "boltlessengineer") { name fullName: nameWithOwner description diskUsage forkCount stargazers(first: 5) { totalCount nodes { login name } } watchers { totalCount } }}]], }, vim.json.decode(req.body.data)) end) it("parse graphql body with json variables", function() local source = open("spec/examples/request_body/graphql.http") local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(2)) local req = parser.parse(req_node, source) assert(req) assert.same("POST", req.method) assert.same("graphql", req.body.__TYPE) assert.same({ query = [[query ($name: String!, $owner: String!) { repository(name: $name, owner: $owner) { name fullName: nameWithOwner description diskUsage forkCount stargazers(first: 5) { totalCount nodes { login name } } watchers { totalCount } }}]], variables = { name = "NativeVim", owner = "boltlessengineer", }, }, vim.json.decode(req.body.data)) end) end)
describe("variables", function() it("parse with variables in header", function() vim.env["TOKEN"] = "xxx" local source = [[POST https://example.comAuthorization: Bearer {{TOKEN}}]] local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) local req = parser.parse(req_node, source) assert.not_nil(req) ---@cast req rest.Request assert.same({ ["authorization"] = { "Bearer xxx" }, }, req.headers) end) it("parse with variables in body", function() vim.env["DATE"] = "2024-07-28" local source = [[POST https://example.com
{ "date": "{{DATE}}"}]] local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) local req = parser.parse(req_node, source) assert.not_nil(req) ---@cast req rest.Request assert.same({ __TYPE = "json", data = [[{ "date": "2024-07-28"}]], }, req.body) end) it("parse with variables in urlencoded body", function() vim.env["VAR"] = "variable" local source = [[POST https://example.comContent-Type: application/x-www-form-urlencoded
foo={{VAR}}]] local _, tree = utils.ts_parse_source(source) local req_node = assert(tree:root():child(0)) local req = parser.parse(req_node, source) assert.not_nil(req) ---@cast req rest.Request assert.same({ __TYPE = "raw", data = "foo=variable", }, req.body) end) it("parse variable declaration", function() local source = "@foo = bar\n" local _, tree = utils.ts_parse_source(source) local vd_node = assert(tree:root():child(0):child(0)) assert.same("variable_declaration", vd_node:type()) local c = context:new() parser.parse_variable_declaration(vd_node, source, c) assert.same({ foo = "bar", }, c.vars) end) it("parse variable declaration with other variable", function() local source = "@foo = bar\n@baz = {{foo}} {{$date}}\n" local _, tree = utils.ts_parse_source(source) local c = context:new() parser.parse_variable_declaration(assert(tree:root():child(0):child(0)), source, c) parser.parse_variable_declaration(assert(tree:root():child(0):child(1)), source, c) assert.same({ foo = "bar", baz = "bar " .. os.date("%Y-%m-%d"), }, c.vars) end) end)
it("parse pre-request script", function() local source = "# @lang=lua\n< {%\nrequest.variables.set('foo', 'bar')\n%}\n" local _, tree = utils.ts_parse_source(source) local c = context:new() local script_node = tree:root():child(0):child(1) assert(script_node) assert.same("pre_request_script", script_node:type()) parser.parse_pre_request_script(script_node, source, c) assert.same({ foo = "bar", }, c.lv) end)
it("parse response-redirect syntax", function() local source = "GET localhost:3000\n\n>> path/to/file.json\n" local _, tree = utils.ts_parse_source(source) local node = assert(tree:root():child(0)) local req = assert(parser.parse(node, source)) assert.same(1, #req.handlers) end)
-- TODO: update this testcase -- it("create context from source", function() -- local source = [[ -- @foo=bar -- @bar=1234 -- @baz={{foo}} adsf -- ]] -- local ctx = parser.create_context(source) -- assert.same({ -- foo = "bar", -- bar = "1234", -- baz = "bar adsf", -- }, ctx.vars) -- end)end)