diff options
| author | ThePrimeagen <the.primeagen@gmail.com> | 2026-02-28 14:20:33 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-28 14:20:33 -0700 |
| commit | d485196b0a7956e9efb9f73eccfb126b95d113b3 (patch) | |
| tree | 17a463a60db88a2027950257f5ace294c01e936e /lua/99/test/files_spec.lua | |
| parent | d3e0a45d8ab67ab618a07dd40d7b15fa421ef0aa (diff) | |
| parent | 86a2e9c723945b3531f899deb2b69278457c4a2e (diff) | |
| download | a4-d485196b0a7956e9efb9f73eccfb126b95d113b3.tar.xz a4-d485196b0a7956e9efb9f73eccfb126b95d113b3.zip | |
Merge pull request #132 from codegirl-007/just-gitignore-me
Exclude files/paths in .gitingore during completion
Diffstat (limited to 'lua/99/test/files_spec.lua')
| -rw-r--r-- | lua/99/test/files_spec.lua | 323 |
1 files changed, 321 insertions, 2 deletions
diff --git a/lua/99/test/files_spec.lua b/lua/99/test/files_spec.lua index e033abe..53d9458 100644 --- a/lua/99/test/files_spec.lua +++ b/lua/99/test/files_spec.lua @@ -33,13 +33,11 @@ describe("files", function() paths[f.path] = f end - -- known fixture files must be present assert.is_not_nil(paths["scratch/refresh.lua"]) assert.is_not_nil(paths["scratch/test.ts"]) eq("refresh.lua", paths["scratch/refresh.lua"].name) eq("test.ts", paths["scratch/test.ts"].name) - -- .git must be excluded for path, _ in pairs(paths) do assert.is_nil( path:match("^%.git/"), @@ -199,3 +197,324 @@ describe("files", function() ) end) end) + +describe("files git integration", function() + -- Mock storage + local _mocks = { + system_output = "", + system_exit = 0, + stat_type = nil, + stat_exists = false, + orig_system = nil, + orig_stat = nil, + orig_shell_error = nil, + system_calls = {}, + } + + before_each(function() + _mocks.orig_system = vim.fn.system + _mocks.orig_stat = vim.uv.fs_stat + + _mocks.system_output = "" + _mocks.system_exit = 0 + _mocks.stat_type = nil + _mocks.stat_exists = false + _mocks.system_calls = {} + + vim.fn.system = function(cmd) + table.insert(_mocks.system_calls, cmd) + + pcall(function() + rawset(vim.v, "shell_error", _mocks.system_exit) + end) + return _mocks.system_output + end + + vim.uv.fs_stat = function(_path) + if _mocks.stat_exists then + return { type = _mocks.stat_type } + end + return nil + end + + Files.set_project_root("/test/repo") + end) + + after_each(function() + vim.fn.system = _mocks.orig_system + vim.uv.fs_stat = _mocks.orig_stat + + pcall(function() + rawset(vim.v, "shell_error", 0) + end) + Files.set_project_root("") + end) + + it( + "detects git repo with .git directory and uses git-based discovery", + function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + _mocks.system_output = "README.md\n" + _mocks.system_exit = 0 + + local files = Files.discover_files() + + assert.is_true( + #_mocks.system_calls > 0, + "git command should have been called" + ) + local git_called = false + for _, cmd in ipairs(_mocks.system_calls) do + if cmd:match("git.*ls%-files") then + git_called = true + break + end + end + assert.is_true(git_called, "git ls-files should have been executed") + + assert.is_true(#files > 0, "should return files from git") + eq("README.md", files[1].path) + end + ) + + it( + "detects git repo with .git file (worktree) and uses git-based discovery", + function() + _mocks.stat_exists = true + _mocks.stat_type = "file" + _mocks.system_output = "src/main.lua\ntest/file.lua\n" + _mocks.system_exit = 0 + + local files = Files.discover_files() + + assert.is_true( + #_mocks.system_calls > 0, + "git command should have been called for worktree" + ) + local git_called = false + for _, cmd in ipairs(_mocks.system_calls) do + if cmd:match("git.*ls%-files") then + git_called = true + break + end + end + assert.is_true(git_called, "should use git for worktree .git file") + + assert.are.equal(2, #files) + eq("src/main.lua", files[1].path) + eq("test/file.lua", files[2].path) + end + ) + + it("returns files when git command succeeds", function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + _mocks.system_output = "README.md\nsrc/init.lua\nsrc/utils.lua\n" + _mocks.system_exit = 0 + + local files = Files.discover_files() + + assert.are.equal(3, #files) + eq("README.md", files[1].path) + eq("src/init.lua", files[2].path) + eq("src/utils.lua", files[3].path) + + for _, f in ipairs(files) do + assert.is_not_nil(f.path, "file should have path") + assert.is_not_nil(f.name, "file should have name") + assert.is_not_nil(f.absolute_path, "file should have absolute_path") + end + end) + + it("returns empty table (not nil) for empty repo", function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + _mocks.system_output = "" + _mocks.system_exit = 0 + + local files = Files.discover_files() + + assert.is_not_nil(files, "should return table, not nil") + assert.are.equal(0, #files, "should return empty table for empty repo") + + for _, cmd in ipairs(_mocks.system_calls) do + assert.is_true( + cmd:match("git") ~= nil, + "should only call git, not fs commands" + ) + end + end) + + it("returns nil on git command failure", function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + _mocks.system_output = "fatal: not a git repository" + _mocks.system_exit = 128 -- Git failure + + local orig_scandir = vim.uv.fs_scandir + vim.uv.fs_scandir = function(_dir) + return nil -- Empty directory + end + + local files = Files.discover_files() + + vim.uv.fs_scandir = orig_scandir + + local git_failed = false + for _, cmd in ipairs(_mocks.system_calls) do + if cmd:match("git") and vim.v.shell_error ~= 0 then + git_failed = true + break + end + end + assert.is_true(git_failed, "git should have been called and failed") + end) + + it("applies manual excludes on top of git output", function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + _mocks.system_output = + "README.md\n.env\n.env.local\nnode_modules/package.json\nsrc/main.lua\n" + _mocks.system_exit = 0 + + Files.setup({ + enabled = true, + exclude = { ".env", ".env.*", "node_modules" }, + }, {}) + + local files = Files.discover_files() + + assert.are.equal(2, #files) + eq("README.md", files[1].path) + eq("src/main.lua", files[2].path) + + for _, f in ipairs(files) do + assert.is_nil(f.path:match("%.env"), ".env files should be excluded") + assert.is_nil( + f.path:match("node_modules"), + "node_modules should be excluded" + ) + end + end) + + it( + "excludes files by filename (not just path) consistent with fs scanner", + function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + _mocks.system_output = "README.md\nsrc/builder.js\nsrc/build/config.lua\n" + _mocks.system_exit = 0 + + Files.setup({ + enabled = true, + exclude = { "build" }, + }, {}) + + local files = Files.discover_files() + + assert.are.equal(1, #files) + eq("README.md", files[1].path) + + for _, f in ipairs(files) do + assert.is_nil( + f.name:match("^build"), + "files starting with 'build' should be excluded" + ) + end + end + ) + + it("uses --deduplicate flag to handle merge conflict duplicates", function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + + _mocks.system_output = "README.md\nREADME.md\nREADME.md\n" + _mocks.system_exit = 0 + + local files = Files.discover_files() + + local has_deduplicate = false + for _, cmd in ipairs(_mocks.system_calls) do + if cmd:match("%-%-deduplicate") then + has_deduplicate = true + break + end + end + assert.is_true( + has_deduplicate, + "git command should include --deduplicate flag" + ) + end) + + it("uses git-based discovery in git repo", function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + _mocks.system_output = "tracked.txt\n" + _mocks.system_exit = 0 + + Files.discover_files() + + local git_called = false + for _, cmd in ipairs(_mocks.system_calls) do + if cmd:match("git") then + git_called = true + break + end + end + assert.is_true(git_called, "should use git ls-files in git repo") + end) + + it("falls back to filesystem when not in git repo", function() + _mocks.stat_exists = false + local orig_scandir = vim.uv.fs_scandir + local fs_called = false + vim.uv.fs_scandir = function(_dir) + fs_called = true + return nil -- Empty + end + + Files.discover_files() + + vim.uv.fs_scandir = orig_scandir + + for _, cmd in ipairs(_mocks.system_calls) do + assert.is_nil( + cmd:match("git"), + "git should not be called in non-git repo" + ) + end + + assert.is_true(fs_called, "filesystem fallback should be used") + end) + + it("returns cached files on subsequent calls", function() + _mocks.stat_exists = true + _mocks.stat_type = "directory" + _mocks.system_output = "file.txt\n" + _mocks.system_exit = 0 + + local first = Files.get_files() + local first_call_count = #_mocks.system_calls + + local second = Files.get_files() + local second_call_count = #_mocks.system_calls + + eq(first, second) + + assert.are.equal( + first_call_count, + second_call_count, + "should not re-scan, use cache" + ) + end) + + it("handles empty root gracefully", function() + Files.set_project_root("") + + local files = Files.discover_files() + + assert.is_not_nil(files, "should return table") + assert.are.equal(0, #files, "should return empty for empty root") + end) +end) |
