jquote.nvim/tests/test_runner.lua
jank 6d065862b0
refactor: Refactor everything
BREAKING CHANGE: Actually move to the next pair of quotes
2025-07-28 21:19:35 +02:00

217 lines
No EOL
6.4 KiB
Lua

#!/usr/bin/env lua
--- Simple Test Runner for JQuote Plugin
--- @author Jan
--- @license MIT
local test_runner = {}
-- Test result tracking
local stats = {
total = 0,
passed = 0,
failed = 0,
errors = {},
start_time = os.clock()
}
-- ANSI color codes for terminal output
local colors = {
reset = "\27[0m",
red = "\27[31m",
green = "\27[32m",
yellow = "\27[33m",
blue = "\27[34m",
magenta = "\27[35m",
cyan = "\27[36m",
white = "\27[37m",
bold = "\27[1m"
}
-- Simple assertion library
local assert = {
is_true = function(value, message)
if value ~= true then
error(message or string.format("Expected true, got %s", tostring(value)))
end
end,
is_false = function(value, message)
if value ~= false then
error(message or string.format("Expected false, got %s", tostring(value)))
end
end,
are = {
equal = function(expected, actual, message)
if expected ~= actual then
error(message or string.format("Expected %s, got %s", tostring(expected), tostring(actual)))
end
end,
same = function(expected, actual, message)
if not test_runner.deep_equal(expected, actual) then
error(message or string.format("Tables are not the same.\nExpected: %s\nActual: %s",
test_runner.table_tostring(expected), test_runner.table_tostring(actual)))
end
end
},
is_not_nil = function(value, message)
if value == nil then
error(message or "Expected non-nil value")
end
end,
is_string = function(value, message)
if type(value) ~= "string" then
error(message or string.format("Expected string, got %s", type(value)))
end
end,
is_table = function(value, message)
if type(value) ~= "table" then
error(message or string.format("Expected table, got %s", type(value)))
end
end,
matches = function(pattern, str, message)
if not string.match(str, pattern) then
error(message or string.format("String '%s' does not match pattern '%s'", str, pattern))
end
end
}
-- Make assert global for tests
_G.assert = assert
-- Test context management
local current_context = ""
local current_test = ""
-- Utility functions
function test_runner.deep_equal(a, b)
if type(a) ~= type(b) then return false end
if type(a) ~= "table" then return a == b end
for k, v in pairs(a) do
if not test_runner.deep_equal(v, b[k]) then return false end
end
for k, v in pairs(b) do
if not test_runner.deep_equal(v, a[k]) then return false end
end
return true
end
function test_runner.table_tostring(t, indent)
if type(t) ~= "table" then return tostring(t) end
indent = indent or 0
local spaces = string.rep(" ", indent)
local result = "{\n"
for k, v in pairs(t) do
result = result .. spaces .. " " .. tostring(k) .. " = "
if type(v) == "table" then
result = result .. test_runner.table_tostring(v, indent + 1)
else
result = result .. tostring(v)
end
result = result .. ",\n"
end
result = result .. spaces .. "}"
return result
end
-- Test framework functions
function describe(description, func)
current_context = description
print(colors.blue .. colors.bold .. "\n" .. description .. colors.reset)
func()
current_context = ""
end
function it(description, func)
current_test = description
stats.total = stats.total + 1
local success, error_msg = pcall(func)
if success then
stats.passed = stats.passed + 1
print(colors.green .. "" .. description .. colors.reset)
else
stats.failed = stats.failed + 1
local full_description = current_context .. " - " .. description
table.insert(stats.errors, {
test = full_description,
error = error_msg
})
print(colors.red .. "" .. description .. colors.reset)
print(colors.red .. " " .. error_msg .. colors.reset)
end
current_test = ""
end
function before_each(func)
-- Simple implementation - just call the function before each test
-- In a more sophisticated runner, this would be stored and called appropriately
_G._before_each = func
end
-- Override 'it' to call before_each if it exists
local original_it = it
function it(description, func)
if _G._before_each then
_G._before_each()
end
original_it(description, func)
end
-- Test execution
function test_runner.run_tests()
print(colors.cyan .. colors.bold .. "JQuote Plugin Test Suite" .. colors.reset)
print(colors.cyan .. "========================" .. colors.reset)
-- Load and run tests
local success, error_msg = pcall(dofile, "tests/init_spec.lua")
if not success then
print(colors.red .. colors.bold .. "Failed to load test file:" .. colors.reset)
print(colors.red .. error_msg .. colors.reset)
return false
end
-- Print summary
local duration = os.clock() - stats.start_time
print(colors.cyan .. "\n========================" .. colors.reset)
print(colors.white .. colors.bold .. "Test Summary:" .. colors.reset)
print(string.format(" Total tests: %d", stats.total))
print(colors.green .. string.format(" Passed: %d", stats.passed) .. colors.reset)
if stats.failed > 0 then
print(colors.red .. string.format(" Failed: %d", stats.failed) .. colors.reset)
print(colors.red .. "\nFailure Details:" .. colors.reset)
for _, error_info in ipairs(stats.errors) do
print(colors.red .. "" .. error_info.test .. colors.reset)
print(colors.red .. " " .. error_info.error .. colors.reset)
end
end
print(string.format(" Duration: %.3fs", duration))
local success_rate = stats.total > 0 and (stats.passed / stats.total * 100) or 0
if success_rate == 100 then
print(colors.green .. colors.bold .. "\n🎉 All tests passed!" .. colors.reset)
else
print(colors.red .. colors.bold .. string.format("\n❌ %.1f%% tests passed", success_rate) .. colors.reset)
end
return stats.failed == 0
end
-- Command line interface
if arg and arg[0] and arg[0]:match("test_runner%.lua$") then
local success = test_runner.run_tests()
os.exit(success and 0 or 1)
end
return test_runner