diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/functional/api/server_requests_spec.lua | 61 | ||||
-rw-r--r-- | test/functional/ex_cmds/ctrl_c_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/terminal/window_spec.lua | 55 | ||||
-rw-r--r-- | test/functional/ui/cmdline_spec.lua | 525 |
4 files changed, 618 insertions, 25 deletions
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index 9f245d913b..4380e52b8b 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -109,7 +109,28 @@ describe('server -> client', function() end) describe('requests and notifications interleaved', function() - -- This tests that the following scenario won't happen: + it('does not delay notifications during pending request', function() + local received = false + local function on_setup() + eq("retval", funcs.rpcrequest(cid, "doit")) + stop() + end + local function on_request(method) + if method == "doit" then + funcs.rpcnotify(cid, "headsup") + eq(true,received) + return "retval" + end + end + local function on_notification(method) + if method == "headsup" then + received = true + end + end + run(on_request, on_notification, on_setup) + end) + + -- This tests the following scenario: -- -- server->client [request ] (1) -- client->server [request ] (2) triggered by (1) @@ -124,36 +145,38 @@ describe('server -> client', function() -- only deals with one server->client request at a time. (In other words, -- the client cannot send a response to a request that is not at the top -- of nvim's request stack). - -- - -- But above scenario shoudn't happen by the way notifications are dealt in - -- Nvim: they are only sent after there are no pending server->client - -- request(the request stack fully unwinds). So (3) is only sent after the - -- client returns (6). - it('works', function() - local expected = 300 - local notified = 0 + pending('will close connection if not properly synchronized', function() local function on_setup() eq('notified!', eval('rpcrequest('..cid..', "notify")')) end local function on_request(method) - eq('notify', method) - eq(1, eval('rpcnotify('..cid..', "notification")')) - return 'notified!' + if method == "notify" then + eq(1, eval('rpcnotify('..cid..', "notification")')) + return 'notified!' + elseif method == "nested" then + -- do some busywork, so the first request will return + -- before this one + for _ = 1, 5 do + eq(2, eval("1+1")) + end + eq(1, eval('rpcnotify('..cid..', "nested_done")')) + return 'done!' + end end local function on_notification(method) - eq('notification', method) - if notified == expected then - stop() - return + if method == "notification" then + eq('done!', eval('rpcrequest('..cid..', "nested")')) + elseif method == "nested_done" then + -- this should never have been sent + ok(false) end - notified = notified + 1 - eq('notified!', eval('rpcrequest('..cid..', "notify")')) end run(on_request, on_notification, on_setup) - eq(expected, notified) + -- ignore disconnect failure, otherwise detected by after_each + clear() end) end) diff --git a/test/functional/ex_cmds/ctrl_c_spec.lua b/test/functional/ex_cmds/ctrl_c_spec.lua index 091a008814..8f76099f79 100644 --- a/test/functional/ex_cmds/ctrl_c_spec.lua +++ b/test/functional/ex_cmds/ctrl_c_spec.lua @@ -47,7 +47,7 @@ describe("CTRL-C (mapped)", function() end -- The test is time-sensitive. Try different sleep values. - local ms_values = {1, 10, 100, 1000, 10000} + local ms_values = {100, 1000, 10000} for i, ms in ipairs(ms_values) do if i < #ms_values then local status, _ = pcall(test_ctrl_c, ms) diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua index 0f705cfe40..231618c5da 100644 --- a/test/functional/terminal/window_spec.lua +++ b/test/functional/terminal/window_spec.lua @@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local feed, clear = helpers.feed, helpers.clear local wait = helpers.wait +local iswin = helpers.iswin describe('terminal window', function() local screen @@ -11,9 +12,53 @@ describe('terminal window', function() screen = thelpers.screen_setup() end) - describe('with colorcolumn set', function() + describe("with 'number'", function() + it('wraps text', function() + feed([[<C-\><C-N>]]) + feed([[:set numberwidth=1 number<CR>i]]) + screen:expect([[ + {7:1 }tty ready | + {7:2 }rows: 6, cols: 48 | + {7:3 }{1: } | + {7:4 } | + {7:5 } | + {7:6 } | + {3:-- TERMINAL --} | + ]]) + thelpers.feed_data({'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'}) + screen:expect([[ + {7:1 }tty ready | + {7:2 }rows: 6, cols: 48 | + {7:3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV| + {7:4 }WXYZ{1: } | + {7:5 } | + {7:6 } | + {3:-- TERMINAL --} | + ]]) + + if iswin() then + return -- win: :terminal resize is unreliable #7007 + end + + -- numberwidth=9 + feed([[<C-\><C-N>]]) + feed([[:set numberwidth=9 number<CR>i]]) + thelpers.feed_data({' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'}) + screen:expect([[ + {7: 1 }tty ready | + {7: 2 }rows: 6, cols: 48 | + {7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO| + {7: 4 }WXYZ abcdefghijklmnopqrstuvwxyzABCDEFGHIJ| + {7: 5 }KLMNOPQRSTUVWXYZrows: 6, cols: 41 | + {7: 6 }{1: } | + {3:-- TERMINAL --} | + ]]) + end) + end) + + describe("with 'colorcolumn'", function() before_each(function() - feed('<c-\\><c-n>') + feed([[<C-\><C-N>]]) screen:expect([[ tty ready | {2:^ } | @@ -23,7 +68,7 @@ describe('terminal window', function() | | ]]) - feed(':set colorcolumn=20<cr>i') + feed(':set colorcolumn=20<CR>i') end) it('wont show the color column', function() @@ -41,7 +86,7 @@ describe('terminal window', function() describe('with fold set', function() before_each(function() - feed('<c-\\><c-n>:set foldenable foldmethod=manual<cr>i') + feed([[<C-\><C-N>:set foldenable foldmethod=manual<CR>i]]) thelpers.feed_data({'line1', 'line2', 'line3', 'line4', ''}) screen:expect([[ tty ready | @@ -55,7 +100,7 @@ describe('terminal window', function() end) it('wont show any folds', function() - feed('<c-\\><c-n>ggvGzf') + feed([[<C-\><C-N>ggvGzf]]) wait() screen:expect([[ ^tty ready | diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua new file mode 100644 index 0000000000..0f8302b036 --- /dev/null +++ b/test/functional/ui/cmdline_spec.lua @@ -0,0 +1,525 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq +local source = helpers.source +local ok = helpers.ok +local command = helpers.command + +describe('external cmdline', function() + local screen + local last_level = 0 + local cmdline = {} + local block = nil + + before_each(function() + clear() + cmdline, block = {}, nil + screen = Screen.new(25, 5) + screen:attach({rgb=true, ext_cmdline=true}) + screen:set_on_event_handler(function(name, data) + if name == "cmdline_show" then + local content, pos, firstc, prompt, indent, level = unpack(data) + ok(level > 0) + cmdline[level] = {content=content, pos=pos, firstc=firstc, + prompt=prompt, indent=indent} + last_level = level + elseif name == "cmdline_hide" then + local level = data[1] + cmdline[level] = nil + elseif name == "cmdline_special_char" then + local char, shift, level = unpack(data) + cmdline[level].special = {char, shift} + elseif name == "cmdline_pos" then + local pos, level = unpack(data) + cmdline[level].pos = pos + elseif name == "cmdline_block_show" then + block = data[1] + elseif name == "cmdline_block_append" then + block[#block+1] = data[1] + elseif name == "cmdline_block_hide" then + block = nil + end + end) + end) + + after_each(function() + screen:detach() + end) + + local function expect_cmdline(level, expected) + local attr_ids = screen._default_attr_ids + local attr_ignore = screen._default_attr_ignore + local actual = '' + for _, chunk in ipairs(cmdline[level] and cmdline[level].content or {}) do + local attrs, text = chunk[1], chunk[2] + if screen:_equal_attrs(attrs, {}) then + actual = actual..text + else + local attr_id = screen:_get_attr_id(attr_ids, attr_ignore, attrs) + actual = actual..'{' .. attr_id .. ':' .. text .. '}' + end + end + eq(expected, actual) + end + + it('works', function() + feed(':') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq(1, last_level) + eq({{ + content = { { {}, "" } }, + firstc = ":", + indent = 0, + pos = 0, + prompt = "" + }}, cmdline) + end) + + feed('sign') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "sign" } }, + firstc = ":", + indent = 0, + pos = 4, + prompt = "" + }}, cmdline) + end) + + feed('<Left>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "sign" } }, + firstc = ":", + indent = 0, + pos = 3, + prompt = "" + }}, cmdline) + end) + + feed('<bs>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "sin" } }, + firstc = ":", + indent = 0, + pos = 2, + prompt = "" + }}, cmdline) + end) + + feed('<Esc>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({}, cmdline) + end) + end) + + it("works with input()", function() + feed(':call input("input", "default")<cr>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "default" } }, + firstc = "", + indent = 0, + pos = 7, + prompt = "input" + }}, cmdline) + end) + feed('<cr>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({}, cmdline) + end) + + end) + + it("works with special chars and nested cmdline", function() + feed(':xx<c-r>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "xx" } }, + firstc = ":", + indent = 0, + pos = 2, + prompt = "", + special = {'"', true}, + }}, cmdline) + end) + + feed('=') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "xx" } }, + firstc = ":", + indent = 0, + pos = 2, + prompt = "", + special = {'"', true}, + },{ + content = { { {}, "" } }, + firstc = "=", + indent = 0, + pos = 0, + prompt = "", + }}, cmdline) + end) + + feed('1+2') + local expectation = {{ + content = { { {}, "xx" } }, + firstc = ":", + indent = 0, + pos = 2, + prompt = "", + special = {'"', true}, + },{ + content = { { {}, "1+2" } }, + firstc = "=", + indent = 0, + pos = 3, + prompt = "", + }} + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq(expectation, cmdline) + end) + + -- erase information, so we check if it is retransmitted + cmdline = {} + command("redraw!") + -- redraw! forgets cursor position. Be OK with that, as UI should indicate + -- focus is at external cmdline anyway. + screen:expect([[ + | + ~ | + ~ | + ~ | + ^ | + ]], nil, nil, function() + eq(expectation, cmdline) + end) + + + feed('<cr>') + screen:expect([[ + | + ~ | + ~ | + ~ | + ^ | + ]], nil, nil, function() + eq({{ + content = { { {}, "xx3" } }, + firstc = ":", + indent = 0, + pos = 3, + prompt = "", + }}, cmdline) + end) + + feed('<esc>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({}, cmdline) + end) + end) + + it("works with function definitions", function() + feed(':function Foo()<cr>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "" } }, + firstc = ":", + indent = 2, + pos = 0, + prompt = "", + }}, cmdline) + eq({{{{}, 'function Foo()'}}}, block) + end) + + feed('line1<cr>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{{{}, 'function Foo()'}}, + {{{}, ' line1'}}}, block) + end) + + block = {} + command("redraw!") + screen:expect([[ + | + ~ | + ~ | + ~ | + ^ | + ]], nil, nil, function() + eq({{{{}, 'function Foo()'}}, + {{{}, ' line1'}}}, block) + end) + + + feed('endfunction<cr>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq(nil, block) + end) + end) + + it("works with cmdline window", function() + feed(':make') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "make" } }, + firstc = ":", + indent = 0, + pos = 4, + prompt = "" + }}, cmdline) + end) + + feed('<c-f>') + screen:expect([[ + | + [No Name] | + :make^ | + [Command Line] | + | + ]], nil, nil, function() + eq({}, cmdline) + end) + + -- nested cmdline + feed(':yank') + screen:expect([[ + | + [No Name] | + :make^ | + [Command Line] | + | + ]], nil, nil, function() + eq({nil, { + content = { { {}, "yank" } }, + firstc = ":", + indent = 0, + pos = 4, + prompt = "" + }}, cmdline) + end) + + cmdline = {} + command("redraw!") + screen:expect([[ + | + [No Name] | + :make | + [Command Line] | + ^ | + ]], nil, nil, function() + eq({nil, { + content = { { {}, "yank" } }, + firstc = ":", + indent = 0, + pos = 4, + prompt = "" + }}, cmdline) + end) + + feed("<c-c>") + screen:expect([[ + | + [No Name] | + :make^ | + [Command Line] | + | + ]], nil, nil, function() + eq({}, cmdline) + end) + + feed("<c-c>") + screen:expect([[ + | + [No Name] | + :make^ | + [Command Line] | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "make" } }, + firstc = ":", + indent = 0, + pos = 4, + prompt = "" + }}, cmdline) + end) + + cmdline = {} + command("redraw!") + screen:expect([[ + | + ~ | + ~ | + ~ | + ^ | + ]], nil, nil, function() + eq({{ + content = { { {}, "make" } }, + firstc = ":", + indent = 0, + pos = 4, + prompt = "" + }}, cmdline) + end) + end) + + it('works with inputsecret()', function() + feed(":call inputsecret('secret:')<cr>abc123") + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({{ + content = { { {}, "******" } }, + firstc = "", + indent = 0, + pos = 6, + prompt = "secret:" + }}, cmdline) + end) + end) + + it('works with highlighted cmdline', function() + source([[ + highlight RBP1 guibg=Red + highlight RBP2 guibg=Yellow + highlight RBP3 guibg=Green + highlight RBP4 guibg=Blue + let g:NUM_LVLS = 4 + function RainBowParens(cmdline) + let ret = [] + let i = 0 + let lvl = 0 + while i < len(a:cmdline) + if a:cmdline[i] is# '(' + call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)]) + let lvl += 1 + elseif a:cmdline[i] is# ')' + let lvl -= 1 + call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)]) + endif + let i += 1 + endwhile + return ret + endfunction + map <f5> :let x = input({'prompt':'>','highlight':'RainBowParens'})<cr> + "map <f5> :let x = input({'prompt':'>'})<cr> + ]]) + screen:set_default_attr_ids({ + RBP1={background = Screen.colors.Red}, + RBP2={background = Screen.colors.Yellow}, + RBP3={background = Screen.colors.Green}, + RBP4={background = Screen.colors.Blue}, + EOB={bold = true, foreground = Screen.colors.Blue1}, + ERR={foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + SK={foreground = Screen.colors.Blue}, + PE={bold = true, foreground = Screen.colors.SeaGreen4} + }) + feed('<f5>(a(b)a)') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + | + ]], nil, nil, function() + expect_cmdline(1, '{RBP1:(}a{RBP2:(}b{RBP2:)}a{RBP1:)}') + end) + end) +end) |