From 4649b803ab4f71743219a33f3c95234dcefe889f Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Fri, 8 May 2026 00:31:57 +0200 Subject: [PATCH] test(git): cover resolve_sha, place_split reuse, content dispatch --- test/git/cmd_test.lua | 104 +++++++++++++++++++++++++++++++++++++++++ test/git/repo_test.lua | 27 +++++++++++ 2 files changed, 131 insertions(+) diff --git a/test/git/cmd_test.lua b/test/git/cmd_test.lua index 28efd6e..d968d28 100644 --- a/test/git/cmd_test.lua +++ b/test/git/cmd_test.lua @@ -234,3 +234,107 @@ t.test("complete unknown subcommand falls back to tracked paths", function() local matches = cmd.complete("", "G nonexistent ", 14) eq_sorted(matches, { "a", "b" }) end) + +---@param name_pattern string +---@return integer count +local function count_bufs_named(name_pattern) + local n = 0 + for _, b in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_get_name(b):match(name_pattern) then + n = n + 1 + end + end + return n +end + +---@param buf_name_pattern string +---@param timeout integer? +local function wait_buf_populated(buf_name_pattern, timeout) + vim.wait(timeout or 1000, function() + for _, b in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_get_name(b):match(buf_name_pattern) then + return #vim.api.nvim_buf_get_lines(b, 0, -1, false) > 1 + end + end + return false + end) +end + +t.test("run :G diff reuses the same buffer across invocations", function() + local dir = make_repo({ a = "v1\n" }) + t.write(dir, "a", "v2\n") + + cmd.run({ "diff" }) + wait_buf_populated("%[Git diff%]") + local first_count = count_bufs_named("%[Git diff%]") + t.eq(first_count, 1) + + t.write(dir, "a", "v3\n") + cmd.run({ "diff" }) + vim.wait(300) + t.eq(count_bufs_named("%[Git diff%]"), 1, "second :G diff should reuse") + + cmd.run({ "diff" }) + vim.wait(300) + t.eq(count_bufs_named("%[Git diff%]"), 1, "third :G diff should reuse") +end) + +---@param buf integer +---@param prefix string +---@return integer? lnum +local function find_line(buf, prefix) + for i, l in ipairs(vim.api.nvim_buf_get_lines(buf, 0, -1, false)) do + if l:sub(1, #prefix) == prefix then + return i + end + end +end + +t.test(":G show on + line opens the blob URI", function() + local dir = make_repo({ a = "first\n" }) + t.write(dir, "a", "second\n") + git(dir, "add", "a") + git(dir, "commit", "-q", "-m", "second") + local r = assert(require("git.repo").resolve(dir)) + local blob = vim.trim(git(dir, "rev-parse", "HEAD:a").stdout) + + cmd.run({ "show", "HEAD" }) + wait_buf_populated("%[Git show HEAD%]") + local diff_buf + for _, b in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_get_name(b):match("%[Git show HEAD%]") then + diff_buf = b + end + end + assert(diff_buf, "expected [Git show HEAD] buffer") + local win = vim.fn.bufwinid(diff_buf) + vim.api.nvim_set_current_win(win) + local lnum = assert(find_line(diff_buf, "+second")) + vim.api.nvim_win_set_cursor(win, { lnum, 0 }) + + t.truthy(require("git.object").open_under_cursor()) + t.eq(vim.api.nvim_buf_get_name(0), "git://" .. blob) +end) + +t.test(":G diff on + line falls back to worktree file", function() + local dir = make_repo({ a = "v1\n" }) + t.write(dir, "a", "v2\n") + local r = assert(require("git.repo").resolve(dir)) + + cmd.run({ "diff" }) + wait_buf_populated("%[Git diff%]") + local diff_buf + for _, b in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_get_name(b):match("%[Git diff%]") then + diff_buf = b + end + end + assert(diff_buf, "expected [Git diff] buffer") + local win = vim.fn.bufwinid(diff_buf) + vim.api.nvim_set_current_win(win) + local lnum = assert(find_line(diff_buf, "+v2")) + vim.api.nvim_win_set_cursor(win, { lnum, 0 }) + + t.truthy(require("git.object").open_under_cursor()) + t.eq(vim.api.nvim_buf_get_name(0), vim.fs.joinpath(dir, "a")) +end) diff --git a/test/git/repo_test.lua b/test/git/repo_test.lua index 0dfb35d..0479f28 100644 --- a/test/git/repo_test.lua +++ b/test/git/repo_test.lua @@ -111,6 +111,33 @@ t.test("cache clears after deeply nested slash branch", function() t.eq(refs, { "deep/a/b/c", "main" }) end) +t.test("resolve_sha returns ok + full sha for a known blob", function() + local dir = make_repo({ a = "hello\n" }) + local r = assert(require("git.repo").resolve(dir)) + local blob = vim.trim(git(dir, "rev-parse", "HEAD:a").stdout) + local short = blob:sub(1, 7) + local full, status = r:resolve_sha(short) + t.eq(status, "ok") + t.eq(full, blob) +end) + +t.test("resolve_sha returns missing for an unknown prefix", function() + local dir = make_repo({ a = "x" }) + local r = assert(require("git.repo").resolve(dir)) + local full, status = r:resolve_sha("0000deadbeef") + t.eq(full, nil) + t.eq(status, "missing") +end) + +t.test("resolve_sha caches by prefix", function() + local dir = make_repo({ a = "x" }) + local r = assert(require("git.repo").resolve(dir)) + local blob = vim.trim(git(dir, "rev-parse", "HEAD:a").stdout) + local short = blob:sub(1, 7) + local _, _ = r:resolve_sha(short) + t.truthy(r._cache["resolve:" .. short], "result should be cached") +end) + t.test("watcher cleans up after a slash-branch dir is removed", function() local dir = make_repo({ a = "x" }) local r = assert(require("git.repo").resolve(dir))