Skip to content

Commit

Permalink
Add healthcheck (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
MisanthropicBit authored Apr 4, 2024
1 parent 2c0f553 commit d783d35
Show file tree
Hide file tree
Showing 8 changed files with 311 additions and 53 deletions.
112 changes: 112 additions & 0 deletions lua/neotest-busted/config.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
local config = {}

---@type neotest-busted.Config
local default_config = {
busted_command = nil,
busted_args = nil,
busted_paths = nil,
busted_cpaths = nil,
minimal_init = nil,
}

local _user_config = default_config

---@param value any
---@return boolean
local function is_non_empty_string(value)
return value == nil or (type(value) == "string" and #value > 0)
end

---@param value any
---@return boolean
---@return string?
local function is_optional_string_list(value)
if value == nil then
return true
end

if not vim.tbl_islist(value) then
return false, "must be a list-like table"
end

for idx, item in ipairs(value) do
if type(item) ~= "string" then
return false, "item at index " .. tostring(idx)
end
end

return true
end

--- Validate a config
---@param _config neotest-busted.Config
---@return boolean
---@return any?
function config.validate(_config)
-- stylua: ignore start
local ok, error = pcall(vim.validate, {
busted_command = {
_config.busted_command,
is_non_empty_string,
"optional non-empty string"
},
busted_args = {
_config.busted_args,
is_optional_string_list,
"an optional string list",
},
busted_paths = {
_config.busted_paths,
is_optional_string_list,
"an optional string list",
},
busted_cpaths = {
_config.busted_cpaths,
is_optional_string_list,
"an optional string list",
},
minimal_init = {
_config.minimal_init,
is_non_empty_string,
"optional non-empty string"
},
})
-- stylua: ignore end

if not ok then
return ok, error
end

if type(_config.busted_command) == "string" then
if vim.fn.executable(_config.busted_command) == 0 then
return false, "busted command in configuration is not executable"
end
end

return ok
end

---@param user_config table<string, any>?
---@return boolean
---@return any?
function config.configure(user_config)
_user_config = vim.tbl_deep_extend("keep", user_config or {}, default_config)

local ok, error = config.validate(_user_config)

if not ok then
vim.api.nvim_echo({
{ "[neotest-busted]: ", "ErrorMsg" },
{ "Invalid config: " },
{ error },
}, true, {})
end

return ok, error
end

return setmetatable(config, {
__index = function(_, key)
return _user_config[key]
end,
})
58 changes: 58 additions & 0 deletions lua/neotest-busted/health.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
local health = {}

local adapter = require("neotest-busted")
local config = require("neotest-busted.config")

local min_neovim_version = "0.9.0"

---@param module_name string
local function check_module_installed(module_name)
local installed, _ = pcall(require, module_name)

if installed then
vim.health.report_ok(("`%s` is installed"):format(module_name))
else
vim.health.report_error(("`%s` is not installed"):format(module_name))
end
end

function health.check()
vim.health.report_start("neotest-busted")

if vim.fn.has("nvim-" .. min_neovim_version) == 1 then
vim.health.report_ok(("has neovim %s+"):format(min_neovim_version))
else
vim.health.report_error("neotest-busted requires at least neovim " .. min_neovim_version)
end

-- NOTE: We cannot check the neotest version because it isn't avertised as
-- part of its public api
check_module_installed("neotest")
check_module_installed("nio")

local ok, error = config.validate(config)

if ok then
vim.health.report_ok("found no errors in config")
else
vim.health.report_error("config has errors: " .. error)
end

local busted = adapter.find_busted_command(true)

if busted then
vim.health.report_ok(
("found `busted` (type: %s) at\n%s"):format(
busted.type,
vim.loop.fs_realpath(busted.command)
)
)
else
vim.health.report_warn(
"could not find busted executable globally or in user home folder",
"if not already installed locally, please install busted using luarocks (https://luarocks.org/)"
)
end
end

return health
82 changes: 34 additions & 48 deletions lua/neotest-busted/init.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local config = require("neotest-busted.config")
local util = require("neotest-busted.util")

local async = require("neotest.async")
Expand All @@ -6,54 +7,53 @@ local logger = require("neotest.logging")
local types = require("neotest.types")

local function get_strategy_config(strategy)
local config = {
local strategy_configs = {
dap = nil, -- TODO: Add dap config
}
if config[strategy] then
return config[strategy]()
if strategy_configs[strategy] then
return strategy_configs[strategy]()
end
end

---@type neotest-busted.Config
local config = {
busted_command = nil,
busted_args = nil,
busted_paths = nil,
busted_cpaths = nil,
minimal_init = nil,
}
---@type neotest.Adapter
local BustedNeotestAdapter = { name = "neotest-busted" }

--- Find busted command and additional paths
---@param ignore_local? boolean
---@return neotest-busted.BustedCommand?
local function find_busted_command()
function BustedNeotestAdapter.find_busted_command(ignore_local)
if config.busted_command and #config.busted_command > 0 then
logger.debug("Using busted command from config")

return {
type = "config",
command = config.busted_command,
lua_paths = {},
lua_cpaths = {},
}
end

-- Try to find a directory-local busted executable
local local_globs =
util.glob(util.create_path("lua_modules", "lib", "luarocks", "**", "bin", "busted"))

if #local_globs > 0 then
logger.debug("Using project-local busted executable")

return {
command = local_globs[1],
lua_paths = {
util.create_path("lua_modules", "share", "lua", "5.1", "?.lua"),
util.create_path("lua_modules", "share", "lua", "5.1", "?", "init.lua"),
},
lua_cpaths = {
util.create_path("lua_modules", "lib", "lua", "5.1", "?.so"),
util.create_path("lua_modules", "lib", "lua", "5.1", "?", "?.so"),
},
}
if not ignore_local then
-- Try to find a directory-local busted executable
local local_globs =
util.glob(util.create_path("lua_modules", "lib", "luarocks", "**", "bin", "busted"))

if #local_globs > 0 then
logger.debug("Using project-local busted executable")

return {
type = "project",
command = local_globs[1],
lua_paths = {
util.create_path("lua_modules", "share", "lua", "5.1", "?.lua"),
util.create_path("lua_modules", "share", "lua", "5.1", "?", "init.lua"),
},
lua_cpaths = {
util.create_path("lua_modules", "lib", "lua", "5.1", "?.so"),
util.create_path("lua_modules", "lib", "lua", "5.1", "?", "?.so"),
},
}
end
end

-- Try to find a local (user home directory) busted executable
Expand All @@ -64,6 +64,7 @@ local function find_busted_command()
logger.debug("Using local (~/.luarocks) busted executable")

return {
type = "local",
command = user_globs[1],
lua_paths = {
util.create_path("~", ".luarocks", "share", "lua", "5.1", "?.lua"),
Expand All @@ -81,6 +82,7 @@ local function find_busted_command()
logger.debug("Using global busted executable")

return {
type = "global",
command = "busted",
lua_paths = {},
lua_cpaths = {},
Expand Down Expand Up @@ -144,7 +146,7 @@ end
---@param filters string[]
---@return neotest-busted.BustedCommand?
local function create_busted_command(results_path, paths, filters)
local busted = find_busted_command()
local busted = BustedNeotestAdapter.find_busted_command()

if not busted then
return
Expand Down Expand Up @@ -218,9 +220,6 @@ local function create_busted_command(results_path, paths, filters)
}
end

---@type neotest.Adapter
local BustedNeotestAdapter = { name = "neotest-busted" }

BustedNeotestAdapter.root =
lib.files.match_root_pattern(".busted", ".luarocks", "lua_modules", "*.rockspec")

Expand Down Expand Up @@ -493,20 +492,7 @@ end
setmetatable(BustedNeotestAdapter, {
---@param user_config neotest-busted.Config?
__call = function(_, user_config)
local _user_config = user_config or {}

if type(_user_config.busted_command) == "string" and #_user_config.busted_command > 0 then
if vim.fn.executable(_user_config.busted_command) == 0 then
vim.notify(
("Busted command in configuration is not executable: '%s'"):format(
_user_config.busted_command
),
vim.log.levels.ERROR
)
end
end

config = vim.tbl_extend("force", config, _user_config)
config.configure(user_config)

return BustedNeotestAdapter
end,
Expand Down
3 changes: 2 additions & 1 deletion lua/neotest-busted/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
---@field minimal_init string?

---@class neotest-busted.BustedCommand
---@field command string[]
---@field type "config" | "project" | "user" | "global"
---@field command string
---@field lua_paths string[]
---@field lua_cpaths string[]

Expand Down
8 changes: 8 additions & 0 deletions tests/adapter_build_spec_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ local stub = require("luassert.stub")
local async = _async.tests

describe("adapter.build_spec", function()
before_each(function()
stub(vim.api, "nvim_echo")
end)

after_each(function()
vim.api.nvim_echo:revert()
end)

local function assert_spec_command(spec_command, items)
assert.are.same(#spec_command, #items)

Expand Down
Loading

0 comments on commit d783d35

Please sign in to comment.