neovim/test/functional/lua/vim_spec.lua

1352 lines
44 KiB
Lua
Raw Normal View History

2017-08-15 06:31:11 -07:00
-- Test suite for testing interactions with API bindings
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
2017-08-15 06:31:11 -07:00
local funcs = helpers.funcs
local meths = helpers.meths
local command = helpers.command
2017-08-15 06:31:11 -07:00
local clear = helpers.clear
local eq = helpers.eq
local ok = helpers.ok
2019-06-04 10:32:43 -07:00
local eval = helpers.eval
local feed = helpers.feed
local pcall_err = helpers.pcall_err
local exec_lua = helpers.exec_lua
local matches = helpers.matches
local contains = helpers.contains
local source = helpers.source
local NIL = helpers.NIL
2019-11-10 09:12:41 -07:00
local retry = helpers.retry
2017-08-15 06:31:11 -07:00
before_each(clear)
describe('lua stdlib', function()
2017-08-15 06:31:11 -07:00
-- İ: `tolower("İ")` is `i` which has length 1 while `İ` itself has
-- length 2 (in bytes).
-- Ⱥ: `tolower("Ⱥ")` is `ⱥ` which has length 2 while `Ⱥ` itself has
-- length 3 (in bytes).
--
-- Note: 'i' !=? 'İ' and 'ⱥ' !=? 'Ⱥ' on some systems.
-- Note: Built-in Nvim comparison (on systems lacking `strcasecmp`) works
-- only on ASCII characters.
2019-06-04 10:32:43 -07:00
it('vim.stricmp', function()
eq(0, funcs.luaeval('vim.stricmp("a", "A")'))
eq(0, funcs.luaeval('vim.stricmp("A", "a")'))
eq(0, funcs.luaeval('vim.stricmp("a", "a")'))
eq(0, funcs.luaeval('vim.stricmp("A", "A")'))
eq(0, funcs.luaeval('vim.stricmp("", "")'))
eq(0, funcs.luaeval('vim.stricmp("\\0", "\\0")'))
eq(0, funcs.luaeval('vim.stricmp("\\0\\0", "\\0\\0")'))
eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0", "\\0\\0\\0")'))
eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0A", "\\0\\0\\0a")'))
eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0A")'))
eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0a")'))
eq(0, funcs.luaeval('vim.stricmp("a\\0", "A\\0")'))
eq(0, funcs.luaeval('vim.stricmp("A\\0", "a\\0")'))
eq(0, funcs.luaeval('vim.stricmp("a\\0", "a\\0")'))
eq(0, funcs.luaeval('vim.stricmp("A\\0", "A\\0")'))
eq(0, funcs.luaeval('vim.stricmp("\\0a", "\\0A")'))
eq(0, funcs.luaeval('vim.stricmp("\\0A", "\\0a")'))
eq(0, funcs.luaeval('vim.stricmp("\\0a", "\\0a")'))
eq(0, funcs.luaeval('vim.stricmp("\\0A", "\\0A")'))
eq(0, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0A\\0")'))
eq(0, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0a\\0")'))
eq(0, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0a\\0")'))
eq(0, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0A\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("a", "B")'))
eq(-1, funcs.luaeval('vim.stricmp("A", "b")'))
eq(-1, funcs.luaeval('vim.stricmp("a", "b")'))
eq(-1, funcs.luaeval('vim.stricmp("A", "B")'))
eq(-1, funcs.luaeval('vim.stricmp("", "\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0", "\\0\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0\\0", "\\0\\0\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0A", "\\0\\0\\0b")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0B")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0b")'))
eq(-1, funcs.luaeval('vim.stricmp("a\\0", "B\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("A\\0", "b\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("a\\0", "b\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("A\\0", "B\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0a", "\\0B")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0A", "\\0b")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0a", "\\0b")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0A", "\\0B")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0B\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0b\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0b\\0")'))
eq(-1, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0B\\0")'))
eq(1, funcs.luaeval('vim.stricmp("c", "B")'))
eq(1, funcs.luaeval('vim.stricmp("C", "b")'))
eq(1, funcs.luaeval('vim.stricmp("c", "b")'))
eq(1, funcs.luaeval('vim.stricmp("C", "B")'))
eq(1, funcs.luaeval('vim.stricmp("\\0", "")'))
eq(1, funcs.luaeval('vim.stricmp("\\0\\0", "\\0")'))
eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0", "\\0\\0")'))
eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0\\0", "\\0\\0\\0")'))
eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0C", "\\0\\0\\0b")'))
eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0c", "\\0\\0\\0B")'))
eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0c", "\\0\\0\\0b")'))
eq(1, funcs.luaeval('vim.stricmp("c\\0", "B\\0")'))
eq(1, funcs.luaeval('vim.stricmp("C\\0", "b\\0")'))
eq(1, funcs.luaeval('vim.stricmp("c\\0", "b\\0")'))
eq(1, funcs.luaeval('vim.stricmp("C\\0", "B\\0")'))
eq(1, funcs.luaeval('vim.stricmp("c\\0", "B")'))
eq(1, funcs.luaeval('vim.stricmp("C\\0", "b")'))
eq(1, funcs.luaeval('vim.stricmp("c\\0", "b")'))
eq(1, funcs.luaeval('vim.stricmp("C\\0", "B")'))
eq(1, funcs.luaeval('vim.stricmp("\\0c", "\\0B")'))
eq(1, funcs.luaeval('vim.stricmp("\\0C", "\\0b")'))
eq(1, funcs.luaeval('vim.stricmp("\\0c", "\\0b")'))
eq(1, funcs.luaeval('vim.stricmp("\\0C", "\\0B")'))
eq(1, funcs.luaeval('vim.stricmp("\\0c\\0", "\\0B\\0")'))
eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0b\\0")'))
eq(1, funcs.luaeval('vim.stricmp("\\0c\\0", "\\0b\\0")'))
eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
2017-08-15 06:31:11 -07:00
end)
it('vim.startswith', function()
eq(true, funcs.luaeval('vim.startswith("123", "1")'))
eq(true, funcs.luaeval('vim.startswith("123", "")'))
eq(true, funcs.luaeval('vim.startswith("123", "123")'))
eq(true, funcs.luaeval('vim.startswith("", "")'))
eq(false, funcs.luaeval('vim.startswith("123", " ")'))
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")')))
end)
it('vim.endswith', function()
eq(true, funcs.luaeval('vim.endswith("123", "3")'))
eq(true, funcs.luaeval('vim.endswith("123", "")'))
eq(true, funcs.luaeval('vim.endswith("123", "123")'))
eq(true, funcs.luaeval('vim.endswith("", "")'))
eq(false, funcs.luaeval('vim.endswith("123", " ")'))
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")')))
end)
it("vim.str_utfindex/str_byteindex", function()
exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
local indicies32 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,29,33,34,35,37,38,40,42,44,46,48}
local indicies16 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,28,29,33,33,34,35,37,38,40,42,44,46,48}
for i,k in pairs(indicies32) do
eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ...)", i), i)
end
for i,k in pairs(indicies16) do
eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ..., true)", i), i)
end
local i32, i16 = 0, 0
for k = 0,48 do
if indicies32[i32] < k then
i32 = i32 + 1
end
if indicies16[i16] < k then
i16 = i16 + 1
if indicies16[i16+1] == indicies16[i16] then
i16 = i16 + 1
end
end
eq({i32, i16}, exec_lua("return {vim.str_utfindex(_G.test_text, ...)}", k), k)
end
end)
2019-06-04 10:32:43 -07:00
it("vim.schedule", function()
exec_lua([[
2019-06-04 10:32:43 -07:00
test_table = {}
vim.schedule(function()
table.insert(test_table, "xx")
end)
table.insert(test_table, "yy")
]])
eq({"yy","xx"}, exec_lua("return test_table"))
2019-06-04 10:32:43 -07:00
-- Validates args.
eq('Error executing lua: vim.schedule: expected function',
pcall_err(exec_lua, "vim.schedule('stringly')"))
eq('Error executing lua: vim.schedule: expected function',
pcall_err(exec_lua, "vim.schedule()"))
2019-06-04 10:32:43 -07:00
exec_lua([[
2019-06-04 10:32:43 -07:00
vim.schedule(function()
error("big failure\nvery async")
end)
]])
2019-06-04 10:32:43 -07:00
feed("<cr>")
eq('Error executing vim.schedule lua callback: [string "<nvim>"]:2: big failure\nvery async', eval("v:errmsg"))
local screen = Screen.new(60,5)
screen:set_default_attr_ids({
[1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {bold = true, reverse = true},
[3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[4] = {bold = true, foreground = Screen.colors.SeaGreen4},
})
screen:attach()
screen:expect{grid=[[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
-- nvim_command causes a vimL exception, check that it is properly caught
-- and propagated as an error message in async contexts.. #10809
exec_lua([[
vim.schedule(function()
vim.api.nvim_command(":echo 'err")
end)
]])
screen:expect{grid=[[
|
{2: }|
{3:Error executing vim.schedule lua callback: [string "<nvim>"]}|
{3::2: Vim(echo):E115: Missing quote: 'err} |
{4:Press ENTER or type command to continue}^ |
]]}
2019-06-04 10:32:43 -07:00
end)
it("vim.split", function()
local split = function(str, sep, plain)
return exec_lua('return vim.split(...)', str, sep, plain)
end
local tests = {
{ "a,b", ",", false, { 'a', 'b' } },
{ ":aa::bb:", ":", false, { '', 'aa', '', 'bb', '' } },
{ "::ee::ff:", ":", false, { '', '', 'ee', '', 'ff', '' } },
{ "ab", ".", false, { '', '', '' } },
{ "a1b2c", "[0-9]", false, { 'a', 'b', 'c' } },
{ "xy", "", false, { 'x', 'y' } },
{ "here be dragons", " ", false, { "here", "be", "dragons"} },
{ "axaby", "ab?", false, { '', 'x', 'y' } },
{ "f v2v v3v w2w ", "([vw])2%1", false, { 'f ', ' v3v ', ' ' } },
{ "", "", false, {} },
{ "", "a", false, { '' } },
{ "x*yz*oo*l", "*", true, { 'x', 'yz', 'oo', 'l' } },
}
for _, t in ipairs(tests) do
eq(t[4], split(t[1], t[2], t[3]))
end
local loops = {
{ "abc", ".-" },
}
for _, t in ipairs(loops) do
matches(".*Infinite loop detected", pcall_err(split, t[1], t[2]))
end
-- Validates args.
eq(true, pcall(split, 'string', 'string'))
contains('s: expected string, got number', pcall_err(split, 1, 'string'))
contains('sep: expected string, got number', pcall_err(split, 'string', 1))
contains('plain: expected boolean, got number', pcall_err(split, 'string', 'string', 1))
end)
2019-06-04 10:32:43 -07:00
it('vim.trim', function()
local trim = function(s)
return exec_lua('return vim.trim(...)', s)
end
local trims = {
{ " a", "a" },
{ " b ", "b" },
{ "\tc" , "c" },
{ "r\n", "r" },
}
for _, t in ipairs(trims) do
assert(t[2], trim(t[1]))
end
-- Validates args.
contains('s: expected string, got number', pcall_err(trim, 2))
end)
2019-06-04 10:32:43 -07:00
it('vim.inspect', function()
-- just make sure it basically works, it has its own test suite
local inspect = function(t, opts)
return exec_lua('return vim.inspect(...)', t, opts)
end
eq('2', inspect(2))
eq('{+a = {+b = 1+}+}',
inspect({ a = { b = 1 } }, { newline = '+', indent = '' }))
-- special value vim.inspect.KEY works
eq('{ KEY_a = "x", KEY_b = "y"}', exec_lua([[
return vim.inspect({a="x", b="y"}, {newline = '', process = function(item, path)
if path[#path] == vim.inspect.KEY then
return 'KEY_'..item
end
return item
end})
]]))
end)
2019-06-04 10:32:43 -07:00
it("vim.deepcopy", function()
ok(exec_lua([[
local a = { x = { 1, 2 }, y = 5}
local b = vim.deepcopy(a)
2020-03-02 00:38:43 -07:00
return b.x[1] == 1 and b.x[2] == 2 and b.y == 5 and vim.tbl_count(b) == 2
and tostring(a) ~= tostring(b)
]]))
ok(exec_lua([[
local a = {}
local b = vim.deepcopy(a)
2020-03-02 00:38:43 -07:00
return vim.tbl_islist(b) and vim.tbl_count(b) == 0 and tostring(a) ~= tostring(b)
]]))
ok(exec_lua([[
local a = vim.empty_dict()
local b = vim.deepcopy(a)
2020-03-02 00:38:43 -07:00
return not vim.tbl_islist(b) and vim.tbl_count(b) == 0
]]))
ok(exec_lua([[
local a = {x = vim.empty_dict(), y = {}}
local b = vim.deepcopy(a)
return not vim.tbl_islist(b.x) and vim.tbl_islist(b.y)
2020-03-02 00:38:43 -07:00
and vim.tbl_count(b) == 2
and tostring(a) ~= tostring(b)
]]))
ok(exec_lua([[
local f1 = function() return 1 end
local f2 = function() return 2 end
local t1 = {f = f1}
local t2 = vim.deepcopy(t1)
t1.f = f2
return t1.f() ~= t2.f()
]]))
eq('Error executing lua: .../shared.lua: Cannot deepcopy object of type thread',
pcall_err(exec_lua, [[
local thread = coroutine.create(function () return 0 end)
local t = {thr = thread}
vim.deepcopy(t)
]]))
end)
it('vim.pesc', function()
eq('foo%-bar', exec_lua([[return vim.pesc('foo-bar')]]))
eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]]))
-- Validates args.
contains('s: expected string, got number',
pcall_err(exec_lua, [[return vim.pesc(2)]]))
end)
it('vim.tbl_keys', function()
eq({}, exec_lua("return vim.tbl_keys({})"))
for _, v in pairs(exec_lua("return vim.tbl_keys({'a', 'b', 'c'})")) do
eq(true, exec_lua("return vim.tbl_contains({ 1, 2, 3 }, ...)", v))
end
for _, v in pairs(exec_lua("return vim.tbl_keys({a=1, b=2, c=3})")) do
eq(true, exec_lua("return vim.tbl_contains({ 'a', 'b', 'c' }, ...)", v))
end
end)
it('vim.tbl_values', function()
eq({}, exec_lua("return vim.tbl_values({})"))
for _, v in pairs(exec_lua("return vim.tbl_values({'a', 'b', 'c'})")) do
eq(true, exec_lua("return vim.tbl_contains({ 'a', 'b', 'c' }, ...)", v))
end
for _, v in pairs(exec_lua("return vim.tbl_values({a=1, b=2, c=3})")) do
eq(true, exec_lua("return vim.tbl_contains({ 1, 2, 3 }, ...)", v))
end
end)
it('vim.tbl_map', function()
eq({}, exec_lua([[
return vim.tbl_map(function(v) return v * 2 end, {})
]]))
eq({2, 4, 6}, exec_lua([[
return vim.tbl_map(function(v) return v * 2 end, {1, 2, 3})
]]))
eq({{i=2}, {i=4}, {i=6}}, exec_lua([[
return vim.tbl_map(function(v) return { i = v.i * 2 } end, {{i=1}, {i=2}, {i=3}})
]]))
end)
it('vim.tbl_filter', function()
eq({}, exec_lua([[
return vim.tbl_filter(function(v) return (v % 2) == 0 end, {})
]]))
eq({2}, exec_lua([[
return vim.tbl_filter(function(v) return (v % 2) == 0 end, {1, 2, 3})
]]))
eq({{i=2}}, exec_lua([[
return vim.tbl_filter(function(v) return (v.i % 2) == 0 end, {{i=1}, {i=2}, {i=3}})
]]))
end)
it('vim.tbl_islist', function()
2019-11-27 12:45:41 -07:00
eq(true, exec_lua("return vim.tbl_islist({})"))
eq(false, exec_lua("return vim.tbl_islist(vim.empty_dict())"))
eq(true, exec_lua("return vim.tbl_islist({'a', 'b', 'c'})"))
eq(false, exec_lua("return vim.tbl_islist({'a', '32', a='hello', b='baz'})"))
eq(false, exec_lua("return vim.tbl_islist({1, a='hello', b='baz'})"))
eq(false, exec_lua("return vim.tbl_islist({a='hello', b='baz', 1})"))
eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, a='hello'})"))
end)
it('vim.tbl_isempty', function()
eq(true, exec_lua("return vim.tbl_isempty({})"))
eq(false, exec_lua("return vim.tbl_isempty({ 1, 2, 3 })"))
eq(false, exec_lua("return vim.tbl_isempty({a=1, b=2, c=3})"))
end)
it('vim.tbl_extend', function()
ok(exec_lua([[
local a = {x = 1}
local b = {y = 2}
local c = vim.tbl_extend("keep", a, b)
2020-03-02 00:38:43 -07:00
return c.x == 1 and b.y == 2 and vim.tbl_count(c) == 2
]]))
ok(exec_lua([[
local a = {x = 1}
local b = {y = 2}
local c = {z = 3}
local d = vim.tbl_extend("keep", a, b, c)
2020-03-02 00:38:43 -07:00
return d.x == 1 and d.y == 2 and d.z == 3 and vim.tbl_count(d) == 3
]]))
ok(exec_lua([[
local a = {x = 1}
local b = {x = 3}
local c = vim.tbl_extend("keep", a, b)
2020-03-02 00:38:43 -07:00
return c.x == 1 and vim.tbl_count(c) == 1
]]))
ok(exec_lua([[
local a = {x = 1}
local b = {x = 3}
local c = vim.tbl_extend("force", a, b)
2020-03-02 00:38:43 -07:00
return c.x == 3 and vim.tbl_count(c) == 1
]]))
ok(exec_lua([[
local a = vim.empty_dict()
local b = {}
local c = vim.tbl_extend("keep", a, b)
2020-03-02 00:38:43 -07:00
return not vim.tbl_islist(c) and vim.tbl_count(c) == 0
]]))
ok(exec_lua([[
local a = {}
local b = vim.empty_dict()
local c = vim.tbl_extend("keep", a, b)
2020-03-02 00:38:43 -07:00
return vim.tbl_islist(c) and vim.tbl_count(c) == 0
]]))
2020-05-17 10:24:34 -07:00
ok(exec_lua([[
local a = {x = {a = 1, b = 2}}
local b = {x = {a = 2, c = {y = 3}}}
local c = vim.tbl_extend("keep", a, b)
local count = 0
for _ in pairs(c) do count = count + 1 end
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',
pcall_err(exec_lua, [[
return vim.tbl_extend()
]])
)
eq('Error executing lua: .../shared.lua: 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)',
pcall_err(exec_lua, [[
return vim.tbl_extend("keep", {})
]])
)
end)
2020-05-17 10:24:34 -07:00
it('vim.tbl_deep_extend', function()
ok(exec_lua([[
local a = {x = {a = 1, b = 2}}
local b = {x = {a = 2, c = {y = 3}}}
local c = vim.tbl_deep_extend("keep", a, b)
local count = 0
for _ in pairs(c) do count = count + 1 end
return c.x.a == 1 and c.x.b == 2 and c.x.c.y == 3 and count == 1
]]))
ok(exec_lua([[
local a = {x = {a = 1, b = 2}}
local b = {x = {a = 2, c = {y = 3}}}
local c = vim.tbl_deep_extend("force", a, b)
local count = 0
for _ in pairs(c) do count = count + 1 end
return c.x.a == 2 and c.x.b == 2 and c.x.c.y == 3 and count == 1
]]))
ok(exec_lua([[
local a = {x = {a = 1, b = 2}}
local b = {x = {a = 2, c = {y = 3}}}
local c = {x = {c = 4, d = {y = 4}}}
local d = vim.tbl_deep_extend("keep", a, b, c)
local count = 0
for _ in pairs(c) do count = count + 1 end
return d.x.a == 1 and d.x.b == 2 and d.x.c.y == 3 and d.x.d.y == 4 and count == 1
]]))
ok(exec_lua([[
local a = {x = {a = 1, b = 2}}
local b = {x = {a = 2, c = {y = 3}}}
local c = {x = {c = 4, d = {y = 4}}}
local d = vim.tbl_deep_extend("force", a, b, c)
local count = 0
for _ in pairs(c) do count = count + 1 end
return d.x.a == 2 and d.x.b == 2 and d.x.c == 4 and d.x.d.y == 4 and count == 1
]]))
ok(exec_lua([[
local a = vim.empty_dict()
local b = {}
local c = vim.tbl_deep_extend("keep", a, b)
local count = 0
for _ in pairs(c) do count = count + 1 end
return not vim.tbl_islist(c) and count == 0
]]))
ok(exec_lua([[
local a = {}
local b = vim.empty_dict()
local c = vim.tbl_deep_extend("keep", a, b)
local count = 0
for _ in pairs(c) do count = count + 1 end
return vim.tbl_islist(c) and count == 0
]]))
eq('Error executing lua: .../shared.lua: 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)',
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)',
pcall_err(exec_lua, [[
return vim.tbl_deep_extend("keep", {})
]])
)
end)
2020-03-02 00:38:43 -07:00
it('vim.tbl_count', function()
eq(0, exec_lua [[ return vim.tbl_count({}) ]])
eq(0, exec_lua [[ return vim.tbl_count(vim.empty_dict()) ]])
eq(0, exec_lua [[ return vim.tbl_count({nil}) ]])
eq(0, exec_lua [[ return vim.tbl_count({a=nil}) ]])
eq(1, exec_lua [[ return vim.tbl_count({1}) ]])
eq(2, exec_lua [[ return vim.tbl_count({1, 2}) ]])
eq(2, exec_lua [[ return vim.tbl_count({1, nil, 3}) ]])
eq(1, exec_lua [[ return vim.tbl_count({a=1}) ]])
eq(2, exec_lua [[ return vim.tbl_count({a=1, b=2}) ]])
eq(2, exec_lua [[ return vim.tbl_count({a=1, b=nil, c=3}) ]])
end)
it('vim.deep_equal', function()
eq(true, exec_lua [[ return vim.deep_equal({a=1}, {a=1}) ]])
eq(true, exec_lua [[ return vim.deep_equal({a={b=1}}, {a={b=1}}) ]])
eq(true, exec_lua [[ return vim.deep_equal({a={b={nil}}}, {a={b={}}}) ]])
eq(true, exec_lua [[ return vim.deep_equal({a=1, [5]=5}, {nil,nil,nil,nil,5,a=1}) ]])
eq(false, exec_lua [[ return vim.deep_equal(1, {nil,nil,nil,nil,5,a=1}) ]])
eq(false, exec_lua [[ return vim.deep_equal(1, 3) ]])
eq(false, exec_lua [[ return vim.deep_equal(nil, 3) ]])
eq(false, exec_lua [[ return vim.deep_equal({a=1}, {a=2}) ]])
end)
it('vim.list_extend', function()
eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]])
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 ]])
eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1) ]])
eq({}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 2) ]])
eq({}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1, -1) ]])
eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, -1, 2) ]])
contains('src: expected table, got nil', pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]]))
end)
it('vim.tbl_add_reverse_lookup', function()
eq(true, exec_lua [[
local a = { A = 1 }
vim.tbl_add_reverse_lookup(a)
return vim.deep_equal(a, { A = 1; [1] = 'A'; })
]])
-- Throw an error for trying to do it twice (run into an existing key)
local code = [[
local res = {}
local a = { A = 1 }
vim.tbl_add_reverse_lookup(a)
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]"',
pcall_err(exec_lua, code))
end)
it('vim.call, vim.fn', function()
eq(true, exec_lua([[return vim.call('sin', 0.0) == 0.0 ]]))
eq(true, exec_lua([[return vim.fn.sin(0.0) == 0.0 ]]))
-- compat: nvim_call_function uses "special" value for vimL float
eq(false, exec_lua([[return vim.api.nvim_call_function('sin', {0.0}) == 0.0 ]]))
source([[
func! FooFunc(test)
let g:test = a:test
return {}
endfunc
func! VarArg(...)
return a:000
endfunc
func! Nilly()
return [v:null, v:null]
endfunc
]])
eq(true, exec_lua([[return next(vim.fn.FooFunc(3)) == nil ]]))
eq(3, eval("g:test"))
-- compat: nvim_call_function uses "special" value for empty dict
eq(true, exec_lua([[return next(vim.api.nvim_call_function("FooFunc", {5})) == true ]]))
eq(5, eval("g:test"))
eq({2, "foo", true}, exec_lua([[return vim.fn.VarArg(2, "foo", true)]]))
eq(true, exec_lua([[
local x = vim.fn.Nilly()
return #x == 2 and x[1] == vim.NIL and x[2] == vim.NIL
]]))
eq({NIL, NIL}, exec_lua([[return vim.fn.Nilly()]]))
-- error handling
eq({false, 'Vim:E714: List required'}, exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]]))
end)
it('vim.rpcrequest and vim.rpcnotify', function()
exec_lua([[
chan = vim.fn.jobstart({'cat'}, {rpc=true})
vim.rpcrequest(chan, 'nvim_set_current_line', 'meow')
]])
eq('meow', meths.get_current_line())
command("let x = [3, 'aa', v:true, v:null]")
eq(true, exec_lua([[
ret = vim.rpcrequest(chan, 'nvim_get_var', 'x')
return #ret == 4 and ret[1] == 3 and ret[2] == 'aa' and ret[3] == true and ret[4] == vim.NIL
]]))
eq({3, 'aa', true, NIL}, exec_lua([[return ret]]))
2019-11-27 12:45:41 -07:00
eq({{}, {}, false, true}, exec_lua([[
vim.rpcrequest(chan, 'nvim_exec', 'let xx = {}\nlet yy = []', false)
local dict = vim.rpcrequest(chan, 'nvim_eval', 'xx')
local list = vim.rpcrequest(chan, 'nvim_eval', 'yy')
return {dict, list, vim.tbl_islist(dict), vim.tbl_islist(list)}
]]))
exec_lua([[
vim.rpcrequest(chan, 'nvim_set_var', 'aa', {})
vim.rpcrequest(chan, 'nvim_set_var', 'bb', vim.empty_dict())
]])
eq({1, 1}, eval('[type(g:aa) == type([]), type(g:bb) == type({})]'))
-- error handling
eq({false, 'Invalid channel: 23'},
exec_lua([[return {pcall(vim.rpcrequest, 23, 'foo')}]]))
eq({false, 'Invalid channel: 23'},
exec_lua([[return {pcall(vim.rpcnotify, 23, 'foo')}]]))
eq({false, 'Vim:E121: Undefined variable: foobar'},
exec_lua([[return {pcall(vim.rpcrequest, chan, 'nvim_eval', "foobar")}]]))
-- rpcnotify doesn't wait on request
eq('meow', exec_lua([[
vim.rpcnotify(chan, 'nvim_set_current_line', 'foo')
return vim.api.nvim_get_current_line()
]]))
2019-11-10 09:12:41 -07:00
retry(10, nil, function()
eq('foo', meths.get_current_line())
end)
local screen = Screen.new(50,7)
screen:set_default_attr_ids({
[1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {bold = true, reverse = true},
[3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[4] = {bold = true, foreground = Screen.colors.SeaGreen4},
})
screen:attach()
exec_lua([[
2019-11-27 12:45:41 -07:00
timer = vim.loop.new_timer()
timer:start(20, 0, function ()
-- notify ok (executed later when safe)
vim.rpcnotify(chan, 'nvim_set_var', 'yy', {3, vim.NIL})
-- rpcrequest an error
vim.rpcrequest(chan, 'nvim_set_current_line', 'bork')
end)
]])
screen:expect{grid=[[
foo |
{1:~ }|
{2: }|
{3:Error executing luv callback:} |
{3:[string "<nvim>"]:6: E5560: rpcrequest must not be}|
{3: called in a lua loop callback} |
{4:Press ENTER or type command to continue}^ |
]]}
feed('<cr>')
eq({3, NIL}, meths.get_var('yy'))
2019-11-27 12:45:41 -07:00
exec_lua([[timer:close()]])
end)
it('vim.empty_dict()', function()
eq({true, false, true, true}, exec_lua([[
vim.api.nvim_set_var('listy', {})
vim.api.nvim_set_var('dicty', vim.empty_dict())
local listy = vim.fn.eval("listy")
local dicty = vim.fn.eval("dicty")
return {vim.tbl_islist(listy), vim.tbl_islist(dicty), next(listy) == nil, next(dicty) == nil}
]]))
-- vim.empty_dict() gives new value each time
-- equality is not overriden (still by ref)
-- non-empty table uses the usual heuristics (ignores the tag)
eq({false, {"foo"}, {namey="bar"}}, exec_lua([[
local aa = vim.empty_dict()
local bb = vim.empty_dict()
local equally = (aa == bb)
aa[1] = "foo"
bb["namey"] = "bar"
return {equally, aa, bb}
]]))
eq("{ {}, vim.empty_dict() }", exec_lua("return vim.inspect({{}, vim.empty_dict()})"))
eq('{}', exec_lua([[ return vim.fn.json_encode(vim.empty_dict()) ]]))
eq('{"a": {}, "b": []}', exec_lua([[ return vim.fn.json_encode({a=vim.empty_dict(), b={}}) ]]))
end)
it('vim.validate', function()
2019-11-10 20:58:14 -07:00
exec_lua("vim.validate{arg1={{}, 'table' }}")
exec_lua("vim.validate{arg1={{}, 't' }}")
exec_lua("vim.validate{arg1={nil, 't', true }}")
exec_lua("vim.validate{arg1={{ foo='foo' }, 't' }}")
exec_lua("vim.validate{arg1={{ 'foo' }, 't' }}")
exec_lua("vim.validate{arg1={'foo', 'string' }}")
exec_lua("vim.validate{arg1={'foo', 's' }}")
exec_lua("vim.validate{arg1={'', 's' }}")
exec_lua("vim.validate{arg1={nil, 's', true }}")
exec_lua("vim.validate{arg1={1, 'number' }}")
exec_lua("vim.validate{arg1={1, 'n' }}")
exec_lua("vim.validate{arg1={0, 'n' }}")
exec_lua("vim.validate{arg1={0.1, 'n' }}")
exec_lua("vim.validate{arg1={nil, 'n', true }}")
exec_lua("vim.validate{arg1={true, 'boolean' }}")
exec_lua("vim.validate{arg1={true, 'b' }}")
exec_lua("vim.validate{arg1={false, 'b' }}")
exec_lua("vim.validate{arg1={nil, 'b', true }}")
exec_lua("vim.validate{arg1={function()end, 'function' }}")
exec_lua("vim.validate{arg1={function()end, 'f' }}")
exec_lua("vim.validate{arg1={nil, 'f', true }}")
exec_lua("vim.validate{arg1={nil, 'nil' }}")
exec_lua("vim.validate{arg1={nil, 'nil', true }}")
exec_lua("vim.validate{arg1={coroutine.create(function()end), 'thread' }}")
exec_lua("vim.validate{arg1={nil, 'thread', true }}")
exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}")
exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}")
contains("expected table, got number", pcall_err(exec_lua, "vim.validate{ 1, 'x' }"))
contains("invalid type name: x", pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
contains("invalid type name: 1", pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}"))
contains("invalid type name: nil", pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}"))
2019-11-10 20:58:14 -07:00
-- Validated parameters are required by default.
contains("arg1: expected string, got nil",
pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}"))
-- Explicitly required.
contains("arg1: expected string, got nil",
pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}"))
contains("arg1: expected table, got number",
2019-11-10 20:58:14 -07:00
pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}"))
contains("arg2: expected string, got number",
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}"))
contains("arg2: expected string, got nil",
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
contains("arg2: expected string, got nil",
2019-11-10 20:58:14 -07:00
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
contains("arg1: expected even number, got 3",
2019-11-10 20:58:14 -07:00
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
contains("arg1: expected %?, got 3",
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
end)
it('vim.is_callable', function()
eq(true, exec_lua("return vim.is_callable(function()end)"))
eq(true, exec_lua([[
local meta = { __call = function()end }
local function new_callable()
return setmetatable({}, meta)
end
local callable = new_callable()
return vim.is_callable(callable)
]]))
eq(false, exec_lua("return vim.is_callable(1)"))
eq(false, exec_lua("return vim.is_callable('foo')"))
eq(false, exec_lua("return vim.is_callable({})"))
end)
it('vim.g', function()
exec_lua [[
vim.api.nvim_set_var("testing", "hi")
vim.api.nvim_set_var("other", 123)
vim.api.nvim_set_var("to_delete", {hello="world"})
]]
eq('hi', funcs.luaeval "vim.g.testing")
eq(123, funcs.luaeval "vim.g.other")
eq(NIL, funcs.luaeval "vim.g.nonexistant")
eq({hello="world"}, funcs.luaeval "vim.g.to_delete")
exec_lua [[
vim.g.to_delete = nil
]]
eq(NIL, funcs.luaeval "vim.g.to_delete")
end)
it('vim.b', function()
exec_lua [[
vim.api.nvim_buf_set_var(0, "testing", "hi")
vim.api.nvim_buf_set_var(0, "other", 123)
vim.api.nvim_buf_set_var(0, "to_delete", {hello="world"})
]]
eq('hi', funcs.luaeval "vim.b.testing")
eq(123, funcs.luaeval "vim.b.other")
eq(NIL, funcs.luaeval "vim.b.nonexistant")
eq({hello="world"}, funcs.luaeval "vim.b.to_delete")
exec_lua [[
vim.b.to_delete = nil
]]
eq(NIL, funcs.luaeval "vim.b.to_delete")
exec_lua [[
vim.cmd "vnew"
]]
eq(NIL, funcs.luaeval "vim.b.testing")
eq(NIL, funcs.luaeval "vim.b.other")
eq(NIL, funcs.luaeval "vim.b.nonexistant")
end)
it('vim.w', function()
exec_lua [[
vim.api.nvim_win_set_var(0, "testing", "hi")
vim.api.nvim_win_set_var(0, "other", 123)
vim.api.nvim_win_set_var(0, "to_delete", {hello="world"})
]]
eq('hi', funcs.luaeval "vim.w.testing")
eq(123, funcs.luaeval "vim.w.other")
eq(NIL, funcs.luaeval "vim.w.nonexistant")
eq({hello="world"}, funcs.luaeval "vim.w.to_delete")
exec_lua [[
vim.w.to_delete = nil
]]
eq(NIL, funcs.luaeval "vim.w.to_delete")
exec_lua [[
vim.cmd "vnew"
]]
eq(NIL, funcs.luaeval "vim.w.testing")
eq(NIL, funcs.luaeval "vim.w.other")
eq(NIL, funcs.luaeval "vim.w.nonexistant")
end)
it('vim.t', function()
exec_lua [[
vim.api.nvim_tabpage_set_var(0, "testing", "hi")
vim.api.nvim_tabpage_set_var(0, "other", 123)
vim.api.nvim_tabpage_set_var(0, "to_delete", {hello="world"})
]]
eq('hi', funcs.luaeval "vim.t.testing")
eq(123, funcs.luaeval "vim.t.other")
eq(NIL, funcs.luaeval "vim.t.nonexistant")
eq({hello="world"}, funcs.luaeval "vim.t.to_delete")
exec_lua [[
vim.t.to_delete = nil
]]
eq(NIL, funcs.luaeval "vim.t.to_delete")
exec_lua [[
vim.cmd "tabnew"
]]
eq(NIL, funcs.luaeval "vim.t.testing")
eq(NIL, funcs.luaeval "vim.t.other")
eq(NIL, funcs.luaeval "vim.t.nonexistant")
end)
it('vim.env', function()
exec_lua [[
vim.fn.setenv("A", 123)
]]
eq('123', funcs.luaeval "vim.env.A")
eq(true, funcs.luaeval "vim.env.B == nil")
end)
it('vim.v', function()
eq(funcs.luaeval "vim.api.nvim_get_vvar('progpath')", funcs.luaeval "vim.v.progpath")
eq(false, funcs.luaeval "vim.v['false']")
eq(NIL, funcs.luaeval "vim.v.null")
end)
it('vim.bo', function()
eq('', funcs.luaeval "vim.bo.filetype")
exec_lua [[
vim.api.nvim_buf_set_option(0, "filetype", "markdown")
BUF = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_option(BUF, "modifiable", false)
]]
eq(false, funcs.luaeval "vim.bo.modified")
eq('markdown', funcs.luaeval "vim.bo.filetype")
eq(false, funcs.luaeval "vim.bo[BUF].modifiable")
exec_lua [[
vim.bo.filetype = ''
vim.bo[BUF].modifiable = true
]]
eq('', funcs.luaeval "vim.bo.filetype")
eq(true, funcs.luaeval "vim.bo[BUF].modifiable")
matches("^Error executing lua: .*: Invalid option name: 'nosuchopt'$",
pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
matches("^Error executing lua: .*: Expected lua string$",
pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
end)
it('vim.wo', function()
exec_lua [[
vim.api.nvim_win_set_option(0, "cole", 2)
vim.cmd "split"
vim.api.nvim_win_set_option(0, "cole", 2)
]]
eq(2, funcs.luaeval "vim.wo.cole")
exec_lua [[
vim.wo.conceallevel = 0
]]
eq(0, funcs.luaeval "vim.wo.cole")
eq(0, funcs.luaeval "vim.wo[0].cole")
eq(0, funcs.luaeval "vim.wo[1001].cole")
matches("^Error executing lua: .*: Invalid option name: 'notanopt'$",
pcall_err(exec_lua, 'return vim.wo.notanopt'))
matches("^Error executing lua: .*: Expected lua string$",
pcall_err(exec_lua, 'return vim.wo[0][0].list'))
eq(2, funcs.luaeval "vim.wo[1000].cole")
exec_lua [[
vim.wo[1000].cole = 0
]]
eq(0, funcs.luaeval "vim.wo[1000].cole")
end)
it('vim.cmd', function()
exec_lua [[
vim.cmd "autocmd BufNew * ++once lua BUF = vim.fn.expand('<abuf>')"
vim.cmd "new"
]]
eq('2', funcs.luaeval "BUF")
eq(2, funcs.luaeval "#vim.api.nvim_list_bufs()")
end)
it('vim.regex', function()
exec_lua [[
re1 = vim.regex"ab\\+c"
vim.cmd "set nomagic ignorecase"
re2 = vim.regex"xYz"
]]
eq({}, exec_lua[[return {re1:match_str("x ac")}]])
eq({3,7}, exec_lua[[return {re1:match_str("ac abbc")}]])
meths.buf_set_lines(0, 0, -1, true, {"yy", "abc abbc"})
eq({}, exec_lua[[return {re1:match_line(0, 0)}]])
eq({0,3}, exec_lua[[return {re1:match_line(0, 1)}]])
eq({3,7}, exec_lua[[return {re1:match_line(0, 1, 1)}]])
eq({3,7}, exec_lua[[return {re1:match_line(0, 1, 1, 8)}]])
eq({}, exec_lua[[return {re1:match_line(0, 1, 1, 7)}]])
eq({0,3}, exec_lua[[return {re1:match_line(0, 1, 0, 7)}]])
end)
it('vim.defer_fn', function()
2020-05-20 08:08:19 -07:00
eq(false, exec_lua [[
vim.g.test = false
vim.defer_fn(function() vim.g.test = true end, 150)
return vim.g.test
]])
exec_lua [[vim.wait(1000, function() return vim.g.test end)]]
eq(true, exec_lua[[return vim.g.test]])
end)
it('vim.region', function()
helpers.insert(helpers.dedent( [[
text tααt tααt text
text tαxt txtα tex
text tαxt tαxt
]]))
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)
2020-05-20 08:08:19 -07:00
describe('vim.wait', function()
before_each(function()
exec_lua[[
-- high precision timer
get_time = function()
return vim.fn.reltimefloat(vim.fn.reltime())
end
]]
end)
it('should run from lua', function()
exec_lua[[vim.wait(100, function() return true end)]]
end)
it('should wait the expected time if false', function()
eq({time = true, wait_result = {false, -1}}, exec_lua[[
start_time = get_time()
wait_succeed, wait_fail_val = vim.wait(200, function() return false end)
return {
-- 150ms waiting or more results in true. Flaky tests are bad.
time = (start_time + 0.15) < get_time(),
wait_result = {wait_succeed, wait_fail_val}
}
]])
end)
it('should not block other events', function()
eq({time = true, wait_result = true}, 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))
-- Would wait ten seconds if results blocked.
wait_result = vim.wait(10000, function() return vim.g.timer_result end)
return {
time = (start_time + 5) > get_time(),
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()
vim.defer_fn(function() vim.g.timer_result = true end, 100)
wait_result = vim.wait(10000, function() return vim.g.timer_result end)
return {
time = (start_time + 5) > get_time(),
wait_result = wait_result,
}
]])
end)
it('should require functions to be passed', function()
local pcall_result = exec_lua [[
return {pcall(function() vim.wait(1000, 13) end)}
]]
eq(pcall_result[1], false)
matches('condition must be a function', pcall_result[2])
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)}
]]
eq(pcall_result[1], false)
matches('As Expected', pcall_result[2])
end)
it('should call callbacks exactly once if they return true immediately', function()
eq(true, exec_lua [[
vim.g.wait_count = 0
vim.wait(1000, function()
vim.g.wait_count = vim.g.wait_count + 1
return true
end, 20)
return vim.g.wait_count == 1
]])
end)
it('should call callbacks few times with large `interval`', function()
eq(true, exec_lua [[
vim.g.wait_count = 0
vim.wait(50, function() vim.g.wait_count = vim.g.wait_count + 1 end, 200)
return vim.g.wait_count < 5
]])
end)
it('should play nice with `not` when fails', function()
eq(true, exec_lua [[
if not vim.wait(50, function() end) then
return true
end
return false
]])
end)
it('should play nice with `if` when success', function()
eq(true, exec_lua [[
if vim.wait(50, function() return true end) then
return true
end
return false
]])
end)
it('should return immediately with false if timeout is 0', function()
eq({false, -1}, exec_lua [[
return {
vim.wait(0, function() return false end)
}
]])
end)
it('should work with tables with __call', function()
eq(true, exec_lua [[
local t = setmetatable({}, {__call = function(...) return true end})
return vim.wait(100, t, 10)
]])
end)
it('should work with tables with __call that change', function()
eq(true, exec_lua [[
local t = {count = 0}
setmetatable(t, {
__call = function()
t.count = t.count + 1
return t.count > 3
end
})
return vim.wait(1000, t, 10)
]])
end)
it('should not work with negative intervals', function()
local pcall_result = exec_lua [[
return pcall(function() vim.wait(1000, function() return false end, -1) end)
]]
eq(false, pcall_result)
end)
it('should not work with weird intervals', function()
local pcall_result = exec_lua [[
return pcall(function() vim.wait(1000, function() return false end, 'a string value') end)
]]
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)
2020-05-20 08:08:19 -07:00
end)