feat: add luatest (#1064)

This commit is contained in:
yetone
2025-01-10 00:23:59 +08:00
committed by GitHub
parent 6c10081899
commit e14eb002d5
5 changed files with 319 additions and 6 deletions

141
tests/utils/file_spec.lua Normal file
View File

@@ -0,0 +1,141 @@
local File = require("avante.utils.file")
local mock = require("luassert.mock")
local stub = require("luassert.stub")
describe("File", function()
local test_file = "test.txt"
local test_content = "test content\nline 2"
-- Mock vim API
local api_mock
local loop_mock
before_each(function()
-- Setup mocks
api_mock = mock(vim.api, true)
loop_mock = mock(vim.loop, true)
end)
after_each(function()
-- Clean up mocks
mock.revert(api_mock)
mock.revert(loop_mock)
end)
describe("read_content", function()
it("should read file content", function()
vim.fn.readfile = stub().returns({ "test content", "line 2" })
local content = File.read_content(test_file)
assert.equals(test_content, content)
assert.stub(vim.fn.readfile).was_called_with(test_file)
end)
it("should return nil for non-existent file", function()
vim.fn.readfile = stub().returns(nil)
local content = File.read_content("nonexistent.txt")
assert.is_nil(content)
end)
it("should use cache for subsequent reads", function()
vim.fn.readfile = stub().returns({ "test content", "line 2" })
local new_test_file = "test1.txt"
-- First read
local content1 = File.read_content(new_test_file)
assert.equals(test_content, content1)
-- Second read (should use cache)
local content2 = File.read_content(new_test_file)
assert.equals(test_content, content2)
-- readfile should only be called once
assert.stub(vim.fn.readfile).was_called(1)
end)
end)
describe("exists", function()
it("should return true for existing file", function()
loop_mock.fs_stat.returns({ type = "file" })
assert.is_true(File.exists(test_file))
assert.stub(loop_mock.fs_stat).was_called_with(test_file)
end)
it("should return false for non-existent file", function()
loop_mock.fs_stat.returns(nil)
assert.is_false(File.exists("nonexistent.txt"))
end)
end)
describe("get_file_icon", function()
local Filetype
local devicons_mock
before_each(function()
-- Mock plenary.filetype
Filetype = mock(require("plenary.filetype"), true)
-- Prepare devicons mock
devicons_mock = {
get_icon = stub().returns(""),
}
-- Reset _G.MiniIcons
_G.MiniIcons = nil
end)
after_each(function() mock.revert(Filetype) end)
it("should get icon using nvim-web-devicons", function()
Filetype.detect.returns("lua")
devicons_mock.get_icon.returns("")
-- Mock require for nvim-web-devicons
local old_require = _G.require
_G.require = function(module)
if module == "nvim-web-devicons" then return devicons_mock end
return old_require(module)
end
local icon = File.get_file_icon("test.lua")
assert.equals("", icon)
assert.stub(Filetype.detect).was_called_with("test.lua", {})
assert.stub(devicons_mock.get_icon).was_called()
_G.require = old_require
end)
it("should get icon using MiniIcons if available", function()
_G.MiniIcons = {
get = stub().returns("", "color", "name"),
}
Filetype.detect.returns("lua")
local icon = File.get_file_icon("test.lua")
assert.equals("", icon)
assert.stub(Filetype.detect).was_called_with("test.lua", {})
assert.stub(_G.MiniIcons.get).was_called_with("filetype", "lua")
_G.MiniIcons = nil
end)
it("should handle unknown filetypes", function()
Filetype.detect.returns(nil)
devicons_mock.get_icon.returns("")
-- Mock require for nvim-web-devicons
local old_require = _G.require
_G.require = function(module)
if module == "nvim-web-devicons" then return devicons_mock end
return old_require(module)
end
local icon = File.get_file_icon("unknown.xyz")
assert.equals("", icon)
_G.require = old_require
end)
end)
end)

123
tests/utils/init_spec.lua Normal file
View File

@@ -0,0 +1,123 @@
local Utils = require("avante.utils")
describe("Utils", function()
describe("trim", function()
it("should trim prefix", function() assert.equals("test", Utils.trim("prefix_test", { prefix = "prefix_" })) end)
it("should trim suffix", function() assert.equals("test", Utils.trim("test_suffix", { suffix = "_suffix" })) end)
it(
"should trim both prefix and suffix",
function() assert.equals("test", Utils.trim("prefix_test_suffix", { prefix = "prefix_", suffix = "_suffix" })) end
)
it(
"should return original string if no match",
function() assert.equals("test", Utils.trim("test", { prefix = "xxx", suffix = "yyy" })) end
)
end)
describe("url_join", function()
it("should join url parts correctly", function()
assert.equals("http://example.com/path", Utils.url_join("http://example.com", "path"))
assert.equals("http://example.com/path", Utils.url_join("http://example.com/", "/path"))
assert.equals("http://example.com/path/to", Utils.url_join("http://example.com", "path", "to"))
assert.equals("http://example.com/path", Utils.url_join("http://example.com/", "/path/"))
end)
it("should handle empty parts", function()
assert.equals("http://example.com", Utils.url_join("http://example.com", ""))
assert.equals("http://example.com", Utils.url_join("http://example.com", nil))
end)
end)
describe("is_type", function()
it("should check basic types correctly", function()
assert.is_true(Utils.is_type("string", "test"))
assert.is_true(Utils.is_type("number", 123))
assert.is_true(Utils.is_type("boolean", true))
assert.is_true(Utils.is_type("table", {}))
assert.is_true(Utils.is_type("function", function() end))
assert.is_true(Utils.is_type("nil", nil))
end)
it("should check list type correctly", function()
assert.is_true(Utils.is_type("list", { 1, 2, 3 }))
assert.is_false(Utils.is_type("list", { a = 1, b = 2 }))
end)
it("should check map type correctly", function()
assert.is_true(Utils.is_type("map", { a = 1, b = 2 }))
assert.is_false(Utils.is_type("map", { 1, 2, 3 }))
end)
end)
describe("get_indentation", function()
it("should get correct indentation", function()
assert.equals(" ", Utils.get_indentation(" test"))
assert.equals("\t", Utils.get_indentation("\ttest"))
assert.equals("", Utils.get_indentation("test"))
end)
it("should handle empty or nil input", function()
assert.equals("", Utils.get_indentation(""))
assert.equals("", Utils.get_indentation(nil))
end)
end)
describe("remove_indentation", function()
it("should remove indentation correctly", function()
assert.equals("test", Utils.remove_indentation(" test"))
assert.equals("test", Utils.remove_indentation("\ttest"))
assert.equals("test", Utils.remove_indentation("test"))
end)
it("should handle empty or nil input", function()
assert.equals("", Utils.remove_indentation(""))
assert.equals(nil, Utils.remove_indentation(nil))
end)
end)
describe("is_first_letter_uppercase", function()
it("should detect uppercase first letter", function()
assert.is_true(Utils.is_first_letter_uppercase("Test"))
assert.is_true(Utils.is_first_letter_uppercase("ABC"))
end)
it("should detect lowercase first letter", function()
assert.is_false(Utils.is_first_letter_uppercase("test"))
assert.is_false(Utils.is_first_letter_uppercase("abc"))
end)
end)
describe("extract_mentions", function()
it("should extract @codebase mention", function()
local result = Utils.extract_mentions("test @codebase")
assert.equals("test ", result.new_content)
assert.is_true(result.enable_project_context)
assert.is_false(result.enable_diagnostics)
end)
it("should extract @diagnostics mention", function()
local result = Utils.extract_mentions("test @diagnostics")
assert.equals("test @diagnostics", result.new_content)
assert.is_false(result.enable_project_context)
assert.is_true(result.enable_diagnostics)
end)
it("should handle multiple mentions", function()
local result = Utils.extract_mentions("test @codebase @diagnostics")
assert.equals("test @diagnostics", result.new_content)
assert.is_true(result.enable_project_context)
assert.is_true(result.enable_diagnostics)
end)
end)
describe("get_mentions", function()
it("should return valid mentions", function()
local mentions = Utils.get_mentions()
assert.equals("codebase", mentions[1].command)
assert.equals("diagnostics", mentions[2].command)
end)
end)
end)