Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/bugabinga/cmdline/render_spec.lua

Raw
describe('render.show', function()
  before_each(function()
    package.loaded['bugabinga.cmdline.state'] = nil
    package.loaded['bugabinga.cmdline.format'] = nil
    package.loaded['bugabinga.cmdline.position'] = nil
    package.loaded['bugabinga.cmdline.cursor'] = nil
    package.loaded['bugabinga.cmdline.render'] = nil
  end)

  after_each(function()
    local ok, render = pcall(require, 'bugabinga.cmdline.render')
    if ok then
      render.hide()
    end
    local ok2, pos = pcall(require, 'bugabinga.cmdline.position')
    if ok2 then
      pos.set_cmdline_anchor(nil)
    end
  end)

  it('creates a floating window', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, ':hello' },
    }, 1, ':', '', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    assert.is_not_nil(anchor)
    assert.is_not_nil(anchor.win)
    render.hide()
  end)

  it('sets buffer text without icon prefix (icon via extmark)', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, ':test' },
    }, 1, ':', '', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local buf = anchor.buf
    local lines = vim.api.nvim_buf_get_lines(buf, 0, 1, false)
    assert.is_true(#lines > 0)
    assert.is_true(lines[1]:find('󰘳') == nil)
    assert.is_true(lines[1]:find(':test') ~= nil)
    local ns = vim.api.nvim_create_namespace 'bugabinga.cmdline'
    local extmarks = vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, { details = true })
    assert.is_true(#extmarks > 0)
    render.hide()
  end)

  it('has leading and trailing space for icon and cursor positioning', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, ':vim' },
    }, 4, ':', '', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local buf = anchor.buf
    local lines = vim.api.nvim_buf_get_lines(buf, 0, 1, false)
    assert.equal('  :vim ', lines[1])
    local cursor_byte = cmdline_state:cursor_byte()
    local expected_col = 1 + cursor_byte
    assert.equal(1 + 4, expected_col)
    assert.equal(7, #lines[1])
    render.hide()
  end)

  it('hides safely when no window exists', function()
    local render = require 'bugabinga.cmdline.render'
    local ok = pcall(function()
      render.hide()
      render.hide()
    end)
    assert.is_true(ok)
  end)

  it('updates winhighlight when format changes between show calls', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state1 = state.new({
      { {}, '' },
    }, 1, ':', '', 0, 1)
    render.show(cmdline_state1)
    local pos = require('bugabinga.cmdline.position')
    local anchor1 = assert(pos.get_cmdline_anchor())
    local win1 = anchor1.win
    local wh1 = vim.wo[win1].winhighlight
    local cmdline_state2 = state.new({
      { {}, 'h' },
    }, 2, ':', '', 0, 1)
    render.show(cmdline_state2)
    local anchor2 = assert(pos.get_cmdline_anchor())
    local win2 = anchor2.win
    local wh2 = vim.wo[win2].winhighlight
    assert(wh1 ~= wh2, 'winhighlight should differ between cmdline and help formats')
    render.hide()
  end)
end)

describe('render.hide', function()
  before_each(function()
    package.loaded['bugabinga.cmdline.state'] = nil
    package.loaded['bugabinga.cmdline.format'] = nil
    package.loaded['bugabinga.cmdline.position'] = nil
    package.loaded['bugabinga.cmdline.cursor'] = nil
    package.loaded['bugabinga.cmdline.render'] = nil
  end)

  after_each(function()
    local ok, render = pcall(require, 'bugabinga.cmdline.render')
    if ok then
      render.hide()
    end
    local ok2, pos = pcall(require, 'bugabinga.cmdline.position')
    if ok2 then
      pos.set_cmdline_anchor(nil)
    end
  end)

  it('clears anchor after hide', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, ':test' },
    }, 1, ':', '', 0, 1)
    render.show(cmdline_state)
    render.hide()
    local pos = require('bugabinga.cmdline.position')
    local anchor = pos.get_cmdline_anchor()
    assert.is_nil(anchor)
  end)
end)

describe('render corner highlights', function()
  before_each(function()
    package.loaded['bugabinga.cmdline.state'] = nil
    package.loaded['bugabinga.cmdline.format'] = nil
    package.loaded['bugabinga.cmdline.position'] = nil
    package.loaded['bugabinga.cmdline.cursor'] = nil
    package.loaded['bugabinga.cmdline.render'] = nil
  end)

  after_each(function()
    local ok, render = pcall(require, 'bugabinga.cmdline.render')
    if ok then
      render.hide()
    end
    local ok2, pos = pcall(require, 'bugabinga.cmdline.position')
    if ok2 then
      pos.set_cmdline_anchor(nil)
    end
  end)

  it('winhighlight contains different border and corner highlights', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, ':test' },
    }, 1, ':', '', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local wh = vim.wo[anchor.win].winhighlight
    local border_hl = wh:match 'FloatBorder:(%w+)'
    local corner_hl = wh:match 'FloatBorderCorner:(%w+)'
    assert(border_hl ~= nil, 'FloatBorder highlight not found in: ' .. wh)
    assert(corner_hl ~= nil, 'FloatBorderCorner highlight not found in: ' .. wh)
    assert(border_hl ~= corner_hl, 'border and corner should differ')
    render.hide()
  end)

  it('corner highlight is CmdlineBorderCornerCmdline for cmdline format', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, '' },
    }, 1, ':', '', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local wh = vim.wo[anchor.win].winhighlight
    local corner_hl = wh:match 'FloatBorderCorner:(%w+)'
    assert.equal('CmdlineBorderCornerCmdline', corner_hl)
    render.hide()
  end)

  it('corner highlight is CmdlineBorderCornerHelp for help format', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, 'h' },
    }, 2, ':', '', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local wh = vim.wo[anchor.win].winhighlight
    local corner_hl = wh:match 'FloatBorderCorner:(%w+)'
    assert.equal('CmdlineBorderCornerHelp', corner_hl)
    render.hide()
  end)

  it('corner highlight updates when format changes between show calls', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state1 = state.new({
      { {}, '' },
    }, 1, ':', '', 0, 1)
    render.show(cmdline_state1)
    local pos = require('bugabinga.cmdline.position')
    local anchor1 = assert(pos.get_cmdline_anchor())
    local wh1 = vim.wo[anchor1.win].winhighlight
    local corner1 = wh1:match 'FloatBorderCorner:(%w+)'
    local cmdline_state2 = state.new({
      { {}, 'h' },
    }, 2, ':', '', 0, 1)
    render.show(cmdline_state2)
    local anchor2 = assert(pos.get_cmdline_anchor())
    local wh2 = vim.wo[anchor2.win].winhighlight
    local corner2 = wh2:match 'FloatBorderCorner:(%w+)'
    assert(corner1 ~= corner2, 'corner should change: ' .. corner1 .. ' vs ' .. corner2)
    render.hide()
  end)
end)

describe('render.show with input prompt', function()
  before_each(function()
    package.loaded['bugabinga.cmdline.state'] = nil
    package.loaded['bugabinga.cmdline.format'] = nil
    package.loaded['bugabinga.cmdline.position'] = nil
    package.loaded['bugabinga.cmdline.cursor'] = nil
    package.loaded['bugabinga.cmdline.highlight'] = nil
    package.loaded['bugabinga.cmdline.render'] = nil
  end)

  after_each(function()
    local ok, render = pcall(require, 'bugabinga.cmdline.render')
    if ok then
      render.hide()
    end
    local ok2, pos = pcall(require, 'bugabinga.cmdline.position')
    if ok2 then
      pos.set_cmdline_anchor(nil)
    end
  end)

  it('input with short prompt does not put prompt in buffer text', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, 'my input' },
    }, 8, ':', 'Name: ', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local buf = anchor.buf
    local lines = vim.api.nvim_buf_get_lines(buf, 0, 1, false)
    assert(lines[1]:find('Name:') == nil, 'prompt should not appear in buffer: ' .. lines[1])
    assert(lines[1]:find('my input') ~= nil, 'user input should appear in buffer')
    render.hide()
  end)

  it('input with empty prompt uses normal rendering', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, ':hello' },
    }, 6, ':', '', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local buf = anchor.buf
    local lines = vim.api.nvim_buf_get_lines(buf, 0, 1, false)
    assert.is_true(lines[1]:find(':hello') ~= nil)
    render.hide()
  end)

  it('input format uses input icon (prompt_prefix)', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, '' },
    }, 0, ':', 'Prompt: ', 0, 1)
    render.show(cmdline_state)
    local fmt_type = render.get_format_type()
    assert.equal('input', fmt_type)
    render.hide()
  end)

  it('cursor column is offset by 2 for input', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, 'test' },
    }, 2, ':', 'Prompt: ', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local cursor = vim.api.nvim_win_get_cursor(anchor.win)
    assert.equal(2 + 2, cursor[2], 'cursor should be 2 + cursor_byte')
    render.hide()
  end)
end)

describe('render.show with input prompt - multi-line (virt_lines)', function()
  before_each(function()
    package.loaded['bugabinga.cmdline.state'] = nil
    package.loaded['bugabinga.cmdline.format'] = nil
    package.loaded['bugabinga.cmdline.position'] = nil
    package.loaded['bugabinga.cmdline.cursor'] = nil
    package.loaded['bugabinga.cmdline.highlight'] = nil
    package.loaded['bugabinga.cmdline.render'] = nil
  end)

  after_each(function()
    local ok, render = pcall(require, 'bugabinga.cmdline.render')
    if ok then
      render.hide()
    end
    local ok2, pos = pcall(require, 'bugabinga.cmdline.position')
    if ok2 then
      pos.set_cmdline_anchor(nil)
    end
  end)

  it('multi-line prompt sets virt_lines in buffer', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, 'input' },
    }, 5, ':', 'Line 1\nLine 2\nLine 3', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local buf = anchor.buf
    local prompt_ns = vim.api.nvim_create_namespace('bugabinga.cmdline.prompt')
    local extmarks = vim.api.nvim_buf_get_extmarks(buf, prompt_ns, 0, -1, { details = true })
    assert(#extmarks > 0, 'should have virt_lines extmark for multi-line prompt')
    local mark = assert(extmarks[1])
    local opts = assert(mark[4])
    assert(opts.virt_lines ~= nil, 'extmark should have virt_lines')
    assert(opts.virt_lines_above, 'virt_lines should be above')
    render.hide()
  end)

  it('multi-line prompt window height is prompt_chunks + 1', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, 'x' },
    }, 1, ':', 'Line 1\nLine 2', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local height = vim.api.nvim_win_get_config(anchor.win).height
    assert.equal(2 + 1, height, 'height should be 2 (prompt lines) + 1 (input line)')
    render.hide()
  end)

  it('multi-line prompt splits on newlines', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, 'x' },
    }, 1, ':', 'first line\nsecond line', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local buf = anchor.buf
    local prompt_ns = vim.api.nvim_create_namespace('bugabinga.cmdline.prompt')
    local extmarks = vim.api.nvim_buf_get_extmarks(buf, prompt_ns, 0, -1, { details = true })
    local mark = assert(extmarks[1])
    local opts = assert(mark[4])
    local virt_lines = assert(opts.virt_lines)
    assert.equal(2, #virt_lines, 'should have 2 virt_lines for 2 prompt lines')
    render.hide()
  end)

  it('double newline creates blank virt_line', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, 'x' },
    }, 1, ':', 'a\n\nb', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local buf = anchor.buf
    local prompt_ns = vim.api.nvim_create_namespace('bugabinga.cmdline.prompt')
    local extmarks = vim.api.nvim_buf_get_extmarks(buf, prompt_ns, 0, -1, { details = true })
    local mark = assert(extmarks[1])
    local opts = assert(mark[4])
    local virt_lines = assert(opts.virt_lines)
    assert.equal(3, #virt_lines, 'should have 3 virt_lines: a, blank, b')
    render.hide()
  end)
end)

describe('render.hide clears prompt state', function()
  before_each(function()
    package.loaded['bugabinga.cmdline.state'] = nil
    package.loaded['bugabinga.cmdline.format'] = nil
    package.loaded['bugabinga.cmdline.position'] = nil
    package.loaded['bugabinga.cmdline.cursor'] = nil
    package.loaded['bugabinga.cmdline.highlight'] = nil
    package.loaded['bugabinga.cmdline.render'] = nil
  end)

  after_each(function()
    local ok, render = pcall(require, 'bugabinga.cmdline.render')
    if ok then
      render.hide()
    end
    local ok2, pos = pcall(require, 'bugabinga.cmdline.position')
    if ok2 then
      pos.set_cmdline_anchor(nil)
    end
  end)

  it('hide after input clears prompt namespace', function()
    local state = require 'bugabinga.cmdline.state'
    local render = require 'bugabinga.cmdline.render'
    local cmdline_state = state.new({
      { {}, 'x' },
    }, 1, ':', 'Line 1\nLine 2', 0, 1)
    render.show(cmdline_state)
    local pos = require('bugabinga.cmdline.position')
    local anchor = assert(pos.get_cmdline_anchor())
    local buf = anchor.buf
    render.hide()
    local prompt_ns = vim.api.nvim_create_namespace('bugabinga.cmdline.prompt')
    local extmarks = vim.api.nvim_buf_get_extmarks(buf, prompt_ns, 0, -1, {})
    assert.equal(0, #extmarks, 'prompt namespace should be empty after hide')
  end)
end)