Skip to content

Commit b8b0c3b

Browse files
committed
test(cmdline): use wrapper to type every character in child process
Details: - Some tests (mostly for autocorrect) can depend on accurately emulating state tracking. This requires mocking every single key press separately so that state is updated as expected.
1 parent 14a8b43 commit b8b0c3b

File tree

2 files changed

+60
-33
lines changed

2 files changed

+60
-33
lines changed
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--|---------|---------|
2-
01|aa
2+
01|"a
33
02|aaa
44
03|aaaa
55
04|~
@@ -14,10 +14,10 @@
1414
01|01222222222222222222
1515
02|11122222222222222222
1616
03|11112222222222222222
17-
04|33333333333333333333
18-
05|33333333333333333333
19-
06|33333333333333333333
20-
07|33333333333333333333
21-
08|33333333333333333333
22-
09|33333333333333333333
23-
10|45444444444444444444
17+
04|00000000000000000000
18+
05|00000000000000000000
19+
06|00000000000000000000
20+
07|00000000000000000000
21+
08|00000000000000000000
22+
09|00000000000000000000
23+
10|34333333333333333333

tests/test_cmdline.lua

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,36 @@ local type_keys = function(...) return child.type_keys(...) end
1616
local sleep = function(ms) helpers.sleep(ms, child) end
1717
--stylua: ignore end
1818

19+
-- Create a helper for mock-typing every key separately because state tracking
20+
-- can depend on emulating one-by-one key presses (mostly for autocorrect).
21+
local tbl_flatten = vim.fn.has('nvim-0.10') == 1 and function(x) return vim.iter(x):flatten(math.huge):totable() end
22+
or vim.tbl_flatten
23+
24+
local slice_keys = function(keys)
25+
local res, cur_key = {}, ''
26+
for i = 1, vim.fn.strchars(keys) do
27+
cur_key = cur_key .. vim.fn.strcharpart(keys, i - 1, 1)
28+
if cur_key:sub(1, 1) ~= '<' or cur_key:sub(-1) == '>' then
29+
table.insert(res, cur_key)
30+
cur_key = ''
31+
end
32+
end
33+
return res
34+
end
35+
36+
local type_every_key = function(...)
37+
local wait, keys = nil, tbl_flatten({ ... })
38+
if type(keys[1]) == 'number' then
39+
wait, keys = keys[1], vim.list_slice(keys, 2)
40+
end
41+
local args = slice_keys(table.concat(keys, ''))
42+
if wait ~= nil then table.insert(args, 1, wait) end
43+
44+
-- Always type keys one-by-one as this is needed to mock actual typing.
45+
-- Otherwise state tracking is not emulated properly
46+
child.type_keys(unpack(args))
47+
end
48+
1949
local test_dir = 'tests/dir-cmdline'
2050

2151
-- Common test wrappers
@@ -482,7 +512,7 @@ T['Autocomplete']['works in different command types'] = function()
482512

483513
local validate = function(keys)
484514
eq(child.fn.mode(), 'n')
485-
type_keys(keys)
515+
type_every_key(keys)
486516
if child.fn.has('nvim-0.12') == 1 then
487517
child.expect_screenshot()
488518
else
@@ -626,7 +656,7 @@ T['Autocorrect'] = new_set({
626656

627657
T['Autocorrect']['works for commands'] = function()
628658
local validate = function(bad_word, ref_word)
629-
type_keys(':', bad_word, ' ')
659+
type_every_key(':', bad_word, ' ')
630660
validate_cmdline(ref_word .. ' ')
631661
type_keys('<Esc>')
632662
end
@@ -687,39 +717,36 @@ end
687717
T['Autocorrect']['works for options'] = function()
688718
local validate_option = function(input, ref)
689719
-- In progress
690-
type_keys(':', input, ' ')
720+
type_every_key(':', input, ' ')
691721
validate_cmdline(ref .. ' ')
692722
type_keys('<Esc>')
693723

694724
-- Final
695-
type_keys(':', input, '<CR>')
725+
type_every_key(':', input, '<CR>')
696726
eq(child.fn.histget('cmd', -1), ref)
697727
end
698728

699-
-- NOTE: Need to emulate `n-o-...` and `i-n-v-...` as separate keys as these
700-
-- case detection relies on user interactively typing keys
701729
validate_option('set expndtb', 'set expandtab')
702-
validate_option({ 'set ', 'n', 'o', 'expndtb' }, 'set noexpandtab')
703-
validate_option({ 'set ', 'i', 'n', 'v', 'expndtb' }, 'set invexpandtab')
730+
validate_option('set noexpndtb', 'set noexpandtab')
731+
validate_option('set invexpndtb', 'set invexpandtab')
704732
validate_option('set ET', 'set et')
705-
validate_option({ 'set ', 'n', 'o', 'ET' }, 'set noet')
706-
validate_option({ 'set ', 'i', 'n', 'v', 'ET' }, 'set invet')
733+
validate_option('set noET', 'set noet')
734+
validate_option('set invET', 'set invet')
707735

708736
validate_option('setlocal expndtb', 'setlocal expandtab')
709737

710738
-- Should work multiple times
711-
type_keys(':', 'set ET', ' ', 'inorecase', ' ', 'nowrp', ' ', 'invmgic', ' ')
739+
type_every_key(':set ET inorecase nowrp invmgic ')
712740
validate_cmdline('set et ignorecase nowrap invmagic ')
713741
type_keys('<Esc>')
714742

715743
-- Correction when option is followed by not space
716744
local validate_option_char = function(char)
717-
-- Similarly to `n-o-...` case, need to emulate key before tested character
718-
type_keys(':', 'set lstchar', 's', char)
745+
type_every_key(':', 'set lstchars', char)
719746
validate_cmdline('set listchars' .. char)
720747
type_keys('<Esc>')
721748

722-
type_keys(':', 'set LC', 'S', char)
749+
type_every_key(':', 'set LCS', char)
723750
validate_cmdline('set lcs' .. char)
724751
type_keys('<Esc>')
725752
end
@@ -735,12 +762,12 @@ end
735762

736763
T['Autocorrect']['works for other types'] = function()
737764
local validate_inprogress = function(input, ref)
738-
type_keys(':', input, ' ')
765+
type_every_key(':', input, ' ')
739766
validate_cmdline(ref .. ' ')
740767
type_keys('<Esc>')
741768
end
742769
local validate_final = function(input, ref)
743-
type_keys(':', input, '<CR>')
770+
type_every_key(':', input, '<CR>')
744771
eq(child.fn.histget('cmd', -1), ref)
745772
end
746773

@@ -805,7 +832,7 @@ T['Autocorrect']['works for other types'] = function()
805832
-- Neovim<0.11 has wrong `complpat` computation in this case
806833
if child.fn.has('nvim-0.11') == 1 then
807834
-- - No in-progress check since `:mapclear` expects single argument
808-
validate_final({ 'mapclear ', '<', 'bfr', '>' }, 'mapclear <buffer>')
835+
validate_final('mapclear <LT>bfr>', 'mapclear <buffer>')
809836
end
810837

811838
-- messages
@@ -833,31 +860,31 @@ T['Autocorrect']['works for other types'] = function()
833860
end
834861

835862
T['Autocorrect']['works multiple times'] = function()
836-
type_keys(':', 'srot', ' ')
863+
type_every_key(':', 'srot', ' ')
837864
validate_cmdline('sort ')
838865

839866
-- After delete
840-
type_keys('<C-u>', 'abvoelfet', ' ')
867+
type_every_key('<C-u>', 'abvoelfet', ' ')
841868
validate_cmdline('aboveleft ')
842869

843870
-- After another typed autocorrection
844-
type_keys('noutocmd', ' ')
871+
type_every_key('noutocmd', ' ')
845872
validate_cmdline('aboveleft noautocmd ')
846873

847-
type_keys('sort', ' ')
874+
type_every_key('sort', ' ')
848875
validate_cmdline('aboveleft noautocmd sort ')
849876
end
850877

851878
T['Autocorrect']['works only in `:` command type'] = function()
852879
local validate = function(keys, ref)
853880
eq(child.fn.mode(), 'n')
854-
type_keys(keys)
881+
type_every_key(keys)
855882
validate_cmdline(ref)
856883
type_keys('<Esc>', '<Esc>')
857884
end
858-
validate({ '/', 'srot', ' ' }, 'srot ')
859-
validate({ '?', 'srot', ' ' }, 'srot ')
860-
validate({ 'i', '<C-r>=', 'srot ' }, 'srot ')
885+
validate('/srot ', 'srot ')
886+
validate('?srot ', 'srot ')
887+
validate('i<C-r>=srot ', 'srot ')
861888
end
862889

863890
T['Autocorrect']['respects mappings'] = function()

0 commit comments

Comments
 (0)