change test runner to plenary.busted
All checks were successful
tests / test (push) Successful in 8s
All checks were successful
tests / test (push) Successful in 8s
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
nvim --headless -u NONE -c "lua dofile('tests/run.lua')" -c "qa"
|
||||
nvim --headless -u tests/minimal_init.lua -c "PlenaryBustedDirectory tests" -c qa
|
||||
|
||||
15
tests/minimal_init.lua
Normal file
15
tests/minimal_init.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
vim.cmd("set rtp^=.")
|
||||
|
||||
local data_path = vim.fn.stdpath("data")
|
||||
local plenary_paths = {
|
||||
data_path .. "/site/pack/packer/start/plenary.nvim",
|
||||
data_path .. "/lazy/plenary.nvim",
|
||||
}
|
||||
|
||||
for _, path in ipairs(plenary_paths) do
|
||||
if vim.fn.isdirectory(path) == 1 then
|
||||
vim.cmd("set rtp^=" .. path)
|
||||
end
|
||||
end
|
||||
|
||||
vim.cmd("runtime! plugin/plenary.vim")
|
||||
252
tests/run.lua
252
tests/run.lua
@@ -1,252 +0,0 @@
|
||||
local function ok(condition, message)
|
||||
if not condition then
|
||||
error(message or "assertion failed")
|
||||
end
|
||||
end
|
||||
|
||||
vim.opt.runtimepath:append(vim.fn.getcwd())
|
||||
package.path = package.path
|
||||
.. ";"
|
||||
.. vim.fn.getcwd()
|
||||
.. "/lua/?.lua;"
|
||||
.. vim.fn.getcwd()
|
||||
.. "/lua/?/init.lua"
|
||||
|
||||
local function eq(actual, expected, message)
|
||||
if actual ~= expected then
|
||||
error(message or string.format("expected %s, got %s", tostring(expected), tostring(actual)))
|
||||
end
|
||||
end
|
||||
|
||||
local function write_file(path, content)
|
||||
local dir = vim.fn.fnamemodify(path, ":h")
|
||||
vim.fn.mkdir(dir, "p")
|
||||
vim.fn.writefile(vim.split(content, "\n"), path)
|
||||
end
|
||||
|
||||
local function make_buffer(path, content)
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, vim.split(content, "\n"))
|
||||
return bufnr
|
||||
end
|
||||
|
||||
local function with_project(structure, fn)
|
||||
local root = vim.fn.tempname()
|
||||
vim.fn.mkdir(root, "p")
|
||||
for rel_path, content in pairs(structure) do
|
||||
write_file(root .. "/" .. rel_path, content)
|
||||
end
|
||||
fn(root)
|
||||
end
|
||||
|
||||
local function test_is_test_file_with_mocha_dependency()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"mocha":"10.0.0"}}]],
|
||||
}, function(root)
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local bufnr = make_buffer(root .. "/test/sample.spec.js", "describe('x', function() {})")
|
||||
ok(runner.is_test_file(bufnr), "expected mocha project to be detected")
|
||||
end)
|
||||
end
|
||||
|
||||
local function test_is_test_file_without_mocha_dependency()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"jest":"29.0.0"}}]],
|
||||
}, function(root)
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local bufnr = make_buffer(root .. "/test/sample.spec.js", "describe('x', function() {})")
|
||||
ok(not runner.is_test_file(bufnr), "expected non-mocha project to be ignored")
|
||||
end)
|
||||
end
|
||||
|
||||
local function test_find_nearest_priorities()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"mocha":"10.0.0"}}]],
|
||||
}, function(root)
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local content = table.concat({
|
||||
"describe(\"Math\", function() {",
|
||||
" it(\"adds\", function() {",
|
||||
" expect(1).to.equal(1)",
|
||||
" })",
|
||||
"",
|
||||
" it(\"subs\", function() {",
|
||||
" expect(1).to.equal(1)",
|
||||
" })",
|
||||
"})",
|
||||
"",
|
||||
"const value = 1",
|
||||
}, "\n")
|
||||
local bufnr = make_buffer(root .. "/test/math.spec.js", content)
|
||||
|
||||
local spec_test = assert(runner.find_nearest(bufnr, 3, 0))
|
||||
eq(spec_test.kind, "test", "expected test kind")
|
||||
eq(spec_test.full_name, "Math/adds", "expected full test name")
|
||||
|
||||
local spec_suite = assert(runner.find_nearest(bufnr, 5, 0))
|
||||
eq(spec_suite.kind, "suite", "expected suite kind")
|
||||
eq(spec_suite.full_name, "Math", "expected suite name")
|
||||
|
||||
local spec_file = assert(runner.find_nearest(bufnr, 11, 0))
|
||||
eq(spec_file.kind, "file", "expected file kind")
|
||||
end)
|
||||
end
|
||||
|
||||
local function test_missing_package_json_errors()
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local content = table.concat({
|
||||
"describe(\"Math\", function() {",
|
||||
" it(\"adds\", function() {",
|
||||
" expect(1).to.equal(1)",
|
||||
" })",
|
||||
"})",
|
||||
}, "\n")
|
||||
local bufnr = make_buffer("/tmp/no-root.test.js", content)
|
||||
|
||||
local spec, err = runner.find_nearest(bufnr, 2, 0)
|
||||
ok(spec == nil, "expected no spec without package.json")
|
||||
eq(err, "no package.json found", "expected package.json error")
|
||||
|
||||
local command = runner.build_file_command(bufnr)
|
||||
eq(command.cmd[1], "echo")
|
||||
eq(command.cmd[2], "no package.json found")
|
||||
end
|
||||
|
||||
local function test_command_building()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"mocha":"10.0.0"}}]],
|
||||
}, function(root)
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local spec = {
|
||||
file = root .. "/test/math.spec.js",
|
||||
cwd = root,
|
||||
kind = "test",
|
||||
mocha_full_title = "Math adds",
|
||||
full_name = "Math/adds",
|
||||
}
|
||||
local command = runner.build_command(spec)
|
||||
eq(command.cmd[1], "npx")
|
||||
eq(command.cmd[2], "mocha")
|
||||
ok(vim.tbl_contains(command.cmd, "--reporter"), "expected reporter flag")
|
||||
ok(vim.tbl_contains(command.cmd, "json-stream"), "expected json-stream reporter")
|
||||
ok(vim.tbl_contains(command.cmd, "--grep"), "expected grep flag")
|
||||
end)
|
||||
end
|
||||
|
||||
local function test_build_all_command_includes_glob()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"mocha":"10.0.0"}}]],
|
||||
}, function(root)
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local bufnr = make_buffer(root .. "/test/sample.spec.js", "")
|
||||
local command = runner.build_all_command(bufnr)
|
||||
ok(vim.tbl_contains(command.cmd, "test/**/*.{test,spec}.{t,j}s"), "expected test glob")
|
||||
end)
|
||||
end
|
||||
|
||||
local function test_output_parser_and_locations()
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local output_lines = {
|
||||
[=[["suite",{"title":"Math","fullTitle":"Math"}]]=],
|
||||
[=[["pass",{"title":"adds","fullTitle":"Math adds","file":"/tmp/math.spec.js"}]]=],
|
||||
[=[["pass",{"title":"adds","fullTitle":"Math adds","file":"/tmp/math.spec.js"}]]=],
|
||||
[=[["fail",{"title":"subs","fullTitle":"Math subs","file":"/tmp/math.spec.js","err":"oops","stack":"Error: oops\n at Context.<anonymous> (/tmp/math.spec.js:10:5)"}]]=],
|
||||
[=[["pending",{"title":"skips","fullTitle":"Math skips","file":"/tmp/math.spec.js"}]]=],
|
||||
[=[["suite end",{"title":"Math","fullTitle":"Math"}]]=],
|
||||
}
|
||||
local parser = runner.output_parser()
|
||||
local state = {}
|
||||
local aggregated = { passes = {}, failures = {}, skips = {} }
|
||||
for _, line in ipairs(output_lines) do
|
||||
local results = parser.on_line(line, state)
|
||||
if results then
|
||||
for _, name in ipairs(results.passes or {}) do
|
||||
table.insert(aggregated.passes, name)
|
||||
end
|
||||
for _, name in ipairs(results.failures or {}) do
|
||||
table.insert(aggregated.failures, name)
|
||||
end
|
||||
for _, name in ipairs(results.skips or {}) do
|
||||
table.insert(aggregated.skips, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
eq(aggregated.passes[1], "Math/adds", "expected pass name")
|
||||
eq(#aggregated.passes, 1, "expected no duplicate passes")
|
||||
eq(aggregated.failures[1], "Math/subs", "expected failure name")
|
||||
eq(aggregated.skips[1], "Math/skips", "expected skip name")
|
||||
|
||||
local items = runner.collect_failed_locations(aggregated.failures, {}, "nearest")
|
||||
eq(items[1].filename, "/tmp/math.spec.js", "expected filename from stack")
|
||||
eq(items[1].lnum, 10, "expected line from stack")
|
||||
eq(items[1].col, 5, "expected col from stack")
|
||||
end
|
||||
|
||||
local function test_failed_only_command()
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
runner._last_mocha_titles = {
|
||||
["Math/adds"] = "Math adds",
|
||||
["Math/subs"] = "Math subs",
|
||||
}
|
||||
local command = runner.build_failed_command({ cwd = "/tmp" }, { "Math/adds", "Math/subs" }, "file")
|
||||
eq(command.cmd[1], "npx")
|
||||
ok(vim.tbl_contains(command.cmd, "--grep"), "expected grep for failed-only")
|
||||
local grep_index
|
||||
for idx, value in ipairs(command.cmd) do
|
||||
if value == "--grep" then
|
||||
grep_index = idx + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
ok(grep_index, "expected grep argument")
|
||||
ok(command.cmd[grep_index]:match("Math%.%*adds"), "expected grep pattern for first failure")
|
||||
end
|
||||
|
||||
local function test_parse_results_and_test_output()
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local output = table.concat({
|
||||
[=[["suite",{"title":"Math","fullTitle":"Math"}]]=],
|
||||
[=[["fail",{"title":"subs","fullTitle":"Math subs","file":"/tmp/math.spec.js","err":"oops","stack":"Error: oops\n at Context.<anonymous> (/tmp/math.spec.js:10:5)\n at processImmediate"}]]=],
|
||||
[=[["suite end",{"title":"Math","fullTitle":"Math"}]]=],
|
||||
}, "\n")
|
||||
local results = runner.parse_results(output)
|
||||
eq(results.failures[1], "Math/subs", "expected failure from parse_results")
|
||||
|
||||
local outputs = runner.parse_test_output(output)
|
||||
ok(outputs["Math/subs"], "expected test output for failure")
|
||||
local found = false
|
||||
for _, line in ipairs(outputs["Math/subs"]) do
|
||||
if line:match("oops") then
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
ok(found, "expected error output line")
|
||||
end
|
||||
|
||||
local function test_output_parser_on_complete_returns_nil()
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
local parser = runner.output_parser()
|
||||
local state = {}
|
||||
local output = [=[["pass",{"title":"adds","fullTitle":"Math adds","file":"/tmp/math.spec.js"}]]=]
|
||||
local results = parser.on_complete(output, state)
|
||||
ok(results == nil, "expected nil on_complete to avoid duplicate listings")
|
||||
end
|
||||
|
||||
local tests = {
|
||||
test_is_test_file_with_mocha_dependency,
|
||||
test_is_test_file_without_mocha_dependency,
|
||||
test_find_nearest_priorities,
|
||||
test_missing_package_json_errors,
|
||||
test_command_building,
|
||||
test_build_all_command_includes_glob,
|
||||
test_output_parser_and_locations,
|
||||
test_failed_only_command,
|
||||
test_parse_results_and_test_output,
|
||||
test_output_parser_on_complete_returns_nil,
|
||||
}
|
||||
|
||||
for _, test_fn in ipairs(tests) do
|
||||
test_fn()
|
||||
end
|
||||
200
tests/test_mocha_runner_spec.lua
Normal file
200
tests/test_mocha_runner_spec.lua
Normal file
@@ -0,0 +1,200 @@
|
||||
local runner = require("test-samurai-mocha-runner")
|
||||
|
||||
local function write_file(path, content)
|
||||
local dir = vim.fn.fnamemodify(path, ":h")
|
||||
vim.fn.mkdir(dir, "p")
|
||||
vim.fn.writefile(vim.split(content, "\n"), path)
|
||||
end
|
||||
|
||||
local function make_buffer(path, content)
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, vim.split(content, "\n"))
|
||||
return bufnr
|
||||
end
|
||||
|
||||
local function with_project(structure, fn)
|
||||
local root = vim.fn.tempname()
|
||||
vim.fn.mkdir(root, "p")
|
||||
root = vim.loop.fs_realpath(root) or root
|
||||
for rel_path, content in pairs(structure) do
|
||||
write_file(root .. "/" .. rel_path, content)
|
||||
end
|
||||
fn(root)
|
||||
end
|
||||
|
||||
describe("test-samurai-mocha-runner", function()
|
||||
it("detects mocha test files via package.json", function()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"mocha":"10.0.0"}}]],
|
||||
}, function(root)
|
||||
local bufnr = make_buffer(root .. "/test/sample.spec.js", "describe('x', function() {})")
|
||||
assert.is_true(runner.is_test_file(bufnr))
|
||||
end)
|
||||
end)
|
||||
|
||||
it("rejects non-mocha projects", function()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"jest":"29.0.0"}}]],
|
||||
}, function(root)
|
||||
local bufnr = make_buffer(root .. "/test/sample.spec.js", "describe('x', function() {})")
|
||||
assert.is_false(runner.is_test_file(bufnr))
|
||||
end)
|
||||
end)
|
||||
|
||||
it("finds nearest with test > suite > file priority", function()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"mocha":"10.0.0"}}]],
|
||||
}, function(root)
|
||||
local content = table.concat({
|
||||
"describe(\"Math\", function() {",
|
||||
" it(\"adds\", function() {",
|
||||
" expect(1).to.equal(1)",
|
||||
" })",
|
||||
"",
|
||||
" it(\"subs\", function() {",
|
||||
" expect(1).to.equal(1)",
|
||||
" })",
|
||||
"})",
|
||||
"",
|
||||
"const value = 1",
|
||||
}, "\n")
|
||||
local bufnr = make_buffer(root .. "/test/math.spec.js", content)
|
||||
|
||||
local spec_test = assert(runner.find_nearest(bufnr, 3, 0))
|
||||
assert.equals("test", spec_test.kind)
|
||||
assert.equals("Math/adds", spec_test.full_name)
|
||||
|
||||
local spec_suite = assert(runner.find_nearest(bufnr, 5, 0))
|
||||
assert.equals("suite", spec_suite.kind)
|
||||
assert.equals("Math", spec_suite.full_name)
|
||||
|
||||
local spec_file = assert(runner.find_nearest(bufnr, 11, 0))
|
||||
assert.equals("file", spec_file.kind)
|
||||
end)
|
||||
end)
|
||||
|
||||
it("returns error when no package.json found", function()
|
||||
local content = table.concat({
|
||||
"describe(\"Math\", function() {",
|
||||
" it(\"adds\", function() {",
|
||||
" expect(1).to.equal(1)",
|
||||
" })",
|
||||
"})",
|
||||
}, "\n")
|
||||
local bufnr = make_buffer("/tmp/no-root.test.js", content)
|
||||
|
||||
local spec, err = runner.find_nearest(bufnr, 2, 0)
|
||||
assert.is_nil(spec)
|
||||
assert.equals("no package.json found", err)
|
||||
|
||||
local command = runner.build_file_command(bufnr)
|
||||
assert.are.same({ "echo", "no package.json found" }, command.cmd)
|
||||
end)
|
||||
|
||||
it("builds command with mocha json-stream and grep", function()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"mocha":"10.0.0"}}]],
|
||||
}, function(root)
|
||||
local spec = {
|
||||
file = root .. "/test/math.spec.js",
|
||||
cwd = root,
|
||||
kind = "test",
|
||||
mocha_full_title = "Math adds",
|
||||
full_name = "Math/adds",
|
||||
}
|
||||
local command = runner.build_command(spec)
|
||||
assert.equals("npx", command.cmd[1])
|
||||
assert.equals("mocha", command.cmd[2])
|
||||
assert.is_true(vim.tbl_contains(command.cmd, "--reporter"))
|
||||
assert.is_true(vim.tbl_contains(command.cmd, "json-stream"))
|
||||
assert.is_true(vim.tbl_contains(command.cmd, "--grep"))
|
||||
end)
|
||||
end)
|
||||
|
||||
it("builds TSamAll with test glob", function()
|
||||
with_project({
|
||||
["package.json"] = [[{"devDependencies":{"mocha":"10.0.0"}}]],
|
||||
}, function(root)
|
||||
local bufnr = make_buffer(root .. "/test/sample.spec.js", "")
|
||||
local command = runner.build_all_command(bufnr)
|
||||
assert.is_true(vim.tbl_contains(command.cmd, "test/**/*.{test,spec}.{t,j}s"))
|
||||
end)
|
||||
end)
|
||||
|
||||
it("streams results without duplicates", function()
|
||||
local output_lines = {
|
||||
[=["suite",{"title":"Math","fullTitle":"Math"}]=],
|
||||
[=["pass",{"title":"adds","fullTitle":"Math adds","file":"/tmp/math.spec.js"}]=],
|
||||
[=["pass",{"title":"adds","fullTitle":"Math adds","file":"/tmp/math.spec.js"}]=],
|
||||
[=["fail",{"title":"subs","fullTitle":"Math subs","file":"/tmp/math.spec.js","err":"oops","stack":"Error: oops\n at Context.<anonymous> (/tmp/math.spec.js:10:5)"}]=],
|
||||
[=["pending",{"title":"skips","fullTitle":"Math skips","file":"/tmp/math.spec.js"}]=],
|
||||
[=["suite end",{"title":"Math","fullTitle":"Math"}]=],
|
||||
}
|
||||
local parser = runner.output_parser()
|
||||
local state = {}
|
||||
local aggregated = { passes = {}, failures = {}, skips = {} }
|
||||
for _, line in ipairs(output_lines) do
|
||||
local results = parser.on_line("[" .. line .. "]", state)
|
||||
if results then
|
||||
for _, name in ipairs(results.passes or {}) do
|
||||
table.insert(aggregated.passes, name)
|
||||
end
|
||||
for _, name in ipairs(results.failures or {}) do
|
||||
table.insert(aggregated.failures, name)
|
||||
end
|
||||
for _, name in ipairs(results.skips or {}) do
|
||||
table.insert(aggregated.skips, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
assert.equals("Math/adds", aggregated.passes[1])
|
||||
assert.equals(1, #aggregated.passes)
|
||||
assert.equals("Math/subs", aggregated.failures[1])
|
||||
assert.equals("Math/skips", aggregated.skips[1])
|
||||
|
||||
local items = runner.collect_failed_locations(aggregated.failures, {}, "nearest")
|
||||
assert.equals("/tmp/math.spec.js", items[1].filename)
|
||||
assert.equals(10, items[1].lnum)
|
||||
assert.equals(5, items[1].col)
|
||||
end)
|
||||
|
||||
it("builds failed-only command with grep pattern", function()
|
||||
runner._last_mocha_titles = {
|
||||
["Math/adds"] = "Math adds",
|
||||
["Math/subs"] = "Math subs",
|
||||
}
|
||||
local command = runner.build_failed_command({ cwd = "/tmp" }, { "Math/adds", "Math/subs" }, "file")
|
||||
assert.equals("npx", command.cmd[1])
|
||||
assert.is_true(vim.tbl_contains(command.cmd, "--grep"))
|
||||
local grep_index
|
||||
for idx, value in ipairs(command.cmd) do
|
||||
if value == "--grep" then
|
||||
grep_index = idx + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
assert.is_true(command.cmd[grep_index]:match("Math%.%*adds") ~= nil)
|
||||
end)
|
||||
|
||||
it("parses results and per-test output", function()
|
||||
local output = table.concat({
|
||||
[=["suite",{"title":"Math","fullTitle":"Math"}]=],
|
||||
[=["fail",{"title":"subs","fullTitle":"Math subs","file":"/tmp/math.spec.js","err":"oops","stack":"Error: oops\n at Context.<anonymous> (/tmp/math.spec.js:10:5)\n at processImmediate"}]=],
|
||||
[=["suite end",{"title":"Math","fullTitle":"Math"}]=],
|
||||
}, "\n")
|
||||
local results = runner.parse_results("[" .. output:gsub("\n", "]\n[") .. "]")
|
||||
assert.equals("Math/subs", results.failures[1])
|
||||
|
||||
local outputs = runner.parse_test_output("[" .. output:gsub("\n", "]\n[") .. "]")
|
||||
assert.is_true(outputs["Math/subs"] ~= nil)
|
||||
end)
|
||||
|
||||
it("does not return results on complete", function()
|
||||
local parser = runner.output_parser()
|
||||
local state = {}
|
||||
local output = "[" .. [=["pass",{"title":"adds","fullTitle":"Math adds","file":"/tmp/math.spec.js"}]=] .. "]"
|
||||
local results = parser.on_complete(output, state)
|
||||
assert.is_nil(results)
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user