test: automated tests for the input modal

This commit is contained in:
Steven Arcangeli 2021-12-08 18:51:23 -08:00
parent dbfca4da6a
commit 43dd74f512
5 changed files with 177 additions and 0 deletions

View File

@ -92,6 +92,8 @@ M.update = function(opts)
end
end
-- Used to get the effective config value for a module.
-- Use like: config.get_mod_config('input')
M.get_mod_config = function(key, ...)
if not M[key].get_config then
return M[key]

5
run_tests.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
set -e
nvim --headless --noplugin -u tests/init.lua \
-c "PlenaryBustedDirectory ${1-tests} { minimal_init = './tests/init.lua' }"

2
tests/init.lua Normal file
View File

@ -0,0 +1,2 @@
vim.cmd([[set runtimepath+=.]])
vim.cmd([[runtime! plugin/plenary.vim]])

149
tests/input_spec.lua Normal file
View File

@ -0,0 +1,149 @@
require("plenary.async").tests.add_to_env()
local dressing = require("dressing")
local util = require("tests.util")
local channel = a.control.channel
local function run_input(keys, opts)
opts = opts or {}
local tx, rx = channel.oneshot()
vim.ui.input(opts, tx)
util.feedkeys(vim.list_extend(
{ "i" }, -- HACK have to do this because :startinsert doesn't work in tests,
keys
))
if opts.after_fn then
opts.after_fn()
end
return rx()
end
for _, prompt_buffer in ipairs({ true, false }) do
a.describe(
string.format("input (%s)", prompt_buffer and "prompt buffer" or "normal floatwin"),
function()
before_each(function()
dressing.patch()
dressing.setup({
input = {
prompt_buffer = prompt_buffer,
},
})
end)
after_each(function()
-- Clean up all floating windows so one test failure doesn't cascade
for _, winid in ipairs(vim.api.nvim_list_wins()) do
if vim.api.nvim_win_get_config(winid).relative ~= "" then
vim.api.nvim_win_close(winid, true)
end
end
end)
a.it("accepts input", function()
local ret = run_input({
"my text",
"<CR>",
})
assert(ret == "my text", string.format("Got '%s' expected 'my text'", ret))
end)
a.it("Cancels input on <C-c>", function()
local ret = run_input({
"my text",
"<C-c>",
})
assert(ret == nil, string.format("Got '%s' expected nil", ret))
end)
a.it("cancels input when leaving the window", function()
local ret = run_input({
"my text",
}, {
after_fn = function()
vim.cmd([[wincmd p]])
end,
})
assert(ret == nil, string.format("Got '%s' expected nil", ret))
end)
a.it("cancels on <Esc> when insert_only = true", function()
require("dressing.config").input.insert_only = true
local ret = run_input({
"my text",
"<Esc>",
})
assert(ret == nil, string.format("Got '%s' expected nil", ret))
end)
a.it("does not cancel on <Esc> when insert_only = false", function()
require("dressing.config").input.insert_only = false
local ret = run_input({
"my text",
"<Esc>",
"<CR>",
})
assert(ret == "my text", string.format("Got '%s' expected 'my text'", ret))
end)
a.it("cancels first callback if second input is opened", function()
local tx, rx = channel.oneshot()
vim.ui.input({}, tx)
util.feedkeys({
"i", -- HACK have to do this because :startinsert doesn't work in tests,
"my text",
})
vim.ui.input({}, function() end)
local ret = rx()
assert(ret == nil, string.format("Got '%s' expected nil", ret))
end)
-- TODO can't get this working in the prompt buffer test
if not prompt_buffer then
a.it("supports completion", function()
vim.opt.completeopt = { "menu", "menuone", "noselect" }
vim.cmd([[
function! CustomComplete(arglead, cmdline, cursorpos)
return "first\nsecond\nthird"
endfunction
]])
local ret = run_input({
"<Tab><Tab><C-n><CR>", -- Using tab twice to test both versions of the mapping
}, {
completion = "custom,CustomComplete",
})
assert(ret == "second", string.format("Got '%s' expected 'second'", ret))
assert(vim.fn.pumvisible() == 0, "Popup menu should not be visible after leaving modal")
end)
a.it("can cancel out when popup menu is open", function()
vim.opt.completeopt = { "menu", "menuone", "noselect" }
local ret = run_input({
"<Tab>",
"<C-c>",
}, {
completion = "command",
})
assert(ret == nil, string.format("Got '%s' expected nil", ret))
assert(vim.fn.pumvisible() == 0, "Popup menu should not be visible after leaving modal")
end)
a.it("doesn't delete text in original buffer", function()
-- This is a regression test for weird behavior I was seeing with the
-- completion popup menu
vim.api.nvim_buf_set_lines(0, 0, 1, true, { "some text" })
vim.api.nvim_win_set_cursor(0, { 1, 4 })
vim.opt.completeopt = { "menu", "menuone", "noselect" }
local ret = run_input({
"<Tab>",
"<C-c>",
}, {
completion = "command",
})
assert(ret == nil, string.format("Got '%s' expected nil", ret))
local line = vim.api.nvim_buf_get_lines(0, 0, 1, true)[1]
assert(line == "some text", "Doing <C-c> with popup menu open deleted buffer text o.0")
end)
end
end
)
end

19
tests/util.lua Normal file
View File

@ -0,0 +1,19 @@
require("plenary.async").tests.add_to_env()
local M = {}
M.feedkeys = function(actions, timestep)
timestep = timestep or 10
a.util.sleep(timestep)
for _, action in ipairs(actions) do
a.util.sleep(timestep)
local escaped = vim.api.nvim_replace_termcodes(action, true, false, true)
vim.api.nvim_feedkeys(escaped, "m", true)
end
a.util.sleep(timestep)
-- process pending keys until the queue is empty.
-- Note that this will exit insert mode.
vim.api.nvim_feedkeys("", "x", true)
a.util.sleep(timestep)
end
return M