Created
April 27, 2024 22:57
-
-
Save RadicalTeapot/71f91f3e4acbc64b0c24eb550bea0709 to your computer and use it in GitHub Desktop.
Quick and dirty Neovim unit-test runner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local M = { | |
buf_nr = nil, | |
suites = {}, | |
window_title = "Results: ", | |
buffer_namespace = { name = "ResultWindowNS", id = nil }, | |
} | |
M.clear_internal_buffer = function() | |
if M.buf_nr ~= nil and vim.fn.bufexists(M.buf_nr) then | |
vim.api.nvim_buf_delete(M.buf_nr, { force = true }) | |
M.buf_nr = nil | |
end | |
end | |
M.setup_buffer = function() | |
M.clear_internal_buffer() | |
M.buf_nr = vim.api.nvim_create_buf(false, true) | |
vim.bo[M.buf_nr].bufhidden = "wipe" | |
M.buffer_namespace.id = vim.api.nvim_create_namespace(M.buffer_namespace.name) -- Won't be recreated if it already exists | |
vim.api.nvim_buf_clear_namespace(M.buf_nr, M.buffer_namespace.id, 0, -1) | |
-- Key mappings for closing the window (tied to the scratch buffer only) | |
local map_opts = { noremap = true, silent = true } | |
vim.api.nvim_buf_set_keymap(M.buf_nr, "n", "q", "<cmd>bd!<CR>", map_opts) | |
vim.api.nvim_buf_set_keymap(M.buf_nr, "n", "<Esc>", "<cmd>bd!<CR>", map_opts) | |
vim.api.nvim_create_autocmd({ "BufDelete", "BufWipeout" }, { | |
group = vim.api.nvim_create_augroup("ResultWindowGroup", { clear = true }), | |
callback = function() | |
M.buf_nr = nil | |
end, | |
}) | |
end | |
M.open_floating_window = function() | |
assert(M.buf_nr, "Buffer should have been initialized before opening window") | |
-- Define the floating window size and position | |
local width = math.floor(vim.api.nvim_get_option("columns") / 2) | |
local height = math.floor(vim.api.nvim_get_option("lines") / 2) | |
-- Set window options (defined here :h nvim_open_win) | |
local opts = { | |
relative = "editor", | |
width = width, | |
height = height, | |
col = math.floor(vim.api.nvim_get_option("columns") / 4), | |
row = math.floor(vim.api.nvim_get_option("lines") / 4), | |
style = "minimal", | |
border = "rounded", | |
title = " Results ", | |
title_pos = "left", | |
} | |
-- Create the floating window | |
local win = vim.api.nvim_open_win(M.buf_nr, true, opts) | |
vim.wo[win].wrap = true | |
-- Set custom highlight (see :h api-floatwin) | |
vim.api.nvim_set_option_value("winhl", "FloatTitle:PmenuSel", { win = win }) | |
end | |
-- TODO Move to utils | |
M.error_callback = function(err) | |
return err | |
end | |
M.test_runner = function(name, func) | |
local result, ret = xpcall(func, M.error_callback) | |
if result then | |
return true, name | |
end | |
return false, name .. ", reason: " .. ret | |
end | |
M.suite_runner = function(func) | |
local run_results = {} | |
local function it(test_name, test_func) | |
local result, msg = M.test_runner(test_name, test_func) | |
table.insert(run_results, { status = result, message = msg }) | |
end | |
local result, ret = xpcall(func, M.error_callback, it) | |
return result, run_results, ret | |
end | |
M.describe = function(suite_name, suite_func) | |
M.suites[suite_name] = function() | |
return M.suite_runner(suite_func) | |
end | |
end | |
-- TODO Cleanup this function | |
M.run = function() | |
M.setup_buffer() | |
M.open_floating_window() | |
local print_index = 0 | |
for name, runner in pairs(M.suites) do | |
local result, run_results, msg = runner() | |
if not result then | |
local message = "Suite " .. name .. " failed: " .. msg | |
vim.api.nvim_buf_set_lines(M.buf_nr, print_index, -1, false, { message, "" }) | |
print_index = -1 | |
else | |
local passed = vim.tbl_filter(function(r) | |
return r.status | |
end, run_results) | |
local message = "Suite " .. name .. " results" | |
vim.api.nvim_buf_set_lines(M.buf_nr, print_index, -1, false, { message }) | |
local virt_text = {} | |
if #passed > 0 then | |
table.insert(virt_text, { "Passed: " .. #passed, "DiagnosticSignOk" }) | |
table.insert(virt_text, { " " }) | |
end | |
if #passed < #run_results then | |
table.insert(virt_text, { "Failed: " .. (#run_results - #passed), "DiagnosticSignError" }) | |
end | |
vim.api.nvim_buf_set_extmark( | |
M.buf_nr, | |
M.buffer_namespace.id, | |
vim.api.nvim_buf_line_count(M.buf_nr) - 1, | |
0, | |
{ virt_text = virt_text } | |
) | |
print_index = -1 | |
for i, v in ipairs(run_results) do | |
vim.api.nvim_buf_set_lines( | |
M.buf_nr, | |
-1, | |
-1, | |
false, | |
{ "[" .. i .. "/" .. #run_results .. "] " .. v.message } | |
) | |
local hl_grp_name = v.status and "DiagnosticSignOk" or "DiagnosticSignError" | |
local text = v.status and "Passed" or "Failed" | |
vim.api.nvim_buf_set_extmark( | |
M.buf_nr, | |
M.buffer_namespace.id, | |
vim.api.nvim_buf_line_count(M.buf_nr) - 1, | |
0, | |
{ virt_text = { { text, hl_grp_name } } } | |
) | |
end | |
vim.api.nvim_buf_set_lines(M.buf_nr, print_index, -1, false, { "" }) | |
end | |
end | |
end | |
return M |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment