diff --git a/site-modules/core/files/vim/plugin/ts-jest.lua b/site-modules/core/files/vim/plugin/ts-jest.lua new file mode 100644 index 0000000..f9e1340 --- /dev/null +++ b/site-modules/core/files/vim/plugin/ts-jest.lua @@ -0,0 +1,172 @@ +local ts_utils = require "nvim-treesitter.ts_utils" + +local function get_unquoted_node_text(node) + local node_text = vim.treesitter.get_node_text(node, 0) + local value, _ = string.gsub(node_text, '["]', "") + return value +end + +local function get_test_name_at_cursor() + local node = ts_utils.get_node_at_cursor() + local test_name = "" + while node do + if node:type() == "call_expression" then + local named = ts_utils.get_named_children(node) + local function_name = vim.treesitter.get_node_text(named[1], 0) + if function_name == "describe" or function_name == "it" then + test_name = get_unquoted_node_text(named[2]:child(1)) .. " " .. test_name + end + end + + node = node:parent() + end + + local value, _ = string.gsub(test_name, "%s+$", "") + return value +end + +local function get_all_tests() + local parser = vim.treesitter.get_parser(0, "javascript") + local tree, _ = unpack(parser:parse()) + + local function_name_query = vim.treesitter.query.parse( + "javascript", + [[((call_expression + function: (identifier) @function_name + arguments: (arguments (string) @test_name) + (#match? @function_name "(it|describe)")))]] + ) + + local tests = {} + local current_context = { tree } + local prefix = {} + for _, match, _ in function_name_query:iter_matches(tree:root(), 0) do + local function_name_node, test_name_node = unpack(match) + local function_name = get_unquoted_node_text(function_name_node) + local test_name = get_unquoted_node_text(test_name_node) + + if function_name == "describe" then + table.insert(current_context, 1, function_name_node:parent()) + table.insert(prefix, 1, test_name) + end + + if function_name == "it" then + if not vim.treesitter.is_ancestor(current_context[1], function_name_node) then + table.remove(prefix, 1) + table.remove(current_context, 1) + end + + local test_value = test_name + for _, v in ipairs(prefix) do + test_value = v .. " " .. test_value + end + + table.insert(tests, { content = test_value }) + end + end + + return tests +end + +local function parse_results(results) + local issues = {} + + for _, result in ipairs(results.testResults) do + if result.status ~= "passed" then + local file = result.message:match "([^:(]+):%d+:%d+" + local line = result.message:match "[^:]+:(%d+):%d+" + local message = result.message:match "\n\n%s+([^\n]+)" + + table.insert(issues, { text = message, filename = file, lnum = line }) + end + end + + return issues +end + +local function run_at_cursor() + vim.fn.jobstart({ + "jest", + "--maxWorkers=25%", + "--silent", + "--json", + "-t", + get_test_name_at_cursor(), + vim.fn.expand "%", + }, { + stdout_buffered = true, + on_stdout = function(_, output) + local results = vim.json.decode(output[1]) + local issues = parse_results(results) + + if #issues == 0 then + -- print "All tests passed" + else + vim.fn.setqflist({}, "r", { title = "Jest Failers", items = issues }) + vim.cmd "copen" + end + end, + on_stderr = function(_, data) + -- This will display the progress for the tests + print(data[1]) + end, + }) +end + +local function run_file() + vim.fn.jobstart({ + "jest", + "--maxWorkers=25%", + "--silent", + "--json", + vim.fn.expand "%", + }, { + stdout_buffered = true, + on_stdout = function(_, output) + local results = vim.json.decode(output[1]) + local issues = parse_results(results) + + if #issues == 0 then + -- print "All tests passed" + else + vim.fn.setqflist({}, "r", { title = "Jest Failers", items = issues }) + vim.cmd "copen" + end + end, + on_stderr = function(_, data) + -- This will display the progress for the tests + print(data[1]) + end, + }) +end + +local function run_all() + vim.fn.jobstart({ + "jest", + "--maxWorkers=25%", + "--silent", + "--json", + }, { + stdout_buffered = true, + on_stdout = function(_, output) + local results = vim.json.decode(output[1]) + local issues = parse_results(results) + + if #issues == 0 then + -- print "All tests passed" + else + vim.fn.setqflist({}, "r", { title = "Jest Failers", items = issues }) + vim.cmd "copen" + end + end, + on_stderr = function(_, data) + -- This will display the progress for the tests + print(data[1]) + end, + }) +end + +vim.api.nvim_create_user_command("Jest", run_all, { bang = true }) +vim.api.nvim_create_user_command("JestFile", run_file, { bang = true }) +vim.api.nvim_create_user_command("JestAtCursor", run_at_cursor, { bang = true }) +vim.api.nvim_set_keymap("n", "t", "JestAtCursor", { nowait = true, silent = true })