diff options
Diffstat (limited to 'test/functional/lua/vim_spec.lua')
-rw-r--r-- | test/functional/lua/vim_spec.lua | 306 |
1 files changed, 263 insertions, 43 deletions
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 9b2697b3c2..e9e1f7ec12 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -4,6 +4,7 @@ local Screen = require('test.functional.ui.screen') local funcs = helpers.funcs local meths = helpers.meths +local dedent = helpers.dedent local command = helpers.command local clear = helpers.clear local eq = helpers.eq @@ -118,6 +119,11 @@ describe('lua stdlib', function() eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")')) end) + -- for brevity, match only the error header (not the traceback) + local function pcall_header(...) + return string.gsub(string.gsub(pcall_err(exec_lua, ...), '[\r\n].*', ''), '^Error executing lua: ', '') + end + it('vim.startswith', function() eq(true, funcs.luaeval('vim.startswith("123", "1")')) eq(true, funcs.luaeval('vim.startswith("123", "")')) @@ -128,8 +134,8 @@ describe('lua stdlib', function() eq(false, funcs.luaeval('vim.startswith("123", "2")')) eq(false, funcs.luaeval('vim.startswith("123", "1234")')) - eq("string", type(pcall_err(funcs.luaeval, 'vim.startswith("123", nil)'))) - eq("string", type(pcall_err(funcs.luaeval, 'vim.startswith(nil, "123")'))) + eq("vim/shared.lua:0: prefix: expected string, got nil", pcall_header 'return vim.startswith("123", nil)') + eq("vim/shared.lua:0: s: expected string, got nil", pcall_header 'return vim.startswith(nil, "123")') end) it('vim.endswith', function() @@ -142,8 +148,8 @@ describe('lua stdlib', function() eq(false, funcs.luaeval('vim.endswith("123", "2")')) eq(false, funcs.luaeval('vim.endswith("123", "1234")')) - eq("string", type(pcall_err(funcs.luaeval, 'vim.endswith("123", nil)'))) - eq("string", type(pcall_err(funcs.luaeval, 'vim.endswith(nil, "123")'))) + eq("vim/shared.lua:0: suffix: expected string, got nil", pcall_header 'return vim.endswith("123", nil)') + eq("vim/shared.lua:0: s: expected string, got nil", pcall_header 'return vim.endswith(nil, "123")') end) it("vim.str_utfindex/str_byteindex", function() @@ -257,16 +263,28 @@ describe('lua stdlib', function() } for _, t in ipairs(loops) do - matches(".*Infinite loop detected", pcall_err(split, t[1], t[2])) + eq("Error executing lua: vim/shared.lua:0: Infinite loop detected", pcall_err(split, t[1], t[2])) end -- Validates args. eq(true, pcall(split, 'string', 'string')) - eq('Error executing lua: .../shared.lua: s: expected string, got number', + eq(dedent([[ + Error executing lua: vim/shared.lua:0: s: expected string, got number + stack traceback: + vim/shared.lua:0: in function 'gsplit' + vim/shared.lua:0: in function <vim/shared.lua:0>]]), pcall_err(split, 1, 'string')) - eq('Error executing lua: .../shared.lua: sep: expected string, got number', + eq(dedent([[ + Error executing lua: vim/shared.lua:0: sep: expected string, got number + stack traceback: + vim/shared.lua:0: in function 'gsplit' + vim/shared.lua:0: in function <vim/shared.lua:0>]]), pcall_err(split, 'string', 1)) - eq('Error executing lua: .../shared.lua: plain: expected boolean, got number', + eq(dedent([[ + Error executing lua: vim/shared.lua:0: plain: expected boolean, got number + stack traceback: + vim/shared.lua:0: in function 'gsplit' + vim/shared.lua:0: in function <vim/shared.lua:0>]]), pcall_err(split, 'string', 'string', 1)) end) @@ -287,7 +305,10 @@ describe('lua stdlib', function() end -- Validates args. - eq('Error executing lua: .../shared.lua: s: expected string, got number', + eq(dedent([[ + Error executing lua: vim/shared.lua:0: s: expected string, got number + stack traceback: + vim/shared.lua:0: in function <vim/shared.lua:0>]]), pcall_err(trim, 2)) end) @@ -353,7 +374,7 @@ describe('lua stdlib', function() return t1.f() ~= t2.f() ]])) - eq('Error executing lua: .../shared.lua: Cannot deepcopy object of type thread', + eq('Error executing lua: vim/shared.lua:0: Cannot deepcopy object of type thread', pcall_err(exec_lua, [[ local thread = coroutine.create(function () return 0 end) local t = {thr = thread} @@ -366,7 +387,10 @@ describe('lua stdlib', function() eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]])) -- Validates args. - eq('Error executing lua: .../shared.lua: s: expected string, got number', + eq(dedent([[ + Error executing lua: vim/shared.lua:0: s: expected string, got number + stack traceback: + vim/shared.lua:0: in function <vim/shared.lua:0>]]), pcall_err(exec_lua, [[return vim.pesc(2)]])) end) @@ -491,19 +515,19 @@ describe('lua stdlib', function() return c.x.a == 1 and c.x.b == 2 and c.x.c == nil and count == 1 ]])) - eq('Error executing lua: .../shared.lua: invalid "behavior": nil', + eq('Error executing lua: vim/shared.lua:0: invalid "behavior": nil', pcall_err(exec_lua, [[ return vim.tbl_extend() ]]) ) - eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)', + eq('Error executing lua: vim/shared.lua:0: wrong number of arguments (given 1, expected at least 3)', pcall_err(exec_lua, [[ return vim.tbl_extend("keep") ]]) ) - eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)', + eq('Error executing lua: vim/shared.lua:0: wrong number of arguments (given 2, expected at least 3)', pcall_err(exec_lua, [[ return vim.tbl_extend("keep", {}) ]]) @@ -579,19 +603,19 @@ describe('lua stdlib', function() return vim.tbl_islist(c) and count == 0 ]])) - eq('Error executing lua: .../shared.lua: invalid "behavior": nil', + eq('Error executing lua: vim/shared.lua:0: invalid "behavior": nil', pcall_err(exec_lua, [[ return vim.tbl_deep_extend() ]]) ) - eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)', + eq('Error executing lua: vim/shared.lua:0: wrong number of arguments (given 1, expected at least 3)', pcall_err(exec_lua, [[ return vim.tbl_deep_extend("keep") ]]) ) - eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)', + eq('Error executing lua: vim/shared.lua:0: wrong number of arguments (given 2, expected at least 3)', pcall_err(exec_lua, [[ return vim.tbl_deep_extend("keep", {}) ]]) @@ -624,7 +648,10 @@ describe('lua stdlib', function() it('vim.list_extend', function() eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]]) - eq('Error executing lua: .../shared.lua: src: expected table, got nil', + eq(dedent([[ + Error executing lua: vim/shared.lua:0: src: expected table, got nil + stack traceback: + vim/shared.lua:0: in function <vim/shared.lua:0>]]), pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]])) eq({1,2}, exec_lua [[ return vim.list_extend({1}, {2;a=1}) ]]) eq(true, exec_lua [[ local a = {1} return vim.list_extend(a, {2;a=1}) == a ]]) @@ -648,7 +675,7 @@ describe('lua stdlib', function() assert(vim.deep_equal(a, { A = 1; [1] = 'A'; })) vim.tbl_add_reverse_lookup(a) ]] - matches('Error executing lua: .../shared.lua: The reverse lookup found an existing value for "[1A]" while processing key "[1A]"', + matches('^Error executing lua: vim/shared%.lua:0: The reverse lookup found an existing value for "[1A]" while processing key "[1A]"$', pcall_err(exec_lua, code)) end) @@ -820,34 +847,77 @@ describe('lua stdlib', function() exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}") exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}") - eq("Error executing lua: .../shared.lua: 1: expected table, got number", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: opt[1]: expected table, got number + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{ 1, 'x' }")) - eq("Error executing lua: .../shared.lua: invalid type name: x", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: invalid type name: x + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}")) - eq("Error executing lua: .../shared.lua: invalid type name: 1", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: invalid type name: 1 + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}")) - eq("Error executing lua: .../shared.lua: invalid type name: nil", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: invalid type name: nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}")) -- Validated parameters are required by default. - eq("Error executing lua: .../shared.lua: arg1: expected string, got nil", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}")) -- Explicitly required. - eq("Error executing lua: .../shared.lua: arg1: expected string, got nil", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}")) - eq("Error executing lua: .../shared.lua: arg1: expected table, got number", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg1: expected table, got number + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}")) - eq("Error executing lua: .../shared.lua: arg2: expected string, got number", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg2: expected string, got number + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}")) - eq("Error executing lua: .../shared.lua: arg2: expected string, got nil", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")) - eq("Error executing lua: .../shared.lua: arg2: expected string, got nil", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")) - eq("Error executing lua: .../shared.lua: arg1: expected even number, got 3", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg1: expected even number, got 3 + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}")) - eq("Error executing lua: .../shared.lua: arg1: expected ?, got 3", + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3 + stack traceback: + [string "<nvim>"]:0: in main chunk]]), pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}")) + + -- Pass an additional message back. + eq(dedent([[ + Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3. Info: TEST_MSG + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}")) end) it('vim.is_callable', function() @@ -1068,6 +1138,104 @@ describe('lua stdlib', function() eq({5,15}, exec_lua[[ return vim.region(0,{1,5},{1,14},'v',true)[1] ]]) end) + describe('vim.execute_on_keystroke', function() + it('should keep track of keystrokes', function() + helpers.insert([[hello world ]]) + + exec_lua [[ + KeysPressed = {} + + vim.register_keystroke_callback(function(buf) + if buf:byte() == 27 then + buf = "<ESC>" + end + + table.insert(KeysPressed, buf) + end) + ]] + + helpers.insert([[next 🤦 lines å ]]) + + -- It has escape in the keys pressed + eq('inext 🤦 lines å <ESC>', exec_lua [[return table.concat(KeysPressed, '')]]) + end) + + it('should allow removing trackers.', function() + helpers.insert([[hello world]]) + + exec_lua [[ + KeysPressed = {} + + return vim.register_keystroke_callback(function(buf) + if buf:byte() == 27 then + buf = "<ESC>" + end + + table.insert(KeysPressed, buf) + end, vim.api.nvim_create_namespace("logger")) + ]] + + helpers.insert([[next lines]]) + + exec_lua("vim.register_keystroke_callback(nil, vim.api.nvim_create_namespace('logger'))") + + helpers.insert([[more lines]]) + + -- It has escape in the keys pressed + eq('inext lines<ESC>', exec_lua [[return table.concat(KeysPressed, '')]]) + end) + + it('should not call functions that error again.', function() + helpers.insert([[hello world]]) + + exec_lua [[ + KeysPressed = {} + + return vim.register_keystroke_callback(function(buf) + if buf:byte() == 27 then + buf = "<ESC>" + end + + table.insert(KeysPressed, buf) + + if buf == 'l' then + error("Dumb Error") + end + end) + ]] + + helpers.insert([[next lines]]) + helpers.insert([[more lines]]) + + -- Only the first letter gets added. After that we remove the callback + eq('inext l', exec_lua [[ return table.concat(KeysPressed, '') ]]) + end) + + it('should process mapped keys, not unmapped keys', function() + exec_lua [[ + KeysPressed = {} + + vim.cmd("inoremap hello world") + + vim.register_keystroke_callback(function(buf) + if buf:byte() == 27 then + buf = "<ESC>" + end + + table.insert(KeysPressed, buf) + end) + ]] + + helpers.insert("hello") + + local next_status = exec_lua [[ + return table.concat(KeysPressed, '') + ]] + + eq("iworld<ESC>", next_status) + end) + end) + describe('vim.wait', function() before_each(function() exec_lua[[ @@ -1116,6 +1284,23 @@ describe('lua stdlib', function() ]]) end) + it('should not process non-fast events when commanded', function() + eq({wait_result = false}, exec_lua[[ + start_time = get_time() + + vim.g.timer_result = false + timer = vim.loop.new_timer() + timer:start(100, 0, vim.schedule_wrap(function() + vim.g.timer_result = true + end)) + + wait_result = vim.wait(300, function() return vim.g.timer_result end, nil, true) + + return { + wait_result = wait_result, + } + ]]) + end) it('should work with vim.defer_fn', function() eq({time = true, wait_result = true}, exec_lua[[ start_time = get_time() @@ -1130,22 +1315,32 @@ describe('lua stdlib', function() ]]) end) - it('should require functions to be passed', function() - local pcall_result = exec_lua [[ - return {pcall(function() vim.wait(1000, 13) end)} - ]] + it('should not crash when callback errors', function() + eq({false, '[string "<nvim>"]:1: As Expected'}, exec_lua [[ + return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)} + ]]) + end) - eq(pcall_result[1], false) - matches('condition must be a function', pcall_result[2]) + it('if callback is passed, it must be a function', function() + eq({false, 'vim.wait: if passed, condition must be a function'}, exec_lua [[ + return {pcall(function() vim.wait(1000, 13) end)} + ]]) end) - it('should not crash when callback errors', function() - local pcall_result = exec_lua [[ - return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)} - ]] + it('should allow waiting with no callback, explicit', function() + eq(true, exec_lua [[ + local start_time = vim.loop.hrtime() + vim.wait(50, nil) + return vim.loop.hrtime() - start_time > 25000 + ]]) + end) - eq(pcall_result[1], false) - matches('As Expected', pcall_result[2]) + it('should allow waiting with no callback, implicit', function() + eq(true, exec_lua [[ + local start_time = vim.loop.hrtime() + vim.wait(50) + return vim.loop.hrtime() - start_time > 25000 + ]]) end) it('should call callbacks exactly once if they return true immediately', function() @@ -1232,4 +1427,29 @@ describe('lua stdlib', function() eq(false, pcall_result) end) end) + + describe('vim.api.nvim_buf_call', function() + it('can access buf options', function() + local buf1 = meths.get_current_buf() + local buf2 = exec_lua [[ + buf2 = vim.api.nvim_create_buf(false, true) + return buf2 + ]] + + eq(false, meths.buf_get_option(buf1, 'autoindent')) + eq(false, meths.buf_get_option(buf2, 'autoindent')) + + local val = exec_lua [[ + return vim.api.nvim_buf_call(buf2, function() + vim.cmd "set autoindent" + return vim.api.nvim_get_current_buf() + end) + ]] + + eq(false, meths.buf_get_option(buf1, 'autoindent')) + eq(true, meths.buf_get_option(buf2, 'autoindent')) + eq(buf1, meths.get_current_buf()) + eq(buf2, val) + end) + end) end) |