diff --git a/README.md b/README.md index 5a1bb3f..cb09ea1 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,10 @@ require("neotest").setup({ -- Custom config to load via -u to set up testing. -- If nil, will look for a 'minimal_init.lua' file minimal_init = "custom_init.lua", + -- Only use a luarocks installation in the project's directory. If + -- true, installations in $HOME and global installations will be + -- ignored. Useful for isolating the test environment + local_luarocks_only = true, }), }, }) @@ -124,6 +128,15 @@ listed below and in that priority (i.e. a directory-local install takes precedence over a global install). You can check the installation by running `luarocks list busted`. +> [!WARNING] +> If you have set `busted_command` to a non-nil value in the `setup` function, +> `neotest-busted` will not know where to look for appropriate lua paths and +> will not look for installations as specified below to avoid setting up paths +> for a different busted installation. +> +> In this case, you should set `busted_paths` and `busted_cpaths` to appropriate +> paths. + ### Directory-local install You can install busted in your project's directory by running the following commands. @@ -137,6 +150,10 @@ You can install busted in your project's directory by running the following comm ### User home directory install +> [!IMPORTANT] +> You need to set `local_luarocks_only` to `false` for `neotest-busted` to find +> your home directory installation. + The following command will install busted in your home directory. ```shell @@ -145,6 +162,10 @@ The following command will install busted in your home directory. ### Global install +> [!IMPORTANT] +> You need to set `local_luarocks_only` to `false` for `neotest-busted` to find +> your global installation. + ```shell > luarocks install busted ``` @@ -161,21 +182,7 @@ the command will automatically try to find your tests in a `spec/`, `test/`, or `tests/` directory. ```shell -$ nvim -l ./scripts/test-runner.lua tests/my_spec.lua -``` - -#### Test via rockspec - -If you use a rockspec, you can provide a test command so you can run tests using -`luarocks test`. - -```lua --- Your rockspec... - -test = { - type = "command", - command = "nvim -u NONE -l ./scripts/test-runner.lua", -} +$ nvim -l /scripts/test-runner.lua tests/my_spec.lua ``` ## Debugging tests @@ -193,6 +200,12 @@ Yes. Please see the instructions [here](#async-tests). ([even though the docs still mention it](https://lunarmodules.github.io/busted/#async-tests)) so you could install busted v1 but I haven't tested that. +#### Q: Why is `neotest-busted` tested using plenary? + +The test could be run via `neotest-busted` itself but I decided to use plenary +instead to use another test runner so that bugs in `neotest-busted` won't affect +its own tests. + ## Inspiration * [Using Neovim as Lua interpreter with Luarocks](https://zignar.net/2023/01/21/using-luarocks-as-lua-interpreter-with-luarocks/) diff --git a/lua/neotest-busted/config.lua b/lua/neotest-busted/config.lua index 89b8c94..8b798fd 100644 --- a/lua/neotest-busted/config.lua +++ b/lua/neotest-busted/config.lua @@ -7,6 +7,7 @@ local default_config = { busted_paths = nil, busted_cpaths = nil, minimal_init = nil, + local_luarocks_only = true, } local _user_config = default_config @@ -70,6 +71,10 @@ function config.validate(_config) is_non_empty_string, "optional non-empty string" }, + local_luarocks_only = { + _config.local_luarocks_only, + "boolean", + }, }) -- stylua: ignore end diff --git a/lua/neotest-busted/health.lua b/lua/neotest-busted/health.lua index 3bfb363..e4bbcbe 100644 --- a/lua/neotest-busted/health.lua +++ b/lua/neotest-busted/health.lua @@ -25,7 +25,7 @@ function health.check() 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 + -- NOTE: We cannot check the neotest version because it isn't advertised as -- part of its public api check_module_installed("neotest") check_module_installed("nio") @@ -38,6 +38,8 @@ function health.check() vim.health.report_error("config has errors: " .. error) end + -- We skip looking for a local luarocks installation as the healthcheck + -- could have been invoked from anywhere local busted = adapter.find_busted_command(true) if busted then diff --git a/lua/neotest-busted/init.lua b/lua/neotest-busted/init.lua index 11a94f4..64eb473 100644 --- a/lua/neotest-busted/init.lua +++ b/lua/neotest-busted/init.lua @@ -22,8 +22,10 @@ local function log_and_notify(message, level) return end - logger[log_method](message) - vim.notify(message, level) + vim.schedule(function() + logger[log_method](message) + vim.notify(message, level) + end) end ---@type neotest.Adapter @@ -67,6 +69,11 @@ function BustedNeotestAdapter.find_busted_command(ignore_local) end end + -- Only skip checking further installations if we are not doing the healthcheck + if not ignore_local and config.local_luarocks_only == true then + return nil + end + -- Try to find a local (user home directory) busted executable local user_globs = util.glob(util.create_path("~", ".luarocks", "lib", "luarocks", "**", "bin", "busted")) @@ -75,7 +82,7 @@ function BustedNeotestAdapter.find_busted_command(ignore_local) logger.debug("Using local (~/.luarocks) busted executable") return { - type = "local", + type = "user", command = user_globs[1], lua_paths = { util.create_path("~", ".luarocks", "share", "lua", "5.1", "?.lua"), @@ -171,7 +178,7 @@ function BustedNeotestAdapter.create_test_command(results_path, paths, filters, local busted = BustedNeotestAdapter.find_busted_command() if not busted then - log_and_notify("Could not find a busted command", vim.log.levels.ERROR) + log_and_notify("Could not find busted executable", vim.log.levels.ERROR) return end diff --git a/lua/neotest-busted/types.lua b/lua/neotest-busted/types.lua index 09338d3..c27b7cf 100644 --- a/lua/neotest-busted/types.lua +++ b/lua/neotest-busted/types.lua @@ -4,10 +4,11 @@ ---@field busted_paths string[]? ---@field busted_cpaths string[]? ---@field minimal_init string? +---@field local_luarocks_only boolean? ---@class neotest-busted.BustedCommandConfig ---@field type "config" | "project" | "user" | "global" ----@field command string[] +---@field command string ---@field lua_paths string[] ---@field lua_cpaths string[] diff --git a/neotest-busted-scm-1.rockspec b/neotest-busted-scm-1.rockspec index b380f8d..f05f793 100644 --- a/neotest-busted-scm-1.rockspec +++ b/neotest-busted-scm-1.rockspec @@ -28,6 +28,7 @@ build = { type = "builtin", copy_directories = { "doc", + "scripts", }, } diff --git a/tests/adapter_results_spec.lua b/tests/adapter_results_spec.lua index a2882c9..6eec273 100644 --- a/tests/adapter_results_spec.lua +++ b/tests/adapter_results_spec.lua @@ -147,6 +147,12 @@ describe("adapter.results", function() end) it("handles failure to read json test output", function() + stub(vim, "schedule", function(func) + func() + end) + + stub(vim, "notify") + stub(lib.files, "read", function() error("Could not read file", 0) end) @@ -155,15 +161,26 @@ describe("adapter.results", function() assert.are.same(neotest_results, {}) - assert.stub(lib.files.read).was.called_with(spec.context.results_path) + assert.stub(vim.schedule).was.called() + assert.stub(vim.notify).was.called() assert .stub(logger.error).was .called_with( "Failed to read json test output file test_output.json with error: Could not read file" ) + assert.stub(lib.files.read).was.called_with(spec.context.results_path) + + vim.schedule:revert() + vim.notify:revert() end) it("handles failure to decode json", function() + stub(vim, "schedule", function(func) + func() + end) + + stub(vim, "notify") + stub(vim.json, "decode", function() error("Expected value but found invalid token at character 1", 0) end) @@ -172,15 +189,25 @@ describe("adapter.results", function() assert.are.same(neotest_results, {}) - assert.stub(lib.files.read).was.called_with(spec.context.results_path) + assert.stub(vim.schedule).was.called() + assert.stub(vim.notify).was.called() assert.stub(logger.error).was.called_with( "Failed to parse json test output file test_output.json with error: Expected value but found invalid token at character 1" ) + assert.stub(lib.files.read).was.called_with(spec.context.results_path) + vim.schedule:revert() + vim.notify:revert() vim.json.decode:revert() end) it("logs not finding a matching position id", function() + stub(vim, "schedule", function(func) + func() + end) + + stub(vim, "notify") + spec.context.position_ids[test_path .. "::namespace tests a failing test::7"] = nil local neotest_results = adapter.results(spec, strategy_result) @@ -209,11 +236,16 @@ describe("adapter.results", function() }, }) + assert.stub(vim.schedule).was.called() + assert.stub(vim.notify).was.called() assert.stub(lib.files.read).was.called_with(spec.context.results_path) assert.stub(logger.error).was.called_with( "Failed to find matching position id for key " .. test_path .. "::namespace tests a failing test::7" ) + + vim.schedule:revert() + vim.notify:revert() end) end) diff --git a/tests/async_test_spec.lua b/tests/async_test_spec.lua index 012a2ab..4b11712 100644 --- a/tests/async_test_spec.lua +++ b/tests/async_test_spec.lua @@ -19,8 +19,8 @@ describe("async tests", function() local timer = vim.loop.new_timer() local event = control.event() - -- Print a message after 1 second - timer:start(1000, 0, function() + -- Print a message after 200 milliseconds + timer:start(200, 0, function() timer:stop() timer:close() vim.print("Hello from async test") diff --git a/tests/config_spec.lua b/tests/config_spec.lua index cdb8736..470e880 100644 --- a/tests/config_spec.lua +++ b/tests/config_spec.lua @@ -47,6 +47,10 @@ describe("config", function() config = { minimal_init = "" }, error_message = non_empty_string, }, + { + config = { local_luarocks_only = 1 }, + error_message = "expected boolean, got number", + }, } stub(vim.api, "nvim_echo") @@ -77,6 +81,7 @@ describe("config", function() busted_paths = { "some/path" }, busted_cpaths = {}, minimal_init = "some_init_file.lua", + local_luarocks_only = false, }) assert.is_true(ok)