Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/bugabinga/d2_spec.lua

Raw
require 'bugabinga.d2'

local D2_STUB_OUTPUT = [[
+-------+
| hello |
+-------+

]]

local mock_d2_system = function(output, code)
  local original_system = vim.system
  rawset(vim, 'system', function(cmd, opts)
    local handle = {
      wait = function()
        return { code = code or 0, stdout = output or '', stderr = '' }
      end,
    }
    return handle
  end)
  return function()
    rawset(vim, 'system', original_system)
  end
end

local create_d2_buffer = function(name, lines)
  vim.cmd(('edit! %s'):format(name))
  local bufnr = vim.api.nvim_get_current_buf()
  if lines then
    vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
  end
  return bufnr
end

local cleanup_preview = function()
  local pbnr = vim.fn.bufnr('D2_ASCII_PREVIEW')
  if pbnr ~= -1 and vim.api.nvim_buf_is_valid(pbnr) then
    pcall(vim.api.nvim_buf_delete, pbnr, { force = true })
  end
end

local cleanup_d2_state = function()
  cleanup_preview()
  pcall(vim.api.nvim_del_augroup, 'd2_preview_autosave')
  pcall(vim.api.nvim_del_augroup, 'd2_validate_autosave')
  pcall(vim.api.nvim_del_augroup, 'd2_preview_keymaps')
  pcall(vim.api.nvim_del_user_command, 'D2Preview')
  pcall(vim.api.nvim_del_user_command, 'D2PreviewToggle')
  pcall(vim.api.nvim_del_user_command, 'D2Validate')
  pcall(vim.api.nvim_del_user_command, 'D2ValidateToggle')
end

describe('bugabinga.d2', function()
  before_each(function()
    package.loaded['bugabinga.d2'] = nil
    for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
      if vim.api.nvim_buf_is_valid(bufnr) and vim.bo[bufnr].filetype ~= 'qf' then
        pcall(vim.api.nvim_buf_delete, bufnr, { force = true })
      end
    end
    cleanup_d2_state()
  end)

  after_each(function()
    cleanup_d2_state()
  end)

  describe('module API', function()
    it('should export preview_toggle', function()
      assert.is_function(BugabingaD2.preview_toggle)
    end)

    it('should export preview_update', function()
      assert.is_function(BugabingaD2.preview_update)
    end)

    it('should export preview_copy', function()
      assert.is_function(BugabingaD2.preview_copy)
    end)

    it('should export validate', function()
      assert.is_function(BugabingaD2.validate)
    end)

    it('should export validate_toggle', function()
      assert.is_function(BugabingaD2.validate_toggle)
    end)
  end)

  describe('user commands', function()
    it('should register D2Preview command', function()
      require 'bugabinga.d2'
      local ok = pcall(function() vim.cmd 'command D2Preview' end)
      assert(ok, 'D2Preview command should exist')
    end)

    it('should register D2PreviewToggle command', function()
      require 'bugabinga.d2'
      local ok = pcall(function() vim.cmd 'command D2PreviewToggle' end)
      assert(ok, 'D2PreviewToggle command should exist')
    end)

    it('should register D2Validate command without error', function()
      require 'bugabinga.d2'
      local ok, err = pcall(function() vim.cmd 'D2Validate' end)
      assert(ok, 'D2Validate should not error: ' .. tostring(err))
    end)

    it('should register D2ValidateToggle command without error', function()
      require 'bugabinga.d2'
      local ok, err = pcall(function() vim.cmd 'D2ValidateToggle' end)
      assert(ok, 'D2ValidateToggle should not error: ' .. tostring(err))
    end)
  end)

  describe('validate', function()
    it('should handle validate on unnamed buffer gracefully', function()
      local restore = mock_d2_system('', 0)
      require 'bugabinga.d2'
      vim.cmd 'enew'
      vim.bo.filetype = 'd2'
      local ok, err = pcall(BugabingaD2.validate)
      restore()
      assert(ok, 'validate should not crash on unnamed buffer: ' .. tostring(err))
    end)

    it('should clear previous diagnostics on re-validate', function()
      require 'bugabinga.d2'
      local bufnr = create_d2_buffer('clear_test.d2', { 'x -> y' })
      vim.diagnostic.reset(nil, bufnr)
      local diag_count = #vim.diagnostic.get(bufnr)
      assert.equal(0, diag_count)
    end)
  end)

  describe('validate_toggle', function()
    it('should toggle auto-validate without error', function()
      require 'bugabinga.d2'
      local ok, err = pcall(BugabingaD2.validate_toggle)
      assert(ok, 'validate_toggle should not error: ' .. tostring(err))
      ok, err = pcall(BugabingaD2.validate_toggle)
      assert(ok, 'validate_toggle should not error on second call: ' .. tostring(err))
    end)
  end)

  describe('autocmds', function()
    it('should create d2_preview_autosave autocmds', function()
      require 'bugabinga.d2'
      local autocmds = vim.api.nvim_get_autocmds { group = 'd2_preview_autosave' }
      assert(#autocmds > 0, 'd2_preview_autosave autocmds should exist')
    end)

    it('should create d2_validate_autosave autocmds', function()
      require 'bugabinga.d2'
      local autocmds = vim.api.nvim_get_autocmds { group = 'd2_validate_autosave' }
      assert(#autocmds > 0, 'd2_validate_autosave autocmds should exist')
    end)

    it('should scope preview keymaps to the event buffer', function()
      require 'bugabinga.d2'
      local preview_buf = vim.api.nvim_create_buf(false, true)
      local autocmd = vim.api.nvim_get_autocmds { group = 'd2_preview_keymaps' }[1]
      autocmd.callback { buf = preview_buf }

      local keymaps = vim.api.nvim_buf_get_keymap(preview_buf, 'n')
      assert.is_true(vim.iter(keymaps):any(function(keymap) return keymap.lhs == 'q' end))
    end)
  end)

  describe('parse_validate_output', function()
    it('should parse line:col error format', function()
      local stderr = 'err: /path/file.d2:27:11: unexpected text after map\n'
      local results = BugabingaD2._parse_validate_output(stderr)
      assert.is_table(results)
      assert.is_true(#results >= 1)
      assert.equal(26, results[1].lnum)
      assert.equal(10, results[1].col)
    end)

    it('should parse error with URL prefix', function()
      local stderr = 'err: oss.terrastruct.com/d2/d2cli.validateCmd: 27:9: unexpected text after map\n'
      local results = BugabingaD2._parse_validate_output(stderr)
      assert.is_table(results)
      assert.is_true(#results >= 1)
      assert.equal(26, results[1].lnum)
      assert.equal(8, results[1].col)
    end)

    it('should return empty table for no errors', function()
      local stderr = ''
      local results = BugabingaD2._parse_validate_output(stderr)
      assert.is_table(results)
      assert.equal(0, #results)
    end)
  end)
end)