Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/bugabinga/pivi/command_spec.lua

Raw
---@diagnostic disable: duplicate-set-field, need-check-nil, param-type-mismatch, assign-type-mismatch
local command = require 'bugabinga.pivi.command'
local session = require 'bugabinga.pivi.session'
local transcript = require 'bugabinga.pivi.transcript'
local publish = require 'bugabinga.pivi.publish'
local fake = dofile 'tests/helpers/pivi_fake.lua'

local notices

describe( 'pivi command', function()
  local original_notify, original_select

  before_each( function()
    notices = {}
    original_notify = vim.notify
    original_select = vim.ui.select
    vim.notify = function( message, level ) table.insert( notices, { message, level, } ) end
  end )

  after_each( function()
    fake.drain()
    vim.notify = original_notify
    vim.ui.select = original_select
    session.stop_all()
    transcript.forget_all()
    publish.reset()
    fake.close_extra_windows()
    vim.cmd 'silent! %bwipeout!'
    pcall( vim.api.nvim_del_user_command, 'Pi' )
  end )

  describe( 'slash entry', function()
    it( 'opens only at the first character of a pivi input buffer', function()
      local bufnr = vim.api.nvim_create_buf( false, true )
      vim.bo[bufnr].filetype = command.input_filetype

      assert.is_true( command.slash_opens_commands( bufnr, 0 ) )
      assert.is_false( command.slash_opens_commands( bufnr, 1 ) )
      assert.is_false( command.slash_opens_commands( bufnr, 7 ) )
    end )

    it( 'gives the prompt window an identity and its submit hint', function()
      local channel = fake.new()
      local current = session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }
      local bufnr = command.open_prompt( current )
      local win = vim.fn.bufwinid( bufnr )

      assert.is_true( win > 0 )
      assert.is_true( vim.wo[win].winbar:find( 'spec', 1, true ) ~= nil )
      assert.is_true( vim.wo[win].winbar:find( 'send', 1, true ) ~= nil )
      assert.is_true( vim.api.nvim_buf_get_name( bufnr ):find( 'pivi://', 1, true ) ~= nil )
      assert.equal( 'spec', vim.b[bufnr].pivi_session )

      vim.cmd.stopinsert()
    end )

    it( 'shows the transcript after a prompt submission', function()
      local channel = fake.new()
      local current = session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }
      local bufnr = command.open_prompt( current )
      vim.cmd.stopinsert()

      vim.api.nvim_buf_set_lines( bufnr, 0, -1, false, { 'do the thing', } )

      local mapping
      for _, entry in ipairs( vim.api.nvim_buf_get_keymap( bufnr, 'n' ) ) do
        if entry.lhs == '<Plug>(pivi-submit)' then mapping = entry end
      end
      assert.is_table( mapping )

      mapping.callback()

      assert.is_true( vim.fn.bufwinid( current.buffer ) > 0 )
      assert.same( { '', }, vim.api.nvim_buf_get_lines( bufnr, 0, -1, false ) )
    end )

    it( 'reuses the prompt of a session and keeps an unfinished draft', function()
      local channel = fake.new()
      local current = session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }

      local first = command.open_prompt( current )
      vim.cmd.stopinsert()
      vim.api.nvim_buf_set_lines( first, 0, -1, false, { 'my unfinished draft', } )

      local again = command.open_prompt( current )
      vim.cmd.stopinsert()

      assert.equal( first, again )
      assert.same( { 'my unfinished draft', }, vim.api.nvim_buf_get_lines( again, 0, -1, false ) )

      local alive = 0
      for _, bufnr in ipairs( vim.api.nvim_list_bufs() ) do
        if vim.bo[bufnr].filetype == command.input_filetype then alive = alive + 1 end
      end
      assert.equal( 1, alive )
    end )

    it( 'never opens in an ordinary buffer', function()
      vim.cmd 'enew'
      local bufnr = vim.api.nvim_get_current_buf()
      assert.is_false( command.slash_opens_commands( bufnr, 0 ) )
    end )

    it( 'never opens in an invalid buffer', function()
      local bufnr = vim.api.nvim_create_buf( false, true )
      vim.api.nvim_buf_delete( bufnr, { force = true, } )
      assert.is_false( command.slash_opens_commands( bufnr, 0 ) )
    end )

    it( 'keeps ordinary search behavior away from the first character', function()
      local channel = fake.new()
      local current = session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }
      local bufnr = command.open_prompt( current )

      vim.api.nvim_buf_set_lines( bufnr, 0, -1, false, { 'hello', } )
      vim.api.nvim_win_set_cursor( 0, { 1, 3, } )

      local mapping
      for _, entry in ipairs( vim.api.nvim_buf_get_keymap( bufnr, 'n' ) ) do
        if entry.lhs == '/' then mapping = entry end
      end

      assert.is_table( mapping )
      assert.equal( '/', mapping.callback() )
    end )
  end )

  describe( 'dispatch', function()
    it( 'registers the user command and its subcommand completion', function()
      command.setup()
      assert.is_table( vim.api.nvim_get_commands( {} ).Pi )

      local names = command.names()
      assert.is_true( vim.list_contains( names, 'ask' ) )
      assert.is_true( vim.list_contains( names, 'help' ) )
      assert.is_true( vim.list_contains( names, 'command' ) )
    end )

    it( 'opens the prompt when given no subcommand', function()
      local channel = fake.new()
      session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }

      command.dispatch { args = '', }

      local opened
      for _, bufnr in ipairs( vim.api.nvim_list_bufs() ) do
        if vim.bo[bufnr].filetype == command.input_filetype then opened = bufnr end
      end

      assert.is_number( opened )
      assert.is_true( vim.fn.bufwinid( opened ) > 0 )
      vim.cmd.stopinsert()
    end )

    it( 'reports an unknown subcommand', function()
      command.dispatch { args = 'levitate', }
      assert.equal( 1, #notices )
      assert.equal( vim.log.levels.ERROR, notices[1][2] )
    end )

    it( 'refuses an empty question', function()
      command.dispatch { args = 'help', }
      assert.equal( vim.log.levels.WARN, notices[1][2] )
    end )

    it( 'reports that nothing is running when no session exists', function()
      command.dispatch { args = 'abort', }
      assert.equal( vim.log.levels.WARN, notices[1][2] )
    end )
  end )

  describe( 'slash commands', function()
    it( 'refuses a name pi does not offer, instead of saying it to the model', function()
      local channel = fake.new()
      local current = session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }

      command.subcommands.command 'model'

      local request
      for _, entry in ipairs( channel.commands ) do
        if entry.type == 'get_commands' then request = entry end
      end
      assert.is_table( request )

      channel.frame {
        id = request.id,
        type = 'response',
        command = 'get_commands',
        success = true,
        data = { commands = { { name = 'compact', source = 'extension', }, }, },
      }
      assert.is_true( channel.settle( function() return #notices > 0 end ) )

      -- Nothing was said to the model.
      for _, entry in ipairs( channel.commands ) do
        assert.is_not.equal( 'prompt', entry.type )
      end
      assert.equal( vim.log.levels.WARN, notices[#notices][2] )
      assert.is_true( notices[#notices][1]:find( 'model', 1, true ) ~= nil )
    end )

    it( 'runs a name pi does offer', function()
      local channel = fake.new()
      local current = session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }

      command.subcommands.command 'compact focus on edits'

      local request
      for _, entry in ipairs( channel.commands ) do
        if entry.type == 'get_commands' then request = entry end
      end
      channel.frame {
        id = request.id,
        type = 'response',
        command = 'get_commands',
        success = true,
        data = { commands = { { name = 'compact', source = 'extension', }, }, },
      }

      assert.is_true( channel.settle( function()
        for _, entry in ipairs( channel.commands ) do
          if entry.type == 'prompt' then return true end
        end
        return false
      end ) )

      local prompts = {}
      for _, entry in ipairs( channel.commands ) do
        if entry.type == 'prompt' then table.insert( prompts, entry ) end
      end
      assert.equal( 1, #prompts )
      assert.equal( '/compact focus on edits', prompts[1].message )
    end )

    it( 'filters the picker on the command name alone', function()
      local channel = fake.new()
      local current = session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }

      local offered
      vim.ui.select = function( items, options, on_choice )
        offered = vim.tbl_map( options.format_item, items )
        on_choice( nil )
      end

      command.subcommands.command ''

      local request
      for _, entry in ipairs( channel.commands ) do
        if entry.type == 'get_commands' then request = entry end
      end
      channel.frame {
        id = request.id,
        type = 'response',
        command = 'get_commands',
        success = true,
        data = { commands = {
          { name = 'compact', description = 'Compact the conversation context', source = 'extension', },
        }, },
      }

      assert.is_true( channel.settle( function() return offered ~= nil end ) )
      assert.same( { '/compact', }, offered )
    end )

    it( 'reports when pi offers no commands', function()
      local channel = fake.new()
      session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }

      command.subcommands.command ''

      local request
      for _, entry in ipairs( channel.commands ) do
        if entry.type == 'get_commands' then request = entry end
      end
      channel.frame {
        id = request.id,
        type = 'response',
        command = 'get_commands',
        success = true,
        data = { commands = {}, },
      }

      assert.is_true( channel.settle( function() return #notices > 0 end ) )
      assert.equal( vim.log.levels.WARN, notices[#notices][2] )
    end )
  end )

  describe( 'completion', function()
    it( 'completes subcommands at the first word', function()
      command.setup()
      local offered = vim.fn.getcompletion( 'Pi ', 'cmdline' )
      assert.is_true( vim.list_contains( offered, 'command' ) )
      assert.is_true( vim.list_contains( offered, 'model' ) )
    end )

    it( 'completes the names pi actually offers after `command`', function()
      command.setup()
      local channel = fake.new()
      local current = session.create { spawn = channel.spawn, name = 'spec', extension = false, skill = false, env = {}, }
      current.commands = {
        { name = 'compact', source = 'extension', },
        { name = 'skill:wiki', source = 'skill', },
      }

      local offered = vim.fn.getcompletion( 'Pi command ', 'cmdline' )

      assert.is_true( vim.list_contains( offered, 'compact' ) )
      assert.is_true( vim.list_contains( offered, 'skill:wiki' ) )
    end )

    it( 'completes follow modes', function()
      command.setup()
      local offered = vim.fn.getcompletion( 'Pi follow ', 'cmdline' )

      assert.is_true( vim.list_contains( offered, 'window' ) )
      assert.is_true( vim.list_contains( offered, 'tab' ) )
    end )
  end )

  describe( 'follow', function()
    it( 'toggles follow mode and reports it', function()
      command.subcommands.follow ''
      assert.is_true( notices[1][1]:find( 'window', 1, true ) ~= nil )
      command.subcommands.follow ''
      assert.is_true( notices[2][1]:find( 'off', 1, true ) ~= nil )
    end )
  end )
end )