diff options
| author | William Boman <william@redwill.se> | 2021-12-25 15:11:42 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-25 15:11:42 +0100 |
| commit | d7e233566543d4c83199f5644f90bb116d7070f2 (patch) | |
| tree | ecfcb6e5abb937ee976eed6daac1bf2ab3bac51d /tests | |
| parent | fix: dont pass nil opts (diff) | |
| download | mason-d7e233566543d4c83199f5644f90bb116d7070f2.tar mason-d7e233566543d4c83199f5644f90bb116d7070f2.tar.gz mason-d7e233566543d4c83199f5644f90bb116d7070f2.tar.bz2 mason-d7e233566543d4c83199f5644f90bb116d7070f2.tar.lz mason-d7e233566543d4c83199f5644f90bb116d7070f2.tar.xz mason-d7e233566543d4c83199f5644f90bb116d7070f2.tar.zst mason-d7e233566543d4c83199f5644f90bb116d7070f2.zip | |
add some tests (#360)
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/README.md | 1 | ||||
| -rw-r--r-- | tests/data_spec.lua | 135 | ||||
| -rw-r--r-- | tests/dispatcher_spec.lua | 24 | ||||
| -rw-r--r-- | tests/fs_spec.lua | 18 | ||||
| -rw-r--r-- | tests/luassertx/lua/luassertx.lua | 27 | ||||
| -rw-r--r-- | tests/minimal_init.vim | 30 | ||||
| -rw-r--r-- | tests/path_spec.lua | 23 | ||||
| -rw-r--r-- | tests/server_spec.lua | 56 | ||||
| -rw-r--r-- | tests/ui_spec.lua | 249 |
9 files changed, 563 insertions, 0 deletions
diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..bd9259d4 --- /dev/null +++ b/tests/README.md @@ -0,0 +1 @@ +Refer to https://github.com/williamboman/nvim-lspconfig-test for system tests. diff --git a/tests/data_spec.lua b/tests/data_spec.lua new file mode 100644 index 00000000..0e13d44c --- /dev/null +++ b/tests/data_spec.lua @@ -0,0 +1,135 @@ +local Data = require "nvim-lsp-installer.data" +local spy = require "luassert.spy" + +describe("data", function() + it("creates enums", function() + local colors = Data.enum { + "BLUE", + "YELLOW", + } + assert.equal( + vim.inspect { + ["BLUE"] = "BLUE", + ["YELLOW"] = "YELLOW", + }, + vim.inspect(colors) + ) + end) + + it("creates sets", function() + local colors = Data.set_of { + "BLUE", + "YELLOW", + "BLUE", + "RED", + } + assert.equal( + vim.inspect { + ["BLUE"] = true, + ["YELLOW"] = true, + ["RED"] = true, + }, + vim.inspect(colors) + ) + end) + + it("reverses lists", function() + local colors = { "BLUE", "YELLOW", "RED" } + assert.equal( + vim.inspect { + "RED", + "YELLOW", + "BLUE", + }, + vim.inspect(Data.list_reverse(colors)) + ) + -- should not modify in-place + assert.equal(vim.inspect { "BLUE", "YELLOW", "RED" }, vim.inspect(colors)) + end) + + it("maps over list", function() + local colors = { "BLUE", "YELLOW", "RED" } + assert.equal( + vim.inspect { + "LIGHT_BLUE1", + "LIGHT_YELLOW2", + "LIGHT_RED3", + }, + vim.inspect(Data.list_map(function(color, i) + return "LIGHT_" .. color .. i + end, colors)) + ) + -- should not modify in-place + assert.equal(vim.inspect { "BLUE", "YELLOW", "RED" }, vim.inspect(colors)) + end) + + it("coalesces first non-nil value", function() + assert.equal("Hello World!", Data.coalesce(nil, nil, "Hello World!", "")) + end) + + it("makes a shallow copy of a list", function() + local list = { "BLUE", { nested = "TABLE" }, "RED" } + local list_copy = Data.list_copy(list) + assert.equal(vim.inspect { "BLUE", { nested = "TABLE" }, "RED" }, vim.inspect(list_copy)) + assert.is_not.is_true(list == list_copy) + assert.is_true(list[2] == list_copy[2]) + end) + + it("finds first item that fulfills predicate", function() + local predicate = spy.new(function(item) + return item == "Waldo" + end) + + assert.equal( + "Waldo", + Data.list_find_first({ + "Where", + "On Earth", + "Is", + "Waldo", + "?", + }, predicate) + ) + assert.spy(predicate).was.called(4) + end) + + it("determines whether any item in the list fulfills predicate", function() + local predicate = spy.new(function(item) + return item == "On Earth" + end) + + assert.is_true(Data.list_any({ + "Where", + "On Earth", + "Is", + "Waldo", + "?", + }, predicate)) + + assert.spy(predicate).was.called(2) + end) + + it("memoizes functions with default cache mechanism", function() + local expensive_function = spy.new(function(s) + return s + end) + local memoized_fn = Data.memoize(expensive_function) + assert.equal("key", memoized_fn "key") + assert.equal("key", memoized_fn "key") + assert.equal("new_key", memoized_fn "new_key") + assert.spy(expensive_function).was_called(2) + end) + + it("memoizes function with custom cache mechanism", function() + local expensive_function = spy.new(function(arg1, arg2) + return arg1 .. arg2 + end) + local memoized_fn = Data.memoize(expensive_function, function(arg1, arg2) + return arg1 .. arg2 + end) + assert.equal("key1key2", memoized_fn("key1", "key2")) + assert.equal("key1key2", memoized_fn("key1", "key2")) + assert.equal("key1key3", memoized_fn("key1", "key3")) + assert.spy(expensive_function).was_called(2) + end) +end) diff --git a/tests/dispatcher_spec.lua b/tests/dispatcher_spec.lua new file mode 100644 index 00000000..da2148bc --- /dev/null +++ b/tests/dispatcher_spec.lua @@ -0,0 +1,24 @@ +local dispatcher = require "nvim-lsp-installer.dispatcher" +local spy = require "luassert.spy" + +describe("dispatcher", function() + it("calls registered callbacks", function() + local server = {} + local callback = spy.new() + dispatcher.register_server_ready_callback(callback) + dispatcher.dispatch_server_ready(server) + + assert.spy(callback).was_called(1) + assert.spy(callback).was_called_with(server) + end) + + it("deregisters callbacks", function() + local server = {} + local callback = spy.new() + local deregister = dispatcher.register_server_ready_callback(callback) + deregister() + dispatcher.dispatch_server_ready(server) + + assert.spy(callback).was_not_called() + end) +end) diff --git a/tests/fs_spec.lua b/tests/fs_spec.lua new file mode 100644 index 00000000..e227b9da --- /dev/null +++ b/tests/fs_spec.lua @@ -0,0 +1,18 @@ +local fs = require "nvim-lsp-installer.fs" +local lsp_installer = require "nvim-lsp-installer" + +describe("fs", function() + before_each(function() + lsp_installer.settings { + install_root_dir = "/foo", + } + end) + + it("refuses to rmrf unsafe paths", function() + local e = assert.has.errors(function() + fs.rmrf "/thisisa/path" + end) + + assert.equal("Refusing to operate on path (/thisisa/path) outside of the servers root dir (/foo).", e) + end) +end) diff --git a/tests/luassertx/lua/luassertx.lua b/tests/luassertx/lua/luassertx.lua new file mode 100644 index 00000000..33fa9957 --- /dev/null +++ b/tests/luassertx/lua/luassertx.lua @@ -0,0 +1,27 @@ +local a = require "plenary.async" +local assert = require "luassert" + +local function wait_for(_, arguments) + ---@type fun() @Function to execute until it does not error. + local assertions_fn = arguments[1] + ---@type number @Timeout in milliseconds. Defaults to 5000. + local timeout = arguments[2] + timeout = timeout or 15000 + + local start = vim.loop.hrtime() + local is_ok, err + repeat + is_ok, err = pcall(assertions_fn) + if not is_ok then + a.util.sleep(math.min(timeout, 100)) + end + until is_ok or ((vim.loop.hrtime() - start) / 1e6) > timeout + + if not is_ok then + error(err) + end + + return is_ok +end + +assert:register("assertion", "wait_for", wait_for) diff --git a/tests/minimal_init.vim b/tests/minimal_init.vim new file mode 100644 index 00000000..d0fe4e41 --- /dev/null +++ b/tests/minimal_init.vim @@ -0,0 +1,30 @@ +" Avoid neovim/neovim#11362 +set display=lastline +set directory="" +set noswapfile + +let $lsp_installer = getcwd() +let $luassertx_rtp = getcwd() .. "/tests/luassertx" +let $dependencies = getcwd() .. "/dependencies" + +set rtp+=$lsp_installer,$luassertx_rtp +set packpath=$dependencies + +packloadall + +" Luassert extensions +lua require("luassertx") + +lua <<EOF +require("nvim-lsp-installer").settings { + install_root_dir = os.getenv("INSTALL_ROOT_DIR"), +} +EOF + +function! RunTests() abort + lua <<EOF + require("plenary.test_harness").test_directory(os.getenv("FILE") or "./tests", { + minimal_init = vim.fn.getcwd() .. "/tests/minimal_init.vim", + }) +EOF +endfunction diff --git a/tests/path_spec.lua b/tests/path_spec.lua new file mode 100644 index 00000000..3ccaf3ad --- /dev/null +++ b/tests/path_spec.lua @@ -0,0 +1,23 @@ +local path = require "nvim-lsp-installer.path" + +describe("path", function() + it("concatenates paths", function() + assert.equal("foo/bar/baz/~", path.concat { "foo", "bar", "baz", "~" }) + end) + + it("concatenates paths on Windows", function() + local old_os = jit.os + jit.os = "windows" + package.loaded["nvim-lsp-installer.path"] = nil + local path = require "nvim-lsp-installer.path" + assert.equal([[foo\bar\baz\~]], path.concat { "foo", "bar", "baz", "~" }) + jit.os = old_os + end) + + it("identifies subdirectories", function() + assert.is_true(path.is_subdirectory("/foo/bar", "/foo/bar/baz")) + assert.is_true(path.is_subdirectory("/foo/bar", "/foo/bar")) + assert.is_false(path.is_subdirectory("/foo/bar", "/foo/bas/baz")) + assert.is_false(path.is_subdirectory("/foo/bar", "/foo/bars/baz")) + end) +end) diff --git a/tests/server_spec.lua b/tests/server_spec.lua new file mode 100644 index 00000000..0695710e --- /dev/null +++ b/tests/server_spec.lua @@ -0,0 +1,56 @@ +local lsp_installer = require "nvim-lsp-installer" +local server = require "nvim-lsp-installer.server" +local spy = require "luassert.spy" +local a = require "plenary.async" + +describe("server", function() + a.tests.it("calls registered on_ready handlers upon successful installation", function() + local on_ready_handler = spy.new() + local generic_handler = spy.new() + + lsp_installer.on_server_ready(generic_handler) + + local srv = server.Server:new { + name = "on_ready_fixture", + root_dir = server.get_server_root_path "on_ready_fixture", + installer = function(_, callback) + callback(true) + end, + default_options = { + cmd = { "my-server" }, + }, + } + srv:on_ready(on_ready_handler) + srv:install() + assert.wait_for(function() + assert.spy(on_ready_handler).was_called(1) + assert.spy(generic_handler).was_called(1) + assert.spy(generic_handler).was_called_with(srv) + end) + assert.is_true(srv:is_installed()) + end) + + a.tests.it("doesn't call on_ready handler when server fails installation", function() + local on_ready_handler = spy.new() + local generic_handler = spy.new() + + lsp_installer.on_server_ready(generic_handler) + + local srv = server.Server:new { + name = "on_ready_fixture_failing", + root_dir = server.get_server_root_path "on_ready_fixture_failing", + installer = function(_, callback) + callback(false) + end, + default_options = { + cmd = { "my-server" }, + }, + } + srv:on_ready(on_ready_handler) + srv:install() + a.util.sleep(500) + assert.spy(on_ready_handler).was_not_called() + assert.spy(generic_handler).was_not_called() + assert.is_false(srv:is_installed()) + end) +end) diff --git a/tests/ui_spec.lua b/tests/ui_spec.lua new file mode 100644 index 00000000..df771a4d --- /dev/null +++ b/tests/ui_spec.lua @@ -0,0 +1,249 @@ +local display = require "nvim-lsp-installer.ui.display" +local match = require "luassert.match" +local spy = require "luassert.spy" +local Ui = require "nvim-lsp-installer.ui" +local a = require "plenary.async" + +describe("ui", function() + it("produces a correct tree", function() + local function renderer(state) + return Ui.CascadingStyleNode({ "INDENT" }, { + Ui.When(not state.is_active, function() + return Ui.Text { + "I'm not active", + "Another line", + } + end), + Ui.When(state.is_active, function() + return Ui.Text { + "I'm active", + "Yet another line", + } + end), + }) + end + + assert.equal( + vim.inspect { + children = { + { + type = "HL_TEXT", + lines = { + { { "I'm not active", "" } }, + { { "Another line", "" } }, + }, + }, + { + type = "NODE", + children = {}, + }, + }, + styles = { "INDENT" }, + type = "CASCADING_STYLE", + }, + vim.inspect(renderer { is_active = false }) + ) + + assert.equal( + vim.inspect { + children = { + { + type = "NODE", + children = {}, + }, + { + type = "HL_TEXT", + lines = { + { { "I'm active", "" } }, + { { "Yet another line", "" } }, + }, + }, + }, + styles = { "INDENT" }, + type = "CASCADING_STYLE", + }, + vim.inspect(renderer { is_active = true }) + ) + end) + + it("renders a tree correctly", function() + local render_output = display._render_node( + { + win_width = 120, + }, + Ui.CascadingStyleNode({ "INDENT" }, { + Ui.Keybind("i", "INSTALL_SERVER", { "sumneko_lua" }, true), + Ui.HlTextNode { + { + { "Hello World!", "MyHighlightGroup" }, + }, + { + { "Another Line", "Comment" }, + }, + }, + Ui.HlTextNode { + { + { "Install something idk", "Stuff" }, + }, + }, + Ui.Keybind("<CR>", "INSTALL_SERVER", { "tsserver" }, false), + Ui.Text { "I'm a text node" }, + }) + ) + + assert.equal( + vim.inspect { + highlights = { + { + col_start = 2, + col_end = 14, + line = 0, + hl_group = "MyHighlightGroup", + }, + { + col_start = 2, + col_end = 14, + line = 1, + hl_group = "Comment", + }, + { + col_start = 2, + col_end = 23, + line = 2, + hl_group = "Stuff", + }, + }, + lines = { " Hello World!", " Another Line", " Install something idk", " I'm a text node" }, + virt_texts = {}, + keybinds = { + { + effect = "INSTALL_SERVER", + key = "i", + line = -1, + payload = { "sumneko_lua" }, + }, + { + effect = "INSTALL_SERVER", + key = "<CR>", + line = 3, + payload = { "tsserver" }, + }, + }, + }, + vim.inspect(render_output) + ) + end) +end) + +describe("integration test", function() + a.tests.it("calls vim APIs as expected during rendering", function() + local window = display.new_view_only_win "test" + + window.view(function(state) + return Ui.Node { + Ui.Keybind("U", "EFFECT", nil, true), + Ui.Text { + "Line number 1!", + state.text, + }, + Ui.Keybind("R", "R_EFFECT", { state.text }), + Ui.HlTextNode { + { + { "My highlighted text", "MyHighlightGroup" }, + }, + }, + } + end) + + local mutate_state = window.init { text = "Initial state" } + + window.open { + effects = { + ["EFFECT"] = function() end, + ["R_EFFECT"] = function() end, + }, + highlight_groups = { + "hi def MyHighlight gui=bold", + }, + } + + local clear_namespace = spy.on(vim.api, "nvim_buf_clear_namespace") + local buf_set_option = spy.on(vim.api, "nvim_buf_set_option") + local win_set_option = spy.on(vim.api, "nvim_win_set_option") + local set_lines = spy.on(vim.api, "nvim_buf_set_lines") + local set_extmark = spy.on(vim.api, "nvim_buf_set_extmark") + local add_highlight = spy.on(vim.api, "nvim_buf_add_highlight") + local set_keymap = spy.on(vim.api, "nvim_buf_set_keymap") + + -- Initial window and buffer creation + initial render + a.util.scheduler() + + assert.spy(win_set_option).was_called(8) + assert.spy(win_set_option).was_called_with(match.is_number(), "number", false) + assert.spy(win_set_option).was_called_with(match.is_number(), "relativenumber", false) + assert.spy(win_set_option).was_called_with(match.is_number(), "wrap", false) + assert.spy(win_set_option).was_called_with(match.is_number(), "spell", false) + assert.spy(win_set_option).was_called_with(match.is_number(), "foldenable", false) + assert.spy(win_set_option).was_called_with(match.is_number(), "signcolumn", "no") + assert.spy(win_set_option).was_called_with(match.is_number(), "colorcolumn", "") + assert.spy(win_set_option).was_called_with(match.is_number(), "cursorline", true) + + assert.spy(buf_set_option).was_called(9) + assert.spy(buf_set_option).was_called_with(match.is_number(), "modifiable", false) + assert.spy(buf_set_option).was_called_with(match.is_number(), "swapfile", false) + assert.spy(buf_set_option).was_called_with(match.is_number(), "textwidth", 0) + assert.spy(buf_set_option).was_called_with(match.is_number(), "buftype", "nofile") + assert.spy(buf_set_option).was_called_with(match.is_number(), "bufhidden", "wipe") + assert.spy(buf_set_option).was_called_with(match.is_number(), "buflisted", false) + assert.spy(buf_set_option).was_called_with(match.is_number(), "filetype", "lsp-installer") + + assert.spy(set_lines).was_called(1) + assert.spy(set_lines).was_called_with( + match.is_number(), + 0, + -1, + false, + { "Line number 1!", "Initial state", "My highlighted text" } + ) + + assert.spy(set_extmark).was_called(0) + + assert.spy(add_highlight).was_called(1) + assert.spy(add_highlight).was_called_with(match.is_number(), match.is_number(), "MyHighlightGroup", 2, 0, 19) + + assert.spy(set_keymap).was_called(2) + assert.spy(set_keymap).was_called_with( + match.is_number(), + "n", + "U", + match.has_match [[<cmd>lua require%('nvim%-lsp%-installer%.ui%.display'%)%.dispatch_effect%(%d, "55"%)<cr>]], + { nowait = true, silent = true, noremap = true } + ) + assert.spy(set_keymap).was_called_with( + match.is_number(), + "n", + "R", + match.has_match [[<cmd>lua require%('nvim%-lsp%-installer%.ui%.display'%)%.dispatch_effect%(%d, "52"%)<cr>]], + { nowait = true, silent = true, noremap = true } + ) + + assert.spy(clear_namespace).was_called(1) + assert.spy(clear_namespace).was_called_with(match.is_number(), match.is_number(), 0, -1) + + mutate_state(function(state) + state.text = "New state" + end) + + assert.spy(set_lines).was_called(1) + a.util.scheduler() + assert.spy(set_lines).was_called(2) + + assert.spy(set_lines).was_called_with( + match.is_number(), + 0, + -1, + false, + { "Line number 1!", "New state", "My highlighted text" } + ) + end) +end) |
