Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support nested describe #55

Merged
merged 1 commit into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 29 additions & 87 deletions lua/neotest-vitest/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ function adapter.discover_positions(path)
arguments: (arguments (string (string_fragment) @test.name) (arrow_function))
)) @test.definition
]]

query = query .. string.gsub(query, "arrow_function", "function_expression")
return lib.treesitter.parse_positions(path, query, { nested_tests = true })
end

Expand Down Expand Up @@ -200,17 +200,19 @@ end

local function escapeTestPattern(s)
return (
s:gsub("%(", "%\\(")
:gsub("%)", "%\\)")
:gsub("%]", "%\\]")
:gsub("%[", "%\\[")
:gsub("%*", "%\\*")
:gsub("%+", "%\\+")
:gsub("%-", "%\\-")
:gsub("%?", "%\\?")
:gsub("%$", "%\\$")
:gsub("%^", "%\\^")
:gsub("%/", "%\\/")
s:gsub("%(", "\\(")
:gsub("%)", "\\)")
:gsub("%]", "\\]")
:gsub("%[", "\\[")
:gsub("%.", "\\.")
:gsub("%*", "\\*")
:gsub("%+", "\\+")
:gsub("%-", "\\-")
:gsub("%?", "\\?")
:gsub(" ", "\\s")
:gsub("%$", "\\$")
:gsub("%^", "\\^")
:gsub("%/", "\\/")
)
end

Expand Down Expand Up @@ -244,72 +246,6 @@ local function getCwd(path)
return nil
end

local function cleanAnsi(s)
return s:gsub("\x1b%[%d+;%d+;%d+;%d+;%d+m", "")
:gsub("\x1b%[%d+;%d+;%d+;%d+m", "")
:gsub("\x1b%[%d+;%d+;%d+m", "")
:gsub("\x1b%[%d+;%d+m", "")
:gsub("\x1b%[%d+m", "")
end

local function parsed_json_to_results(data, output_file, consoleOut)
local tests = {}

for _, testResult in pairs(data.testResults) do
local testFn = testResult.name

for _, assertionResult in pairs(testResult.assertionResults) do
local status, name = assertionResult.status, assertionResult.title

if name == nil then
logger.error("Failed to find parsed test result ", assertionResult)
return {}
end

local keyid = testFn

for _, value in ipairs(assertionResult.ancestorTitles) do
if value ~= "" then
keyid = keyid .. "::" .. value
end
end

keyid = keyid .. "::" .. name

if status == "pending" or status == "todo" then
status = "skipped"
end

tests[keyid] = {
status = status,
short = name .. ": " .. status,
output = consoleOut,
location = assertionResult.location,
}

if not vim.tbl_isempty(assertionResult.failureMessages) then
local errors = {}

for i, failMessage in ipairs(assertionResult.failureMessages) do
local msg = cleanAnsi(failMessage)

errors[i] = {
line = (assertionResult.location and assertionResult.location.line - 1 or nil),
column = (assertionResult.location and assertionResult.location.column or nil),
message = msg,
}

tests[keyid].short = tests[keyid].short .. "\n" .. msg
end

tests[keyid].errors = errors
end
end
end

return tests
end

---@param args neotest.RunArgs
---@return neotest.RunSpec | nil
function adapter.build_spec(args)
Expand All @@ -319,16 +255,22 @@ function adapter.build_spec(args)
if not tree then
return
end
local names = {}
while tree and tree:data().type ~= "file" do
table.insert(names, 1, tree:data().name)
tree = tree:parent() --[[@as neotest.Tree]]
end
local testNamePattern = table.concat(names, " ")

local pos = args.tree:data()
local testNamePattern = ".*"

if pos.type == "test" then
testNamePattern = escapeTestPattern(pos.name) .. "$"
if #testNamePattern == 0 then
testNamePattern = ".*"
else
testNamePattern = "^\\s?" .. escapeTestPattern(testNamePattern)
end

if pos.type == "namespace" then
testNamePattern = "^ " .. escapeTestPattern(pos.name)
local pos = args.tree:data()
if pos.type == "test" then
testNamePattern = testNamePattern .. "$"
end

local binary = args.vitestCommand or getVitestCommand(pos.path)
Expand Down Expand Up @@ -377,7 +319,7 @@ function adapter.build_spec(args)
return {}
end

return parsed_json_to_results(parsed, results_path, nil)
return util.parsed_json_to_results(parsed, results_path, nil)
end
end,
strategy = get_strategy_config(args.strategy, command, cwd),
Expand Down Expand Up @@ -407,7 +349,7 @@ function adapter.results(spec, b, tree)
return {}
end

local results = parsed_json_to_results(parsed, output_file, b.output)
local results = util.parsed_json_to_results(parsed, output_file, b.output)

return results
end
Expand Down
67 changes: 66 additions & 1 deletion lua/neotest-vitest/util.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local vim = vim
local logger = require("neotest.logging")
local validate = vim.validate
local uv = vim.loop

Expand Down Expand Up @@ -229,4 +229,69 @@ function M.stream(file_path)
return queue.get, exit_future.set
end

function M.cleanAnsi(s)
return s:gsub("\x1b%[%d+;%d+;%d+;%d+;%d+m", "")
:gsub("\x1b%[%d+;%d+;%d+;%d+m", "")
:gsub("\x1b%[%d+;%d+;%d+m", "")
:gsub("\x1b%[%d+;%d+m", "")
:gsub("\x1b%[%d+m", "")
end
function M.parsed_json_to_results(data, output_file, consoleOut)
local tests = {}

for _, testResult in pairs(data.testResults) do
local testFn = testResult.name

for _, assertionResult in pairs(testResult.assertionResults) do
local status, name = assertionResult.status, assertionResult.title

if name == nil then
logger.error("Failed to find parsed test result ", assertionResult)
return {}
end

local keyid = testFn

for _, value in ipairs(assertionResult.ancestorTitles) do
if value ~= "" then
keyid = keyid .. "::" .. value
end
end

keyid = keyid .. "::" .. name

if status == "pending" or status == "todo" then
status = "skipped"
end

tests[keyid] = {
status = status,
short = name .. ": " .. status,
output = consoleOut,
location = assertionResult.location,
}

if not vim.tbl_isempty(assertionResult.failureMessages) then
local errors = {}

for i, failMessage in ipairs(assertionResult.failureMessages) do
local msg = M.cleanAnsi(failMessage)

errors[i] = {
line = (assertionResult.location and assertionResult.location.line - 1 or nil),
column = (assertionResult.location and assertionResult.location.column or nil),
message = msg,
}

tests[keyid].short = tests[keyid].short .. "\n" .. msg
end

tests[keyid].errors = errors
end
end
end

return tests
end

return M
5 changes: 3 additions & 2 deletions scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ if [ ! -d .testdeps ]; then
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim.git .testdeps/plenary.nvim
git clone --depth 1 https://github.com/nvim-treesitter/nvim-treesitter.git .testdeps/nvim-treesitter
git clone --depth 1 https://github.com/nvim-neotest/neotest.git .testdeps/neotest
git clone --depth 1 https://github.com/nvim-neotest/nvim-nio.git .testdeps/nvim-nio
fi

if [[ -n $1 ]]; then
nvim --headless --noplugin -u tests/init.vim -c "PlenaryBustedFile $1" | tee "${tempfile}"
nvim --headless --noplugin -u tests/minimal_init.vim -c "PlenaryBustedFile $1" | tee "${tempfile}"
else
nvim --headless --noplugin -u tests/init.vim -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.vim'}" | tee "${tempfile}"
nvim --headless --noplugin -u tests/minimal_init.vim -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/minimal_init.vim'}" | tee "${tempfile}"
fi

# Plenary doesn't emit exit code 1 when tests have errors during setup
Expand Down
31 changes: 16 additions & 15 deletions spec/basic.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { describe ,it ,test } from 'vitest'
import { describe, it, test, expect } from 'vitest'

describe("describe text", () => {
it("1", () => {
console.log("do test");
});
describe("describe arrow function", () => {
test("foo", () => {
expect(true).to.equal(true);
});

it("2", async () => {
console.log("do test");
});

test("3", () => {
console.log("do test");
});
it("bar(error)", () => {
expect(true).to.equal(false);
});
});

test("4", async () => {
console.log("do test");
});
describe("describe vanilla function", function() {
AbaoFromCUG marked this conversation as resolved.
Show resolved Hide resolved
test("foo", () => {
console.log("do test");
});
it("bar", () => {
console.log("do test");
});
});
Binary file added spec/bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion spec/config/vitest/basic.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { it } from "vitest";

it("1", () => {
console.log("do test");
console.log("do test");
});
22 changes: 22 additions & 0 deletions spec/nested.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { describe, it, test, expect } from 'vitest'

describe("first level", () => {
describe("second level", () => {
it("foo", () => {
expect(true).to.equal(true);
});
it("bar(error)", () => {
expect(true).to.equal(false);
});
});
});

describe("A", () => {
it("foo", () => {
expect(true).to.equal(true);
});
it("bar(error)", () => {
expect(true).to.equal(false);
});
});

13 changes: 12 additions & 1 deletion tests/init_options_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ local config_override = function()
end

describe("build_spec with override", function()
local raw_tempname
before_each(function()
raw_tempname = require("neotest.async").fn.tempname
require("neotest.async").fn.tempname = function()
return "/tmp/foo"
end
end)
after_each(function()
require("neotest.async").fn.tempname = raw_tempname
end)
async.it("builds command", function()
local plugin = require("neotest-vitest")({
vitestCommand = binary_override,
Expand All @@ -35,9 +45,10 @@ describe("build_spec with override", function()
assert.contains(command, "--reporter=verbose")
--[[ assert.contains(command, "--config=" .. config_override()) ]]
assert.contains(command, "--testNamePattern=.*")
assert.contains(command, "./spec/basic.test.ts")
-- assert.contains(command, "spec/basic.test.ts")
assert.is.truthy(spec.context.file)
assert.is.truthy(spec.context.results_path)

assert.is.same(
spec.env,
{ override = "override", adapter_override = true, spec_override = true }
Expand Down
Loading
Loading