remove built-in runner
This commit is contained in:
@@ -1,12 +1,7 @@
|
||||
local M = {}
|
||||
|
||||
local defaults = {
|
||||
runner_modules = {
|
||||
"test-samurai.runners.go",
|
||||
"test-samurai.runners.js-jest",
|
||||
"test-samurai.runners.js-mocha",
|
||||
"test-samurai.runners.js-vitest",
|
||||
},
|
||||
runner_modules = {},
|
||||
}
|
||||
|
||||
local current = vim.deepcopy(defaults)
|
||||
|
||||
@@ -436,13 +436,6 @@ function M.get_runner_for_buf(bufnr)
|
||||
return nil
|
||||
end
|
||||
|
||||
if path:find(".test.", 1, true) or path:find(".spec.", 1, true) then
|
||||
local ok, jsjest = pcall(require, "test-samurai.runners.js-jest")
|
||||
if ok and type(jsjest) == "table" then
|
||||
return jsjest
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -1915,7 +1908,7 @@ function M.run_nearest()
|
||||
|
||||
local runner = M.get_runner_for_buf(bufnr)
|
||||
if not runner then
|
||||
vim.notify("[test-samurai] No runner for this file", vim.log.levels.WARN)
|
||||
vim.notify("[test-samurai] no runner installed for this kind of test", vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -1959,7 +1952,7 @@ function M.run_file()
|
||||
|
||||
local runner = M.get_runner_for_buf(bufnr)
|
||||
if not runner then
|
||||
vim.notify("[test-samurai] No runner for this file", vim.log.levels.WARN)
|
||||
vim.notify("[test-samurai] no runner installed for this kind of test", vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -1992,7 +1985,7 @@ function M.run_all()
|
||||
|
||||
local runner = M.get_runner_for_buf(bufnr)
|
||||
if not runner then
|
||||
vim.notify("[test-samurai] No runner for this file", vim.log.levels.WARN)
|
||||
vim.notify("[test-samurai] no runner installed for this kind of test", vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -1,502 +0,0 @@
|
||||
local util = require("test-samurai.util")
|
||||
|
||||
local runner = {
|
||||
name = "go",
|
||||
}
|
||||
|
||||
local function find_block_end(lines, start_idx)
|
||||
local depth = 0
|
||||
local started = false
|
||||
for i = start_idx, #lines do
|
||||
local line = lines[i]
|
||||
for j = 1, #line do
|
||||
local ch = line:sub(j, j)
|
||||
if ch == "{" then
|
||||
depth = depth + 1
|
||||
started = true
|
||||
elseif ch == "}" then
|
||||
if started then
|
||||
depth = depth - 1
|
||||
if depth == 0 then
|
||||
return i - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return #lines - 1
|
||||
end
|
||||
|
||||
local function find_test_functions(lines)
|
||||
local funcs = {}
|
||||
for i, line in ipairs(lines) do
|
||||
local name = line:match("^%s*func%s+([%w_]+)%s*%(")
|
||||
if not name then
|
||||
name = line:match("^%s*func%s+%([^)]-%)%s+([%w_]+)%s*%(")
|
||||
end
|
||||
if name and line:find("%*testing%.T") then
|
||||
local start_0 = i - 1
|
||||
local end_0 = find_block_end(lines, i)
|
||||
table.insert(funcs, {
|
||||
name = name,
|
||||
start = start_0,
|
||||
["end"] = end_0,
|
||||
})
|
||||
end
|
||||
end
|
||||
return funcs
|
||||
end
|
||||
|
||||
local function find_t_runs(lines, func)
|
||||
local subtests = {}
|
||||
for i = func.start + 1, func["end"] do
|
||||
local line = lines[i + 1]
|
||||
if line then
|
||||
local name = line:match("t%.Run%(%s*['\"]([^'\"]+)['\"]")
|
||||
if name then
|
||||
local start_idx = i + 1
|
||||
local end_0 = find_block_end(lines, start_idx)
|
||||
table.insert(subtests, {
|
||||
name = name,
|
||||
start = start_idx - 1,
|
||||
["end"] = end_0,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
return subtests
|
||||
end
|
||||
|
||||
local function escape_go_regex(s)
|
||||
s = s or ""
|
||||
return (s:gsub("([\\.^$|()%%[%]{}*+?%-])", "\\\\%1"))
|
||||
end
|
||||
|
||||
local function build_run_pattern(spec)
|
||||
local name = spec.test_path or ""
|
||||
local escaped = escape_go_regex(name)
|
||||
if spec.scope == "function" then
|
||||
return "^" .. escaped .. "($|/)"
|
||||
else
|
||||
return "^" .. escaped .. "$"
|
||||
end
|
||||
end
|
||||
|
||||
local function build_pkg_arg(spec)
|
||||
local file = spec.file
|
||||
local cwd = spec.cwd
|
||||
if not file or not cwd or file == "" or cwd == "" then
|
||||
return "./..."
|
||||
end
|
||||
|
||||
local dir = vim.fs.dirname(file)
|
||||
if dir == cwd then
|
||||
return "./"
|
||||
end
|
||||
|
||||
if file:sub(1, #cwd) ~= cwd then
|
||||
return "./..."
|
||||
end
|
||||
|
||||
local rel = dir:sub(#cwd + 2)
|
||||
if not rel or rel == "" then
|
||||
return "./"
|
||||
end
|
||||
|
||||
return "./" .. rel
|
||||
end
|
||||
|
||||
local function collect_unique(list)
|
||||
local out = {}
|
||||
local seen = {}
|
||||
for _, item in ipairs(list) do
|
||||
if item and item ~= "" and not seen[item] then
|
||||
seen[item] = true
|
||||
table.insert(out, item)
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
function runner.is_test_file(bufnr)
|
||||
local path = util.get_buf_path(bufnr)
|
||||
if not path or path == "" then
|
||||
return false
|
||||
end
|
||||
return path:sub(-8) == "_test.go"
|
||||
end
|
||||
|
||||
function runner.find_nearest(bufnr, row, _col)
|
||||
if not runner.is_test_file(bufnr) then
|
||||
return nil, "not a Go test file"
|
||||
end
|
||||
|
||||
local lines = util.get_buf_lines(bufnr)
|
||||
local funcs = find_test_functions(lines)
|
||||
|
||||
local current
|
||||
for _, f in ipairs(funcs) do
|
||||
if row >= f.start and row <= f["end"] then
|
||||
current = f
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not current then
|
||||
return nil, "cursor not inside a test function"
|
||||
end
|
||||
|
||||
local subtests = find_t_runs(lines, current)
|
||||
local inside_sub
|
||||
for _, sub in ipairs(subtests) do
|
||||
if row >= sub.start and row <= sub["end"] then
|
||||
inside_sub = sub
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local path = util.get_buf_path(bufnr)
|
||||
local root = util.find_root(path, { "go.mod", ".git" })
|
||||
|
||||
if inside_sub then
|
||||
local full = current.name .. "/" .. inside_sub.name
|
||||
return {
|
||||
file = path,
|
||||
cwd = root,
|
||||
test_path = full,
|
||||
scope = "subtest",
|
||||
func = current.name,
|
||||
subtest = inside_sub.name,
|
||||
}
|
||||
else
|
||||
return {
|
||||
file = path,
|
||||
cwd = root,
|
||||
test_path = current.name,
|
||||
scope = "function",
|
||||
func = current.name,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function runner.build_command(spec)
|
||||
local pattern = build_run_pattern(spec)
|
||||
local pkg = build_pkg_arg(spec)
|
||||
local cmd = { "go", "test", "-json", pkg, "-run", pattern }
|
||||
return {
|
||||
cmd = cmd,
|
||||
cwd = spec.cwd,
|
||||
}
|
||||
end
|
||||
|
||||
function runner.build_file_command(bufnr)
|
||||
local path = util.get_buf_path(bufnr)
|
||||
if not path or path == "" then
|
||||
return nil
|
||||
end
|
||||
local root = util.find_root(path, { "go.mod", ".git" })
|
||||
if not root or root == "" then
|
||||
root = vim.loop.cwd()
|
||||
end
|
||||
local spec = { file = path, cwd = root }
|
||||
local pkg = build_pkg_arg(spec)
|
||||
local cmd = { "go", "test", "-json", pkg }
|
||||
local lines = util.get_buf_lines(bufnr)
|
||||
local funcs = find_test_functions(lines)
|
||||
local names = {}
|
||||
for _, fn in ipairs(funcs) do
|
||||
table.insert(names, fn.name)
|
||||
end
|
||||
names = collect_unique(names)
|
||||
if #names > 0 then
|
||||
local pattern_parts = {}
|
||||
for _, name in ipairs(names) do
|
||||
table.insert(pattern_parts, escape_go_regex(name))
|
||||
end
|
||||
local pattern = "^(" .. table.concat(pattern_parts, "|") .. ")$"
|
||||
table.insert(cmd, "-run")
|
||||
table.insert(cmd, pattern)
|
||||
end
|
||||
return {
|
||||
cmd = cmd,
|
||||
cwd = root,
|
||||
}
|
||||
end
|
||||
|
||||
function runner.build_all_command(bufnr)
|
||||
local path = util.get_buf_path(bufnr)
|
||||
local root
|
||||
if path and path ~= "" then
|
||||
root = util.find_root(path, { "go.mod", ".git" })
|
||||
end
|
||||
if not root or root == "" then
|
||||
root = vim.loop.cwd()
|
||||
end
|
||||
local cmd = { "go", "test", "-json", "./..." }
|
||||
return {
|
||||
cmd = cmd,
|
||||
cwd = root,
|
||||
}
|
||||
end
|
||||
|
||||
function runner.parse_results(output)
|
||||
if not output or output == "" then
|
||||
return { passes = {}, failures = {}, skips = {}, display = { passes = {}, failures = {}, skips = {} } }
|
||||
end
|
||||
local passes = {}
|
||||
local failures = {}
|
||||
local skips = {}
|
||||
local display = { passes = {}, failures = {}, skips = {} }
|
||||
for line in output:gmatch("[^\n]+") do
|
||||
local ok, data = pcall(vim.json.decode, line)
|
||||
if ok and type(data) == "table" then
|
||||
if data.Test and data.Test ~= "" then
|
||||
if data.Action == "pass" then
|
||||
table.insert(passes, data.Test)
|
||||
local short = data.Test:match("([^/]+)$") or data.Test
|
||||
table.insert(display.passes, short)
|
||||
elseif data.Action == "fail" then
|
||||
table.insert(failures, data.Test)
|
||||
local short = data.Test:match("([^/]+)$") or data.Test
|
||||
table.insert(display.failures, short)
|
||||
elseif data.Action == "skip" then
|
||||
table.insert(skips, data.Test)
|
||||
local short = data.Test:match("([^/]+)$") or data.Test
|
||||
table.insert(display.skips, short)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return {
|
||||
passes = collect_unique(passes),
|
||||
failures = collect_unique(failures),
|
||||
skips = collect_unique(skips),
|
||||
display = display,
|
||||
}
|
||||
end
|
||||
|
||||
local function split_output_lines(text)
|
||||
if not text or text == "" then
|
||||
return {}
|
||||
end
|
||||
local lines = vim.split(text, "\n", { plain = true })
|
||||
if #lines > 0 and lines[#lines] == "" then
|
||||
table.remove(lines, #lines)
|
||||
end
|
||||
return lines
|
||||
end
|
||||
|
||||
local function normalize_go_name(name)
|
||||
if not name or name == "" then
|
||||
return nil
|
||||
end
|
||||
return (name:gsub("%s+", "_"))
|
||||
end
|
||||
|
||||
local function add_location(target, key, file, line, label)
|
||||
if not key or key == "" or not file or file == "" or not line then
|
||||
return
|
||||
end
|
||||
local text = label or key
|
||||
if not target[key] then
|
||||
target[key] = {}
|
||||
end
|
||||
table.insert(target[key], {
|
||||
filename = file,
|
||||
lnum = line,
|
||||
col = 1,
|
||||
text = text,
|
||||
})
|
||||
end
|
||||
|
||||
local function collect_file_locations(file, target)
|
||||
local ok, lines = pcall(vim.fn.readfile, file)
|
||||
if not ok or type(lines) ~= "table" then
|
||||
return
|
||||
end
|
||||
local funcs = find_test_functions(lines)
|
||||
for _, fn in ipairs(funcs) do
|
||||
add_location(target, fn.name, file, fn.start + 1, fn.name)
|
||||
local normalized = normalize_go_name(fn.name)
|
||||
if normalized and normalized ~= fn.name then
|
||||
add_location(target, normalized, file, fn.start + 1, fn.name)
|
||||
end
|
||||
for _, sub in ipairs(find_t_runs(lines, fn)) do
|
||||
local full = fn.name .. "/" .. sub.name
|
||||
add_location(target, full, file, sub.start + 1, full)
|
||||
local normalized_full = normalize_go_name(full)
|
||||
if normalized_full and normalized_full ~= full then
|
||||
add_location(target, normalized_full, file, sub.start + 1, full)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function collect_go_test_files(root)
|
||||
if not root or root == "" then
|
||||
root = vim.loop.cwd()
|
||||
end
|
||||
local files = vim.fn.globpath(root, "**/*_test.go", false, true)
|
||||
if type(files) ~= "table" then
|
||||
return {}
|
||||
end
|
||||
return files
|
||||
end
|
||||
|
||||
function runner.parse_test_output(output)
|
||||
local out = {}
|
||||
if not output or output == "" then
|
||||
return out
|
||||
end
|
||||
for line in output:gmatch("[^\n]+") do
|
||||
local ok, data = pcall(vim.json.decode, line)
|
||||
if ok and type(data) == "table" and data.Action == "output" and data.Test and data.Output then
|
||||
if not out[data.Test] then
|
||||
out[data.Test] = {}
|
||||
end
|
||||
for _, item in ipairs(split_output_lines(data.Output)) do
|
||||
table.insert(out[data.Test], item)
|
||||
end
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
function runner.output_parser()
|
||||
local seen_pass = {}
|
||||
local seen_fail = {}
|
||||
local failures = {}
|
||||
local passes = {}
|
||||
local skips = {}
|
||||
local display = { passes = {}, failures = {}, skips = {} }
|
||||
|
||||
return {
|
||||
on_line = function(line, _state)
|
||||
local ok, data = pcall(vim.json.decode, line)
|
||||
if not ok or type(data) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
local name = data.Test
|
||||
if not name or name == "" then
|
||||
return nil
|
||||
end
|
||||
local short = name:match("([^/]+)$") or name
|
||||
if data.Action == "pass" and not seen_pass[name] then
|
||||
seen_pass[name] = true
|
||||
table.insert(passes, name)
|
||||
table.insert(display.passes, short)
|
||||
return {
|
||||
passes = { name },
|
||||
failures = {},
|
||||
skips = {},
|
||||
display = { passes = { short }, failures = {}, skips = {} },
|
||||
failures_all = vim.deepcopy(failures),
|
||||
}
|
||||
elseif data.Action == "fail" and not seen_fail[name] then
|
||||
seen_fail[name] = true
|
||||
table.insert(failures, name)
|
||||
table.insert(display.failures, short)
|
||||
return {
|
||||
passes = {},
|
||||
failures = { name },
|
||||
skips = {},
|
||||
display = { passes = {}, failures = { short }, skips = {} },
|
||||
failures_all = vim.deepcopy(failures),
|
||||
}
|
||||
elseif data.Action == "skip" and not seen_pass[name] then
|
||||
seen_pass[name] = true
|
||||
table.insert(skips, name)
|
||||
table.insert(display.skips, short)
|
||||
return {
|
||||
passes = {},
|
||||
failures = {},
|
||||
skips = { name },
|
||||
display = { passes = {}, failures = {}, skips = { short } },
|
||||
failures_all = vim.deepcopy(failures),
|
||||
}
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
on_complete = function(_output, _state)
|
||||
return nil
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
function runner.build_failed_command(last_command, failures, _scope_kind)
|
||||
if not last_command or type(last_command.cmd) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
local pattern_parts = {}
|
||||
for _, name in ipairs(failures or {}) do
|
||||
table.insert(pattern_parts, escape_go_regex(name))
|
||||
end
|
||||
if #pattern_parts == 0 then
|
||||
return nil
|
||||
end
|
||||
local pattern = "^(" .. table.concat(pattern_parts, "|") .. ")$"
|
||||
|
||||
local cmd = {}
|
||||
local skip_next = false
|
||||
for _, arg in ipairs(last_command.cmd) do
|
||||
if skip_next then
|
||||
skip_next = false
|
||||
elseif arg == "-run" then
|
||||
skip_next = true
|
||||
else
|
||||
table.insert(cmd, arg)
|
||||
end
|
||||
end
|
||||
table.insert(cmd, "-run")
|
||||
table.insert(cmd, pattern)
|
||||
|
||||
return {
|
||||
cmd = cmd,
|
||||
cwd = last_command.cwd,
|
||||
}
|
||||
end
|
||||
|
||||
function runner.collect_failed_locations(failures, command, scope_kind)
|
||||
if type(failures) ~= "table" or #failures == 0 then
|
||||
return {}
|
||||
end
|
||||
local files = {}
|
||||
if scope_kind == "all" then
|
||||
files = collect_go_test_files(command and command.cwd or nil)
|
||||
elseif command and command.file then
|
||||
files = { command.file }
|
||||
end
|
||||
if #files == 0 then
|
||||
return {}
|
||||
end
|
||||
local locations = {}
|
||||
for _, file in ipairs(files) do
|
||||
collect_file_locations(file, locations)
|
||||
end
|
||||
local items = {}
|
||||
local seen = {}
|
||||
local function add_locations(name, locs)
|
||||
for _, loc in ipairs(locs or {}) do
|
||||
local key = string.format("%s:%d:%s", loc.filename or "", loc.lnum or 0, loc.text or name or "")
|
||||
if not seen[key] then
|
||||
seen[key] = true
|
||||
table.insert(items, loc)
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, name in ipairs(failures) do
|
||||
local direct = locations[name]
|
||||
if direct then
|
||||
add_locations(name, direct)
|
||||
elseif not name:find("/", 1, true) then
|
||||
for full, locs in pairs(locations) do
|
||||
if full:sub(-#name - 1) == "/" .. name then
|
||||
add_locations(full, locs)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return items
|
||||
end
|
||||
|
||||
return runner
|
||||
@@ -1,8 +0,0 @@
|
||||
local js = require("test-samurai.runners.js")
|
||||
|
||||
return js.new({
|
||||
name = "js-jest",
|
||||
framework = "jest",
|
||||
command = { "npx", "jest" },
|
||||
json_args = { "--json", "--verbose" },
|
||||
})
|
||||
@@ -1,9 +0,0 @@
|
||||
local js = require("test-samurai.runners.js")
|
||||
|
||||
return js.new({
|
||||
name = "js-mocha",
|
||||
framework = "mocha",
|
||||
command = { "npx", "mocha" },
|
||||
all_glob = "test/**/*.test.js",
|
||||
json_args = { "--reporter", "json-stream" },
|
||||
})
|
||||
@@ -1,8 +0,0 @@
|
||||
local js = require("test-samurai.runners.js")
|
||||
|
||||
return js.new({
|
||||
name = "js-vitest",
|
||||
framework = "vitest",
|
||||
command = { "npx", "vitest" },
|
||||
json_args = { "--reporter", "tap-flat" },
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,81 +1,35 @@
|
||||
local test_samurai = require("test-samurai")
|
||||
local core = require("test-samurai.core")
|
||||
local util = require("test-samurai.util")
|
||||
local config = require("test-samurai.config")
|
||||
|
||||
local orig_find_root = util.find_root
|
||||
local orig_fs_stat = vim.loop.fs_stat
|
||||
local orig_readfile = vim.fn.readfile
|
||||
|
||||
describe("test-samurai core", function()
|
||||
describe("test-samurai core (no bundled runners)", function()
|
||||
before_each(function()
|
||||
test_samurai.setup()
|
||||
util.find_root = orig_find_root
|
||||
vim.loop.fs_stat = orig_fs_stat
|
||||
vim.fn.readfile = orig_readfile
|
||||
end)
|
||||
|
||||
it("selects Go runner for _test.go files", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/foo_test.go")
|
||||
local runner = core.get_runner_for_buf(bufnr)
|
||||
assert.is_not_nil(runner)
|
||||
assert.equals("go", runner.name)
|
||||
it("defaults to an empty runner_modules list", function()
|
||||
local cfg = config.get()
|
||||
assert.is_true(type(cfg.runner_modules) == "table")
|
||||
assert.equals(0, #cfg.runner_modules)
|
||||
end)
|
||||
|
||||
it("does not fallback to Go runner when no runners are configured", function()
|
||||
test_samurai.setup({ runner_modules = {} })
|
||||
it("warns when no runner is installed for a test file", function()
|
||||
local notified = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(notified, { msg = msg, level = level })
|
||||
end
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/no_runner_test.go")
|
||||
local runner = core.get_runner_for_buf(bufnr)
|
||||
assert.is_nil(runner)
|
||||
end)
|
||||
vim.bo[bufnr].filetype = "go"
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
|
||||
it("selects JS jest runner for *.test.ts files", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/foo.test.ts")
|
||||
vim.bo[bufnr].filetype = "typescript"
|
||||
core.run_nearest()
|
||||
|
||||
local runner = core.get_runner_for_buf(bufnr)
|
||||
assert.is_not_nil(runner)
|
||||
assert.equals("js-jest", runner.name)
|
||||
end)
|
||||
vim.notify = orig_notify
|
||||
|
||||
it("prefers mocha runner when mocha is in package.json", function()
|
||||
util.find_root = function(_, _)
|
||||
return "/tmp/mocha_proj"
|
||||
end
|
||||
|
||||
vim.loop.fs_stat = function(path)
|
||||
if path == "/tmp/mocha_proj/package.json" then
|
||||
return { type = "file" }
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
vim.fn.readfile = function(path)
|
||||
if path == "/tmp/mocha_proj/package.json" then
|
||||
return {
|
||||
"{",
|
||||
' "devDependencies": { "mocha": "^10.0.0" }',
|
||||
"}",
|
||||
}
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
test_samurai.setup()
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/mocha_proj/foo.test.ts")
|
||||
vim.bo[bufnr].filetype = "typescript"
|
||||
|
||||
local runner = core.get_runner_for_buf(bufnr)
|
||||
|
||||
util.find_root = orig_find_root
|
||||
vim.loop.fs_stat = orig_fs_stat
|
||||
vim.fn.readfile = orig_readfile
|
||||
|
||||
assert.is_not_nil(runner)
|
||||
assert.equals("js-mocha", runner.name)
|
||||
assert.equals(1, #notified)
|
||||
assert.equals("[test-samurai] no runner installed for this kind of test", notified[1].msg)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
local test_samurai = require("test-samurai")
|
||||
local core = require("test-samurai.core")
|
||||
|
||||
local function mkbuf(path, ft, lines)
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = ft
|
||||
if lines then
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
end
|
||||
return bufnr
|
||||
end
|
||||
|
||||
local function stub_jobstart(opts_config)
|
||||
local calls = {}
|
||||
local orig = vim.fn.jobstart
|
||||
local idx = 0
|
||||
local config = opts_config or {}
|
||||
vim.fn.jobstart = function(cmd, opts)
|
||||
idx = idx + 1
|
||||
table.insert(calls, { cmd = cmd, opts = opts })
|
||||
local code = 0
|
||||
if type(config.exit_codes) == "table" then
|
||||
code = config.exit_codes[idx] or 0
|
||||
elseif type(config.exit_codes) == "number" then
|
||||
code = config.exit_codes
|
||||
end
|
||||
local out = config.stdout and config.stdout[idx] or nil
|
||||
if out and opts and opts.on_stdout then
|
||||
if type(out) == "string" then
|
||||
out = { out }
|
||||
end
|
||||
opts.on_stdout(1, out, nil)
|
||||
end
|
||||
local err = config.stderr and config.stderr[idx] or nil
|
||||
if err and opts and opts.on_stderr then
|
||||
if type(err) == "string" then
|
||||
err = { err }
|
||||
end
|
||||
opts.on_stderr(1, err, nil)
|
||||
end
|
||||
if opts and opts.on_exit then
|
||||
opts.on_exit(1, code, nil)
|
||||
end
|
||||
return 1
|
||||
end
|
||||
return calls, orig
|
||||
end
|
||||
|
||||
describe("TSamFailedOnly", function()
|
||||
before_each(function()
|
||||
test_samurai.setup()
|
||||
end)
|
||||
|
||||
it("reruns failed jest tests with --onlyFailures", function()
|
||||
local json = vim.json.encode({
|
||||
testResults = {
|
||||
{
|
||||
assertionResults = {
|
||||
{ status = "passed", title = "inner 1", fullName = "outer inner 1" },
|
||||
{ status = "failed", title = "inner 2", fullName = "outer inner 2" },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
local calls, orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1, 0 },
|
||||
stdout = { { json } },
|
||||
})
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/foo_failed_only.test.ts", "typescript", {
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" -- inside 1",
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" -- inside 2",
|
||||
" })",
|
||||
"})",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 7, 0 })
|
||||
|
||||
core.run_nearest()
|
||||
core.run_failed_only()
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(2, #calls)
|
||||
assert.are.same(
|
||||
{ "npx", "jest", "--json", "--verbose", "/tmp/project/foo_failed_only.test.ts", "-t", "inner 2" },
|
||||
calls[1].cmd
|
||||
)
|
||||
assert.are.same(
|
||||
{ "npx", "jest", "--json", "--verbose", "-t", "outer inner 2", "/tmp/project/foo_failed_only.test.ts" },
|
||||
calls[2].cmd
|
||||
)
|
||||
end)
|
||||
|
||||
it("falls back to TSamLast when last run had no failures", function()
|
||||
local json = vim.json.encode({
|
||||
testResults = {
|
||||
{
|
||||
assertionResults = {
|
||||
{ status = "passed", title = "inner 1", fullName = "outer inner 1" },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
local calls, orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 0, 0 },
|
||||
stdout = { { json } },
|
||||
})
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/foo_failed_only_pass.test.ts", "typescript", {
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" -- inside 1",
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" -- inside 2",
|
||||
" })",
|
||||
"})",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 7, 0 })
|
||||
|
||||
core.run_nearest()
|
||||
core.run_failed_only()
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(2, #calls)
|
||||
assert.are.same(calls[1].cmd, calls[2].cmd)
|
||||
end)
|
||||
|
||||
it("reruns failed go tests with -run regex", function()
|
||||
local json_lines = {
|
||||
vim.json.encode({ Action = "fail", Test = "TestFoo/first" }),
|
||||
vim.json.encode({ Action = "fail", Test = "TestBar" }),
|
||||
}
|
||||
|
||||
local calls, orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1, 0 },
|
||||
stdout = { json_lines },
|
||||
})
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/foo_failed_only_test.go", "go", {
|
||||
"package main",
|
||||
"import \"testing\"",
|
||||
"",
|
||||
"func TestFoo(t *testing.T) {",
|
||||
" t.Run(\"first\", func(t *testing.T) {",
|
||||
" -- inside first",
|
||||
" })",
|
||||
"}",
|
||||
"",
|
||||
"func TestBar(t *testing.T) {",
|
||||
" -- inside bar",
|
||||
"}",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
|
||||
core.run_all()
|
||||
core.run_failed_only()
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(2, #calls)
|
||||
assert.are.same({ "go", "test", "-json", "./..." }, calls[1].cmd)
|
||||
assert.are.same({ "go", "test", "-json", "./...", "-run", "^(TestFoo/first|TestBar)$" }, calls[2].cmd)
|
||||
end)
|
||||
|
||||
it("uses go parser for failed-only output (no raw JSON)", function()
|
||||
local json_line = vim.json.encode({
|
||||
Action = "fail",
|
||||
Test = "TestHandleGet/returns_200",
|
||||
})
|
||||
|
||||
local calls, orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1, 1 },
|
||||
stdout = { { json_line }, { json_line } },
|
||||
})
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/foo_failed_only_output_test.go", "go", {
|
||||
"package main",
|
||||
"import \"testing\"",
|
||||
"",
|
||||
"func TestHandleGet(t *testing.T) {",
|
||||
" t.Run(\"returns_200\", func(t *testing.T) {",
|
||||
" -- inside test",
|
||||
" })",
|
||||
"}",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
|
||||
core.run_all()
|
||||
core.run_failed_only()
|
||||
|
||||
local out_buf = vim.api.nvim_get_current_buf()
|
||||
local lines = vim.api.nvim_buf_get_lines(out_buf, 0, -1, false)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(2, #calls)
|
||||
local has_raw = false
|
||||
for _, line in ipairs(lines) do
|
||||
if line == json_line then
|
||||
has_raw = true
|
||||
break
|
||||
end
|
||||
end
|
||||
assert.is_false(has_raw)
|
||||
end)
|
||||
|
||||
it("reruns failed mocha tests from json-stream array output without raw JSON", function()
|
||||
test_samurai.setup({
|
||||
runner_modules = {
|
||||
"test-samurai.runners.js-mocha",
|
||||
},
|
||||
})
|
||||
|
||||
local fail_line = vim.json.encode({
|
||||
event = "fail",
|
||||
fullTitle = "API :: /brands... GET: /",
|
||||
})
|
||||
local start_line = vim.json.encode({ "start", { total = 1 } })
|
||||
local end_line = vim.json.encode({ "end", { tests = 0 } })
|
||||
|
||||
local calls, orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1, 1 },
|
||||
stdout = { { fail_line }, { start_line, end_line } },
|
||||
})
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/brands.test.js", "javascript", {
|
||||
'describe("API :: /brands...", function() {',
|
||||
' it("GET: /", function() {',
|
||||
" -- inside test",
|
||||
" })",
|
||||
"})",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 3, 0 })
|
||||
|
||||
core.run_file()
|
||||
core.run_failed_only()
|
||||
|
||||
local out_buf = vim.api.nvim_get_current_buf()
|
||||
local lines = vim.api.nvim_buf_get_lines(out_buf, 0, -1, false)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(2, #calls)
|
||||
assert.are.same(
|
||||
{ "npx", "mocha", "--reporter", "json-stream", "/tmp/project/brands.test.js" },
|
||||
calls[1].cmd
|
||||
)
|
||||
local failed_cmd = calls[2].cmd or {}
|
||||
local saw_grep = false
|
||||
local saw_fgrep = false
|
||||
local saw_title = false
|
||||
local plain_title = "API :: /brands... GET: /"
|
||||
for _, arg in ipairs(failed_cmd) do
|
||||
if arg == "--grep" then
|
||||
saw_grep = true
|
||||
elseif arg == "--fgrep" then
|
||||
saw_fgrep = true
|
||||
elseif arg == plain_title then
|
||||
saw_title = true
|
||||
end
|
||||
end
|
||||
assert.is_false(saw_grep)
|
||||
assert.is_true(saw_fgrep)
|
||||
assert.is_true(saw_title)
|
||||
|
||||
local has_raw = false
|
||||
for _, line in ipairs(lines) do
|
||||
if line == start_line or line == end_line then
|
||||
has_raw = true
|
||||
break
|
||||
end
|
||||
end
|
||||
assert.is_false(has_raw)
|
||||
end)
|
||||
|
||||
it("does not affect TSamLast history", function()
|
||||
local json = vim.json.encode({
|
||||
testResults = {
|
||||
{
|
||||
assertionResults = {
|
||||
{ status = "failed", title = "inner 2", fullName = "outer inner 2" },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
local calls, orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1, 1, 1 },
|
||||
stdout = { { json } },
|
||||
})
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/foo_failed_only_last.test.ts", "typescript", {
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" -- inside 1",
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" -- inside 2",
|
||||
" })",
|
||||
"})",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 7, 0 })
|
||||
|
||||
core.run_nearest()
|
||||
core.run_failed_only()
|
||||
core.run_last()
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(3, #calls)
|
||||
assert.are.same(calls[1].cmd, calls[3].cmd)
|
||||
assert.are.same(
|
||||
{ "npx", "jest", "--json", "--verbose", "-t", "outer inner 2", "/tmp/project/foo_failed_only_last.test.ts" },
|
||||
calls[2].cmd
|
||||
)
|
||||
end)
|
||||
end)
|
||||
@@ -1,147 +0,0 @@
|
||||
local go_runner = require("test-samurai.runners.go")
|
||||
local util = require("test-samurai.util")
|
||||
|
||||
describe("test-samurai go runner", function()
|
||||
it("detects Go test files by suffix", function()
|
||||
local bufnr1 = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr1, "/tmp/go_suffix_test.go")
|
||||
assert.is_true(go_runner.is_test_file(bufnr1))
|
||||
|
||||
local bufnr2 = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr2, "/tmp/go_main.go")
|
||||
assert.is_false(go_runner.is_test_file(bufnr2))
|
||||
end)
|
||||
|
||||
it("finds subtest when cursor is inside t.Run block", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/go_subtest_test.go")
|
||||
local lines = {
|
||||
"package main",
|
||||
"import \"testing\"",
|
||||
"",
|
||||
"func TestFoo(t *testing.T) {",
|
||||
" t.Run(\"first\", func(t *testing.T) {",
|
||||
" -- inside first",
|
||||
" })",
|
||||
"",
|
||||
" t.Run(\"second\", func(t *testing.T) {",
|
||||
" -- inside second",
|
||||
" })",
|
||||
"}",
|
||||
}
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
local orig_fs_find = vim.fs.find
|
||||
vim.fs.find = function(markers, opts)
|
||||
return { "/tmp/go.mod" }
|
||||
end
|
||||
|
||||
local row_inside_first = 5
|
||||
local spec, err = go_runner.find_nearest(bufnr, row_inside_first, 0)
|
||||
|
||||
vim.fs.find = orig_fs_find
|
||||
|
||||
assert.is_nil(err)
|
||||
assert.is_not_nil(spec)
|
||||
assert.equals("TestFoo/first", spec.test_path)
|
||||
assert.equals("subtest", spec.scope)
|
||||
assert.is_true(spec.file:match("go_subtest_test%.go$") ~= nil)
|
||||
assert.is_true(spec.cwd:match("tmp$") ~= nil)
|
||||
end)
|
||||
|
||||
it("falls back to whole test function when between subtests", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/go_between_test.go")
|
||||
local lines = {
|
||||
"package main",
|
||||
"import \"testing\"",
|
||||
"",
|
||||
"func TestFoo(t *testing.T) {",
|
||||
" t.Run(\"first\", func(t *testing.T) {",
|
||||
" -- inside first",
|
||||
" })",
|
||||
"",
|
||||
" t.Run(\"second\", func(t *testing.T) {",
|
||||
" -- inside second",
|
||||
" })",
|
||||
"}",
|
||||
}
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
local orig_fs_find = vim.fs.find
|
||||
vim.fs.find = function(markers, opts)
|
||||
return { "/tmp/go.mod" }
|
||||
end
|
||||
|
||||
local row_between = 7
|
||||
local spec, err = go_runner.find_nearest(bufnr, row_between, 0)
|
||||
|
||||
vim.fs.find = orig_fs_find
|
||||
|
||||
assert.is_nil(err)
|
||||
assert.is_not_nil(spec)
|
||||
assert.equals("TestFoo", spec.test_path)
|
||||
assert.equals("function", spec.scope)
|
||||
assert.is_true(spec.file:match("go_between_test%.go$") ~= nil)
|
||||
assert.is_true(spec.cwd:match("tmp$") ~= nil)
|
||||
end)
|
||||
|
||||
it("build_command uses current package and correct run pattern", function()
|
||||
local spec_sub = {
|
||||
file = "/tmp/project/pkg/foo_test.go",
|
||||
cwd = "/tmp/project",
|
||||
test_path = "TestFoo/first",
|
||||
scope = "subtest",
|
||||
}
|
||||
|
||||
local cmd_spec_sub = go_runner.build_command(spec_sub)
|
||||
assert.are.same(
|
||||
{ "go", "test", "-json", "./pkg", "-run", "^TestFoo/first$" },
|
||||
cmd_spec_sub.cmd
|
||||
)
|
||||
|
||||
local spec_func = {
|
||||
file = "/tmp/project/foo_test.go",
|
||||
cwd = "/tmp/project",
|
||||
test_path = "TestFoo",
|
||||
scope = "function",
|
||||
}
|
||||
|
||||
local cmd_spec_func = go_runner.build_command(spec_func)
|
||||
assert.are.same(
|
||||
{ "go", "test", "-json", "./", "-run", "^TestFoo($|/)" },
|
||||
cmd_spec_func.cmd
|
||||
)
|
||||
end)
|
||||
|
||||
it("build_file_command uses exact test names from current file", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/project/get_test.go")
|
||||
local lines = {
|
||||
"package main",
|
||||
"import \"testing\"",
|
||||
"",
|
||||
"func TestHandleGet(t *testing.T) {",
|
||||
" t.Run(\"returns_200\", func(t *testing.T) {",
|
||||
" -- inside test",
|
||||
" })",
|
||||
"}",
|
||||
}
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
local orig_find_root = util.find_root
|
||||
util.find_root = function(path, markers)
|
||||
return "/tmp/project"
|
||||
end
|
||||
|
||||
local cmd_spec = go_runner.build_file_command(bufnr)
|
||||
|
||||
util.find_root = orig_find_root
|
||||
|
||||
assert.are.same(
|
||||
{ "go", "test", "-json", "./", "-run", "^(TestHandleGet)$" },
|
||||
cmd_spec.cmd
|
||||
)
|
||||
assert.equals("/tmp/project", cmd_spec.cwd)
|
||||
end)
|
||||
end)
|
||||
@@ -1,203 +0,0 @@
|
||||
local jest = require("test-samurai.runners.js-jest")
|
||||
local mocha = require("test-samurai.runners.js-mocha")
|
||||
local vitest = require("test-samurai.runners.js-vitest")
|
||||
local util = require("test-samurai.util")
|
||||
|
||||
describe("test-samurai js runner (jest)", function()
|
||||
it("detects JS/TS test files by name and filetype", function()
|
||||
local bufnr1 = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr1, "/tmp/foo_detect.test.ts")
|
||||
vim.bo[bufnr1].filetype = "typescript"
|
||||
assert.is_true(jest.is_test_file(bufnr1))
|
||||
|
||||
local bufnr2 = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr2, "/tmp/foo_detect.ts")
|
||||
vim.bo[bufnr2].filetype = "typescript"
|
||||
assert.is_false(jest.is_test_file(bufnr2))
|
||||
end)
|
||||
|
||||
it("finds nearest it() call as test name and builds full_name when cursor is inside the test", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/foo_nearest.test.ts")
|
||||
vim.bo[bufnr].filetype = "typescript"
|
||||
local lines = {
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" -- inside 1",
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" -- inside 2",
|
||||
" })",
|
||||
"})",
|
||||
}
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
local orig_fs_find = vim.fs.find
|
||||
vim.fs.find = function(names, opts)
|
||||
return { "/tmp/package.json" }
|
||||
end
|
||||
|
||||
local row_inside_second = 6
|
||||
local spec, err = jest.find_nearest(bufnr, row_inside_second, 0)
|
||||
|
||||
vim.fs.find = orig_fs_find
|
||||
|
||||
assert.is_nil(err)
|
||||
assert.is_not_nil(spec)
|
||||
assert.equals("inner 2", spec.test_name)
|
||||
assert.equals("outer inner 2", spec.full_name)
|
||||
assert.equals("jest", spec.framework)
|
||||
assert.is_true(spec.file:match("foo_nearest%.test%.ts$") ~= nil)
|
||||
assert.is_true(spec.cwd:match("tmp$") ~= nil)
|
||||
|
||||
local cmd_spec = jest.build_command(spec)
|
||||
assert.are.same({ "npx", "jest", "--json", "--verbose", spec.file, "-t", "inner 2" }, cmd_spec.cmd)
|
||||
end)
|
||||
|
||||
it("returns describe block when cursor is between it() calls", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/foo_between.test.ts")
|
||||
vim.bo[bufnr].filetype = "typescript"
|
||||
local lines = {
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" -- inside 1",
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" -- inside 2",
|
||||
" })",
|
||||
"})",
|
||||
}
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
local orig_fs_find = vim.fs.find
|
||||
vim.fs.find = function(names, opts)
|
||||
return { "/tmp/package.json" }
|
||||
end
|
||||
|
||||
local row_between = 4
|
||||
local spec, err = jest.find_nearest(bufnr, row_between, 0)
|
||||
|
||||
vim.fs.find = orig_fs_find
|
||||
|
||||
assert.is_nil(err)
|
||||
assert.is_not_nil(spec)
|
||||
assert.equals("outer", spec.test_name)
|
||||
assert.equals("outer", spec.full_name)
|
||||
assert.equals("jest", spec.framework)
|
||||
end)
|
||||
|
||||
it("treats jest.config in test/.bin as project root parent", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/foo_binroot.test.ts")
|
||||
vim.bo[bufnr].filetype = "typescript"
|
||||
local lines = {
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" -- inside 1",
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" -- inside 2",
|
||||
" })",
|
||||
"})",
|
||||
}
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
local orig_fs_find = vim.fs.find
|
||||
vim.fs.find = function(names, opts)
|
||||
return { "/tmp/test/.bin/jest.config.js" }
|
||||
end
|
||||
|
||||
local row_inside_second = 6
|
||||
local spec, err = jest.find_nearest(bufnr, row_inside_second, 0)
|
||||
|
||||
vim.fs.find = orig_fs_find
|
||||
|
||||
assert.is_nil(err)
|
||||
assert.is_not_nil(spec)
|
||||
assert.equals("/tmp", spec.cwd)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("test-samurai js runner (mocha)", function()
|
||||
it("builds mocha command with fgrep and full test title", function()
|
||||
local spec = {
|
||||
file = "/tmp/project/test/foo_nearest.test.ts",
|
||||
cwd = "/tmp/project",
|
||||
test_name = "inner 2",
|
||||
full_name = "outer inner 2",
|
||||
}
|
||||
|
||||
local cmd_spec = mocha.build_command(spec)
|
||||
|
||||
assert.are.same(
|
||||
{ "npx", "mocha", "--reporter", "json-stream", "--fgrep", "outer inner 2", spec.file },
|
||||
cmd_spec.cmd
|
||||
)
|
||||
assert.equals("/tmp/project", cmd_spec.cwd)
|
||||
end)
|
||||
|
||||
it("builds mocha all command with default glob", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/project/test/foo_all.test.js")
|
||||
vim.bo[bufnr].filetype = "javascript"
|
||||
|
||||
local orig_find_root = util.find_root
|
||||
util.find_root = function(path, markers)
|
||||
return "/tmp/project"
|
||||
end
|
||||
|
||||
local cmd_spec = mocha.build_all_command(bufnr)
|
||||
|
||||
util.find_root = orig_find_root
|
||||
|
||||
assert.are.same(
|
||||
{ "npx", "mocha", "--reporter", "json-stream", "test/**/*.test.js" },
|
||||
cmd_spec.cmd
|
||||
)
|
||||
assert.equals("/tmp/project", cmd_spec.cwd)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("test-samurai js runner (vitest)", function()
|
||||
it("builds vitest command with tap-flat reporter", function()
|
||||
local spec = {
|
||||
file = "/tmp/project/test/foo_nearest.test.ts",
|
||||
cwd = "/tmp/project",
|
||||
test_name = "inner 2",
|
||||
full_name = "outer inner 2",
|
||||
}
|
||||
|
||||
local cmd_spec = vitest.build_command(spec)
|
||||
|
||||
assert.are.same(
|
||||
{ "npx", "vitest", "--reporter", "tap-flat", spec.file, "-t", "inner 2" },
|
||||
cmd_spec.cmd
|
||||
)
|
||||
assert.equals("/tmp/project", cmd_spec.cwd)
|
||||
end)
|
||||
|
||||
it("builds vitest all command with tap-flat reporter", function()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, "/tmp/project/test/foo_all.test.ts")
|
||||
vim.bo[bufnr].filetype = "typescript"
|
||||
|
||||
local orig_find_root = util.find_root
|
||||
util.find_root = function(path, markers)
|
||||
return "/tmp/project"
|
||||
end
|
||||
|
||||
local cmd_spec = vitest.build_all_command(bufnr)
|
||||
|
||||
util.find_root = orig_find_root
|
||||
|
||||
assert.are.same(
|
||||
{ "npx", "vitest", "--reporter", "tap-flat" },
|
||||
cmd_spec.cmd
|
||||
)
|
||||
assert.equals("/tmp/project", cmd_spec.cwd)
|
||||
end)
|
||||
end)
|
||||
@@ -1,139 +0,0 @@
|
||||
local test_samurai = require("test-samurai")
|
||||
local core = require("test-samurai.core")
|
||||
|
||||
local function mkbuf(path, ft, lines)
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = ft
|
||||
if lines then
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
end
|
||||
return bufnr
|
||||
end
|
||||
|
||||
local function capture_jobstart()
|
||||
local calls = {}
|
||||
local orig = vim.fn.jobstart
|
||||
vim.fn.jobstart = function(cmd, opts)
|
||||
table.insert(calls, { cmd = cmd, opts = opts })
|
||||
return 1
|
||||
end
|
||||
return calls, orig
|
||||
end
|
||||
|
||||
describe("TSamLast", function()
|
||||
before_each(function()
|
||||
test_samurai.setup()
|
||||
end)
|
||||
|
||||
it("reruns last Go command", function()
|
||||
local calls, orig_jobstart = capture_jobstart()
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/foo_test.go", "go", {
|
||||
"package main",
|
||||
"import \"testing\"",
|
||||
"",
|
||||
"func TestFoo(t *testing.T) {",
|
||||
" t.Run(\"first\", func(t *testing.T) {",
|
||||
" -- inside first",
|
||||
" })",
|
||||
"}",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 6, 0 })
|
||||
|
||||
core.run_nearest()
|
||||
core.run_last()
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(2, #calls)
|
||||
assert.are.same({ "go", "test", "-json", "./", "-run", "^TestFoo/first$" }, calls[1].cmd)
|
||||
assert.are.same(calls[1].cmd, calls[2].cmd)
|
||||
assert.equals(calls[1].opts.cwd, calls[2].opts.cwd)
|
||||
end)
|
||||
|
||||
it("uses go parser for TSamLast output (no raw JSON)", function()
|
||||
local json_line = vim.json.encode({
|
||||
Action = "fail",
|
||||
Test = "TestHandleGet/returns_200",
|
||||
})
|
||||
|
||||
local calls = {}
|
||||
local orig_jobstart = vim.fn.jobstart
|
||||
vim.fn.jobstart = function(cmd, opts)
|
||||
table.insert(calls, { cmd = cmd, opts = opts })
|
||||
if opts and opts.on_stdout then
|
||||
opts.on_stdout(1, { json_line }, nil)
|
||||
end
|
||||
if opts and opts.on_exit then
|
||||
opts.on_exit(1, 1, nil)
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/foo_last_output_test.go", "go", {
|
||||
"package main",
|
||||
"import \"testing\"",
|
||||
"",
|
||||
"func TestHandleGet(t *testing.T) {",
|
||||
" t.Run(\"returns_200\", func(t *testing.T) {",
|
||||
" -- inside test",
|
||||
" })",
|
||||
"}",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
|
||||
core.run_all()
|
||||
core.run_last()
|
||||
|
||||
local out_buf = vim.api.nvim_get_current_buf()
|
||||
local lines = vim.api.nvim_buf_get_lines(out_buf, 0, -1, false)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(2, #calls)
|
||||
local has_raw = false
|
||||
for _, line in ipairs(lines) do
|
||||
if line == json_line then
|
||||
has_raw = true
|
||||
break
|
||||
end
|
||||
end
|
||||
assert.is_false(has_raw)
|
||||
end)
|
||||
|
||||
it("reruns last JS command", function()
|
||||
local calls, orig_jobstart = capture_jobstart()
|
||||
|
||||
local bufnr = mkbuf("/tmp/project/foo_last.test.ts", "typescript", {
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" -- inside 1",
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" -- inside 2",
|
||||
" })",
|
||||
"})",
|
||||
})
|
||||
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 7, 0 })
|
||||
|
||||
core.run_nearest()
|
||||
core.run_last()
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
|
||||
assert.equals(2, #calls)
|
||||
assert.are.same(
|
||||
{ "npx", "jest", "--json", "--verbose", "/tmp/project/foo_last.test.ts", "-t", "inner 2" },
|
||||
calls[1].cmd
|
||||
)
|
||||
assert.are.same(calls[1].cmd, calls[2].cmd)
|
||||
assert.equals(calls[1].opts.cwd, calls[2].opts.cwd)
|
||||
end)
|
||||
end)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,97 +0,0 @@
|
||||
local test_samurai = require("test-samurai")
|
||||
local core = require("test-samurai.core")
|
||||
|
||||
local function close_output_container()
|
||||
local keys = vim.api.nvim_replace_termcodes("<esc><esc>", true, false, true)
|
||||
local attempts = 5
|
||||
while attempts > 0 do
|
||||
local float_win = nil
|
||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||
local cfg = vim.api.nvim_win_get_config(win)
|
||||
if cfg.relative ~= "" then
|
||||
float_win = win
|
||||
break
|
||||
end
|
||||
end
|
||||
if not float_win then
|
||||
break
|
||||
end
|
||||
vim.api.nvim_set_current_win(float_win)
|
||||
vim.api.nvim_feedkeys(keys, "x", false)
|
||||
vim.wait(20, function()
|
||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||
local cfg = vim.api.nvim_win_get_config(win)
|
||||
if cfg.relative ~= "" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end)
|
||||
attempts = attempts - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function stub_jobstart(opts_config)
|
||||
local orig = vim.fn.jobstart
|
||||
local config = opts_config or {}
|
||||
vim.fn.jobstart = function(_cmd, opts)
|
||||
local out = config.stdout or nil
|
||||
if out and opts and opts.on_stdout then
|
||||
if type(out) == "string" then
|
||||
out = { out }
|
||||
end
|
||||
opts.on_stdout(1, out, nil)
|
||||
end
|
||||
if opts and opts.on_exit then
|
||||
opts.on_exit(1, config.exit_code or 0, nil)
|
||||
end
|
||||
return 1
|
||||
end
|
||||
return orig
|
||||
end
|
||||
|
||||
describe("test-samurai quickfix (js)", function()
|
||||
before_each(function()
|
||||
test_samurai.setup()
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
close_output_container()
|
||||
vim.fn.setqflist({}, "r")
|
||||
end)
|
||||
|
||||
it("mappt jest-verbose Failures auf die Zeile des Tests", function()
|
||||
local root = vim.fs.joinpath(vim.loop.cwd(), "tests", "tmp_qf_js")
|
||||
vim.fn.mkdir(root, "p")
|
||||
local path = root .. "/foo_qf.test.ts"
|
||||
vim.fn.writefile({
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" })",
|
||||
"})",
|
||||
}, path)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = "typescript"
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
|
||||
local fail_symbol = string.char(0xE2, 0x9C, 0x95)
|
||||
local orig_jobstart = stub_jobstart({
|
||||
exit_code = 1,
|
||||
stdout = { " " .. fail_symbol .. " inner 2" },
|
||||
})
|
||||
|
||||
core.run_file()
|
||||
|
||||
local qf = vim.fn.getqflist()
|
||||
assert.equals(1, #qf)
|
||||
assert.equals(path, vim.fn.bufname(qf[1].bufnr))
|
||||
assert.equals(5, qf[1].lnum)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
end)
|
||||
end)
|
||||
@@ -1,409 +0,0 @@
|
||||
local test_samurai = require("test-samurai")
|
||||
local core = require("test-samurai.core")
|
||||
|
||||
local function close_output_container()
|
||||
local keys = vim.api.nvim_replace_termcodes("<esc><esc>", true, false, true)
|
||||
local attempts = 5
|
||||
while attempts > 0 do
|
||||
local float_win = nil
|
||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||
local cfg = vim.api.nvim_win_get_config(win)
|
||||
if cfg.relative ~= "" then
|
||||
float_win = win
|
||||
break
|
||||
end
|
||||
end
|
||||
if not float_win then
|
||||
break
|
||||
end
|
||||
vim.api.nvim_set_current_win(float_win)
|
||||
vim.api.nvim_feedkeys(keys, "x", false)
|
||||
vim.wait(20, function()
|
||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||
local cfg = vim.api.nvim_win_get_config(win)
|
||||
if cfg.relative ~= "" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end)
|
||||
attempts = attempts - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function stub_jobstart(opts_config)
|
||||
local orig = vim.fn.jobstart
|
||||
local idx = 0
|
||||
local config = opts_config or {}
|
||||
vim.fn.jobstart = function(cmd, opts)
|
||||
idx = idx + 1
|
||||
local code = 0
|
||||
if type(config.exit_codes) == "table" then
|
||||
code = config.exit_codes[idx] or 0
|
||||
elseif type(config.exit_codes) == "number" then
|
||||
code = config.exit_codes
|
||||
end
|
||||
local out = config.stdout and config.stdout[idx] or nil
|
||||
if out and opts and opts.on_stdout then
|
||||
if type(out) == "string" then
|
||||
out = { out }
|
||||
end
|
||||
opts.on_stdout(1, out, nil)
|
||||
end
|
||||
if opts and opts.on_exit then
|
||||
opts.on_exit(1, code, nil)
|
||||
end
|
||||
return 1
|
||||
end
|
||||
return orig
|
||||
end
|
||||
|
||||
describe("test-samurai quickfix", function()
|
||||
before_each(function()
|
||||
test_samurai.setup()
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
close_output_container()
|
||||
vim.fn.setqflist({}, "r")
|
||||
end)
|
||||
|
||||
it("fuellt die Quickfix-Liste mit Fehltests und leert sie bei Erfolg", function()
|
||||
local root = vim.fs.joinpath(vim.loop.cwd(), "tests", "tmp_qf")
|
||||
vim.fn.mkdir(root, "p")
|
||||
local path = root .. "/foo_test.go"
|
||||
vim.fn.writefile({
|
||||
"package foo",
|
||||
"",
|
||||
"func TestFoo(t *testing.T) {",
|
||||
' t.Run("bar", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
"",
|
||||
"func TestBaz(t *testing.T) {",
|
||||
"}",
|
||||
}, path)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = "go"
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
|
||||
local orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1, 0 },
|
||||
stdout = {
|
||||
{
|
||||
vim.json.encode({ Action = "fail", Test = "TestFoo/bar" }),
|
||||
vim.json.encode({ Action = "fail", Test = "TestBaz" }),
|
||||
},
|
||||
{ vim.json.encode({ Action = "pass", Test = "TestFoo" }) },
|
||||
},
|
||||
})
|
||||
|
||||
core.run_file()
|
||||
|
||||
local first = vim.fn.getqflist()
|
||||
assert.equals(2, #first)
|
||||
assert.equals(path, vim.fn.bufname(first[1].bufnr))
|
||||
assert.equals(4, first[1].lnum)
|
||||
assert.equals(path, vim.fn.bufname(first[2].bufnr))
|
||||
assert.equals(8, first[2].lnum)
|
||||
|
||||
close_output_container()
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
|
||||
core.run_file()
|
||||
|
||||
local second = vim.fn.getqflist()
|
||||
assert.equals(0, #second)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
end)
|
||||
|
||||
it("enthaelt bei Go auch Eltern- und Subtest-Failures im Quickfix", function()
|
||||
local root = vim.fs.joinpath(vim.loop.cwd(), "tests", "tmp_qf_go_sub")
|
||||
vim.fn.mkdir(root, "p")
|
||||
local path = root .. "/foo_sub_test.go"
|
||||
vim.fn.writefile({
|
||||
"package foo",
|
||||
"",
|
||||
"func TestAwesomeThing(t *testing.T) {",
|
||||
' t.Run("evergreen", func(t *testing.T) {',
|
||||
" })",
|
||||
"",
|
||||
' t.Run("everred", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
}, path)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = "go"
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
||||
"package foo",
|
||||
"",
|
||||
"func TestAwesomeThing(t *testing.T) {",
|
||||
' t.Run("evergreen", func(t *testing.T) {',
|
||||
" })",
|
||||
"",
|
||||
' t.Run("everred", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
})
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 6, 0 })
|
||||
|
||||
local orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1 },
|
||||
stdout = {
|
||||
{
|
||||
vim.json.encode({ Action = "fail", Test = "TestAwesomeThing/everred" }),
|
||||
vim.json.encode({ Action = "fail", Test = "TestAwesomeThing" }),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
core.run_nearest()
|
||||
|
||||
local qf = vim.fn.getqflist()
|
||||
assert.equals(2, #qf)
|
||||
assert.equals(path, vim.fn.bufname(qf[1].bufnr))
|
||||
assert.equals(path, vim.fn.bufname(qf[2].bufnr))
|
||||
local lines = { qf[1].lnum, qf[2].lnum }
|
||||
table.sort(lines)
|
||||
assert.are.same({ 3, 7 }, lines)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
end)
|
||||
|
||||
it("vereinigt Failures aus Parser und Scope fuer Go", function()
|
||||
local root = vim.fs.joinpath(vim.loop.cwd(), "tests", "tmp_qf_go_union")
|
||||
vim.fn.mkdir(root, "p")
|
||||
local path = root .. "/foo_union_test.go"
|
||||
vim.fn.writefile({
|
||||
"package foo",
|
||||
"",
|
||||
"func TestAwesomeThing(t *testing.T) {",
|
||||
' t.Run(\"evergreen\", func(t *testing.T) {',
|
||||
" })",
|
||||
"",
|
||||
' t.Run(\"everred\", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
}, path)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = "go"
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
||||
"package foo",
|
||||
"",
|
||||
"func TestAwesomeThing(t *testing.T) {",
|
||||
' t.Run(\"evergreen\", func(t *testing.T) {',
|
||||
" })",
|
||||
"",
|
||||
' t.Run(\"everred\", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
})
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 6, 0 })
|
||||
|
||||
local go = require("test-samurai.runners.go")
|
||||
local orig_parser = go.output_parser
|
||||
go.output_parser = function()
|
||||
local seen = 0
|
||||
return {
|
||||
on_line = function()
|
||||
seen = seen + 1
|
||||
if seen == 1 then
|
||||
return {
|
||||
passes = {},
|
||||
failures = { "TestAwesomeThing/everred" },
|
||||
skips = {},
|
||||
display = { passes = {}, failures = { "everred" }, skips = {} },
|
||||
failures_all = { "TestAwesomeThing" },
|
||||
}
|
||||
end
|
||||
return {
|
||||
passes = {},
|
||||
failures = { "TestAwesomeThing" },
|
||||
skips = {},
|
||||
display = { passes = {}, failures = { "TestAwesomeThing" }, skips = {} },
|
||||
failures_all = { "TestAwesomeThing" },
|
||||
}
|
||||
end,
|
||||
on_complete = function()
|
||||
return nil
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
local orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1 },
|
||||
stdout = {
|
||||
{
|
||||
vim.json.encode({ Action = "fail", Test = "TestAwesomeThing/everred" }),
|
||||
vim.json.encode({ Action = "fail", Test = "TestAwesomeThing" }),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
core.run_nearest()
|
||||
|
||||
local qf = vim.fn.getqflist()
|
||||
assert.equals(2, #qf)
|
||||
assert.equals(path, vim.fn.bufname(qf[1].bufnr))
|
||||
assert.equals(path, vim.fn.bufname(qf[2].bufnr))
|
||||
local lines = { qf[1].lnum, qf[2].lnum }
|
||||
table.sort(lines)
|
||||
assert.are.same({ 3, 7 }, lines)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
go.output_parser = orig_parser
|
||||
end)
|
||||
|
||||
it("nutzt Listing-Namen wenn Parser keine Failure-Liste liefert", function()
|
||||
local root = vim.fs.joinpath(vim.loop.cwd(), "tests", "tmp_qf_go_listing")
|
||||
vim.fn.mkdir(root, "p")
|
||||
local path = root .. "/foo_listing_test.go"
|
||||
vim.fn.writefile({
|
||||
"package foo",
|
||||
"",
|
||||
"func TestAwesomeThing(t *testing.T) {",
|
||||
' t.Run(\"evergreen\", func(t *testing.T) {',
|
||||
" })",
|
||||
"",
|
||||
' t.Run(\"everred\", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
}, path)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = "go"
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
||||
"package foo",
|
||||
"",
|
||||
"func TestAwesomeThing(t *testing.T) {",
|
||||
' t.Run(\"evergreen\", func(t *testing.T) {',
|
||||
" })",
|
||||
"",
|
||||
' t.Run(\"everred\", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
})
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 6, 0 })
|
||||
|
||||
local go = require("test-samurai.runners.go")
|
||||
local orig_parser = go.output_parser
|
||||
go.output_parser = function()
|
||||
local step = 0
|
||||
return {
|
||||
on_line = function()
|
||||
step = step + 1
|
||||
if step == 1 then
|
||||
return {
|
||||
passes = {},
|
||||
failures = {},
|
||||
skips = {},
|
||||
display = { passes = {}, failures = { "TestAwesomeThing" }, skips = {} },
|
||||
}
|
||||
end
|
||||
return {
|
||||
passes = {},
|
||||
failures = {},
|
||||
skips = {},
|
||||
display = { passes = {}, failures = { "everred" }, skips = {} },
|
||||
}
|
||||
end,
|
||||
on_complete = function()
|
||||
return nil
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
local orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1 },
|
||||
stdout = {
|
||||
{
|
||||
vim.json.encode({ Action = "fail", Test = "TestAwesomeThing/everred" }),
|
||||
vim.json.encode({ Action = "fail", Test = "TestAwesomeThing" }),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
core.run_nearest()
|
||||
|
||||
local qf = vim.fn.getqflist()
|
||||
assert.equals(2, #qf)
|
||||
assert.equals(path, vim.fn.bufname(qf[1].bufnr))
|
||||
assert.equals(path, vim.fn.bufname(qf[2].bufnr))
|
||||
local lines = { qf[1].lnum, qf[2].lnum }
|
||||
table.sort(lines)
|
||||
assert.are.same({ 3, 7 }, lines)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
go.output_parser = orig_parser
|
||||
end)
|
||||
|
||||
it("mappt Go-Subtests mit durch Unterstriche normalisierten Namen", function()
|
||||
local root = vim.fs.joinpath(vim.loop.cwd(), "tests", "tmp_qf_go_norm")
|
||||
vim.fn.mkdir(root, "p")
|
||||
local path = root .. "/foo_norm_test.go"
|
||||
vim.fn.writefile({
|
||||
"package foo",
|
||||
"",
|
||||
"func TestHandleGet(t *testing.T) {",
|
||||
' t.Run(\"returns 200 with an list of all badges\", func(t *testing.T) {',
|
||||
" })",
|
||||
"",
|
||||
' t.Run(\"returns 500 on any db error\", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
}, path)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = "go"
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
||||
"package foo",
|
||||
"",
|
||||
"func TestHandleGet(t *testing.T) {",
|
||||
' t.Run(\"returns 200 with an list of all badges\", func(t *testing.T) {',
|
||||
" })",
|
||||
"",
|
||||
' t.Run(\"returns 500 on any db error\", func(t *testing.T) {',
|
||||
" })",
|
||||
"}",
|
||||
})
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
vim.api.nvim_win_set_cursor(0, { 6, 0 })
|
||||
|
||||
local orig_jobstart = stub_jobstart({
|
||||
exit_codes = { 1 },
|
||||
stdout = {
|
||||
{
|
||||
vim.json.encode({
|
||||
Action = "fail",
|
||||
Test = "TestHandleGet/returns_500_on_any_db_error",
|
||||
}),
|
||||
vim.json.encode({ Action = "fail", Test = "TestHandleGet" }),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
core.run_nearest()
|
||||
|
||||
local qf = vim.fn.getqflist()
|
||||
assert.equals(2, #qf)
|
||||
assert.equals(path, vim.fn.bufname(qf[1].bufnr))
|
||||
assert.equals(path, vim.fn.bufname(qf[2].bufnr))
|
||||
local lines = { qf[1].lnum, qf[2].lnum }
|
||||
table.sort(lines)
|
||||
assert.are.same({ 3, 7 }, lines)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
end)
|
||||
end)
|
||||
@@ -1,102 +0,0 @@
|
||||
local test_samurai = require("test-samurai")
|
||||
local core = require("test-samurai.core")
|
||||
|
||||
local function close_output_container()
|
||||
local keys = vim.api.nvim_replace_termcodes("<esc><esc>", true, false, true)
|
||||
local attempts = 5
|
||||
while attempts > 0 do
|
||||
local float_win = nil
|
||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||
local cfg = vim.api.nvim_win_get_config(win)
|
||||
if cfg.relative ~= "" then
|
||||
float_win = win
|
||||
break
|
||||
end
|
||||
end
|
||||
if not float_win then
|
||||
break
|
||||
end
|
||||
vim.api.nvim_set_current_win(float_win)
|
||||
vim.api.nvim_feedkeys(keys, "x", false)
|
||||
vim.wait(20, function()
|
||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||
local cfg = vim.api.nvim_win_get_config(win)
|
||||
if cfg.relative ~= "" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end)
|
||||
attempts = attempts - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function stub_jobstart(opts_config)
|
||||
local orig = vim.fn.jobstart
|
||||
local config = opts_config or {}
|
||||
vim.fn.jobstart = function(_cmd, opts)
|
||||
local out = config.stdout or nil
|
||||
if out and opts and opts.on_stdout then
|
||||
if type(out) == "string" then
|
||||
out = { out }
|
||||
end
|
||||
opts.on_stdout(1, out, nil)
|
||||
end
|
||||
if opts and opts.on_exit then
|
||||
opts.on_exit(1, config.exit_code or 0, nil)
|
||||
end
|
||||
return 1
|
||||
end
|
||||
return orig
|
||||
end
|
||||
|
||||
describe("test-samurai quickfix (vitest)", function()
|
||||
before_each(function()
|
||||
test_samurai.setup()
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
close_output_container()
|
||||
vim.fn.setqflist({}, "r")
|
||||
end)
|
||||
|
||||
it("mappt tap-flat Failures mit >-Trenner auf die Testzeile", function()
|
||||
local root = vim.fs.joinpath(vim.loop.cwd(), "tests", "tmp_qf_vitest")
|
||||
vim.fn.mkdir(root, "p")
|
||||
local path = root .. "/foo_qf.test.ts"
|
||||
local pkg = root .. "/package.json"
|
||||
vim.fn.writefile({
|
||||
"{",
|
||||
' "devDependencies": { "vitest": "^1.0.0" }',
|
||||
"}",
|
||||
}, pkg)
|
||||
vim.fn.writefile({
|
||||
'describe("outer", function() {',
|
||||
' it("inner 1", function() {',
|
||||
" })",
|
||||
"",
|
||||
' it("inner 2", function() {',
|
||||
" })",
|
||||
"})",
|
||||
}, path)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(bufnr, path)
|
||||
vim.bo[bufnr].filetype = "typescript"
|
||||
vim.api.nvim_set_current_buf(bufnr)
|
||||
|
||||
local orig_jobstart = stub_jobstart({
|
||||
exit_code = 1,
|
||||
stdout = { "not ok 1 - outer > inner 2 # time=12.3ms" },
|
||||
})
|
||||
|
||||
core.run_file()
|
||||
|
||||
local qf = vim.fn.getqflist()
|
||||
assert.equals(1, #qf)
|
||||
assert.equals(path, vim.fn.bufname(qf[1].bufnr))
|
||||
assert.equals(5, qf[1].lnum)
|
||||
|
||||
vim.fn.jobstart = orig_jobstart
|
||||
end)
|
||||
end)
|
||||
@@ -1 +0,0 @@
|
||||
{ "name": "mocha-jump" }
|
||||
@@ -1,4 +0,0 @@
|
||||
describe("suite one", function() {
|
||||
it("test one", function() {
|
||||
})
|
||||
})
|
||||
@@ -1,4 +0,0 @@
|
||||
describe("suite two", function() {
|
||||
it("test two", function() {
|
||||
})
|
||||
})
|
||||
@@ -1,9 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestFoo(t *testing.T) {
|
||||
t.Run("bar", func(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestBaz(t *testing.T) {
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestAwesomeThing(t *testing.T) {
|
||||
t.Run("evergreen", func(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("everred", func(t *testing.T) {
|
||||
})
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestHandleGet(t *testing.T) {
|
||||
t.Run("returns 200 with an list of all badges", func(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("returns 500 on any db error", func(t *testing.T) {
|
||||
})
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestAwesomeThing(t *testing.T) {
|
||||
t.Run("evergreen", func(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("everred", func(t *testing.T) {
|
||||
})
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestAwesomeThing(t *testing.T) {
|
||||
t.Run("evergreen", func(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("everred", func(t *testing.T) {
|
||||
})
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
describe("outer", function() {
|
||||
it("inner 1", function() {
|
||||
})
|
||||
|
||||
it("inner 2", function() {
|
||||
})
|
||||
})
|
||||
@@ -1,3 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestFoo(t *testing.T) {}
|
||||
@@ -1,4 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestFoo(t *testing.T) {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestFoo(t *testing.T) {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package foo
|
||||
|
||||
func TestFoo(t *testing.T) {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
describe("outer", function() {
|
||||
it("inner 1", function() {
|
||||
})
|
||||
|
||||
it("inner 2", function() {
|
||||
})
|
||||
})
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"devDependencies": { "vitest": "^1.0.0" }
|
||||
}
|
||||
Reference in New Issue
Block a user