repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
neovim/tests/bugabinga/pivi/help_spec.lua
Raw---@diagnostic disable: duplicate-set-field, need-check-nil, param-type-mismatch, assign-type-mismatch
local help = require 'bugabinga.pivi.help'
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'
describe( 'pivi help', function()
after_each( function()
fake.drain()
session.stop_all()
transcript.forget_all()
publish.reset()
fake.close_extra_windows()
end )
it( 'runs without persisting a session', function()
local channel = fake.new()
help.ask( 'what is a quickfix list', { spawn = channel.spawn, } )
assert.is_true( vim.list_contains( channel.command, '--no-session' ) )
assert.is_true( vim.list_contains( channel.command, '--append-system-prompt' ) )
assert.is_false( vim.list_contains( channel.command, '--no-tools' ) )
end )
it( 'offers only read-only tools', function()
local command = help.build_command {}
local index = vim.fn.index( command, '--tools' ) + 1
assert.is_true( index > 0 )
local allowed = vim.split( command[index + 1], ',', { plain = true, } )
assert.is_true( vim.list_contains( allowed, 'nvim_help' ) )
assert.is_true( vim.list_contains( allowed, 'read' ) )
for _, forbidden in ipairs { 'write', 'edit', 'bash', 'powershell', } do
assert.is_false( vim.list_contains( allowed, forbidden ) )
end
end )
it( 'carries the pivi skill', function()
local command = help.build_command {}
local index = vim.fn.index( command, '--skill' ) + 1
assert.is_true( index > 0 )
assert.is_true( command[index + 1]:find( 'SKILL.md', 1, true ) ~= nil )
assert.is_true( command[index + 1]:find( 'pivi', 1, true ) ~= nil )
end )
it( 'attaches what the user currently sees to the question', function()
vim.cmd 'enew'
local bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_set_lines( bufnr, 0, -1, false, { 'a distinctive visible line', } )
local channel = fake.new()
help.ask( 'why does this look wrong', { spawn = channel.spawn, } )
local sent = channel.commands[1].message
assert.is_true( sent:find( '<editor-view>', 1, true ) ~= nil )
assert.is_true( sent:find( 'a distinctive visible line', 1, true ) ~= nil )
assert.is_true( sent:find( 'why does this look wrong', 1, true ) ~= nil )
end )
it( 'shows what it is doing in its own window', function()
local channel = fake.new()
local run = help.ask( 'a question', { spawn = channel.spawn, } )
local win = transcript.show( run.buffer )
transcript.set_state( run.buffer, help.buffer_name, 'thinking' )
assert.is_true( vim.wo[win].winbar:find( 'thinking', 1, true ) ~= nil )
channel.frame {
type = 'tool_execution_start',
toolCallId = 'c1',
toolName = 'nvim_help',
args = { tag = 'quickfix', },
}
channel.flush()
assert.is_true( vim.wo[win].winbar:find( 'quickfix', 1, true ) ~= nil )
assert.is_true( vim.list_contains( transcript.lines( run.buffer ), 'nvim_help quickfix' ) )
channel.frame { type = 'agent_settled', }
channel.flush()
assert.is_nil( vim.wo[win].winbar:find( 'quickfix', 1, true ) )
assert.is_true( vim.wo[win].winbar:find( help.buffer_name, 1, true ) ~= nil )
end )
it( 'drops the blank lines a model opens with', function()
local channel = fake.new()
local run = help.ask( 'a question', { spawn = channel.spawn, } )
channel.frame {
type = 'message_update',
assistantMessageEvent = { type = 'text_delta', contentIndex = 0, delta = '\n\nUse :cnext.', },
}
channel.flush()
assert.equal( 'Use :cnext.', run.answer )
end )
it( 'can ask without any view', function()
local channel = fake.new()
help.ask( 'plain question', { spawn = channel.spawn, view = false, } )
assert.equal( 'plain question', channel.commands[1].message )
end )
it( 'still loads the user\'s own pi configuration', function()
local channel = fake.new()
help.ask( 'anything', { spawn = channel.spawn, } )
-- Help isolates session state, never the user's providers, extensions,
-- skills, prompts, or context files.
for _, flag in ipairs { '--no-extensions', '--no-skills', '--no-prompt-templates', '--no-context-files', '--system-prompt', } do
assert.is_false( vim.list_contains( channel.command, flag ) )
end
end )
it( 'streams the answer into its own buffer', function()
local channel = fake.new()
local run = help.ask( 'how do I open the quickfix list', { spawn = channel.spawn, } )
channel.frame {
type = 'message_update',
assistantMessageEvent = { type = 'text_delta', contentIndex = 0, delta = 'use :copen', },
}
assert.is_true( channel.settle( function() return run.answer == 'use :copen' end ) )
assert.is_true( vim.list_contains( transcript.lines( run.buffer ), 'use :copen' ) )
end )
it( 'ends its own process once the answer settles', function()
local channel = fake.new()
local finished
local run = help.ask( 'anything', { spawn = channel.spawn, on_done = function( value ) finished = value end, } )
channel.frame { type = 'agent_settled', }
assert.is_true( channel.settle( function() return finished ~= nil end ) )
assert.is_true( run.done )
-- The child is ended by closing its input, not by an immediate kill.
assert.is_true( channel.stdin_closed )
end )
it( 'answers while a working session runs, leaving it untouched', function()
local work = fake.new()
local working = session.create {
spawn = work.spawn,
name = 'work',
extension = false,
skill = false,
env = {},
}
working.submit( 'long task', { capture = false, } )
work.frame { type = 'agent_start', }
assert.is_true( work.settle( function() return working.status.run == 'running' end ) )
local transcript_before = vim.deepcopy( transcript.lines( working.buffer ) )
local commands_before = #work.commands
local status_before = vim.deepcopy( working.status )
local channel = fake.new()
local run = help.ask( 'what does :checktime do', { spawn = channel.spawn, } )
channel.frame {
type = 'message_update',
assistantMessageEvent = { type = 'text_delta', contentIndex = 0, delta = 'it reloads changed files', },
}
assert.is_true( channel.settle( function() return run.answer ~= '' end ) )
assert.is_not.equal( run.buffer, working.buffer )
assert.same( transcript_before, transcript.lines( working.buffer ) )
assert.equal( commands_before, #work.commands )
assert.same( status_before.queue, working.status.queue )
assert.equal( status_before.run, working.status.run )
end )
it( 'reports its own failure without disturbing a working session', function()
local work = fake.new()
local working = session.create { spawn = work.spawn, name = 'work', extension = false, skill = false, env = {}, }
local channel = fake.new()
local run = help.ask( 'anything', { spawn = channel.spawn, } )
local id = channel.commands[1].id
channel.frame { id = id, type = 'response', command = 'prompt', success = false, error = 'help unavailable', }
assert.is_true( channel.settle( function() return run.done end ) )
assert.is_true( vim.list_contains( transcript.lines( run.buffer ), 'help unavailable' ) )
assert.equal( 'running', working.status.connection )
assert.is_nil( working.status.error )
end )
end )