aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/lua/diagnostic_spec.lua289
-rw-r--r--test/functional/lua/snippet_spec.lua27
-rw-r--r--test/functional/plugin/lsp/completion_spec.lua235
3 files changed, 461 insertions, 90 deletions
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index 05082bc132..76246fc2d1 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -843,17 +843,18 @@ describe('vim.diagnostic', function()
end)
end)
- describe('get_next_pos()', function()
+ describe('get_next()', function()
it('can find the next pos with only one namespace', function()
eq(
{ 1, 1 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- return vim.diagnostic.get_next_pos()
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ local next = vim.diagnostic.get_next()
+ return { next.lnum, next.col }
+ ]]
)
end)
@@ -861,14 +862,15 @@ describe('vim.diagnostic', function()
eq(
{ 4, 4 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- make_error('Diagnostic #2', 4, 4, 4, 4),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ local next = vim.diagnostic.get_next({ namespace = diagnostic_ns })
+ return { next.lnum, next.col }
+ ]]
)
end)
@@ -876,27 +878,29 @@ describe('vim.diagnostic', function()
eq(
{ 1, 1 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ local next = vim.diagnostic.get_next({ namespace = diagnostic_ns })
+ return { next.lnum, next.col }
+ ]]
)
end)
it('will not cycle when wrap is off', function()
eq(
- false,
+ vim.NIL,
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.diagnostic.get_next_pos { namespace = diagnostic_ns, wrap = false }
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ local next = vim.diagnostic.get_next({ namespace = diagnostic_ns, wrap = false })
+ return next
+ ]]
)
end)
@@ -904,13 +908,14 @@ describe('vim.diagnostic', function()
eq(
{ 4, 4 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #2', 4, 4, 4, 4),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1})
- return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1})
+ local prev = vim.diagnostic.get_prev({ namespace = diagnostic_ns })
+ return { prev.lnum, prev.col }
+ ]]
)
end)
@@ -918,15 +923,16 @@ describe('vim.diagnostic', function()
eq(
{ 4, 0 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 3, 9001, 3, 9001),
- make_error('Diagnostic #2', 4, 0, 4, 0),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {1, 1})
- vim.diagnostic.goto_next { float = false }
- return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 3, 9001, 3, 9001),
+ make_error('Diagnostic #2', 4, 0, 4, 0),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {1, 1})
+ vim.diagnostic.jump({ count = 1, float = false })
+ local next = vim.diagnostic.get_next({ namespace = diagnostic_ns })
+ return { next.lnum, next.col }
+ ]]
)
end)
@@ -935,13 +941,14 @@ describe('vim.diagnostic', function()
{ 4, 0 },
exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 3, 9001, 3, 9001),
- make_error('Diagnostic #2', 4, -1, 4, -1),
+ make_error('Diagnostic #1', 3, 9001, 3, 9001),
+ make_error('Diagnostic #2', 4, -1, 4, -1),
})
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {1, 1})
- vim.diagnostic.goto_next { float = false }
- return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
+ vim.diagnostic.jump({ count = 1, float = false })
+ local next = vim.diagnostic.get_next({ namespace = diagnostic_ns })
+ return { next.lnum, next.col }
]]
)
end)
@@ -1044,33 +1051,35 @@ describe('vim.diagnostic', function()
end)
end)
- describe('get_prev_pos()', function()
- it('can find the prev pos with only one namespace', function()
+ describe('get_prev()', function()
+ it('can find the previous diagnostic with only one namespace', function()
eq(
{ 1, 1 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.diagnostic.get_prev_pos()
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ local prev = vim.diagnostic.get_prev()
+ return { prev.lnum, prev.col }
+ ]]
)
end)
- it('can find prev pos with two errors', function()
+ it('can find the previous diagnostic with two errors', function()
eq(
{ 1, 1 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- make_error('Diagnostic #2', 4, 4, 4, 4),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ local prev = vim.diagnostic.get_prev({ namespace = diagnostic_ns })
+ return { prev.lnum, prev.col }
+ ]]
)
end)
@@ -1078,27 +1087,29 @@ describe('vim.diagnostic', function()
eq(
{ 4, 4 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #2', 4, 4, 4, 4),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ local prev = vim.diagnostic.get_prev({ namespace = diagnostic_ns })
+ return { prev.lnum, prev.col }
+ ]]
)
end)
it('respects wrap parameter', function()
eq(
- false,
+ vim.NIL,
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #2', 4, 4, 4, 4),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns, wrap = false}
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ local prev = vim.diagnostic.get_prev({ namespace = diagnostic_ns, wrap = false})
+ return prev
+ ]]
)
end)
@@ -1126,6 +1137,118 @@ describe('vim.diagnostic', function()
end)
end)
+ describe('jump()', function()
+ before_each(function()
+ exec_lua([[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 0, 0, 0, 2),
+ make_error('Diagnostic #2', 1, 1, 1, 4),
+ make_warning('Diagnostic #3', 2, -1, 2, -1),
+ make_info('Diagnostic #4', 3, 0, 3, 3),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ ]])
+ end)
+
+ it('can move forward', function()
+ eq(
+ { 2, 1 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 1, 0 })
+ vim.diagnostic.jump({ count = 1 })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 4, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 1, 0 })
+ vim.diagnostic.jump({ count = 3 })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 4, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 1, 0 })
+ vim.diagnostic.jump({ count = math.huge, wrap = false })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+ end)
+
+ it('can move backward', function()
+ eq(
+ { 3, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 4, 0 })
+ vim.diagnostic.jump({ count = -1 })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 1, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 4, 0 })
+ vim.diagnostic.jump({ count = -3 })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 1, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 4, 0 })
+ vim.diagnostic.jump({ count = -math.huge, wrap = false })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+ end)
+
+ it('can filter by severity', function()
+ eq(
+ { 3, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 1, 0 })
+ vim.diagnostic.jump({ count = 1, severity = vim.diagnostic.severity.WARN })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 3, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 1, 0 })
+ vim.diagnostic.jump({ count = 9999, severity = vim.diagnostic.severity.WARN })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+ end)
+
+ it('can wrap', function()
+ eq(
+ { 1, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 4, 0 })
+ vim.diagnostic.jump({ count = 1, wrap = true })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 4, 0 },
+ exec_lua([[
+ vim.api.nvim_win_set_cursor(0, { 1, 0 })
+ vim.diagnostic.jump({ count = -1, wrap = true })
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+ end)
+ end)
+
describe('get()', function()
it('returns an empty table when no diagnostics are present', function()
eq({}, exec_lua [[return vim.diagnostic.get(diagnostic_bufnr, {namespace=diagnostic_ns})]])
diff --git a/test/functional/lua/snippet_spec.lua b/test/functional/lua/snippet_spec.lua
index 413aa93994..bca0a59cb4 100644
--- a/test/functional/lua/snippet_spec.lua
+++ b/test/functional/lua/snippet_spec.lua
@@ -1,3 +1,5 @@
+---@diagnostic disable: no-unknown
+
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
@@ -16,11 +18,6 @@ local retry = t.retry
describe('vim.snippet', function()
before_each(function()
clear()
-
- exec_lua([[
- vim.keymap.set({ 'i', 's' }, '<Tab>', function() vim.snippet.jump(1) end, { buffer = true })
- vim.keymap.set({ 'i', 's' }, '<S-Tab>', function() vim.snippet.jump(-1) end, { buffer = true })
- ]])
end)
after_each(clear)
@@ -286,4 +283,24 @@ describe('vim.snippet', function()
]]
)
end)
+
+ it('restores snippet navigation keymaps', function()
+ -- Create a buffer keymap in insert mode that deletes all lines.
+ local curbuf = api.nvim_get_current_buf()
+ exec_lua('vim.api.nvim_buf_set_keymap(..., "i", "<Tab>", "<cmd>normal ggdG<cr>", {})', curbuf)
+
+ test_expand_success({ 'var $1 = $2' }, { 'var = ' })
+
+ -- While the snippet is active, <Tab> should navigate between tabstops.
+ feed('x')
+ poke_eventloop()
+ feed('<Tab>0')
+ eq({ 'var x = 0' }, buf_lines(0))
+
+ exec_lua('vim.snippet.stop()')
+
+ -- After exiting the snippet, the buffer keymap should be restored.
+ feed('<Esc>O<cr><Tab>')
+ eq({ '' }, buf_lines(0))
+ end)
end)
diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua
index 2798d57381..5b7232ad7e 100644
--- a/test/functional/plugin/lsp/completion_spec.lua
+++ b/test/functional/plugin/lsp/completion_spec.lua
@@ -1,9 +1,16 @@
---@diagnostic disable: no-unknown
local t = require('test.testutil')
+local t_lsp = require('test.functional.plugin.lsp.testutil')
local n = require('test.functional.testnvim')()
+local clear = n.clear
local eq = t.eq
+local neq = t.neq
local exec_lua = n.exec_lua
+local feed = n.feed
+local retry = t.retry
+
+local create_server_definition = t_lsp.create_server_definition
--- Convert completion results.
---
@@ -21,10 +28,11 @@ local function complete(line, candidates, lnum)
local line, cursor_col, lnum, result = ...
local line_to_cursor = line:sub(1, cursor_col)
local client_start_boundary = vim.fn.match(line_to_cursor, '\\k*$')
- local items, server_start_boundary = require("vim.lsp._completion")._convert_results(
+ local items, server_start_boundary = require("vim.lsp.completion")._convert_results(
line,
lnum,
cursor_col,
+ 1,
client_start_boundary,
nil,
result,
@@ -42,7 +50,7 @@ local function complete(line, candidates, lnum)
)
end
-describe('vim.lsp._completion', function()
+describe('vim.lsp.completion: item conversion', function()
before_each(n.clear)
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
@@ -159,6 +167,7 @@ describe('vim.lsp._completion', function()
end, result.items)
eq(expected, result)
end)
+
it('uses correct start boundary', function()
local completion_list = {
isIncomplete = false,
@@ -186,6 +195,7 @@ describe('vim.lsp._completion', function()
dup = 1,
empty = 1,
icase = 1,
+ info = '',
kind = 'Module',
menu = '',
word = 'this_thread',
@@ -240,6 +250,7 @@ describe('vim.lsp._completion', function()
dup = 1,
empty = 1,
icase = 1,
+ info = '',
kind = 'Module',
menu = '',
word = 'this_thread',
@@ -278,4 +289,224 @@ describe('vim.lsp._completion', function()
eq('item-property-has-priority', item.data)
eq({ line = 1, character = 1 }, item.textEdit.range.start)
end)
+
+ it(
+ 'uses insertText as textEdit.newText if there are editRange defaults but no textEditText',
+ function()
+ --- @type lsp.CompletionList
+ local completion_list = {
+ isIncomplete = false,
+ itemDefaults = {
+ editRange = {
+ start = { line = 1, character = 1 },
+ ['end'] = { line = 1, character = 4 },
+ },
+ insertTextFormat = 2,
+ data = 'foobar',
+ },
+ items = {
+ {
+ insertText = 'the-insertText',
+ label = 'hello',
+ data = 'item-property-has-priority',
+ },
+ },
+ }
+ local result = complete('|', completion_list)
+ eq(1, #result.items)
+ local text = result.items[1].user_data.nvim.lsp.completion_item.textEdit.newText
+ eq('the-insertText', text)
+ end
+ )
+end)
+
+describe('vim.lsp.completion: protocol', function()
+ before_each(function()
+ clear()
+ exec_lua(create_server_definition)
+ exec_lua([[
+ _G.capture = {}
+ vim.fn.complete = function(col, matches)
+ _G.capture.col = col
+ _G.capture.matches = matches
+ end
+ ]])
+ end)
+
+ after_each(clear)
+
+ --- @param completion_result lsp.CompletionList
+ --- @return integer
+ local function create_server(completion_result)
+ return exec_lua(
+ [[
+ local result = ...
+ local server = _create_server({
+ capabilities = {
+ completionProvider = {
+ triggerCharacters = { '.' }
+ }
+ },
+ handlers = {
+ ['textDocument/completion'] = function(_, _, callback)
+ callback(nil, result)
+ end
+ }
+ })
+
+ bufnr = vim.api.nvim_get_current_buf()
+ vim.api.nvim_win_set_buf(0, bufnr)
+ return vim.lsp.start({ name = 'dummy', cmd = server.cmd, on_attach = function(client, bufnr)
+ vim.lsp.completion.enable(true, client.id, bufnr)
+ end})
+ ]],
+ completion_result
+ )
+ end
+
+ local function assert_matches(fn)
+ retry(nil, nil, function()
+ fn(exec_lua('return _G.capture.matches'))
+ end)
+ end
+
+ --- @param pos { [1]: integer, [2]: integer }
+ local function trigger_at_pos(pos)
+ exec_lua(
+ [[
+ local win = vim.api.nvim_get_current_win()
+ vim.api.nvim_win_set_cursor(win, ...)
+ vim.lsp.completion.trigger()
+ ]],
+ pos
+ )
+
+ retry(nil, nil, function()
+ neq(nil, exec_lua('return _G.capture.col'))
+ end)
+ end
+
+ it('fetches completions and shows them using complete on trigger', function()
+ create_server({
+ isIncomplete = false,
+ items = {
+ {
+ label = 'hello',
+ },
+ },
+ })
+
+ feed('ih')
+ trigger_at_pos({ 1, 1 })
+
+ assert_matches(function(matches)
+ eq({
+ {
+ abbr = 'hello',
+ dup = 1,
+ empty = 1,
+ icase = 1,
+ info = '',
+ kind = 'Unknown',
+ menu = '',
+ user_data = {
+ nvim = {
+ lsp = {
+ client_id = 1,
+ completion_item = {
+ label = 'hello',
+ },
+ },
+ },
+ },
+ word = 'hello',
+ },
+ }, matches)
+ end)
+ end)
+
+ it('merges results from multiple clients', function()
+ create_server({
+ isIncomplete = false,
+ items = {
+ {
+ label = 'hello',
+ },
+ },
+ })
+ create_server({
+ isIncomplete = false,
+ items = {
+ {
+ label = 'hallo',
+ },
+ },
+ })
+
+ feed('ih')
+ trigger_at_pos({ 1, 1 })
+
+ assert_matches(function(matches)
+ eq(2, #matches)
+ eq('hello', matches[1].word)
+ eq('hallo', matches[2].word)
+ end)
+ end)
+
+ it('executes commands', function()
+ local completion_list = {
+ isIncomplete = false,
+ items = {
+ {
+ label = 'hello',
+ command = {
+ arguments = { '1', '0' },
+ command = 'dummy',
+ title = '',
+ },
+ },
+ },
+ }
+ local client_id = create_server(completion_list)
+
+ exec_lua(
+ [[
+ _G.called = false
+ local client = vim.lsp.get_client_by_id(...)
+ client.commands.dummy = function ()
+ _G.called = true
+ end
+ ]],
+ client_id
+ )
+
+ feed('ih')
+ trigger_at_pos({ 1, 1 })
+
+ exec_lua(
+ [[
+ local client_id, item = ...
+ vim.v.completed_item = {
+ user_data = {
+ nvim = {
+ lsp = {
+ client_id = client_id,
+ completion_item = item
+ }
+ }
+ }
+ }
+ ]],
+ client_id,
+ completion_list.items[1]
+ )
+
+ feed('<C-x><C-o><C-y>')
+
+ assert_matches(function(matches)
+ eq(1, #matches)
+ eq('hello', matches[1].word)
+ eq(true, exec_lua('return _G.called'))
+ end)
+ end)
end)