Plenary test for callback function

Hi,

I am writing a new plugin and attempting to write some unit tests for it.

One of my functions uses vim.ui.select, which takes a list of selection options and a callback as parameters. The selection is used as an argument for the callback function. Here is the example from the help docs:

vim.ui.select({ 'tabs', 'spaces' }, {
           prompt = 'Select tabs or spaces:',
           format_item = function(item)
               return "I'd like to choose " .. item
           end,
       }, function(choice)
           if choice == 'spaces' then
               vim.o.expandtab = true
           else
               vim.o.expandtab = false
           end
       end)

My question is, how would I test this? I’ve tried using mocks and spies with the luassert/plenary to no avail. To make matters worse, I’m 3 functions deep in callback hell. I’d prefer to use vim.ui.select because of the nice telescope integration, but if I can’t test it properly I’ll be stubborn enough to fallback to something synchronous instead.

Specifically what I’m after is this:

  • Ability to mock a selection, e.g. the first call selects response_a and the second (nested) call selects response_b
  • Ability to assert a function call that happens in the final callback

Any advice would be much appreciated; I’ve tried everything I can think of. I’m struggling with lack of documentation and difficulty finding examples.

Thanks!

Could this work?:

local select=vim.ui.select
function vim.ui.select(items, opts, on_choice)
    if opts.choice then
        --NOTE: opts.choice is the index of the item not the item itself
        vim.schedule(function() on_choice(items[opts.choice],opts.choice) end)
    else
        select(items,opts,on_choice)
    end
end
local stat,ret=pcall(test)
vim.ui.select=select
if not stat then error(ret) end

Could you define the callback separately and only test that? That would probably make the selection trivial and you don’t need to test that.