include stdout into the detail-float
All checks were successful
tests / test (push) Successful in 7s
All checks were successful
tests / test (push) Successful in 7s
This commit is contained in:
@@ -12,6 +12,7 @@ Main plugin: https://gitea.mschirmer.com/m13r/test-samurai.nvim
|
|||||||
- Builds `npx jest` commands for nearest, file, all, and failed-only runs.
|
- Builds `npx jest` commands for nearest, file, all, and failed-only runs.
|
||||||
- Streams results via a custom Jest reporter using `onTestCaseResult`.
|
- Streams results via a custom Jest reporter using `onTestCaseResult`.
|
||||||
- Uses `--testLocationInResults` for Quickfix and `<leader>o` support.
|
- Uses `--testLocationInResults` for Quickfix and `<leader>o` support.
|
||||||
|
- Captures `console.*` output per test case and shows it in the detail float.
|
||||||
|
|
||||||
## Installation (lazy.nvim)
|
## Installation (lazy.nvim)
|
||||||
|
|
||||||
@@ -60,3 +61,4 @@ Use the standard `test-samurai.nvim` commands (e.g. `TSamNearest`, `TSamFile`, `
|
|||||||
|
|
||||||
- The reporter lives at `reporter/test_samurai_jest_reporter.js` and is loaded via `--reporters`.
|
- The reporter lives at `reporter/test_samurai_jest_reporter.js` and is loaded via `--reporters`.
|
||||||
- Test names are reported as `Describe/It` for grouping in the listing.
|
- Test names are reported as `Describe/It` for grouping in the listing.
|
||||||
|
- Stdout capture uses `reporter/test_samurai_jest_stdout.js` via `--setupFilesAfterEnv` and tags output as `TSAMURAI_STDOUT`.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ local runner = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local RESULT_PREFIX = "TSAMURAI_RESULT "
|
local RESULT_PREFIX = "TSAMURAI_RESULT "
|
||||||
|
local STDOUT_PREFIX = "TSAMURAI_STDOUT "
|
||||||
local STATUS_MAP = {
|
local STATUS_MAP = {
|
||||||
passed = "passes",
|
passed = "passes",
|
||||||
failed = "failures",
|
failed = "failures",
|
||||||
@@ -341,6 +342,15 @@ local function reporter_path()
|
|||||||
return vim.fs.normalize(dir .. "/../../reporter/test_samurai_jest_reporter.js")
|
return vim.fs.normalize(dir .. "/../../reporter/test_samurai_jest_reporter.js")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function setup_path()
|
||||||
|
local source = debug.getinfo(1, "S").source
|
||||||
|
if source:sub(1, 1) == "@" then
|
||||||
|
source = source:sub(2)
|
||||||
|
end
|
||||||
|
local dir = vim.fs.dirname(source)
|
||||||
|
return vim.fs.normalize(dir .. "/../../reporter/test_samurai_jest_stdout.js")
|
||||||
|
end
|
||||||
|
|
||||||
local function base_cmd()
|
local function base_cmd()
|
||||||
return {
|
return {
|
||||||
"npx",
|
"npx",
|
||||||
@@ -348,6 +358,8 @@ local function base_cmd()
|
|||||||
"--testLocationInResults",
|
"--testLocationInResults",
|
||||||
"--reporters",
|
"--reporters",
|
||||||
reporter_path(),
|
reporter_path(),
|
||||||
|
"--setupFilesAfterEnv",
|
||||||
|
setup_path(),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -366,6 +378,21 @@ local function parse_result_line(line)
|
|||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function parse_stdout_line(line)
|
||||||
|
if not line or line == "" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if line:sub(1, #STDOUT_PREFIX) ~= STDOUT_PREFIX then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local payload = line:sub(#STDOUT_PREFIX + 1)
|
||||||
|
local ok, data = pcall(vim.json.decode, payload)
|
||||||
|
if not ok or type(data) ~= "table" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
local function update_location_cache(name, data)
|
local function update_location_cache(name, data)
|
||||||
if not name or name == "" then
|
if not name or name == "" then
|
||||||
return
|
return
|
||||||
@@ -675,9 +702,14 @@ function runner.parse_test_output(output)
|
|||||||
if not output or output == "" then
|
if not output or output == "" then
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
|
local jest_to_listing = {}
|
||||||
|
local pending = {}
|
||||||
for line in output:gmatch("[^\n]+") do
|
for line in output:gmatch("[^\n]+") do
|
||||||
local data = parse_result_line(line)
|
local data = parse_result_line(line)
|
||||||
if data and data.name and data.output then
|
if data and data.name and data.output then
|
||||||
|
if data.jestName and data.jestName ~= "" then
|
||||||
|
jest_to_listing[data.jestName] = data.name
|
||||||
|
end
|
||||||
out[data.name] = out[data.name] or {}
|
out[data.name] = out[data.name] or {}
|
||||||
if type(data.output) == "string" then
|
if type(data.output) == "string" then
|
||||||
for _, item in ipairs(split_output_lines(data.output)) do
|
for _, item in ipairs(split_output_lines(data.output)) do
|
||||||
@@ -691,6 +723,49 @@ function runner.parse_test_output(output)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local stdout = parse_stdout_line(line)
|
||||||
|
if stdout and (stdout.name or stdout.jestName) and stdout.output then
|
||||||
|
local stdout_name = stdout.name or stdout.jestName
|
||||||
|
local target = jest_to_listing[stdout_name] or stdout_name
|
||||||
|
if not jest_to_listing[stdout_name] then
|
||||||
|
pending[stdout_name] = pending[stdout_name] or {}
|
||||||
|
table.insert(pending[stdout_name], stdout.output)
|
||||||
|
else
|
||||||
|
out[target] = out[target] or {}
|
||||||
|
if type(stdout.output) == "string" then
|
||||||
|
for _, item in ipairs(split_output_lines(stdout.output)) do
|
||||||
|
if item ~= "" then
|
||||||
|
table.insert(out[target], item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif type(stdout.output) == "table" then
|
||||||
|
for _, item in ipairs(stdout.output) do
|
||||||
|
if item and item ~= "" then
|
||||||
|
table.insert(out[target], item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for jest_name, outputs in pairs(pending) do
|
||||||
|
local target = jest_to_listing[jest_name] or jest_name
|
||||||
|
out[target] = out[target] or {}
|
||||||
|
for _, items in ipairs(outputs) do
|
||||||
|
if type(items) == "string" then
|
||||||
|
for _, item in ipairs(split_output_lines(items)) do
|
||||||
|
if item ~= "" then
|
||||||
|
table.insert(out[target], item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif type(items) == "table" then
|
||||||
|
for _, item in ipairs(items) do
|
||||||
|
if item and item ~= "" then
|
||||||
|
table.insert(out[target], item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
|
|||||||
36
reporter/test_samurai_jest_stdout.js
Normal file
36
reporter/test_samurai_jest_stdout.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const util = require('util');
|
||||||
|
|
||||||
|
const STDOUT_PREFIX = 'TSAMURAI_STDOUT ';
|
||||||
|
|
||||||
|
function getCurrentTestName() {
|
||||||
|
if (typeof expect !== 'function') return null;
|
||||||
|
try {
|
||||||
|
const state = expect.getState();
|
||||||
|
if (state && state.currentTestName) {
|
||||||
|
return String(state.currentTestName);
|
||||||
|
}
|
||||||
|
} catch (_err) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitStdout(name, args) {
|
||||||
|
if (!name) return;
|
||||||
|
const message = util.format(...args);
|
||||||
|
if (message === '') return;
|
||||||
|
process.stdout.write(`${STDOUT_PREFIX}${JSON.stringify({ jestName: name, output: message })}\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapConsoleMethod(method) {
|
||||||
|
if (typeof console[method] !== 'function') return;
|
||||||
|
const original = console[method].bind(console);
|
||||||
|
console[method] = (...args) => {
|
||||||
|
emitStdout(getCurrentTestName(), args);
|
||||||
|
return original(...args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
['log', 'info', 'warn', 'error', 'debug'].forEach(wrapConsoleMethod);
|
||||||
@@ -41,6 +41,15 @@ local function get_reporter_path()
|
|||||||
return vim.fs.normalize(dir .. "/../../reporter/test_samurai_jest_reporter.js")
|
return vim.fs.normalize(dir .. "/../../reporter/test_samurai_jest_reporter.js")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function get_setup_path()
|
||||||
|
local source = debug.getinfo(runner.build_command, "S").source
|
||||||
|
if source:sub(1, 1) == "@" then
|
||||||
|
source = source:sub(2)
|
||||||
|
end
|
||||||
|
local dir = vim.fs.dirname(source)
|
||||||
|
return vim.fs.normalize(dir .. "/../../reporter/test_samurai_jest_stdout.js")
|
||||||
|
end
|
||||||
|
|
||||||
describe("test-samurai-jest-runner", function()
|
describe("test-samurai-jest-runner", function()
|
||||||
it("detects Jest test files by suffix and package.json", function()
|
it("detects Jest test files by suffix and package.json", function()
|
||||||
with_project(JEST_PACKAGE, function(root)
|
with_project(JEST_PACKAGE, function(root)
|
||||||
@@ -176,6 +185,8 @@ describe("test-samurai-jest-runner", function()
|
|||||||
"--testLocationInResults",
|
"--testLocationInResults",
|
||||||
"--reporters",
|
"--reporters",
|
||||||
get_reporter_path(),
|
get_reporter_path(),
|
||||||
|
"--setupFilesAfterEnv",
|
||||||
|
get_setup_path(),
|
||||||
"--runTestsByPath",
|
"--runTestsByPath",
|
||||||
cmd_spec.cmd[#cmd_spec.cmd],
|
cmd_spec.cmd[#cmd_spec.cmd],
|
||||||
},
|
},
|
||||||
@@ -200,6 +211,8 @@ describe("test-samurai-jest-runner", function()
|
|||||||
"--testLocationInResults",
|
"--testLocationInResults",
|
||||||
"--reporters",
|
"--reporters",
|
||||||
get_reporter_path(),
|
get_reporter_path(),
|
||||||
|
"--setupFilesAfterEnv",
|
||||||
|
get_setup_path(),
|
||||||
"--runTestsByPath",
|
"--runTestsByPath",
|
||||||
"/tmp/math.test.js",
|
"/tmp/math.test.js",
|
||||||
"--testNamePattern",
|
"--testNamePattern",
|
||||||
@@ -226,6 +239,8 @@ describe("test-samurai-jest-runner", function()
|
|||||||
"--testLocationInResults",
|
"--testLocationInResults",
|
||||||
"--reporters",
|
"--reporters",
|
||||||
get_reporter_path(),
|
get_reporter_path(),
|
||||||
|
"--setupFilesAfterEnv",
|
||||||
|
get_setup_path(),
|
||||||
"--runTestsByPath",
|
"--runTestsByPath",
|
||||||
"/tmp/math.test.js",
|
"/tmp/math.test.js",
|
||||||
"--testNamePattern",
|
"--testNamePattern",
|
||||||
@@ -253,6 +268,8 @@ describe("test-samurai-jest-runner", function()
|
|||||||
"--testLocationInResults",
|
"--testLocationInResults",
|
||||||
"--reporters",
|
"--reporters",
|
||||||
get_reporter_path(),
|
get_reporter_path(),
|
||||||
|
"--setupFilesAfterEnv",
|
||||||
|
get_setup_path(),
|
||||||
"--runTestsByPath",
|
"--runTestsByPath",
|
||||||
root .. "/foo.test.ts",
|
root .. "/foo.test.ts",
|
||||||
},
|
},
|
||||||
@@ -276,6 +293,8 @@ describe("test-samurai-jest-runner", function()
|
|||||||
"--testLocationInResults",
|
"--testLocationInResults",
|
||||||
"--reporters",
|
"--reporters",
|
||||||
get_reporter_path(),
|
get_reporter_path(),
|
||||||
|
"--setupFilesAfterEnv",
|
||||||
|
get_setup_path(),
|
||||||
},
|
},
|
||||||
cmd_spec.cmd
|
cmd_spec.cmd
|
||||||
)
|
)
|
||||||
@@ -291,6 +310,8 @@ describe("test-samurai-jest-runner", function()
|
|||||||
"--testLocationInResults",
|
"--testLocationInResults",
|
||||||
"--reporters",
|
"--reporters",
|
||||||
get_reporter_path(),
|
get_reporter_path(),
|
||||||
|
"--setupFilesAfterEnv",
|
||||||
|
get_setup_path(),
|
||||||
"--runTestsByPath",
|
"--runTestsByPath",
|
||||||
"/tmp/math.test.js",
|
"/tmp/math.test.js",
|
||||||
"--testNamePattern",
|
"--testNamePattern",
|
||||||
@@ -310,6 +331,8 @@ describe("test-samurai-jest-runner", function()
|
|||||||
"--testLocationInResults",
|
"--testLocationInResults",
|
||||||
"--reporters",
|
"--reporters",
|
||||||
get_reporter_path(),
|
get_reporter_path(),
|
||||||
|
"--setupFilesAfterEnv",
|
||||||
|
get_setup_path(),
|
||||||
"--runTestsByPath",
|
"--runTestsByPath",
|
||||||
"/tmp/math.test.js",
|
"/tmp/math.test.js",
|
||||||
"--testNamePattern",
|
"--testNamePattern",
|
||||||
@@ -395,18 +418,24 @@ describe("test-samurai-jest-runner", function()
|
|||||||
local output = table.concat({
|
local output = table.concat({
|
||||||
"TSAMURAI_RESULT " .. vim.json.encode({
|
"TSAMURAI_RESULT " .. vim.json.encode({
|
||||||
name = "Math/adds",
|
name = "Math/adds",
|
||||||
|
jestName = "Math adds",
|
||||||
status = "failed",
|
status = "failed",
|
||||||
output = { "line1", "line2" },
|
output = { "line1", "line2" },
|
||||||
}),
|
}),
|
||||||
|
"TSAMURAI_STDOUT " .. vim.json.encode({
|
||||||
|
jestName = "Math adds",
|
||||||
|
output = "log line",
|
||||||
|
}),
|
||||||
"TSAMURAI_RESULT " .. vim.json.encode({
|
"TSAMURAI_RESULT " .. vim.json.encode({
|
||||||
name = "Math/adds",
|
name = "Math/adds",
|
||||||
|
jestName = "Math adds",
|
||||||
status = "failed",
|
status = "failed",
|
||||||
output = { "line3" },
|
output = { "line3" },
|
||||||
}),
|
}),
|
||||||
}, "\n")
|
}, "\n")
|
||||||
|
|
||||||
local results = runner.parse_test_output(output)
|
local results = runner.parse_test_output(output)
|
||||||
assert.are.same({ "line1", "line2", "line3" }, results["Math/adds"])
|
assert.are.same({ "line1", "line2", "log line", "line3" }, results["Math/adds"])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("collect_failed_locations uses cached locations", function()
|
it("collect_failed_locations uses cached locations", function()
|
||||||
|
|||||||
Reference in New Issue
Block a user