@ 261105.2
current
---@diagnostic disable: unused-local, unused-function, unused
local MiniTest = require("mini.test")
local helpers = require("fzf-lua.test.helpers")
local child = helpers.new_child_neovim()
local eq = helpers.expect.equality
local new_set = MiniTest.new_set
local exec_lua = child.lua
local sleep = function(ms) helpers.sleep(ms, child) end

local repo ---@type string?
local orig_cwd ---@type string?

local T = helpers.new_set_with_child(child, {
  hooks = {
    pre_case = function()
      orig_cwd = child.fn.getcwd()
      repo = exec_lua([[
        local dir = vim.fn.tempname()
        vim.fn.mkdir(dir, "p")
        -- Initialize repo and disable signing so commits work even when the
        -- environment has SSH signing configured and the key does not exist.
        vim.fn.system({ "git", "init", dir })
        vim.fn.system({ "git", "-C", dir, "config", "user.email", "test@fzf-lua" })
        vim.fn.system({ "git", "-C", dir, "config", "user.name", "fzf-lua test" })
        vim.fn.system({ "git", "-C", dir, "config", "commit.gpgsign", "false" })
        vim.fn.system({ "git", "-C", dir, "config", "gpg.format", "openpgp" })
        local file = dir .. "/tracked.txt"
        local fd = io.open(file, "w")
        fd:write("hello\n")
        fd:close()
        vim.fn.system({ "git", "-C", dir, "add", "tracked.txt" })
        vim.fn.system({ "git", "-C", dir, "commit", "--no-gpg-sign", "-m", "initial" })
        return dir
      ]])
      child.cmd("cd " .. vim.fn.fnameescape(assert(repo)))
    end,
    post_case = function()
      if repo then
        -- Return child to the original working directory before deleting repo.
        child.cmd("cd " .. vim.fn.fnameescape(assert(orig_cwd)))
        -- Only clear the reference if deletion succeeded.
        eq(0, vim.fn.delete(repo, "rf"))
        repo = nil
        orig_cwd = nil
      end
    end,
  },
})

T["git_status"] = new_set({ n_retry = not helpers.IS_LINUX() and 5 or nil })

local modify_tracked = function()
  -- Modify a tracked file so git_status shows an unstaged change.
  exec_lua([[
    local file = vim.fn.getcwd() .. "/tracked.txt"
    local fd = io.open(file, "a")
    fd:write("-- useless comment\n")
    fd:close()
  ]])
end

local porcelain = function()
  return exec_lua([[
    return vim.fn.system({ "git", "-C", vim.fn.getcwd(), "status", "--porcelain" })
      :gsub("%s+$", "")
  ]])
end

-- Trigger an action and wait for the picker reload (native fzf `reload` or
-- the "resume" fallback used by skim/old fzf which restarts the picker).
local action_and_wait = function(keys)
  exec_lua([[_G._fzf_load_called = nil]])
  child.type_keys(keys)
  sleep(100)
  if helpers.IS_WIN() then sleep(250) end
  child.wait_until(function() return exec_lua([[return _G._fzf_load_called]]) == true end)
end

T["git_status"]["stage unstage reset"] = function()
  modify_tracked()

  -- Auto-confirm the reset dialog so the headless test does not block.
  exec_lua([[FzfLua.utils.confirm = function() return 1 end]])

  helpers.FzfLua.git_status(child, {
    __no_abort = true,
    __expect_lines = true,
    __screen_opts = { ignore_text = { 28 } },
    previewer = false,
    headers = false,
    multiprocess = false,
    __after_open = function()
      -- Screenshot: unstaged modification (M on the right)
      sleep(100)
      if helpers.IS_WIN() then sleep(250) end
      child.expect_screen_lines({ ignore_text = { 28 } })

      -- Stage with left: M should move to the staged (left) column.
      action_and_wait("<Left>")
      child.expect_screen_lines({ ignore_text = { 28 } })

      -- Unstage with right: M should return to the unstaged (right) column.
      action_and_wait("<Right>")
      child.expect_screen_lines({ ignore_text = { 28 } })

      -- Reset with ctrl-x: file is restored and the picker reloads empty.
      action_and_wait("<c-x>")
    end,
  })

  -- Close the picker.
  child.type_keys("<c-c>")
  child.wait_until(function() return exec_lua([[return _G._fzf_lua_on_create]]) == vim.NIL end)

  -- Verify the working tree is clean after reset.
  eq("", porcelain())

  -- Commit the clean state, ignoring any SSH/GPG signing configuration.
  exec_lua([[
    vim.fn.system({
      "git", "-C", vim.fn.getcwd(), "commit", "--allow-empty", "--no-gpg-sign",
      "-m", "git_status test end",
    })
  ]])
end

-- Regression test for the "resume" fallback used by skim (skim supports
-- `reload` but not `rebind`, which leaves the action keys unbound after the
-- first reload). The fallback restarts the picker, so make sure multiple
-- actions can still be triggered in sequence.
T["git_status"]["stage unstage reset with reload fallback"] = function()
  modify_tracked()

  -- Auto-confirm the reset dialog so the headless test does not block.
  exec_lua([[FzfLua.utils.confirm = function() return 1 end]])

  helpers.FzfLua.git_status(child, {
    __no_abort = true,
    __expect_lines = false,
    -- force the skim/old-fzf restart mechanism, independent of the installed
    -- binary (tests must not rely on skim or an old fzf version)
    _reload_fallback = true,
    previewer = false,
    headers = false,
    multiprocess = false,
    __after_open = function()
      sleep(100)

      -- Multiple consecutive actions must all survive the picker restart.
      action_and_wait("<Left>")
      eq("M  tracked.txt", porcelain())

      action_and_wait("<Right>")
      eq(" M tracked.txt", porcelain())

      action_and_wait("<Left>")
      eq("M  tracked.txt", porcelain())

      -- Reset with ctrl-x: file is restored and the picker reloads empty.
      action_and_wait("<c-x>")
      eq("", porcelain())
    end,
  })

  -- Close the picker.
  child.type_keys("<c-c>")
  child.wait_until(function() return exec_lua([[return _G._fzf_lua_on_create]]) == vim.NIL end)

  -- Verify the working tree is clean after reset.
  eq("", porcelain())

  -- Commit the clean state, ignoring any SSH/GPG signing configuration.
  exec_lua([[
    vim.fn.system({
      "git", "-C", vim.fn.getcwd(), "commit", "--allow-empty", "--no-gpg-sign",
      "-m", "git_status test end",
    })
  ]])
end

return T