Files
nvim/test/git/status_view_test.lua
T

228 lines
7.0 KiB
Lua

local h = require("test.git.helpers")
local t = require("test")
require("git").init()
---Replicate the user's global cursor-restore autocmd. Scoped to a
---named augroup + cleanup so it doesn't leak between tests.
local function install_cursor_restore_autocmd()
local group =
vim.api.nvim_create_augroup("test.cursor_restore", { clear = true })
vim.api.nvim_create_autocmd("BufReadPost", {
group = group,
pattern = "*",
command = 'silent! normal! g`"zv',
})
t.defer(function()
pcall(vim.api.nvim_del_augroup_by_name, "test.cursor_restore")
end)
end
---@param sidebar_buf integer
---@param needle string
---@return integer?
local function find_line(sidebar_buf, needle)
for i, l in ipairs(vim.api.nvim_buf_get_lines(sidebar_buf, 0, -1, false)) do
if l:match(needle) then
return i
end
end
end
---Find the gitstatus sidebar window in the current tabpage.
---@return integer? sidebar_buf
---@return integer? sidebar_win
local function find_sidebar()
for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
local b = vim.api.nvim_win_get_buf(w)
if vim.bo[b].filetype == "gitstatus" then
return b, w
end
end
end
---Find a diff-role window in the given tabpage (or current).
---@param role "left"|"right"
---@param tab integer?
---@return integer?
local function find_diff_win(role, tab)
for _, w in ipairs(vim.api.nvim_tabpage_list_wins(tab or 0)) do
if vim.w[w].git_diff_role == role then
return w
end
end
end
---@param file_path string
---@param committed_content string
---@param worktree_content string
---@return integer sidebar_win
---@return integer entry_line
local function setup_sidebar_with_unstaged_file(
file_path,
committed_content,
worktree_content
)
local repo = h.make_repo({ [file_path] = committed_content })
t.write(repo, file_path, worktree_content)
vim.cmd("cd " .. repo)
require("git.status_view").open({ placement = "sidebar" })
local sidebar_buf, sidebar_win = find_sidebar()
assert(sidebar_buf, "sidebar buffer should exist")
assert(sidebar_win, "sidebar window should exist")
local r = assert(
require("git.repo").find(vim.fn.getcwd()),
"repo should resolve for the test worktree"
)
r:refresh()
t.wait_for(function()
return r.status and #r.status:rows("unstaged") > 0
end, "git status to report unstaged changes")
local entry_line = assert(
find_line(sidebar_buf, vim.pesc(file_path) .. "$"),
file_path .. " should appear in sidebar"
)
return sidebar_win, entry_line
end
t.test("stage with diff open: sidebar cursor stays put", function()
install_cursor_restore_autocmd()
local sidebar_win, line = setup_sidebar_with_unstaged_file(
"zsh/rc",
"ZSH=true\n",
"ZSH=true\nmodified\n"
)
vim.api.nvim_set_current_win(sidebar_win)
vim.api.nvim_win_set_cursor(sidebar_win, { line, 0 })
t.press("<Tab>")
t.wait_for(function()
return find_diff_win("left") ~= nil
end, "diff windows to appear")
local r = assert(require("git.repo").find(vim.fn.getcwd()))
vim.api.nvim_set_current_win(sidebar_win)
t.press("s")
t.wait_for(function()
return #r.status:rows("staged") > 0
end, "stage to propagate to repo state")
t.eq(
vim.api.nvim_win_get_cursor(sidebar_win),
{ line, 0 },
"sidebar cursor should remain at the entry's original line"
)
end)
t.test(
"stage with diff open: diff foldmethod is preserved on refresh",
function()
local sidebar_win, line = setup_sidebar_with_unstaged_file(
"zsh/rc",
"# vim: set ft=zsh nowrap:\nZSH=true\n",
"# vim: set ft=zsh nowrap:\nZSH=true\nmodified\n"
)
vim.api.nvim_set_current_win(sidebar_win)
vim.api.nvim_win_set_cursor(sidebar_win, { line, 0 })
t.press("<Tab>")
t.wait_for(function()
return find_diff_win("left") ~= nil
end, "diff windows to appear")
local left_win = assert(find_diff_win("left"))
t.eq(
vim.wo[left_win].foldmethod,
"diff",
"left diff foldmethod should be 'diff' after Tab"
)
local r = assert(require("git.repo").find(vim.fn.getcwd()))
vim.api.nvim_set_current_win(sidebar_win)
t.press("s")
t.wait_for(function()
return #r.status:rows("staged") > 0
end, "stage to propagate to repo state")
t.eq(
vim.wo[left_win].foldmethod,
"diff",
"left diff foldmethod should still be 'diff' after stage refresh"
)
end
)
t.test(
"<Tab> in a second tabpage opens the diff inside that tabpage",
function()
local sidebar_win, line =
setup_sidebar_with_unstaged_file("foo.txt", "v1\n", "v2\n")
local tab1 = vim.api.nvim_get_current_tabpage()
-- First show diff in tab1, so state.diff_*_win point at tab1.
vim.api.nvim_set_current_win(sidebar_win)
vim.api.nvim_win_set_cursor(sidebar_win, { line, 0 })
t.press("<Tab>")
t.wait_for(function()
return find_diff_win("left", tab1) ~= nil
end, "diff windows in tab1 to appear")
vim.cmd("tabnew")
require("git.status_view").open({ placement = "sidebar" })
local tab2 = vim.api.nvim_get_current_tabpage()
t.truthy(tab2 ~= tab1, "tabnew should produce a distinct tabpage")
local _, sidebar_win2 = find_sidebar()
assert(sidebar_win2, "sidebar window should exist in tab2")
vim.api.nvim_set_current_win(sidebar_win2)
vim.api.nvim_win_set_cursor(sidebar_win2, { line, 0 })
t.press("<Tab>")
t.wait_for(function()
return find_diff_win("left", tab2) ~= nil
end, "diff windows in tab2 to appear")
t.truthy(
find_diff_win("right", tab2),
"right diff window should be in tab2"
)
end
)
t.test("refresh on stage updates the index URI buffer's content", function()
local sidebar_win, line =
setup_sidebar_with_unstaged_file("foo.txt", "v1\n", "v2\n")
vim.api.nvim_set_current_win(sidebar_win)
vim.api.nvim_win_set_cursor(sidebar_win, { line, 0 })
t.press("<Tab>")
t.wait_for(function()
return find_diff_win("left") ~= nil
end, "diff windows to appear")
local left_win = assert(find_diff_win("left"))
local index_buf = vim.api.nvim_win_get_buf(left_win)
t.eq(
vim.api.nvim_buf_get_lines(index_buf, 0, -1, false),
{ "v1" },
"index pane should initially show committed content"
)
vim.api.nvim_set_current_win(sidebar_win)
t.press("s")
t.wait_for(function()
local first = vim.api.nvim_buf_get_lines(index_buf, 0, -1, false)[1]
return first == "v2"
end, "index pane to refresh to staged content")
t.eq(
vim.api.nvim_buf_get_lines(index_buf, 0, -1, false),
{ "v2" },
"index pane should reflect staged content after refresh"
)
end)