Skip to content

Commit

Permalink
feat(ci): test support via plenary test harness
Browse files Browse the repository at this point in the history
 * add a first test for curl command line parsing.
 * add a GHA workflow file

Inspired by https://github.com/nvim-neotest/neotest/blob/master/.github/workflows/workflow.yaml
  • Loading branch information
vyskocilm committed Sep 2, 2024
1 parent 18fd207 commit 684ca20
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 1 deletion.
43 changes: 43 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: kulala tests
on:
push:
branches:
- main
pull_request: ~

tests:
name: tests
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
rev: v0.10.0/nvim-linux64.tar.gz
steps:
- uses: actions/checkout@v4
- name: Restore cache for today's nightly.
uses: actions/cache@v4
with:
path: _neovim
key: ${{ runner.os }}-${{ matrix.rev }}

- name: Prepare dependencies
run: |
test -d _neovim || {
mkdir -p _neovim
curl -sL "https://github.com/neovim/neovim/releases/download/${{ matrix.rev }}" | tar xzf - --strip-components=1 -C "${PWD}/_neovim"
}
mkdir -p ~/.local/share/nvim/site/pack/vendor/start
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim
ln -s $(pwd) ~/.local/share/nvim/site/pack/vendor/start
export PATH="${PWD}/_neovim/bin:${PATH}"
export VIM="${PWD}/_neovim/share/nvim/runtime"
nvim --headless -c 'TSInstallSync lua | quit'
- name: Run tests
run: |
export PATH="${PWD}/_neovim/bin:${PATH}"
export VIM="${PWD}/_neovim/share/nvim/runtime"
nvim --version
/bin/bash ./scripts/test
5 changes: 4 additions & 1 deletion lua/kulala/parser/curl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ function M.parse(curl)
res.headers["content-type"] = "application/x-www-form-urlencoded"
end
elseif arg == "--json" then
if res.method == "" then
res.method = "POST"
end
state = State.Body
res.headers["content-type"] = "application/json"
res.headers["accept"] = "application/json"
Expand All @@ -89,7 +92,7 @@ function M.parse(curl)
res.headers["user-agent"] = arg
elseif state == State.Header then
local header, value = Stringutils.cut(arg, ":")
res.headers[Stringutils.remove_extra_space(header)] = Stringutils.remove_extra_space(value)
res.headers[Stringutils.remove_extra_space(header):lower()] = Stringutils.remove_extra_space(value)
elseif state == State.Body then
res.body = arg
end
Expand Down
21 changes: 21 additions & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash
# Copy from MIT licensed neotest plugin: https://raw.githubusercontent.com/nvim-neotest/neotest/master/scripts/test
tempfile=".test_output.tmp"

if [[ -n $1 ]]; then
nvim --headless --noplugin -u tests/init.vim -c "PlenaryBustedFile $1" | tee "${tempfile}"
else
nvim --headless --noplugin -u tests/init.vim -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.vim'}" | tee "${tempfile}"
fi

# Plenary doesn't emit exit code 1 when tests have errors during setup
errors=$(sed 's/\x1b\[[0-9;]*m//g' "${tempfile}" | awk '/(Errors|Failed) :/ {print $3}' | grep -v '0')

rm "${tempfile}"

if [[ -n $errors ]]; then
echo "Tests failed"
exit 1
fi

exit 0
2 changes: 2 additions & 0 deletions tests/init.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
runtime! plugin/plenary.vim
source tests/minimal_init.lua
9 changes: 9 additions & 0 deletions tests/minimal_init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
local lazypath = vim.fn.stdpath("data") .. "/lazy"
vim.notify = print
vim.opt.rtp:append(".")
vim.opt.rtp:append(lazypath .. "/plenary.nvim")
vim.opt.swapfile = false
vim.cmd("runtime! plugin/plenary.vim")
A = function(...)
print(vim.inspect(...))
end
159 changes: 159 additions & 0 deletions tests/parser/curl_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
local CURL = require("kulala.parser.curl")

describe("curl parse", function()
it("bad command", function()
local args = [[urlc 'http://example.com/get']]
local parsed = CURL.parse(args)
assert.equal(nil, parsed)
end)

it("default GET", function()
local args = [[curl 'http://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("http://example.com/get", parsed.url)
assert.equal(nil, parsed.data)
assert.same({}, parsed.headers)
assert.equal("", parsed.http_version)
end)

it("-X PATCH", function()
local args = [[curl -X PATCH 'http://example.com/patch']]
local parsed = CURL.parse(args)
assert.equal("PATCH", parsed.method)
assert.equal("http://example.com/patch", parsed.url)
end)

it("--request HEAD", function()
local args = [[curl --request HEAD 'http://example.com/head']]
local parsed = CURL.parse(args)
assert.equal("HEAD", parsed.method)
assert.equal("http://example.com/head", parsed.url)
end)

it("-A agent", function()
local args = [[curl -A agent 'http://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("http://example.com/get", parsed.url)
assert.same({ ["user-agent"] = "agent" }, parsed.headers)
end)

it("--user-agent user/agent", function()
local args = [[curl --user-agent user/agent 'http://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("http://example.com/get", parsed.url)
assert.same({ ["user-agent"] = "user/agent" }, parsed.headers)
end)

it("-H 'short: header'", function()
local args = [[curl -H 'short:header' 'http://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("http://example.com/get", parsed.url)
assert.same({ ["short"] = "header" }, parsed.headers)
end)

it("-H 'short: header' --header 'long:header'", function()
local args = [[curl -H 'short:header' --header 'long:header' 'http://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("http://example.com/get", parsed.url)
assert.same({ ["short"] = "header", ["long"] = "header" }, parsed.headers)
end)

it("-d data", function()
local args = [[curl -d data 'https://example.com/post']]
local parsed = CURL.parse(args)
assert.equal("POST", parsed.method)
assert.equal("https://example.com/post", parsed.url)
assert.equal("data", parsed.body)
end)

it("-d data -X PUT", function()
local args = [[curl -d data -X PUT 'https://example.com/put']]
local parsed = CURL.parse(args)
assert.equal("PUT", parsed.method)
assert.equal("https://example.com/put", parsed.url)
assert.equal("data", parsed.body)
assert.equal("application/x-www-form-urlencoded", parsed.headers["content-type"])
end)

it("--data data", function()
local args = [[curl --data data 'https://example.com/post']]
local parsed = CURL.parse(args)
assert.equal("POST", parsed.method)
assert.equal("https://example.com/post", parsed.url)
assert.equal("data", parsed.body)
assert.equal("application/x-www-form-urlencoded", parsed.headers["content-type"])
end)

it("--data-raw data", function()
local args = [[curl --data-raw data 'https://example.com/post']]
local parsed = CURL.parse(args)
assert.equal("POST", parsed.method)
assert.equal("https://example.com/post", parsed.url)
assert.equal("data", parsed.body)
assert.equal("application/x-www-form-urlencoded", parsed.headers["content-type"])
end)

it("-d data -H 'content-type: text/plain'", function()
local args = [[curl -H 'content-type: text/plain' -d data 'https://example.com/post']]
local parsed = CURL.parse(args)
assert.equal("POST", parsed.method)
assert.equal("https://example.com/post", parsed.url)
assert.equal("data", parsed.body)
assert.equal("text/plain", parsed.headers["content-type"])
end)

it("--json", function()
local args = [[curl --json '{"j": "son"}' 'https://example.com/post']]
local parsed = CURL.parse(args)
assert.equal("POST", parsed.method)
assert.equal("https://example.com/post", parsed.url)
assert.equal('{"j": "son"}', parsed.body)
assert.equal("application/json", parsed.headers["content-type"])
assert.equal("application/json", parsed.headers["accept"])
end)

it("--http1.1", function()
local args = [[curl --http1.1 'https://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("https://example.com/get", parsed.url)
assert.equal("HTTP/1.1", parsed.http_version)
end)

it("--http2", function()
local args = [[curl --http2 'https://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("https://example.com/get", parsed.url)
assert.equal("HTTP/2", parsed.http_version)
end)

it("--http3", function()
local args = [[curl --http3 'https://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("https://example.com/get", parsed.url)
assert.equal("HTTP/3", parsed.http_version)
end)

it("trim header value", function()
local args = [[curl -H 'key: value ' 'https://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("https://example.com/get", parsed.url)
assert.equal("value", parsed.headers["key"])
end)

it("header key case", function()
local args = [[curl -H 'Header-Key:value' 'https://example.com/get']]
local parsed = CURL.parse(args)
assert.equal("GET", parsed.method)
assert.equal("https://example.com/get", parsed.url)
assert.equal("value", parsed.headers["header-key"])
end)
end)

0 comments on commit 684ca20

Please sign in to comment.