diff --git a/.github/workflows/luarocks.yml b/.github/workflows/luarocks.yml index 05e3d51d..0e847e52 100644 --- a/.github/workflows/luarocks.yml +++ b/.github/workflows/luarocks.yml @@ -61,7 +61,6 @@ jobs: version: ${{ env.LUAROCKS_VERSION }} dependencies: | neotest - plenary.nvim nvim-nio tree-sitter-java nvim-dap diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 6b6a2998..3329078a 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -20,7 +20,6 @@ off work to one of these: | [`nvim-neotest/neotest`](https://github.com/nvim-neotest/neotest) | Yes | The framework this *is* an adapter for — defines `neotest.Adapter`, `RunSpec`, `Result`, `Tree`, and the `lib.files`/`lib.treesitter` helpers reused directly in `core/`. | | [`nvim-neotest/nvim-nio`](https://github.com/nvim-neotest/nvim-nio) | Yes | Async runtime (`nio`) — lets LSP requests and process calls happen off the main thread without blocking Neovim. | | [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter) + `tree-sitter-java` | Yes | Parses Java source so `positions_discoverer.lua` can find classes and test methods (see [flow 1](#1-test-discovery)). | -| [`nvim-lua/plenary.nvim`](https://github.com/nvim-lua/plenary.nvim) | Yes | Directory scanning fallback and job control for launching the debug JVM (`build_tool/launcher.lua`). | | A Java language server (e.g. [`nvim-jdtls`](https://github.com/mfussenegger/nvim-jdtls)/JDT.LS) | Yes, at runtime | neotest-java doesn't bundle or configure a Java LSP itself — it just looks for an already-attached client named `jdtls` (`core/spec_builder/compiler/client_provider.lua`) to resolve the `java` binary, the classpath, and to trigger workspace compiles (see [flow 2](#2-spec-building)). No `jdtls` client attached means spec building can't proceed. | | [`mfussenegger/nvim-dap`](https://github.com/mfussenegger/nvim-dap) | Only for debugging | Only required if you run tests with `strategy = "dap"`; both `core/spec_builder/init.lua` and `build_tool/launcher.lua` `pcall`-require it and fail gracefully/loudly if it's missing. | | [JUnit Platform Console Standalone](https://mvnrepository.com/artifact/org.junit.platform/junit-platform-console-standalone) (a jar, not a plugin) | Yes | The actual test runner — downloaded by `install.lua` and invoked as a subprocess by the command built in [flow 2](#2-spec-building). | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5b866dc4..748be561 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,7 +37,7 @@ make This command will: -1. Clone neotest, plenary and nvim-treesitter +1. Clone neotest and nvim-treesitter 2. Install the Java parser for nvim-treesitter 3. Build the Java projects (some failing tests are expected) 4. Run the neotest-java test suite diff --git a/Makefile b/Makefile index 463e62ac..b5a51926 100755 --- a/Makefile +++ b/Makefile @@ -17,6 +17,12 @@ test-e2e: install install: deps/nvim-treesitter deps/nvim-treesitter/parser/java.so deps/neotest deps/nvim-nio deps/plenary.nvim +# plenary.nvim is NOT a dependency of neotest-java (see #317 — our code now +# uses vim.system/vim.uv directly). It IS a transitive dependency of +# nvim-neotest/neotest itself (neotest.lib.file/positions/subprocess require +# plenary.path), so the e2e harness — which builds a real user-like +# environment by hand instead of using a plugin manager — must provide it, +# just as lazy.nvim/packer would in a real setup. deps/plenary.nvim: mkdir -p deps git clone --depth 1 https://github.com/nvim-lua/plenary.nvim.git $@ diff --git a/lua/neotest-java/build_tool/launcher.lua b/lua/neotest-java/build_tool/launcher.lua index 8780413a..eb058488 100644 --- a/lua/neotest-java/build_tool/launcher.lua +++ b/lua/neotest-java/build_tool/launcher.lua @@ -2,25 +2,46 @@ local log = require("neotest-java.logger") local nio = require("nio") local lib = require("neotest.lib") ---- A minimal shape of the job runner this module needs. The default ---- implementation is backed by `plenary.job`, but it can be swapped out ---- (e.g. in tests, or by a future implementation that drops the ---- plenary.nvim dependency) as long as it honors this contract: ---- * `new(opts)` accepts the same callback fields plenary.Job does ---- (`command`, `cwd`, `args`, `on_stderr`, `on_stdout`, `on_exit`) +--- A minimal shape of the job runner this module needs: +--- * `new(opts)` accepts `command`, `cwd`, `args`, `on_stderr`, `on_stdout`, +--- `on_exit` callback fields --- * the returned job exposes a `start()` method --- @class neotest-java.JobRunner --- @field new fun(self: neotest-java.JobRunner, opts: table): { start: fun() } +--- Default job runner, built directly on `vim.system` (see #317), matching +--- the same `vim.system` usage already established in +--- `command/command_executor.lua`. Unlike that module this doesn't need +--- `nio.wrap`, since `launch_debug_test` below already waits on its own +--- `nio.control.event()` rather than blocking on the process exiting. +--- @type neotest-java.JobRunner +local default_job_runner = { + new = function(_, opts) + return { + start = function() + vim.system(vim.list_extend({ opts.command }, opts.args), { + cwd = opts.cwd, + stdout = opts.on_stdout, + stderr = opts.on_stderr, + }, function(obj) + if opts.on_exit then + opts.on_exit(nil, obj.code) + end + end) + end, + } + end, +} + ---@param deps neotest-java.BuildToolLauncherDeps | nil ---@return neotest-java.BuildToolLauncher local function BuildToolLauncher(deps) deps = deps or {} - deps.job_runner = deps.job_runner or require("plenary.job") + deps.job_runner = deps.job_runner or default_job_runner deps.dap_repl = deps.dap_repl if deps.dap_repl == nil then - local _, repl = pcall(require, "dap.repl") - deps.dap_repl = repl + local ok, repl = pcall(require, "dap.repl") + deps.dap_repl = ok and repl or nil end return { @@ -101,8 +122,7 @@ end local launcher = BuildToolLauncher() -- Exposed for tests / future callers that want to inject a custom job_runner --- (e.g. a stub, or a non-plenary implementation) without going through the --- module-level singleton. +-- (e.g. a stub) without going through the module-level singleton. launcher.new = BuildToolLauncher return launcher diff --git a/lua/neotest-java/health.lua b/lua/neotest-java/health.lua index 434b9b60..e40116c4 100644 --- a/lua/neotest-java/health.lua +++ b/lua/neotest-java/health.lua @@ -56,7 +56,6 @@ return { check_plugin("nvim-treesitter", "nvim-treesitter/nvim-treesitter") check_treesitter() check_plugin("nio", "nvim-neotest/nvim-nio") - check_plugin("plenary", "nvim-lua/plenary.nvim") check_plugin("jdtls", "mfussenegger/nvim-jdtls") health.start("Required plugin dependencies for debugging") diff --git a/lua/neotest-java/util/detect_project_type.lua b/lua/neotest-java/util/detect_project_type.lua index 13ddd574..8a8df165 100644 --- a/lua/neotest-java/util/detect_project_type.lua +++ b/lua/neotest-java/util/detect_project_type.lua @@ -1,4 +1,37 @@ -local scan = require("plenary.scandir") +local dir_scan = require("neotest-java.util.dir_scan") +local Path = require("neotest-java.model.path") + +-- Build-marker file name patterns, reused as `dir_scan`'s search patterns +-- so we only collect entries we actually care about while walking the tree. +local MARKER_PATTERNS = { + "pom%.xml$", + "mvnw$", + "mvnw%.cmd$", + "settings%.gradle$", + "settings%.gradle%.kts$", + "build%.gradle$", + "build%.gradle%.kts$", + "gradlew$", + "gradlew%.bat$", +} + +--- Default recursive scandir, built on top of `util/dir_scan.lua`'s +--- existing `vim.uv.fs_scandir`-based walk, replacing the previous +--- `plenary.scandir` default (see #317). `dir_scan.scan` already filters +--- entries by `search_patterns` and returns a flat array of matching +--- `Path`s directly (not `{path, typ}` wrapper tables) — a directory +--- happening to be named exactly like one of our marker filenames is not +--- a realistic concern, so every match is treated as a file path. +--- @param root_str string +--- @return string[] +local function default_scandir(root_str) + local matches = dir_scan(Path(root_str), { search_patterns = MARKER_PATTERNS }) + local files = {} + for i, path in ipairs(matches) do + files[i] = path:to_string() + end + return files +end --- Detect project type (maven | gradle | unknown) --- @param root_dir neotest-java.Path @@ -6,7 +39,7 @@ local scan = require("plenary.scandir") --- @param readdir? fun(path: string): string[] --- @return "maven"|"gradle"|"unknown" local function detect_project_type(root_dir, scandir, readdir) - scandir = scandir or scan.scan_dir + scandir = scandir or default_scandir readdir = readdir or vim.fn.readdir local root_str = root_dir:to_string() diff --git a/lua/neotest-java/util/dir_scan.lua b/lua/neotest-java/util/dir_scan.lua index b6514cc4..e3356052 100644 --- a/lua/neotest-java/util/dir_scan.lua +++ b/lua/neotest-java/util/dir_scan.lua @@ -4,7 +4,7 @@ --- @param dir neotest-java.Path --- @return fun(): neotest-java.DirScanResultItem | nil -local iter_dir = function(dir) +local default_iter_dir = function(dir) local handle, _ = vim.uv.fs_scandir(dir:to_string()) if not handle then return function() @@ -46,7 +46,11 @@ end local function scan(dir, opts, dependencies) opts = opts or {} dependencies = dependencies or {} - iter_dir = dependencies.iter_dir or iter_dir + -- IMPORTANT: local, not a reassignment of the module-level default — + -- otherwise an injected stub (e.g. from a test) would permanently + -- replace the real implementation for every subsequent call in the + -- same process, not just this one. + local iter_dir = dependencies.iter_dir or default_iter_dir local stack = { dir } local result = {} diff --git a/scripts/minimal_init.lua b/scripts/minimal_init.lua index 8c603d9d..49f53867 100644 --- a/scripts/minimal_init.lua +++ b/scripts/minimal_init.lua @@ -46,7 +46,6 @@ ensure_repo(DEPENDENCIES_DIR .. "/mini.nvim", "https://github.com/echasnovski/mi ensure_repo(DEPENDENCIES_DIR .. "/nvim-nio", "https://github.com/nvim-neotest/nvim-nio") ensure_repo(DEPENDENCIES_DIR .. "/neotest", "https://github.com/nvim-neotest/neotest") ensure_repo(DEPENDENCIES_DIR .. "/nvim-treesitter", "https://github.com/nvim-treesitter/nvim-treesitter") -ensure_repo(DEPENDENCIES_DIR .. "/plenary.nvim", "https://github.com/nvim-lua/plenary.nvim") -- ───────────────────────────────────────────────────────────── -- Ensure the Java treesitter parser (.so) is compiled and present @@ -113,14 +112,11 @@ vim.opt.runtimepath:append(DEPENDENCIES_DIR .. "/mini.nvim") vim.opt.runtimepath:append(DEPENDENCIES_DIR .. "/nvim-nio") vim.opt.runtimepath:append(DEPENDENCIES_DIR .. "/neotest") vim.opt.runtimepath:append(DEPENDENCIES_DIR .. "/nvim-treesitter") -vim.opt.runtimepath:append(DEPENDENCIES_DIR .. "/plenary.nvim") -- ───────────────────────────────────────────────────────────── -- Enable mini.test -- ───────────────────────────────────────────────────────────── --- Inject luassert as global 'assert' so tests can use assert.are.same etc. -_G.assert = require("luassert") vim.opt.rtp:append(vim.fn.getcwd()) package.path = package.path .. ";" .. vim.fn.getcwd() .. "/?.lua" diff --git a/tests/e2e/full_workflow_spec.lua b/tests/e2e/full_workflow_spec.lua index 01dba2cf..303542d7 100644 --- a/tests/e2e/full_workflow_spec.lua +++ b/tests/e2e/full_workflow_spec.lua @@ -27,7 +27,7 @@ describe("E2E: neotest-java full workflow", function() it("runs tests and reports correct pass/fail results", function() -- Make sure test file exists - assert.is_true(vim.fn.filereadable(test_file) == 1, "Test file should exist: " .. test_file) + assert(vim.fn.filereadable(test_file) == 1, "Test file should exist: " .. test_file) -- Run the tests (this triggers async execution) nio.run(function() @@ -49,9 +49,9 @@ describe("E2E: neotest-java full workflow", function() end -- Verify we got results - assert.is_not_nil(results, "Should have test results") + assert(results ~= nil, "Should have test results") ---@diagnostic disable-next-line: param-type-mismatch - assert.is_true(next(results) ~= nil, "Results should not be empty") + assert(next(results) ~= nil, "Results should not be empty") -- Count pass/fail local passed = 0 @@ -72,9 +72,9 @@ describe("E2E: neotest-java full workflow", function() -- Verify counts -- SampleTest has 4 tests: 2 should pass, 2 should fail - assert.is_true(total >= 4, "Should have at least 4 test results, got " .. total) - assert.is_true(passed >= 2, "Should have at least 2 passing tests, got " .. passed) - assert.is_true(failed >= 2, "Should have at least 2 failing tests, got " .. failed) + assert(total >= 4, "Should have at least 4 test results, got " .. total) + assert(passed >= 2, "Should have at least 2 passing tests, got " .. passed) + assert(failed >= 2, "Should have at least 2 failing tests, got " .. failed) print(string.format("\n✓ E2E Test Results: %d total, %d passed, %d failed", total, passed, failed)) end) diff --git a/tests/integration/test_detect_project_type_spec.lua b/tests/integration/test_detect_project_type_spec.lua index f1f5d91f..926a02f7 100644 --- a/tests/integration/test_detect_project_type_spec.lua +++ b/tests/integration/test_detect_project_type_spec.lua @@ -6,9 +6,8 @@ local detect_project_type = require("neotest-java.util.detect_project_type") --- Real-filesystem integration coverage for `detect_project_type`'s --- fallback path: a genuine multi-directory layout with no build markers ---- at the top level, scanned by the *real* `plenary.scandir` (no stubs ---- injected), exactly as it runs in production. This is the exact ---- behavior a future non-plenary implementation (see #317) must preserve. +--- at the top level, scanned by the *real* default `dir_scan`-based +--- recursive walk (no stubs injected), exactly as it runs in production. describe("detect_project_type (real filesystem integration)", function() local root_dir diff --git a/tests/integration/test_launcher_spec.lua b/tests/integration/test_launcher_spec.lua index 1c4fbe01..07a7fda6 100644 --- a/tests/integration/test_launcher_spec.lua +++ b/tests/integration/test_launcher_spec.lua @@ -21,9 +21,8 @@ local launcher = BuildToolLauncher({ dap_repl = false }) --- "Listening for transport dt_socket at address: " to stdout as --- soon as the debug socket is open, then continues running normally. --- ---- This exercises the real `plenary.job` spawn + JDWP "Listening" wait + ---- process-exit logic end-to-end, which is the exact behavior a future ---- non-plenary implementation (see #317) must preserve. +--- This exercises the real default `vim.system`-backed job runner's spawn + +--- JDWP "Listening" wait + process-exit logic end-to-end. describe("BuildToolLauncher (real JVM integration)", function() it( "detects the JDWP 'Listening' message from a real JVM and waits for it to exit", @@ -41,7 +40,7 @@ describe("BuildToolLauncher (real JVM integration)", function() local terminated_event = launcher.launch_debug_test("java", args, Path(vim.uv.cwd())) -- `launch_debug_test` only returns once the JVM has printed the - -- "Listening" line, proving the real plenary.job stdout wiring + -- "Listening" line, proving the real vim.system-backed stdout wiring -- correctly detects it. assert(terminated_event ~= nil, "should return a terminated_command_event") diff --git a/tests/performance/path_benchmark.lua b/tests/performance/path_benchmark.lua index 85ab333c..857c3783 100644 --- a/tests/performance/path_benchmark.lua +++ b/tests/performance/path_benchmark.lua @@ -2,14 +2,9 @@ -- Native (vim.fs + strings) : 83.88 ms (0.0008 ms/op) -- Path Struct : 550.41 ms (0.0055 ms/op) -- Allocation Cost (Path()) : 10.25 ms (0.0001 ms/op) --- Plenary Path (Creation) : 199.67 ms (0.0020 ms/op) --- Plenary Path (Parent) : 1843.74 ms (0.0184 ms/op) -- -- === MEMORY FOOTPRINT === -- Path (Allocation) : 21875.00 KB total (0.2188 KB/op) --- Plenary Path (Creation) : 21256.73 KB total (0.2126 KB/op) - -local has_plenary, PlenaryPath = pcall(require, "plenary.path") local Path = require("neotest-java.model.path") @@ -61,28 +56,7 @@ benchmark("Allocation Cost (Path())", function() local _ = Path(LONG_PATH) end) -if has_plenary then - benchmark("Plenary Path (Creation)", function() - local _ = PlenaryPath:new(LONG_PATH) - end) - - benchmark("Plenary Path (Parent)", function() - local p = PlenaryPath:new(LONG_PATH) - local _ = p:parent() - end) -else - print("Skipping Plenary benchmark (plugin not found)") -end - print("\n=== MEMORY FOOTPRINT ===") benchmark_memory("Path (Allocation)", function() local _ = Path(LONG_PATH) end) - -if has_plenary then - benchmark_memory("Plenary Path (Creation)", function() - local _ = PlenaryPath:new(LONG_PATH) - end) -else - print("Skipping Plenary benchmark (plugin not found)") -end diff --git a/tests/testrc.vim b/tests/testrc.vim index d367f1c2..009a4174 100644 --- a/tests/testrc.vim +++ b/tests/testrc.vim @@ -2,4 +2,6 @@ set runtimepath+=. set runtimepath+=./deps/neotest set runtimepath+=./deps/nvim-treesitter set runtimepath+=./deps/nvim-nio +" Transitive dependency of neotest itself (see Makefile note); not required +" by neotest-java directly. set runtimepath+=./deps/plenary.nvim diff --git a/tests/unit/test_async_helpers_spec.lua b/tests/unit/test_async_helpers_spec.lua index d063a02b..68d3d20a 100644 --- a/tests/unit/test_async_helpers_spec.lua +++ b/tests/unit/test_async_helpers_spec.lua @@ -1,44 +1,44 @@ local run_sync = require("tests.async_helpers").run_sync ----@diagnostic disable: undefined-field local async = require("tests.async_helpers").async +local eq = require("tests.assertions").eq describe("async_helpers.run_sync", function() it("returns the value produced by the wrapped function", function() local v = run_sync(function() return 42 end) - assert.are.same(42, v) + eq(42, v) end) it("returns multiple values", function() local a, b = run_sync(function() return 1, "two" end) - assert.are.same(1, a) - assert.are.same("two", b) + eq(1, a) + eq("two", b) end) it("forwards arguments to the wrapped function", function() local v = run_sync(function(x, y) return x + y end, 2, 3) - assert.are.same(5, v) + eq(5, v) end) it("re-raises a sync error from the wrapped function", function() local ok, err = pcall(run_sync, function() error("BOOM") end) - assert.is_false(ok) - assert.is_not_nil(err:match("BOOM")) + assert(not ok) + assert(err:match("BOOM") ~= nil) end) - it("re-raises a luassert assertion failure from the wrapped function", function() + it("re-raises an assertion failure from the wrapped function", function() local ok, err = pcall(run_sync, function() - assert.are.same(1, 2) + eq(1, 2) end) - assert.is_false(ok) - assert.is_not_nil(err:match("Expected objects to be the same")) + assert(not ok) + assert(err:match("tables not equal") ~= nil) end) end) @@ -46,7 +46,7 @@ describe("async_helpers.async", function() it( "runs the wrapped body inside an nio task (no failure)", async(function() - assert.are.same(1, 1) + eq(1, 1) end) ) @@ -55,9 +55,9 @@ describe("async_helpers.async", function() local wrapped = async(function() ran = true end) - assert.is_function(wrapped) + assert(type(wrapped) == "function") wrapped() - assert.is_true(ran) + assert(ran) end) it("propagates errors from the wrapped body when invoked", function() @@ -65,16 +65,16 @@ describe("async_helpers.async", function() error("KABOOM") end) local ok, err = pcall(wrapped) - assert.is_false(ok) - assert.is_not_nil(err:match("KABOOM")) + assert(not ok) + assert(err:match("KABOOM") ~= nil) end) it("propagates assertion failures from the wrapped body when invoked", function() local wrapped = async(function() - assert.are.same(1, 2) + eq(1, 2) end) local ok, err = pcall(wrapped) - assert.is_false(ok) - assert.is_not_nil(err:match("Expected objects to be the same")) + assert(not ok) + assert(err:match("tables not equal") ~= nil) end) end) diff --git a/tests/unit/test_checksum_spec.lua b/tests/unit/test_checksum_spec.lua index 95acd960..a2c8588b 100644 --- a/tests/unit/test_checksum_spec.lua +++ b/tests/unit/test_checksum_spec.lua @@ -1,4 +1,3 @@ ----@diagnostic disable: undefined-field local checksum = require("neotest-java.util.checksum") local eq = require("tests.assertions").eq @@ -25,14 +24,14 @@ describe("Checksum", function() os.remove(tmp_file) -- Verify - assert.is_nil(err, "Expected no error, got: " .. tostring(err)) - assert.is_nil(err2, "Expected no error on second call, got: " .. tostring(err2)) - assert.is_not_nil(hash, "Expected hash to be computed") + assert(err == nil, "Expected no error, got: " .. tostring(err)) + assert(err2 == nil, "Expected no error on second call, got: " .. tostring(err2)) + assert(hash ~= nil, "Expected hash to be computed") eq(64, #hash, "SHA256 hash should be 64 characters (hex)") eq(hash, hash2, "Checksum should be consistent") -- Verify it's a valid hex string local is_hex = hash and hash:match("^[a-f0-9]+$") ~= nil - assert.is_true(is_hex, "Hash should be lowercase hex: " .. hash) + assert(is_hex, "Hash should be lowercase hex: " .. hash) end) it("computes checksum for binary files", function() @@ -51,8 +50,8 @@ describe("Checksum", function() os.remove(tmp_file) -- Verify - assert.is_nil(err, "Expected no error, got: " .. tostring(err)) - assert.is_not_nil(hash, "Expected hash to be computed") + assert(err == nil, "Expected no error, got: " .. tostring(err)) + assert(hash ~= nil, "Expected hash to be computed") eq(64, #hash, "SHA256 hash should be 64 characters (hex)") end) @@ -61,12 +60,9 @@ describe("Checksum", function() local hash, err = checksum.sha256(non_existent) - assert.is_nil(hash, "Expected hash to be nil") - assert.is_not_nil(err, "Expected error message") - assert.is_true( - err and err:match("Failed to compute checksum") ~= nil, - "Error should mention checksum failure" - ) + assert(hash == nil, "Expected hash to be nil") + assert(err ~= nil, "Expected error message") + assert(err and err:match("Failed to compute checksum") ~= nil, "Error should mention checksum failure") end) it("works cross-platform (unix and windows)", function() @@ -87,13 +83,13 @@ describe("Checksum", function() os.remove(tmp_file) -- Verify - assert.is_nil(err, "Expected no error on current platform, got: " .. tostring(err)) - assert.is_not_nil(hash, "Expected hash to be computed on current platform") + assert(err == nil, "Expected no error on current platform, got: " .. tostring(err)) + assert(hash ~= nil, "Expected hash to be computed on current platform") eq(64, #hash, "SHA256 hash should be 64 characters (hex)") -- Verify it's a valid hex string local is_hex = hash and hash:match("^[a-f0-9]+$") ~= nil - assert.is_true(is_hex, "Hash should be lowercase hex: " .. hash) + assert(is_hex, "Hash should be lowercase hex: " .. hash) end) end) end) diff --git a/tests/unit/test_dir_filter_spec.lua b/tests/unit/test_dir_filter_spec.lua index dafce860..69e13667 100644 --- a/tests/unit/test_dir_filter_spec.lua +++ b/tests/unit/test_dir_filter_spec.lua @@ -21,12 +21,7 @@ describe("DirFilter", function() for _, path in ipairs(relative_paths) do local result = plugin.filter_dir(name, path, root) - -- print path when test fails - if result then - print("Expected to filter out: " .. path) - end - - assert.is_false(result) + assert(not result, "Expected to filter out: " .. path) end end) @@ -47,11 +42,7 @@ describe("DirFilter", function() for _, path in ipairs(relative_paths) do local result = plugin.filter_dir(name, path, root) - -- print path when test fails - if not result then - print("Expected to not filter out: " .. path) - end - assert.is_true(result) + assert(result, "Expected to not filter out: " .. path) end end) end) diff --git a/tests/unit/test_file_checker_spec.lua b/tests/unit/test_file_checker_spec.lua index c26b9d5f..1a161410 100644 --- a/tests/unit/test_file_checker_spec.lua +++ b/tests/unit/test_file_checker_spec.lua @@ -26,7 +26,7 @@ describe("file_checker", function() } for _, file_path in ipairs(test_files) do - assert.is_true(file_checker_undertest.is_test_file(file_path), file_path) + assert(file_checker_undertest.is_test_file(file_path), file_path) end end) @@ -37,7 +37,7 @@ describe("file_checker", function() "src/test/java/neotest/Neotest.java", } for _, file_path in ipairs(non_test_files) do - assert.is_false(file_checker_undertest.is_test_file(file_path), file_path) + assert(not (file_checker_undertest.is_test_file(file_path)), file_path) end end) @@ -46,7 +46,7 @@ describe("file_checker", function() "/home/user/repo/src/main/java/neotest/NeotestTest.java", } for _, file_path in ipairs(non_test_files) do - assert.is_false(file_checker_undertest.is_test_file(file_path), file_path) + assert(not (file_checker_undertest.is_test_file(file_path)), file_path) end end) @@ -55,7 +55,7 @@ describe("file_checker", function() "/absolute_path/main/src/java/neotest/NeotestTest.java", } for _, file_path in ipairs(non_test_files) do - assert.is_true(file_checker_undertest.is_test_file(file_path)) + assert(file_checker_undertest.is_test_file(file_path)) end end) @@ -64,7 +64,7 @@ describe("file_checker", function() "C:\\absolute_path\\src\\main\\java\\neotest\\NeotestTest.java", } for _, file_path in ipairs(non_test_files) do - assert.is_false(file_checker_undertest.is_test_file(file_path)) + assert(not (file_checker_undertest.is_test_file(file_path))) end end) @@ -73,7 +73,7 @@ describe("file_checker", function() "C:\\absolute_path\\main\\src\\java\\neotest\\NeotestTest.java", } for _, file_path in ipairs(non_test_files) do - assert.is_true(FileChecker({ + assert(FileChecker({ patterns = patterns, root_getter = function() return Path("C:\\absolute_path\\main\\src") @@ -91,6 +91,6 @@ describe("file_checker", function() end, }) - assert.is_false(file_checker.is_test_file("/any/path/Test.java")) + assert(not (file_checker.is_test_file("/any/path/Test.java"))) end) end) diff --git a/tests/unit/test_launcher_spec.lua b/tests/unit/test_launcher_spec.lua index 109a48f2..0ffd30a5 100644 --- a/tests/unit/test_launcher_spec.lua +++ b/tests/unit/test_launcher_spec.lua @@ -5,8 +5,8 @@ local eq = assertions.eq local Path = require("neotest-java.model.path") local BuildToolLauncher = require("neotest-java.build_tool.launcher").new ---- Build a stub job runner mimicking the shape `plenary.job` exposes ---- (`Job:new(opts)` returning an object with `start()`). The stub captures +--- Build a stub job runner mimicking the shape the job runner contract +--- exposes (`Job:new(opts)` returning an object with `start()`). The stub captures --- the callbacks and lets `start()` drive them synchronously via --- `on_start`, matching how a real job would invoke them from its own --- process lifecycle (started -> stdout/stderr chunks -> exit) without @@ -105,7 +105,7 @@ describe("BuildToolLauncher", function() end) ) - it("defaults to plenary.job when no job_runner is injected", function() + it("defaults to a vim.system-backed job runner when no job_runner is injected", function() local launcher = BuildToolLauncher({ dap_repl = false }) assert(launcher.launch_debug_test ~= nil, "launch_debug_test should exist with default deps") end) diff --git a/tests/unit/test_positions_discoverer_spec.lua b/tests/unit/test_positions_discoverer_spec.lua index 39761ace..29c524dd 100644 --- a/tests/unit/test_positions_discoverer_spec.lua +++ b/tests/unit/test_positions_discoverer_spec.lua @@ -1,4 +1,3 @@ ----@module "luassert" local _ = require("vim.treesitter") -- NOTE: needed for loading treesitter upfront for the tests local assertions = require("tests.assertions") diff --git a/tests/unit/test_root_finder_spec.lua b/tests/unit/test_root_finder_spec.lua index 1c76ff6a..1244324e 100644 --- a/tests/unit/test_root_finder_spec.lua +++ b/tests/unit/test_root_finder_spec.lua @@ -1,5 +1,5 @@ local root_finder = require("neotest-java.core.root_finder") ----@diagnostic disable: undefined-field +local eq = require("tests.assertions").eq describe("RootFinder", function() it("should find the root when matcher matches", function() @@ -15,7 +15,7 @@ describe("RootFinder", function() local actualRoot = root_finder.find_root(dir, matcher) -- then - assert.are.same(dir, actualRoot) + eq(dir, actualRoot) end) it("should not find the root when matcher does not match", function() @@ -31,7 +31,7 @@ describe("RootFinder", function() local actualRoot = root_finder.find_root(dir, matcher) -- then - assert.is_nil(actualRoot) + assert(actualRoot == nil) end) it("should find build.gradle before .git for single-module Gradle projects", function() @@ -48,9 +48,9 @@ describe("RootFinder", function() local root = root_finder.find_root("/some/dir", matcher) - assert.are.same("/path/to/project", root) - assert.is_true(patterns_checked[#patterns_checked] == "build.gradle") - assert.is_true(patterns_checked[#patterns_checked - 1] ~= ".git") + eq("/path/to/project", root) + assert(patterns_checked[#patterns_checked] == "build.gradle") + assert(patterns_checked[#patterns_checked - 1] ~= ".git") end) it("prefers .git root when it also contains a gradlew wrapper", function() @@ -71,7 +71,7 @@ describe("RootFinder", function() local root = root_finder.find_root("/repo/module/src", matcher) - assert.are.same("/repo", root) + eq("/repo", root) end) it("prefers .git root when it also contains a mvnw wrapper", function() @@ -92,7 +92,7 @@ describe("RootFinder", function() local root = root_finder.find_root("/repo/module/src", matcher) - assert.are.same("/repo", root) + eq("/repo", root) end) it("prefers .git root when it also contains a build file (multi-module Maven)", function() @@ -115,7 +115,7 @@ describe("RootFinder", function() local root = root_finder.find_root("/repo/module/src", matcher) - assert.are.same("/repo", root) + eq("/repo", root) end) it("falls back to nearest build file when .git root has no build file or wrapper", function() @@ -136,7 +136,7 @@ describe("RootFinder", function() local root = root_finder.find_root("/repo/module/src", matcher) - assert.are.same("/repo/module", root) + eq("/repo/module", root) end) it("falls back to .git alone when no build file or wrapper exists anywhere", function() @@ -151,6 +151,6 @@ describe("RootFinder", function() local root = root_finder.find_root("/repo/module/src", matcher) - assert.are.same("/repo", root) + eq("/repo", root) end) end) diff --git a/tests/unit/test_xml_reader_spec.lua b/tests/unit/test_xml_reader_spec.lua index 30da6b37..a5a13d06 100644 --- a/tests/unit/test_xml_reader_spec.lua +++ b/tests/unit/test_xml_reader_spec.lua @@ -109,8 +109,8 @@ describe("XmlReader", function() -- then eq(false, result.found) eq(nil, result.value) - assert.is_not_nil(result.error) - assert.is_truthy(result.error:find("disk on fire")) + assert(result.error ~= nil) + assert(result.error:find("disk on fire"), "expected error to mention: disk on fire") end) it("surfaces XML parse errors instead of throwing", function() @@ -128,8 +128,8 @@ describe("XmlReader", function() -- then eq(false, result.found) eq(nil, result.value) - assert.is_not_nil(result.error) - assert.is_truthy(result.error:find("unexpected token")) + assert(result.error ~= nil) + assert(result.error:find("unexpected token"), "expected error to mention: unexpected token") end) it("uses injected stubs and never touches the real neotest.lib.file or neotest.lib.xml", function() @@ -196,8 +196,8 @@ describe("XmlReader", function() -- then eq(nil, result.tree) - assert.is_not_nil(result.error) - assert.is_truthy(result.error:find("cannot stat file")) + assert(result.error ~= nil) + assert(result.error:find("cannot stat file"), "expected error to mention: cannot stat file") end) it("surfaces XML parse errors", function() @@ -214,8 +214,8 @@ describe("XmlReader", function() -- then eq(nil, result.tree) - assert.is_not_nil(result.error) - assert.is_truthy(result.error:find("malformed XML")) + assert(result.error ~= nil) + assert(result.error:find("malformed XML"), "expected error to mention: malformed XML") end) end)