refactor(tests): rename terminal/testutil.lua => testterm.lua #30372

This module is generally used by any tests that need the full Nvim TUI
instead of `screen.lua`. Thus it should live in `functional/` instead of
in `functional/terminal/`.
This commit is contained in:
Justin M. Keyes 2024-09-15 03:28:14 -07:00 committed by GitHub
parent 3b54adc6c6
commit 5792546777
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 107 additions and 99 deletions

View File

@ -114,6 +114,7 @@ function Session:request(method, ...)
return true, result return true, result
end end
--- Runs the event loop.
function Session:run(request_cb, notification_cb, setup_cb, timeout) function Session:run(request_cb, notification_cb, setup_cb, timeout)
local function on_request(method, args, response) local function on_request(method, args, response)
coroutine_exec(request_cb, method, args, function(status, result, flag) coroutine_exec(request_cb, method, args, function(status, result, flag)

View File

@ -1,6 +1,6 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local clear = n.clear local clear = n.clear
local feed_command = n.feed_command local feed_command = n.feed_command

View File

@ -1,6 +1,6 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local uv = vim.uv local uv = vim.uv
local clear, command, testprg = n.clear, n.command, n.testprg local clear, command, testprg = n.clear, n.command, n.testprg
@ -199,7 +199,7 @@ end)
describe('autocmd TextChangedT', function() describe('autocmd TextChangedT', function()
clear() clear()
local screen = tt.screen_setup() local screen = tt.setup_screen()
it('works', function() it('works', function()
command('autocmd TextChangedT * ++once let g:called = 1') command('autocmd TextChangedT * ++once let g:called = 1')

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local clear = n.clear local clear = n.clear
local eq = t.eq local eq = t.eq

View File

@ -1,6 +1,6 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local assert_log = t.assert_log local assert_log = t.assert_log
local clear = n.clear local clear = n.clear

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local clear, eq, api = n.clear, t.eq, n.api local clear, eq, api = n.clear, t.eq, n.api
local feed = n.feed local feed = n.feed
local feed_data = tt.feed_data local feed_data = tt.feed_data
@ -17,7 +17,7 @@ describe(':terminal altscreen', function()
before_each(function() before_each(function()
clear() clear()
screen = tt.screen_setup() screen = tt.setup_screen()
feed_data({ feed_data({
'line1', 'line1',
'line2', 'line2',

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local ok = t.ok local ok = t.ok
if t.skip(t.is_os('win')) then if t.skip(t.is_os('win')) then

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local assert_alive = n.assert_alive local assert_alive = n.assert_alive
local feed, clear = n.feed, n.clear local feed, clear = n.feed, n.clear
@ -29,7 +29,7 @@ describe(':terminal buffer', function()
before_each(function() before_each(function()
clear() clear()
command('set modifiable swapfile undolevels=20') command('set modifiable swapfile undolevels=20')
screen = tt.screen_setup() screen = tt.setup_screen()
end) end)
it('terminal-mode forces various options', function() it('terminal-mode forces various options', function()
@ -574,7 +574,7 @@ if is_os('win') then
feed_command('set modifiable swapfile undolevels=20') feed_command('set modifiable swapfile undolevels=20')
poke_eventloop() poke_eventloop()
local cmd = { 'cmd.exe', '/K', 'PROMPT=$g$s' } local cmd = { 'cmd.exe', '/K', 'PROMPT=$g$s' }
screen = tt.screen_setup(nil, cmd) screen = tt.setup_screen(nil, cmd)
end) end)
it('"put" operator sends data normally', function() it('"put" operator sends data normally', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local feed, clear = n.feed, n.clear local feed, clear = n.feed, n.clear
local testprg, command = n.testprg, n.command local testprg, command = n.testprg, n.command
@ -18,7 +18,7 @@ describe(':terminal cursor', function()
before_each(function() before_each(function()
clear() clear()
screen = tt.screen_setup() screen = tt.setup_screen()
end) end)
it('moves the screen cursor when focused', function() it('moves the screen cursor when focused', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local feed, clear = n.feed, n.clear local feed, clear = n.feed, n.clear
local api = n.api local api = n.api

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local clear, eq, eval = n.clear, t.eq, n.eval local clear, eq, eval = n.clear, t.eq, n.eval
local feed, api, command = n.feed, n.api, n.command local feed, api, command = n.feed, n.api, n.command
local feed_data = tt.feed_data local feed_data = tt.feed_data
@ -14,7 +14,7 @@ describe(':terminal mouse', function()
before_each(function() before_each(function()
clear() clear()
api.nvim_set_option_value('statusline', '==========', {}) api.nvim_set_option_value('statusline', '==========', {})
screen = tt.screen_setup() screen = tt.setup_screen()
command('highlight StatusLine NONE') command('highlight StatusLine NONE')
command('highlight StatusLineNC NONE') command('highlight StatusLineNC NONE')
command('highlight StatusLineTerm NONE') command('highlight StatusLineTerm NONE')

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local clear, eq = n.clear, t.eq local clear, eq = n.clear, t.eq
local feed, testprg = n.feed, n.testprg local feed, testprg = n.feed, n.testprg
@ -22,7 +22,7 @@ describe(':terminal scrollback', function()
before_each(function() before_each(function()
clear() clear()
screen = tt.screen_setup(nil, nil, 30) screen = tt.setup_screen(nil, nil, 30)
end) end)
describe('when the limit is exceeded', function() describe('when the limit is exceeded', function()
@ -399,9 +399,9 @@ describe("'scrollback' option", function()
it('set to 0 behaves as 1', function() it('set to 0 behaves as 1', function()
local screen local screen
if is_os('win') then if is_os('win') then
screen = tt.screen_setup(nil, { 'cmd.exe' }, 30) screen = tt.setup_screen(nil, { 'cmd.exe' }, 30)
else else
screen = tt.screen_setup(nil, { 'sh' }, 30) screen = tt.setup_screen(nil, { 'sh' }, 30)
end end
api.nvim_set_option_value('scrollback', 0, {}) api.nvim_set_option_value('scrollback', 0, {})
@ -416,10 +416,10 @@ describe("'scrollback' option", function()
local screen local screen
if is_os('win') then if is_os('win') then
command([[let $PROMPT='$$']]) command([[let $PROMPT='$$']])
screen = tt.screen_setup(nil, { 'cmd.exe' }, 30) screen = tt.setup_screen(nil, { 'cmd.exe' }, 30)
else else
command('let $PS1 = "$"') command('let $PS1 = "$"')
screen = tt.screen_setup(nil, { 'sh' }, 30) screen = tt.setup_screen(nil, { 'sh' }, 30)
end end
api.nvim_set_option_value('scrollback', 200, {}) api.nvim_set_option_value('scrollback', 200, {})
@ -480,8 +480,8 @@ describe("'scrollback' option", function()
end) end)
it('deletes extra lines immediately', function() it('deletes extra lines immediately', function()
-- Scrollback is 10 on screen_setup -- Scrollback is 10 on setup_screen
local screen = tt.screen_setup(nil, nil, 30) local screen = tt.setup_screen(nil, nil, 30)
local lines = {} local lines = {}
for i = 1, 30 do for i = 1, 30 do
table.insert(lines, 'line' .. tostring(i)) table.insert(lines, 'line' .. tostring(i))

View File

@ -7,7 +7,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local eq = t.eq local eq = t.eq
local feed_data = tt.feed_data local feed_data = tt.feed_data
@ -2111,7 +2111,7 @@ describe('TUI', function()
finally(function() finally(function()
os.remove('testF') os.remove('testF')
end) end)
local screen = tt.screen_setup( local screen = tt.setup_screen(
0, 0,
('"%s" -u NONE -i NONE --cmd "set noswapfile noshowcmd noruler" --cmd "normal iabc" > /dev/null 2>&1 && cat testF && rm testF'):format( ('"%s" -u NONE -i NONE --cmd "set noswapfile noshowcmd noruler" --cmd "normal iabc" > /dev/null 2>&1 && cat testF && rm testF'):format(
nvim_prog nvim_prog

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local feed_data = tt.feed_data local feed_data = tt.feed_data
local feed, clear = n.feed, n.clear local feed, clear = n.feed, n.clear
local poke_eventloop = n.poke_eventloop local poke_eventloop = n.poke_eventloop
@ -37,7 +37,7 @@ describe(':terminal window', function()
before_each(function() before_each(function()
clear() clear()
screen = tt.screen_setup() screen = tt.setup_screen()
end) end)
it('sets topline correctly #8556', function() it('sets topline correctly #8556', function()
@ -198,7 +198,7 @@ describe(':terminal with multigrid', function()
before_each(function() before_each(function()
clear() clear()
screen = tt.screen_setup(0, nil, 50, nil, { ext_multigrid = true }) screen = tt.setup_screen(0, nil, 50, nil, { ext_multigrid = true })
end) end)
it('resizes to requested size', function() it('resizes to requested size', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local assert_alive = n.assert_alive local assert_alive = n.assert_alive
local clear = n.clear local clear = n.clear
local feed = n.feed local feed = n.feed
@ -22,7 +22,7 @@ describe(':terminal', function()
-- set the statusline to a constant value because of variables like pid -- set the statusline to a constant value because of variables like pid
-- and current directory and to improve visibility of splits -- and current directory and to improve visibility of splits
api.nvim_set_option_value('statusline', '==========', {}) api.nvim_set_option_value('statusline', '==========', {})
screen = tt.screen_setup(3) screen = tt.setup_screen(3)
command('highlight StatusLine NONE') command('highlight StatusLine NONE')
command('highlight StatusLineNC NONE') command('highlight StatusLineNC NONE')
command('highlight StatusLineTerm NONE') command('highlight StatusLineTerm NONE')

View File

@ -250,6 +250,8 @@ function M.set_method_error(err)
method_error = err method_error = err
end end
--- Runs the event loop of the given session.
---
--- @param lsession test.Session --- @param lsession test.Session
--- @param request_cb function? --- @param request_cb function?
--- @param notification_cb function? --- @param notification_cb function?
@ -296,6 +298,7 @@ function M.run_session(lsession, request_cb, notification_cb, setup_cb, timeout)
return lsession.eof_err return lsession.eof_err
end end
--- Runs the event loop of the current global session.
function M.run(request_cb, notification_cb, setup_cb, timeout) function M.run(request_cb, notification_cb, setup_cb, timeout)
assert(session) assert(session)
return M.run_session(session, request_cb, notification_cb, setup_cb, timeout) return M.run_session(session, request_cb, notification_cb, setup_cb, timeout)

View File

@ -1,6 +1,13 @@
-- To test tui/input.c, this module spawns `nvim` inside :terminal and sends -- Functions to test :terminal and the Nvim TUI.
-- bytes via jobsend(). Note: the functional/testutil.lua test-session methods -- Starts a child process in a `:terminal` and sends bytes to the child via nvim_chan_send().
-- operate on the _host_ session, _not_ the child session. -- Note: the global functional/testutil.lua test-session is _host_ session, _not_
-- the child session.
--
-- - Use `setup_screen()` to test `:terminal` behavior with an arbitrary command.
-- - Use `setup_child_nvim()` to test the Nvim TUI.
-- - NOTE: Only use this if your test actually needs the full lifecycle/capabilities of the
-- builtin Nvim TUI. Most tests should just use `Screen.new()` directly, or plain old API calls.
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
@ -9,18 +16,20 @@ local exec_lua = n.exec_lua
local api = n.api local api = n.api
local nvim_prog = n.nvim_prog local nvim_prog = n.nvim_prog
local function feed_data(data) local M = {}
function M.feed_data(data)
if type(data) == 'table' then if type(data) == 'table' then
data = table.concat(data, '\n') data = table.concat(data, '\n')
end end
exec_lua('vim.api.nvim_chan_send(vim.b.terminal_job_id, ...)', data) exec_lua('vim.api.nvim_chan_send(vim.b.terminal_job_id, ...)', data)
end end
local function feed_termcode(data) function M.feed_termcode(data)
feed_data('\027' .. data) M.feed_data('\027' .. data)
end end
local function make_lua_executor(session) function M.make_lua_executor(session)
return function(code, ...) return function(code, ...)
local status, rv = session:request('nvim_exec_lua', code, { ... }) local status, rv = session:request('nvim_exec_lua', code, { ... })
if not status then if not status then
@ -34,60 +43,68 @@ end
-- some t for controlling the terminal. the codes were taken from -- some t for controlling the terminal. the codes were taken from
-- infocmp xterm-256color which is less what libvterm understands -- infocmp xterm-256color which is less what libvterm understands
-- civis/cnorm -- civis/cnorm
local function hide_cursor() function M.hide_cursor()
feed_termcode('[?25l') M.feed_termcode('[?25l')
end end
local function show_cursor() function M.show_cursor()
feed_termcode('[?25h') M.feed_termcode('[?25h')
end end
-- smcup/rmcup -- smcup/rmcup
local function enter_altscreen() function M.enter_altscreen()
feed_termcode('[?1049h') M.feed_termcode('[?1049h')
end end
local function exit_altscreen() function M.exit_altscreen()
feed_termcode('[?1049l') M.feed_termcode('[?1049l')
end end
-- character attributes -- character attributes
local function set_fg(num) function M.set_fg(num)
feed_termcode('[38;5;' .. num .. 'm') M.feed_termcode('[38;5;' .. num .. 'm')
end end
local function set_bg(num) function M.set_bg(num)
feed_termcode('[48;5;' .. num .. 'm') M.feed_termcode('[48;5;' .. num .. 'm')
end end
local function set_bold() function M.set_bold()
feed_termcode('[1m') M.feed_termcode('[1m')
end end
local function set_italic() function M.set_italic()
feed_termcode('[3m') M.feed_termcode('[3m')
end end
local function set_underline() function M.set_underline()
feed_termcode('[4m') M.feed_termcode('[4m')
end end
local function set_underdouble() function M.set_underdouble()
feed_termcode('[4:2m') M.feed_termcode('[4:2m')
end end
local function set_undercurl() function M.set_undercurl()
feed_termcode('[4:3m') M.feed_termcode('[4:3m')
end end
local function set_strikethrough() function M.set_strikethrough()
feed_termcode('[9m') M.feed_termcode('[9m')
end end
local function clear_attrs() function M.clear_attrs()
feed_termcode('[0;10m') M.feed_termcode('[0;10m')
end end
-- mouse -- mouse
local function enable_mouse() function M.enable_mouse()
feed_termcode('[?1002h') M.feed_termcode('[?1002h')
end end
local function disable_mouse() function M.disable_mouse()
feed_termcode('[?1002l') M.feed_termcode('[?1002l')
end end
local default_command = { testprg('tty-test') } local default_command = { testprg('tty-test') }
local function screen_setup(extra_rows, command, cols, env, screen_opts) --- Runs `cmd` in a :terminal, and returns a `Screen` object.
---
---@param extra_rows? integer Extra rows to add to the default screen.
---@param cmd? string|string[] Command to run in the terminal (default: `{ 'tty-test' }`)
---@param cols? integer Create screen with this many columns (default: 50)
---@param env? table Environment set on the `cmd` job.
---@param screen_opts? table Options for `Screen.new()`.
---@return test.functional.ui.screen # Screen attached to the global (not child) Nvim session.
function M.setup_screen(extra_rows, cmd, cols, env, screen_opts)
extra_rows = extra_rows and extra_rows or 0 extra_rows = extra_rows and extra_rows or 0
command = command and command or default_command cmd = cmd and cmd or default_command
cols = cols and cols or 50 cols = cols and cols or 50
api.nvim_command('highlight TermCursor cterm=reverse') api.nvim_command('highlight TermCursor cterm=reverse')
@ -120,7 +137,7 @@ local function screen_setup(extra_rows, command, cols, env, screen_opts)
screen:attach(screen_opts or { rgb = false }) screen:attach(screen_opts or { rgb = false })
api.nvim_command('enew') api.nvim_command('enew')
api.nvim_call_function('termopen', { command, env and { env = env } or nil }) api.nvim_call_function('termopen', { cmd, env and { env = env } or nil })
api.nvim_input('<CR>') api.nvim_input('<CR>')
local vim_errmsg = api.nvim_eval('v:errmsg') local vim_errmsg = api.nvim_eval('v:errmsg')
if vim_errmsg and '' ~= vim_errmsg then if vim_errmsg and '' ~= vim_errmsg then
@ -133,7 +150,7 @@ local function screen_setup(extra_rows, command, cols, env, screen_opts)
-- tty-test puts the terminal into raw mode and echoes input. Tests work by -- tty-test puts the terminal into raw mode and echoes input. Tests work by
-- feeding termcodes to control the display and asserting by screen:expect. -- feeding termcodes to control the display and asserting by screen:expect.
if command == default_command and screen_opts == nil then if cmd == default_command and screen_opts == nil then
-- Wait for "tty ready" to be printed before each test or the terminal may -- Wait for "tty ready" to be printed before each test or the terminal may
-- still be in canonical mode (will echo characters for example). -- still be in canonical mode (will echo characters for example).
local empty_line = (' '):rep(cols) local empty_line = (' '):rep(cols)
@ -160,37 +177,24 @@ local function screen_setup(extra_rows, command, cols, env, screen_opts)
return screen return screen
end end
local function setup_child_nvim(args, opts) --- Spawns Nvim with `args` in a :terminal, and returns a `Screen` object.
---
--- @note Only use this if you actually need the full lifecycle/capabilities of the builtin Nvim
--- TUI. Most tests should just use `Screen.new()` directly, or plain old API calls.
---
---@param args? string[] Args passed to child Nvim.
---@param opts? table Options
---@return test.functional.ui.screen # Screen attached to the global (not child) Nvim session.
function M.setup_child_nvim(args, opts)
opts = opts or {} opts = opts or {}
local argv = { nvim_prog, unpack(args) } local argv = { nvim_prog, unpack(args or {}) }
local env = opts.env or {} local env = opts.env or {}
if not env.VIMRUNTIME then if not env.VIMRUNTIME then
env.VIMRUNTIME = os.getenv('VIMRUNTIME') env.VIMRUNTIME = os.getenv('VIMRUNTIME')
end end
return screen_setup(opts.extra_rows, argv, opts.cols, env) return M.setup_screen(opts.extra_rows, argv, opts.cols, env)
end end
return { return M
feed_data = feed_data,
feed_termcode = feed_termcode,
make_lua_executor = make_lua_executor,
hide_cursor = hide_cursor,
show_cursor = show_cursor,
enter_altscreen = enter_altscreen,
exit_altscreen = exit_altscreen,
set_fg = set_fg,
set_bg = set_bg,
set_bold = set_bold,
set_italic = set_italic,
set_underline = set_underline,
set_underdouble = set_underdouble,
set_undercurl = set_undercurl,
set_strikethrough = set_strikethrough,
clear_attrs = clear_attrs,
enable_mouse = enable_mouse,
disable_mouse = disable_mouse,
screen_setup = screen_setup,
setup_child_nvim = setup_child_nvim,
}

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local clear, insert = n.clear, n.insert local clear, insert = n.clear, n.insert
local command = n.command local command = n.command

View File

@ -1,7 +1,7 @@
local t = require('test.testutil') local t = require('test.testutil')
local n = require('test.functional.testnvim')() local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.terminal.testutil') local tt = require('test.functional.testterm')
local assert_alive = n.assert_alive local assert_alive = n.assert_alive
local mkdir, write_file, rmdir = t.mkdir, t.write_file, n.rmdir local mkdir, write_file, rmdir = t.mkdir, t.write_file, n.rmdir