repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
neovim/tests/bugabinga/cmdline/popupmenu_spec.lua
Rawdescribe('popupmenu.on_show', function()
before_each(function()
package.loaded['bugabinga.cmdline.popupmenu'] = nil
end)
after_each(function()
local ok, popupmenu = pcall(require, 'bugabinga.cmdline.popupmenu')
if ok then
popupmenu.on_hide()
end
end)
it('handles empty items', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
local ok = pcall(function()
popupmenu.on_show({}, -1, 0, 0, -1)
end)
assert.is_true(ok)
end)
it('creates window with items', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
local initial_win_count = #vim.api.nvim_list_wins()
popupmenu.on_show({{'foo', 'Variable', ''}, {'bar', 'Function', ''}}, 0, 0, 0, -1)
local wins = vim.api.nvim_list_wins()
assert.equal(initial_win_count + 1, #wins, 'should create a new window')
local new_win = wins[#wins]
local config = vim.api.nvim_win_get_config(new_win)
assert(type(config) == 'table', 'window config should be a table')
local buf = vim.api.nvim_win_get_buf(new_win)
local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false)
assert(#lines > 0, 'buffer should have lines')
end)
it('hides safely when no window exists', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
local ok = pcall(function()
popupmenu.on_hide()
popupmenu.on_hide()
end)
assert.is_true(ok)
end)
end)
describe('popupmenu.on_select', function()
before_each(function()
package.loaded['bugabinga.cmdline.popupmenu'] = nil
end)
after_each(function()
local ok, popupmenu = pcall(require, 'bugabinga.cmdline.popupmenu')
if ok then
popupmenu.on_hide()
end
end)
it('does not error without window', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
local ok = pcall(function()
popupmenu.on_select(0)
end)
assert.is_true(ok)
end)
end)
describe('popupmenu buffer cleanup', function()
before_each(function()
package.loaded['bugabinga.cmdline.popupmenu'] = nil
end)
after_each(function()
local ok, popupmenu = pcall(require, 'bugabinga.cmdline.popupmenu')
if ok then
popupmenu.on_hide()
end
end)
it('deletes buffer after on_hide', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
local initial_buf_count = #vim.api.nvim_list_bufs()
popupmenu.on_show({{'foo', 'Variable', ''}}, 0, 0, 0, -1)
local buf_count_after_show = #vim.api.nvim_list_bufs()
assert(buf_count_after_show > initial_buf_count, 'should create a new buffer')
local wins_before_hide = #vim.api.nvim_list_wins()
popupmenu.on_hide()
local wins_after_hide = #vim.api.nvim_list_wins()
assert(wins_after_hide < wins_before_hide, 'window should be hidden')
assert(buf_count_after_show > #vim.api.nvim_list_bufs(), 'buffer should be deleted')
local ok = pcall(popupmenu.on_hide)
assert(ok, 'on_hide should be idempotent')
end)
end)
describe('popupmenu highlights', function()
before_each(function()
package.loaded['bugabinga.cmdline.popupmenu'] = nil
package.loaded['bugabinga.cmdline.render'] = nil
package.loaded['bugabinga.cmdline.position'] = nil
end)
after_each(function()
local ok, popupmenu = pcall(require, 'bugabinga.cmdline.popupmenu')
if ok then
popupmenu.on_hide()
end
end)
local function find_buf()
local wins = vim.api.nvim_list_wins()
for _, win in ipairs(wins) do
local config = vim.api.nvim_win_get_config(win)
if config.zindex and config.zindex == 201 then
return vim.api.nvim_win_get_buf(win)
end
end
return nil
end
local function get_extmarks(buf)
local ns = vim.api.nvim_create_namespace 'bugabinga.cmdline.popupmenu'
return vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, { details = true })
end
it('applies PmenuMatch extmark when prefix matches abbr', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
popupmenu.on_show({{'foobar', '', ''}}, 0, 0, 0, -1, 'foo')
local buf = find_buf()
assert(buf ~= nil, 'popupmenu buffer should exist')
local extmarks = get_extmarks(buf)
local match_marks = vim.iter(extmarks):filter(function(m)
return m[4].hl_group == 'PmenuMatch'
end):totable()
assert.equal(1, #match_marks, 'should have one PmenuMatch extmark')
assert.equal(0, match_marks[1][3], 'PmenuMatch should start at col 0')
assert.equal(3, match_marks[1][4].end_col, 'PmenuMatch should span 3 bytes (foo)')
end)
it('applies PmenuKind extmark over kind icon', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
popupmenu.on_show({{'bar', 'Function', ''}}, 0, 0, 0, -1, '')
local buf = find_buf()
assert.is_not_nil(buf)
local extmarks = get_extmarks(buf)
local kind_marks = vim.iter(extmarks):filter(function(m)
return m[4].hl_group == 'PmenuKind'
end):totable()
assert.equal(1, #kind_marks, 'should have one PmenuKind extmark')
assert.equal(0, kind_marks[1][3], 'PmenuKind should start at col 0')
assert(kind_marks[1][4].end_col > 1, 'PmenuKind should span icon + space')
end)
it('applies no extmarks when prefix empty and no kind', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
popupmenu.on_show({{'baz', '', ''}}, 0, 0, 0, -1, '')
local buf = find_buf()
assert.is_not_nil(buf)
local extmarks = get_extmarks(buf)
assert.equal(0, #extmarks, 'should have no extmarks')
end)
it('applies both PmenuMatch and PmenuKind when both apply', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
local icon = require 'std.icon'
popupmenu.on_show({{'foobar', 'Variable', ''}}, 0, 0, 0, -1, 'foo')
local buf = find_buf()
assert.is_not_nil(buf)
local extmarks = get_extmarks(buf)
local hl_groups = vim.iter(extmarks):map(function(m)
return m[4].hl_group
end):totable()
assert(vim.list_contains(hl_groups, 'PmenuMatch'), 'should have PmenuMatch')
assert(vim.list_contains(hl_groups, 'PmenuKind'), 'should have PmenuKind')
end)
it('applies no PmenuMatch when prefix does not match abbr', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
popupmenu.on_show({{'bar', '', ''}}, 0, 0, 0, -1, 'foo')
local buf = find_buf()
assert.is_not_nil(buf)
local extmarks = get_extmarks(buf)
local match_marks = vim.iter(extmarks):filter(function(m)
return m[4].hl_group == 'PmenuMatch'
end):totable()
assert.equal(0, #match_marks, 'should have no PmenuMatch when prefix does not match')
end)
it('offsets PmenuMatch by kind icon when kind present', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
popupmenu.on_show({{'foobar', 'Function', ''}}, 0, 0, 0, -1, 'foo')
local buf = find_buf()
assert.is_not_nil(buf)
local extmarks = get_extmarks(buf)
local match_marks = vim.iter(extmarks):filter(function(m)
return m[4].hl_group == 'PmenuMatch'
end):totable()
assert.equal(1, #match_marks)
local kind_marks = vim.iter(extmarks):filter(function(m)
return m[4].hl_group == 'PmenuKind'
end):totable()
assert.equal(1, #kind_marks, 'should have a PmenuKind extmark')
assert.equal(kind_marks[1][4].end_col, match_marks[1][3], 'PmenuMatch should start where PmenuKind ended')
assert.equal(match_marks[1][3] + 3, match_marks[1][4].end_col, 'PmenuMatch should span 3 bytes')
end)
it('highlights multiple items each with their own match extmark', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
popupmenu.on_show({{'foo', '', ''}, {'fbar', '', ''}}, 0, 0, 0, -1, 'f')
local buf = find_buf()
assert.is_not_nil(buf)
local extmarks = get_extmarks(buf)
local match_marks = vim.iter(extmarks):filter(function(m)
return m[4].hl_group == 'PmenuMatch'
end):totable()
assert.equal(2, #match_marks, 'each item should have its own PmenuMatch extmark')
end)
it('does not error when prefix is nil', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
local ok = pcall(function()
popupmenu.on_show({{'foo', '', ''}}, 0, 0, 0, -1)
end)
assert(ok, 'should not error with nil prefix')
local buf = find_buf()
assert.is_not_nil(buf)
local extmarks = get_extmarks(buf)
local match_marks = vim.iter(extmarks):filter(function(m)
return m[4].hl_group == 'PmenuMatch'
end):totable()
assert.equal(0, #match_marks, 'should have no PmenuMatch with nil/empty prefix')
end)
end)
describe('popupmenu scrollbar', function()
before_each(function()
package.loaded['bugabinga.cmdline.popupmenu'] = nil
package.loaded['bugabinga.cmdline.render'] = nil
package.loaded['bugabinga.cmdline.position'] = nil
end)
after_each(function()
local ok, popupmenu = pcall(require, 'bugabinga.cmdline.popupmenu')
if ok then
popupmenu.on_hide()
end
end)
local function find_buf()
local wins = vim.api.nvim_list_wins()
for _, win in ipairs(wins) do
local config = vim.api.nvim_win_get_config(win)
if config.zindex and config.zindex == 201 then
return vim.api.nvim_win_get_buf(win)
end
end
return nil
end
local function get_scroll_extmarks(buf)
if not buf or not vim.api.nvim_buf_is_valid(buf) then
return {}
end
local ns = vim.api.nvim_create_namespace 'bugabinga.cmdline.popupmenu'
local marks = vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, { details = true })
return vim.iter(marks):filter(function(m)
local vt = m[4].virt_text
return vt and (#vt > 0)
end):totable()
end
it('no scrollbar when items fit in viewport', function()
local popupmenu = require 'bugabinga.cmdline.popupmenu'
popupmenu.on_show({{'a','',''}, {'b','',''}, {'c','',''}}, 0, 0, 0, -1, '')
local buf = find_buf()
assert(buf ~= nil, 'popupmenu should exist')
local scroll_marks = get_scroll_extmarks(buf)
assert.equal(0, #scroll_marks, 'no scrollbar when items fit (pumheight unlimited = all visible)')
end)
end)