fix TSamFailedOnly and the output formatting for the go-runner

This commit is contained in:
2025-12-25 17:27:30 +01:00
parent 1e2e881acd
commit 2c2cb35953
6 changed files with 443 additions and 2 deletions

View File

@@ -178,6 +178,49 @@ describe("TSamFailedOnly", function()
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("does not affect TSamLast history", function()
local json = vim.json.encode({
testResults = {

View File

@@ -1,4 +1,5 @@
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()
@@ -112,4 +113,35 @@ describe("test-samurai go runner", function()
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)

View File

@@ -54,6 +54,57 @@ describe("TSamLast", function()
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()

View File

@@ -164,6 +164,280 @@ describe("test-samurai output formatting", function()
assert.is_true(has_fail)
end)
it("does not print raw JSON output for jest runs", function()
local json = vim.json.encode({
testResults = {
{
assertionResults = {
{ status = "passed", title = "inner 1", fullName = "outer inner 1" },
},
},
},
})
local orig_jobstart = vim.fn.jobstart
vim.fn.jobstart = function(_cmd, opts)
if opts and opts.on_stdout then
opts.on_stdout(1, { json }, nil)
end
if opts and opts.on_exit then
opts.on_exit(1, 0, nil)
end
return 1
end
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(bufnr, "/tmp/output_raw_json.test.ts")
vim.bo[bufnr].filetype = "typescript"
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
'describe("outer", function() {',
' it("inner 1", function() {',
" -- inside 1",
" })",
"})",
})
vim.api.nvim_set_current_buf(bufnr)
vim.api.nvim_win_set_cursor(0, { 3, 0 })
core.run_nearest()
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
local has_raw_json = false
for _, line in ipairs(lines) do
if line == json then
has_raw_json = true
break
end
end
assert.is_false(has_raw_json)
end)
it("does not print raw JSON output for mocha json-stream", function()
test_samurai.setup({
runner_modules = {
"test-samurai.runners.js-mocha",
},
})
local json_line = vim.json.encode({
event = "pass",
fullTitle = "outer inner 1",
})
local orig_jobstart = vim.fn.jobstart
vim.fn.jobstart = function(_cmd, 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, 0, nil)
end
return 1
end
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(bufnr, "/tmp/output_raw_json.test.js")
vim.bo[bufnr].filetype = "javascript"
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
'describe("outer", function() {',
' it("inner 1", function() {',
" -- inside 1",
" })",
"})",
})
vim.api.nvim_set_current_buf(bufnr)
vim.api.nvim_win_set_cursor(0, { 3, 0 })
core.run_nearest()
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
local has_raw_json = false
for _, line in ipairs(lines) do
if line == json_line then
has_raw_json = true
break
end
end
assert.is_false(has_raw_json)
end)
it("does not print raw JSON when JSON arrives on stdout and stderr", function()
test_samurai.setup({
runner_modules = {
"test-samurai.runners.js-jest",
},
})
local json1 = vim.json.encode({
testResults = {
{
assertionResults = {
{ status = "passed", title = "inner 1", fullName = "outer inner 1" },
},
},
},
})
local json2 = vim.json.encode({
testResults = {
{
assertionResults = {
{ status = "failed", title = "inner 2", fullName = "outer inner 2" },
},
},
},
})
local orig_jobstart = vim.fn.jobstart
vim.fn.jobstart = function(_cmd, opts)
if opts and opts.on_stdout then
opts.on_stdout(1, { json1 }, nil)
end
if opts and opts.on_stderr then
opts.on_stderr(1, { json2 }, nil)
end
if opts and opts.on_exit then
opts.on_exit(1, 1, nil)
end
return 1
end
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(bufnr, "/tmp/output_raw_json_both.test.ts")
vim.bo[bufnr].filetype = "typescript"
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
'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()
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
local has_raw_json = false
for _, line in ipairs(lines) do
if line == json1 or line == json2 then
has_raw_json = true
break
end
end
assert.is_false(has_raw_json)
end)
it("handles mixed mocha json-stream events and tracks failures for failed-only", function()
test_samurai.setup({
runner_modules = {
"test-samurai.runners.js-mocha",
},
})
local pass_line = vim.json.encode({
event = "pass",
fullTitle = "outer inner 1",
})
local fail_line = vim.json.encode({
event = "fail",
fullTitle = "outer inner 2",
})
local job_calls = {}
local orig_jobstart = vim.fn.jobstart
vim.fn.jobstart = function(cmd, opts)
table.insert(job_calls, { cmd = cmd, opts = opts })
if #job_calls == 1 then
if opts and opts.on_stdout then
opts.on_stdout(1, { pass_line, fail_line }, nil)
end
if opts and opts.on_exit then
opts.on_exit(1, 1, nil)
end
else
if opts and opts.on_exit then
opts.on_exit(1, 1, nil)
end
end
return 1
end
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(bufnr, "/tmp/output_mixed_json.test.js")
vim.bo[bufnr].filetype = "javascript"
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
'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()
local out_buf = vim.api.nvim_get_current_buf()
local lines = vim.api.nvim_buf_get_lines(out_buf, 0, -1, false)
core.run_failed_only()
vim.fn.jobstart = orig_jobstart
local has_pass = false
local has_fail = false
for _, line in ipairs(lines) do
if line == "[ PASS ] - outer inner 1" then
has_pass = true
elseif line == "[ FAIL ] - outer inner 2" then
has_fail = true
end
end
assert.is_true(has_pass)
assert.is_true(has_fail)
assert.is_true(#job_calls >= 2)
local failed_cmd = job_calls[2].cmd or {}
local saw_grep = false
local saw_title = false
for _, arg in ipairs(failed_cmd) do
if arg == "--grep" then
saw_grep = true
elseif arg == "outer inner 2" then
saw_title = true
end
end
assert.is_true(saw_grep)
assert.is_true(saw_title)
end)
it("formats TAP output as PASS/FAIL lines", function()
test_samurai.setup({
runner_modules = {