diff options
| author | Mike Vink <mike@pionative.com> | 2025-01-19 13:52:31 +0100 |
|---|---|---|
| committer | Mike Vink <mike@pionative.com> | 2025-01-19 13:52:31 +0100 |
| commit | c65afb488eb9eab85063d79783d40ae1d7138586 (patch) | |
| tree | 48ce8318f6fc22eb0b82df83b5c175469b853643 /tests | |
Squashed 'mut/neovim/pack/plugins/start/quicker.nvim/' content from commit 049def7
git-subtree-dir: mut/neovim/pack/plugins/start/quicker.nvim
git-subtree-split: 049def718213d3cdf49fdf29835aded09b3e54a3
Diffstat (limited to 'tests')
43 files changed, 1144 insertions, 0 deletions
diff --git a/tests/context_spec.lua b/tests/context_spec.lua new file mode 100644 index 0000000..4a4ef5a --- /dev/null +++ b/tests/context_spec.lua @@ -0,0 +1,134 @@ +local quicker = require("quicker") +local test_util = require("tests.test_util") + +describe("context", function() + after_each(function() + test_util.reset_editor() + end) + + it("expand results", function() + local first = test_util.make_tmp_file("expand_1.txt", 10) + local second = test_util.make_tmp_file("expand_2.txt", 10) + local first_buf = vim.fn.bufadd(first) + local second_buf = vim.fn.bufadd(second) + vim.fn.setqflist({ + { + bufnr = first_buf, + text = "line 2", + lnum = 2, + valid = 1, + }, + { + bufnr = first_buf, + text = "line 8", + lnum = 8, + valid = 1, + }, + { + bufnr = second_buf, + text = "line 4", + lnum = 4, + valid = 1, + }, + }) + vim.cmd.copen() + test_util.assert_snapshot(0, "expand_1") + + vim.api.nvim_win_set_cursor(0, { 3, 0 }) + quicker.expand() + test_util.assert_snapshot(0, "expand_2") + -- Cursor stays on the same item + assert.equals(12, vim.api.nvim_win_get_cursor(0)[1]) + vim.api.nvim_win_set_cursor(0, { 14, 0 }) + + -- Expanding again will produce the same result + quicker.expand() + test_util.assert_snapshot(0, "expand_2") + assert.equals(14, vim.api.nvim_win_get_cursor(0)[1]) + + -- Expanding again will produce the same result + quicker.expand({ add_to_existing = true }) + test_util.assert_snapshot(0, "expand_3") + + -- Collapsing will return to the original state + quicker.collapse() + test_util.assert_snapshot(0, "expand_1") + assert.equals(3, vim.api.nvim_win_get_cursor(0)[1]) + end) + + it("expand loclist results", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("expand_loclist.txt", 10)) + vim.fn.setloclist(0, { + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + valid = 1, + }, + }) + vim.cmd.lopen() + quicker.expand() + test_util.assert_snapshot(0, "expand_loclist") + end) + + it("expand when items missing bufnr", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("expand_missing.txt", 10)) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + valid = 1, + }, + { + text = "Valid line with no bufnr", + lnum = 4, + valid = 1, + }, + { + bufnr = bufnr, + text = "Invalid line with a bufnr", + lnum = 5, + valid = 0, + }, + { + text = "Invalid line with no bufnr", + lnum = 6, + valid = 0, + }, + }) + vim.cmd.copen() + quicker.expand() + -- The last three lines should be stripped after expansion + test_util.assert_snapshot(0, "expand_missing") + end) + + it("expand removes duplicate line entries", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("expand_dupe.txt", 10)) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + valid = 1, + }, + { + bufnr = bufnr, + text = "line 3", + lnum = 3, + valid = 1, + }, + { + bufnr = bufnr, + text = "line 3", + lnum = 3, + valid = 1, + }, + }) + vim.cmd.copen() + test_util.assert_snapshot(0, "expand_dupe_1") + + quicker.expand() + test_util.assert_snapshot(0, "expand_dupe_2") + end) +end) diff --git a/tests/display_spec.lua b/tests/display_spec.lua new file mode 100644 index 0000000..c3404ad --- /dev/null +++ b/tests/display_spec.lua @@ -0,0 +1,145 @@ +require("plenary.async").tests.add_to_env() +local config = require("quicker.config") +local test_util = require("tests.test_util") + +local sleep = require("plenary.async.util").sleep + +a.describe("display", function() + after_each(function() + test_util.reset_editor() + end) + + it("renders quickfix items", function() + vim.fn.setqflist({ + { + bufnr = vim.fn.bufadd("README.md"), + text = "text", + lnum = 5, + valid = 1, + }, + { + filename = "README.md", + text = "text", + lnum = 10, + col = 0, + end_col = 4, + nr = 3, + type = "E", + valid = 1, + }, + { + module = "mod", + bufnr = vim.fn.bufadd("README.md"), + text = "text", + valid = 1, + }, + { + bufnr = vim.fn.bufadd("README.md"), + text = "text", + valid = 0, + }, + { + bufnr = vim.fn.bufadd("README.md"), + lnum = 1, + text = "", + valid = 0, + }, + }) + vim.cmd.copen() + test_util.assert_snapshot(0, "display_1") + end) + + a.it("truncates long filenames", function() + config.max_filename_width = function() + return 10 + end + local bufnr = vim.fn.bufadd(test_util.make_tmp_file(string.rep("f", 10) .. ".txt", 10)) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "text", + lnum = 5, + valid = 1, + }, + }) + vim.cmd.copen() + -- Wait for highlights to be applied + sleep(50) + test_util.assert_snapshot(0, "display_long_1") + end) + + a.it("renders minimal line when no filenames in results", function() + vim.fn.setqflist({ + { + text = "text", + }, + }) + vim.cmd.copen() + -- Wait for highlights to be applied + sleep(50) + test_util.assert_snapshot(0, "display_minimal_1") + end) + + a.it("sets signs for diagnostics", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("sign_test.txt", 10)) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "text", + lnum = 1, + type = "E", + valid = 1, + }, + { + bufnr = bufnr, + text = "text", + lnum = 2, + type = "W", + valid = 1, + }, + { + bufnr = bufnr, + text = "text", + lnum = 3, + type = "I", + valid = 1, + }, + { + bufnr = bufnr, + text = "text", + lnum = 4, + type = "H", + valid = 1, + }, + { + bufnr = bufnr, + text = "text", + lnum = 5, + type = "N", + valid = 1, + }, + }) + vim.cmd.copen() + + -- Wait for highlights to be applied + sleep(50) + local ns = vim.api.nvim_create_namespace("quicker_highlights") + local marks = vim.api.nvim_buf_get_extmarks(0, ns, 0, -1, { type = "sign" }) + assert.equals(5, #marks) + local expected = { + { "DiagnosticSignError", config.type_icons.E }, + { "DiagnosticSignWarn", config.type_icons.W }, + { "DiagnosticSignInfo", config.type_icons.I }, + { "DiagnosticSignHint", config.type_icons.H }, + { "DiagnosticSignHint", config.type_icons.N }, + } + for i, mark_data in ipairs(marks) do + local extmark_id, row = mark_data[1], mark_data[2] + local mark = vim.api.nvim_buf_get_extmark_by_id(0, ns, extmark_id, { details = true }) + local hl_group, icon = unpack(expected[i]) + assert.equals(i - 1, row) + assert.equals(hl_group, mark[3].sign_hl_group) + assert.equals(icon, mark[3].sign_text) + end + end) +end) diff --git a/tests/editor_spec.lua b/tests/editor_spec.lua new file mode 100644 index 0000000..0999508 --- /dev/null +++ b/tests/editor_spec.lua @@ -0,0 +1,347 @@ +local config = require("quicker.config") +local display = require("quicker.display") +local quicker = require("quicker") +local test_util = require("tests.test_util") + +---@param lnum integer +---@param line string +local function replace_text(lnum, line) + local prev_line = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, true)[1] + local idx = prev_line:find(display.EM_QUAD, 1, true) + vim.api.nvim_buf_set_text(0, lnum - 1, idx + display.EM_QUAD_LEN - 1, lnum - 1, -1, { line }) +end + +---@param lnum integer +local function del_line(lnum) + vim.cmd.normal({ args = { string.format("%dggdd", lnum) }, bang = true }) +end + +local function wait_virt_text() + vim.wait(10, function() + return false + end) +end + +describe("editor", function() + after_each(function() + test_util.reset_editor() + end) + + it("can edit one line in file", function() + vim.cmd.edit({ args = { test_util.make_tmp_file("edit_1.txt", 10) } }) + local bufnr = vim.api.nvim_get_current_buf() + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + }, + }) + vim.cmd.copen() + wait_virt_text() + replace_text(1, "new text") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_1") + end) + + it("can edit across multiple files", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("edit_multiple_1.txt", 10)) + vim.fn.bufload(bufnr) + local buf2 = vim.fn.bufadd(test_util.make_tmp_file("edit_multiple_2.txt", 10)) + vim.fn.bufload(buf2) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = "line 9", + lnum = 9, + }, + { + bufnr = buf2, + text = "line 5", + lnum = 5, + }, + }) + vim.cmd.copen() + quicker.expand() + wait_virt_text() + replace_text(2, "new text") + replace_text(3, "some text") + replace_text(7, "other text") + replace_text(11, "final text") + local last_line = vim.api.nvim_buf_line_count(0) + vim.api.nvim_win_set_cursor(0, { last_line, 0 }) + vim.cmd.write() + test_util.assert_snapshot(0, "edit_multiple_qf") + test_util.assert_snapshot(bufnr, "edit_multiple_1") + test_util.assert_snapshot(buf2, "edit_multiple_2") + -- We should keep the cursor position + assert.equals(last_line, vim.api.nvim_win_get_cursor(0)[1]) + end) + + it("can expand then edit expanded line", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("edit_expanded.txt", 10)) + vim.fn.bufload(bufnr) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + }, + }) + vim.cmd.copen() + quicker.expand() + wait_virt_text() + replace_text(1, "first") + replace_text(2, "second") + replace_text(3, "third") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_expanded") + test_util.assert_snapshot(0, "edit_expanded_qf") + end) + + it("fails when source text is different", function() + vim.cmd.edit({ args = { test_util.make_tmp_file("edit_fail.txt", 10) } }) + local bufnr = vim.api.nvim_get_current_buf() + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "buzz buzz", + lnum = 2, + }, + }) + vim.cmd.copen() + wait_virt_text() + replace_text(1, "new text") + test_util.with(function() + local notify = vim.notify + ---@diagnostic disable-next-line: duplicate-set-field + vim.notify = function() end + return function() + vim.notify = notify + end + end, function() + vim.cmd.write() + end) + test_util.assert_snapshot(bufnr, "edit_fail") + test_util.assert_snapshot(0, "edit_fail_qf") + end) + + it("can handle multiple qf items on same lnum", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("edit_dupe.txt", 10)) + vim.fn.bufload(bufnr) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + col = 0, + }, + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + col = 3, + }, + }) + vim.cmd.copen() + wait_virt_text() + replace_text(1, "first") + replace_text(2, "second") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_dupe") + test_util.assert_snapshot(0, "edit_dupe_qf") + + -- If only one of them has a change, it should go through + replace_text(1, "line 2") + replace_text(2, "second") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_dupe_2") + test_util.assert_snapshot(0, "edit_dupe_qf_2") + end) + + it("handles deleting lines (shrinks quickfix)", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("edit_delete.txt", 10)) + vim.fn.bufload(bufnr) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = "line 3", + lnum = 3, + }, + { + bufnr = bufnr, + text = "line 6", + lnum = 6, + }, + }) + vim.cmd.copen() + wait_virt_text() + del_line(3) + del_line(2) + vim.cmd.write() + assert.are.same({ + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + col = 0, + end_col = 0, + vcol = 0, + end_lnum = 0, + module = "", + nr = 0, + pattern = "", + type = "", + valid = 1, + }, + }, vim.fn.getqflist()) + end) + + it("handles loclist", function() + vim.cmd.edit({ args = { test_util.make_tmp_file("edit_ll.txt", 10) } }) + local bufnr = vim.api.nvim_get_current_buf() + vim.fn.setloclist(0, { + { + bufnr = bufnr, + text = "line 2", + lnum = 2, + }, + }) + vim.cmd.lopen() + wait_virt_text() + replace_text(1, "new text") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_ll") + end) + + it("handles text that contains the delimiter", function() + vim.cmd.edit({ args = { test_util.make_tmp_file("edit_delim.txt", 10) } }) + local bufnr = vim.api.nvim_get_current_buf() + local line = "line 2 " .. config.borders.vert .. " text" + vim.api.nvim_buf_set_lines(bufnr, 1, 2, false, { line }) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = line, + lnum = 2, + }, + }) + vim.cmd.copen() + wait_virt_text() + replace_text(1, line .. " " .. config.borders.vert .. " more text") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_delim") + end) + + it("can edit lines with trimmed common whitespace", function() + require("quicker.config").trim_leading_whitespace = "common" + vim.cmd.edit({ + args = { + test_util.make_tmp_file("edit_whitespace.txt", { + " line 1", + " line 2", + " line 3", + " line 4", + }), + }, + }) + local bufnr = vim.api.nvim_get_current_buf() + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = " line 3", + lnum = 3, + }, + }) + vim.cmd.copen() + wait_virt_text() + test_util.assert_snapshot(0, "edit_whitespace_qf") + replace_text(1, "foo") + replace_text(2, "bar") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_whitespace") + end) + + it("can edit lines with trimmed all whitespace", function() + require("quicker.config").trim_leading_whitespace = "all" + vim.cmd.edit({ + args = { + test_util.make_tmp_file("edit_whitespace.txt", { + " line 1", + " line 2", + " line 3", + " line 4", + }), + }, + }) + local bufnr = vim.api.nvim_get_current_buf() + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = " line 3", + lnum = 3, + }, + }) + vim.cmd.copen() + wait_virt_text() + test_util.assert_snapshot(0, "edit_all_whitespace_qf") + replace_text(1, "foo") + replace_text(2, "bar") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_all_whitespace") + end) + + it("can edit lines with untrimmed whitespace", function() + require("quicker.config").trim_leading_whitespace = false + vim.cmd.edit({ + args = { + test_util.make_tmp_file("edit_whitespace.txt", { + " line 1", + " line 2", + " line 3", + " line 4", + }), + }, + }) + local bufnr = vim.api.nvim_get_current_buf() + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = " line 3", + lnum = 3, + }, + }) + vim.cmd.copen() + wait_virt_text() + test_util.assert_snapshot(0, "edit_none_whitespace_qf") + replace_text(1, "foo") + replace_text(2, "bar") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_none_whitespace") + end) +end) diff --git a/tests/fs_spec.lua b/tests/fs_spec.lua new file mode 100644 index 0000000..2e1e54f --- /dev/null +++ b/tests/fs_spec.lua @@ -0,0 +1,20 @@ +local fs = require("quicker.fs") + +local home = os.getenv("HOME") +local cwd = vim.fn.getcwd() + +describe("fs", function() + it("shortens path", function() + assert.equals("~/bar/baz.txt", fs.shorten_path(home .. "/bar/baz.txt")) + assert.equals("bar/baz.txt", fs.shorten_path(cwd .. "/bar/baz.txt")) + assert.equals("/foo/bar.txt", fs.shorten_path("/foo/bar.txt")) + end) + + it("finds subpath", function() + assert.truthy(fs.is_subpath("/root", "/root/foo")) + assert.truthy(fs.is_subpath(cwd, "foo")) + assert.falsy(fs.is_subpath("/root", "/foo")) + assert.falsy(fs.is_subpath("/root", "/rooter/foo")) + assert.falsy(fs.is_subpath("/root", "/root/../foo")) + end) +end) diff --git a/tests/minimal_init.lua b/tests/minimal_init.lua new file mode 100644 index 0000000..486b213 --- /dev/null +++ b/tests/minimal_init.lua @@ -0,0 +1,16 @@ +vim.cmd([[set runtimepath+=.]]) + +vim.o.swapfile = false +vim.bo.swapfile = false +require("tests.test_util").reset_editor() + +-- TODO test highlighting (both highlight.lua module and adding them in display.lua) +-- TODO test syntax highlighting when customizing delimiter + +vim.api.nvim_create_user_command("RunTests", function(opts) + local path = opts.fargs[1] or "tests" + require("plenary.test_harness").test_directory( + path, + { minimal_init = "./tests/minimal_init.lua" } + ) +end, { nargs = "?" }) diff --git a/tests/opts_spec.lua b/tests/opts_spec.lua new file mode 100644 index 0000000..0732da2 --- /dev/null +++ b/tests/opts_spec.lua @@ -0,0 +1,52 @@ +local quicker = require("quicker") +local test_util = require("tests.test_util") + +describe("opts", function() + after_each(function() + test_util.reset_editor() + end) + + it("sets buffer opts", function() + quicker.setup({ + opts = { + buflisted = true, + bufhidden = "wipe", + cindent = true, + }, + }) + vim.fn.setqflist({ + { + bufnr = vim.fn.bufadd("README.md"), + text = "text", + lnum = 5, + valid = 1, + }, + }) + vim.cmd.copen() + assert.truthy(vim.bo.buflisted) + assert.equals("wipe", vim.bo.bufhidden) + assert.truthy(vim.bo.cindent) + end) + + it("sets window opts", function() + quicker.setup({ + opts = { + wrap = false, + number = true, + list = true, + }, + }) + vim.fn.setqflist({ + { + bufnr = vim.fn.bufadd("README.md"), + text = "text", + lnum = 5, + valid = 1, + }, + }) + vim.cmd.copen() + assert.falsy(vim.wo.wrap) + assert.truthy(vim.wo.number) + assert.truthy(vim.wo.list) + end) +end) diff --git a/tests/snapshots/display_1 b/tests/snapshots/display_1 new file mode 100644 index 0000000..270a164 --- /dev/null +++ b/tests/snapshots/display_1 @@ -0,0 +1,5 @@ +README.md ┃ 5┃text +README.md ┃10┃text +mod ┃ ┃text +README.md ┃ ┃text +README.md ┃ 1┃
\ No newline at end of file diff --git a/tests/snapshots/display_long_1 b/tests/snapshots/display_long_1 new file mode 100644 index 0000000..d585beb --- /dev/null +++ b/tests/snapshots/display_long_1 @@ -0,0 +1 @@ +…ffffffff.txt ┃ 5┃text
\ No newline at end of file diff --git a/tests/snapshots/display_minimal_1 b/tests/snapshots/display_minimal_1 new file mode 100644 index 0000000..46190e7 --- /dev/null +++ b/tests/snapshots/display_minimal_1 @@ -0,0 +1 @@ + ┃text
\ No newline at end of file diff --git a/tests/snapshots/edit_1 b/tests/snapshots/edit_1 new file mode 100644 index 0000000..a18ed5a --- /dev/null +++ b/tests/snapshots/edit_1 @@ -0,0 +1,10 @@ +line 1 +new text +line 3 +line 4 +line 5 +line 6 +line 7 +line 8 +line 9 +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_all_whitespace b/tests/snapshots/edit_all_whitespace new file mode 100644 index 0000000..998c877 --- /dev/null +++ b/tests/snapshots/edit_all_whitespace @@ -0,0 +1,4 @@ + line 1 + foo + bar + line 4
\ No newline at end of file diff --git a/tests/snapshots/edit_all_whitespace_qf b/tests/snapshots/edit_all_whitespace_qf new file mode 100644 index 0000000..baf8533 --- /dev/null +++ b/tests/snapshots/edit_all_whitespace_qf @@ -0,0 +1,2 @@ +tests/tmp/edit_whitespace.txt ┃ 2┃line 2 +tests/tmp/edit_whitespace.txt ┃ 3┃line 3
\ No newline at end of file diff --git a/tests/snapshots/edit_delim b/tests/snapshots/edit_delim new file mode 100644 index 0000000..75a9e7f --- /dev/null +++ b/tests/snapshots/edit_delim @@ -0,0 +1,10 @@ +line 1 +line 2 ┃ text ┃ more text +line 3 +line 4 +line 5 +line 6 +line 7 +line 8 +line 9 +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_dupe b/tests/snapshots/edit_dupe new file mode 100644 index 0000000..b3f56ae --- /dev/null +++ b/tests/snapshots/edit_dupe @@ -0,0 +1,10 @@ +line 1 +line 2 +line 3 +line 4 +line 5 +line 6 +line 7 +line 8 +line 9 +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_dupe_2 b/tests/snapshots/edit_dupe_2 new file mode 100644 index 0000000..3ae9ccc --- /dev/null +++ b/tests/snapshots/edit_dupe_2 @@ -0,0 +1,10 @@ +line 1 +second +line 3 +line 4 +line 5 +line 6 +line 7 +line 8 +line 9 +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_dupe_qf b/tests/snapshots/edit_dupe_qf new file mode 100644 index 0000000..7e01207 --- /dev/null +++ b/tests/snapshots/edit_dupe_qf @@ -0,0 +1,2 @@ +tests/tmp/edit_dupe.txt ┃ 2┃first +tests/tmp/edit_dupe.txt ┃ 2┃second
\ No newline at end of file diff --git a/tests/snapshots/edit_dupe_qf_2 b/tests/snapshots/edit_dupe_qf_2 new file mode 100644 index 0000000..1acfd8e --- /dev/null +++ b/tests/snapshots/edit_dupe_qf_2 @@ -0,0 +1,2 @@ +tests/tmp/edit_dupe.txt ┃ 2┃line 2 +tests/tmp/edit_dupe.txt ┃ 2┃second
\ No newline at end of file diff --git a/tests/snapshots/edit_expanded b/tests/snapshots/edit_expanded new file mode 100644 index 0000000..afc39ad --- /dev/null +++ b/tests/snapshots/edit_expanded @@ -0,0 +1,10 @@ +first +second +third +line 4 +line 5 +line 6 +line 7 +line 8 +line 9 +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_expanded_qf b/tests/snapshots/edit_expanded_qf new file mode 100644 index 0000000..991dd06 --- /dev/null +++ b/tests/snapshots/edit_expanded_qf @@ -0,0 +1,4 @@ + ┃ 1┃first +tests/tmp/edit_expanded.txt ┃ 2┃second + ┃ 3┃third + ┃ 4┃line 4
\ No newline at end of file diff --git a/tests/snapshots/edit_fail b/tests/snapshots/edit_fail new file mode 100644 index 0000000..b3f56ae --- /dev/null +++ b/tests/snapshots/edit_fail @@ -0,0 +1,10 @@ +line 1 +line 2 +line 3 +line 4 +line 5 +line 6 +line 7 +line 8 +line 9 +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_fail_qf b/tests/snapshots/edit_fail_qf new file mode 100644 index 0000000..3eb9f10 --- /dev/null +++ b/tests/snapshots/edit_fail_qf @@ -0,0 +1 @@ +tests/tmp/edit_fail.txt ┃ 2┃new text
\ No newline at end of file diff --git a/tests/snapshots/edit_invalid b/tests/snapshots/edit_invalid new file mode 100644 index 0000000..386c994 --- /dev/null +++ b/tests/snapshots/edit_invalid @@ -0,0 +1 @@ + ┃ ┃new text diff --git a/tests/snapshots/edit_ll b/tests/snapshots/edit_ll new file mode 100644 index 0000000..a18ed5a --- /dev/null +++ b/tests/snapshots/edit_ll @@ -0,0 +1,10 @@ +line 1 +new text +line 3 +line 4 +line 5 +line 6 +line 7 +line 8 +line 9 +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_multiple_1 b/tests/snapshots/edit_multiple_1 new file mode 100644 index 0000000..765403a --- /dev/null +++ b/tests/snapshots/edit_multiple_1 @@ -0,0 +1,10 @@ +line 1 +new text +some text +line 4 +line 5 +line 6 +line 7 +line 8 +other text +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_multiple_2 b/tests/snapshots/edit_multiple_2 new file mode 100644 index 0000000..c988ea1 --- /dev/null +++ b/tests/snapshots/edit_multiple_2 @@ -0,0 +1,10 @@ +line 1 +line 2 +line 3 +line 4 +final text +line 6 +line 7 +line 8 +line 9 +line 10
\ No newline at end of file diff --git a/tests/snapshots/edit_multiple_qf b/tests/snapshots/edit_multiple_qf new file mode 100644 index 0000000..3de41ad --- /dev/null +++ b/tests/snapshots/edit_multiple_qf @@ -0,0 +1,15 @@ + ┃ 1┃line 1 +tests/tmp/edit_multiple_1.txt ┃ 2┃new text + ┃ 3┃some text + ┃ 4┃line 4 +╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╂╌╌╂╌╌╌╌╌╌╌╌ + ┃ 7┃line 7 + ┃ 8┃line 8 +tests/tmp/edit_multiple_1.txt ┃ 9┃other text + ┃10┃line 10 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━╋━━━━━━━━ + ┃ 3┃line 3 + ┃ 4┃line 4 +tests/tmp/edit_multiple_2.txt ┃ 5┃final text + ┃ 6┃line 6 + ┃ 7┃line 7
\ No newline at end of file diff --git a/tests/snapshots/edit_none_whitespace b/tests/snapshots/edit_none_whitespace new file mode 100644 index 0000000..4b592c2 --- /dev/null +++ b/tests/snapshots/edit_none_whitespace @@ -0,0 +1,4 @@ + line 1 +foo +bar + line 4
\ No newline at end of file diff --git a/tests/snapshots/edit_none_whitespace_qf b/tests/snapshots/edit_none_whitespace_qf new file mode 100644 index 0000000..5be47f1 --- /dev/null +++ b/tests/snapshots/edit_none_whitespace_qf @@ -0,0 +1,2 @@ +tests/tmp/edit_whitespace.txt ┃ 2┃ line 2 +tests/tmp/edit_whitespace.txt ┃ 3┃ line 3
\ No newline at end of file diff --git a/tests/snapshots/edit_whitespace b/tests/snapshots/edit_whitespace new file mode 100644 index 0000000..6a5ca4b --- /dev/null +++ b/tests/snapshots/edit_whitespace @@ -0,0 +1,4 @@ + line 1 + foo + bar + line 4
\ No newline at end of file diff --git a/tests/snapshots/edit_whitespace_qf b/tests/snapshots/edit_whitespace_qf new file mode 100644 index 0000000..e26d928 --- /dev/null +++ b/tests/snapshots/edit_whitespace_qf @@ -0,0 +1,2 @@ +tests/tmp/edit_whitespace.txt ┃ 2┃line 2 +tests/tmp/edit_whitespace.txt ┃ 3┃ line 3
\ No newline at end of file diff --git a/tests/snapshots/expand_1 b/tests/snapshots/expand_1 new file mode 100644 index 0000000..ab1901f --- /dev/null +++ b/tests/snapshots/expand_1 @@ -0,0 +1,3 @@ +tests/tmp/expand_1.txt ┃ 2┃line 2 +tests/tmp/expand_1.txt ┃ 8┃line 8 +tests/tmp/expand_2.txt ┃ 4┃line 4
\ No newline at end of file diff --git a/tests/snapshots/expand_2 b/tests/snapshots/expand_2 new file mode 100644 index 0000000..e0a2139 --- /dev/null +++ b/tests/snapshots/expand_2 @@ -0,0 +1,16 @@ + ┃ 1┃line 1 +tests/tmp/expand_1.txt ┃ 2┃line 2 + ┃ 3┃line 3 + ┃ 4┃line 4 +╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╂╌╌╂╌╌╌╌╌╌╌╌ + ┃ 6┃line 6 + ┃ 7┃line 7 +tests/tmp/expand_1.txt ┃ 8┃line 8 + ┃ 9┃line 9 + ┃10┃line 10 +━━━━━━━━━━━━━━━━━━━━━━━╋━━╋━━━━━━━━ + ┃ 2┃line 2 + ┃ 3┃line 3 +tests/tmp/expand_2.txt ┃ 4┃line 4 + ┃ 5┃line 5 + ┃ 6┃line 6
\ No newline at end of file diff --git a/tests/snapshots/expand_3 b/tests/snapshots/expand_3 new file mode 100644 index 0000000..0a20a1c --- /dev/null +++ b/tests/snapshots/expand_3 @@ -0,0 +1,19 @@ + ┃ 1┃line 1 +tests/tmp/expand_1.txt ┃ 2┃line 2 + ┃ 3┃line 3 + ┃ 4┃line 4 + ┃ 5┃line 5 + ┃ 6┃line 6 + ┃ 7┃line 7 +tests/tmp/expand_1.txt ┃ 8┃line 8 + ┃ 9┃line 9 + ┃10┃line 10 +━━━━━━━━━━━━━━━━━━━━━━━╋━━╋━━━━━━━━ + ┃ 1┃line 1 + ┃ 2┃line 2 + ┃ 3┃line 3 +tests/tmp/expand_2.txt ┃ 4┃line 4 + ┃ 5┃line 5 + ┃ 6┃line 6 + ┃ 7┃line 7 + ┃ 8┃line 8
\ No newline at end of file diff --git a/tests/snapshots/expand_dupe_1 b/tests/snapshots/expand_dupe_1 new file mode 100644 index 0000000..8e32cb4 --- /dev/null +++ b/tests/snapshots/expand_dupe_1 @@ -0,0 +1,3 @@ +tests/tmp/expand_dupe.txt ┃ 2┃line 2 +tests/tmp/expand_dupe.txt ┃ 3┃line 3 +tests/tmp/expand_dupe.txt ┃ 3┃line 3
\ No newline at end of file diff --git a/tests/snapshots/expand_dupe_2 b/tests/snapshots/expand_dupe_2 new file mode 100644 index 0000000..b51efa8 --- /dev/null +++ b/tests/snapshots/expand_dupe_2 @@ -0,0 +1,5 @@ + ┃ 1┃line 1 +tests/tmp/expand_dupe.txt ┃ 2┃line 2 +tests/tmp/expand_dupe.txt ┃ 3┃line 3 + ┃ 4┃line 4 + ┃ 5┃line 5
\ No newline at end of file diff --git a/tests/snapshots/expand_loclist b/tests/snapshots/expand_loclist new file mode 100644 index 0000000..66a6207 --- /dev/null +++ b/tests/snapshots/expand_loclist @@ -0,0 +1,4 @@ + ┃ 1┃line 1 +tests/tmp/expand_loclist.txt ┃ 2┃line 2 + ┃ 3┃line 3 + ┃ 4┃line 4
\ No newline at end of file diff --git a/tests/snapshots/expand_missing b/tests/snapshots/expand_missing new file mode 100644 index 0000000..f29a273 --- /dev/null +++ b/tests/snapshots/expand_missing @@ -0,0 +1,4 @@ + ┃ 1┃line 1 +tests/tmp/expand_missing.txt ┃ 2┃line 2 + ┃ 3┃line 3 + ┃ 4┃line 4
\ No newline at end of file diff --git a/tests/snapshots/trim_all_whitespace b/tests/snapshots/trim_all_whitespace new file mode 100644 index 0000000..e664f80 --- /dev/null +++ b/tests/snapshots/trim_all_whitespace @@ -0,0 +1,2 @@ +tests/tmp/whitespace_1.txt ┃ 2┃line 2 +tests/tmp/whitespace_1.txt ┃ 3┃line 3
\ No newline at end of file diff --git a/tests/snapshots/trim_mixed_whitespace b/tests/snapshots/trim_mixed_whitespace new file mode 100644 index 0000000..f6464d4 --- /dev/null +++ b/tests/snapshots/trim_mixed_whitespace @@ -0,0 +1,2 @@ +tests/tmp/mixed_whitespace.txt ┃ 1┃ line 1 +tests/tmp/mixed_whitespace.txt ┃ 2┃ line 2
\ No newline at end of file diff --git a/tests/snapshots/trim_whitespace b/tests/snapshots/trim_whitespace new file mode 100644 index 0000000..49a6e20 --- /dev/null +++ b/tests/snapshots/trim_whitespace @@ -0,0 +1,2 @@ +tests/tmp/whitespace.txt ┃ 2┃line 2 +tests/tmp/whitespace.txt ┃ 3┃ line 3
\ No newline at end of file diff --git a/tests/snapshots/trim_whitespace_expanded b/tests/snapshots/trim_whitespace_expanded new file mode 100644 index 0000000..07b70d1 --- /dev/null +++ b/tests/snapshots/trim_whitespace_expanded @@ -0,0 +1,5 @@ + ┃ 1┃ line 1 +tests/tmp/whitespace.txt ┃ 2┃line 2 +tests/tmp/whitespace.txt ┃ 3┃ line 3 + ┃ 4┃ + ┃ 5┃ line 4
\ No newline at end of file diff --git a/tests/test_util.lua b/tests/test_util.lua new file mode 100644 index 0000000..94b0a40 --- /dev/null +++ b/tests/test_util.lua @@ -0,0 +1,142 @@ +require("plenary.async").tests.add_to_env() +local M = {} + +local tmp_files = {} +M.reset_editor = function() + vim.cmd.tabonly({ mods = { silent = true } }) + for i, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if i > 1 then + vim.api.nvim_win_close(winid, true) + end + end + vim.api.nvim_win_set_buf(0, vim.api.nvim_create_buf(false, true)) + for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do + vim.api.nvim_buf_delete(bufnr, { force = true }) + end + vim.fn.setqflist({}) + vim.fn.setloclist(0, {}) + for _, filename in ipairs(tmp_files) do + vim.uv.fs_unlink(filename) + end + tmp_files = {} + + require("quicker").setup({ + header_length = function() + -- Make this deterministic so the snapshots are stable + return 8 + end, + }) +end + +---@param basename string +---@param lines integer|string[] +---@return string +M.make_tmp_file = function(basename, lines) + vim.fn.mkdir("tests/tmp", "p") + local filename = "tests/tmp/" .. basename + table.insert(tmp_files, filename) + local f = assert(io.open(filename, "w")) + if type(lines) == "table" then + for _, line in ipairs(lines) do + f:write(line .. "\n") + end + else + for i = 1, lines do + f:write("line " .. i .. "\n") + end + end + f:close() + return filename +end + +---@param name string +---@return string[] +local function load_snapshot(name) + local path = "tests/snapshots/" .. name + if vim.fn.filereadable(path) == 0 then + return {} + end + local f = assert(io.open(path, "r")) + local lines = {} + for line in f:lines() do + table.insert(lines, line) + end + f:close() + return lines +end + +---@param name string +---@param lines string[] +local function save_snapshot(name, lines) + vim.fn.mkdir("tests/snapshots", "p") + local path = "tests/snapshots/" .. name + local f = assert(io.open(path, "w")) + f:write(table.concat(lines, "\n")) + f:close() + return lines +end + +---@param bufnr integer +---@param name string +M.assert_snapshot = function(bufnr, name) + -- Wait for the virtual text extmarks to be set + if vim.bo[bufnr].filetype == "qf" then + vim.wait(10, function() + return false + end) + end + local util = require("quicker.util") + local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + + -- Add virtual text to lines + local headers = {} + local header_ns = vim.api.nvim_create_namespace("quicker_headers") + for i, v in ipairs(lines) do + local extmarks = util.get_lnum_extmarks(bufnr, i, v:len()) + assert(#extmarks <= 1, "Expected at most one extmark per line") + local mark = extmarks[1] + if mark then + local start_col = mark[3] + local data = mark[4] + local virt_text = table.concat( + vim.tbl_map(function(vt) + return vt[1] + end, data.virt_text), + "" + ) + lines[i] = v:sub(0, start_col) .. virt_text .. v:sub(start_col + 1) + + extmarks = util.get_lnum_extmarks(bufnr, i, v:len(), header_ns) + assert(#extmarks <= 1, "Expected at most one extmark per line") + mark = extmarks[1] + if mark and mark[4].virt_lines then + table.insert(headers, { i, mark[4].virt_lines[1][1][1] }) + end + end + end + + for i = #headers, 1, -1 do + local lnum, header = unpack(headers[i]) + table.insert(lines, lnum, header) + end + + if os.getenv("UPDATE_SNAPSHOTS") then + save_snapshot(name, lines) + else + local expected = load_snapshot(name) + assert.are.same(expected, lines) + end +end + +---@param context fun(): fun() +---@param fn fun() +M.with = function(context, fn) + local cleanup = context() + local ok, err = pcall(fn) + cleanup() + if not ok then + error(err) + end +end + +return M diff --git a/tests/whitespace_spec.lua b/tests/whitespace_spec.lua new file mode 100644 index 0000000..0933276 --- /dev/null +++ b/tests/whitespace_spec.lua @@ -0,0 +1,83 @@ +local quicker = require("quicker") +local test_util = require("tests.test_util") + +describe("whitespace", function() + before_each(function() + require("quicker.config").trim_leading_whitespace = "common" + end) + after_each(function() + test_util.reset_editor() + end) + + it("removes common leading whitespace from valid results", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("whitespace.txt", { + " line 1", + " line 2", + " line 3", + "", + " line 4", + })) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = " line 3", + lnum = 3, + }, + }) + vim.cmd.copen() + test_util.assert_snapshot(0, "trim_whitespace") + quicker.expand() + test_util.assert_snapshot(0, "trim_whitespace_expanded") + end) + + it("handles mixed tabs and spaces", function() + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("mixed_whitespace.txt", { + " line 1", + "\t\tline 2", + })) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 1", + lnum = 1, + }, + { + bufnr = bufnr, + text = "\t\tline 2", + lnum = 2, + }, + }) + vim.cmd.copen() + test_util.assert_snapshot(0, "trim_mixed_whitespace") + end) + + it("removes all leading whitespace", function() + require("quicker.config").trim_leading_whitespace = "all" + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("whitespace_1.txt", { + " line 1", + " line 2", + " line 3", + "", + " line 4", + })) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = " line 3", + lnum = 3, + }, + }) + vim.cmd.copen() + test_util.assert_snapshot(0, "trim_all_whitespace") + end) +end) |
