diff options
| author | ThePrimeAgain <theprimeagain@theprimeagain.com> | 2026-01-14 18:32:30 -0700 |
|---|---|---|
| committer | ThePrimeAgain <theprimeagain@theprimeagain.com> | 2026-01-14 18:32:30 -0700 |
| commit | 6c88a9537ae829cd8a4b92312e115c311e6beb42 (patch) | |
| tree | d2b1796d453cbbd7374ed740fa50a1be411362b1 /lua/99/test | |
| parent | 701b4c34a1e3de34327d21cc6f51c79b49d26b51 (diff) | |
| download | a4-6c88a9537ae829cd8a4b92312e115c311e6beb42.tar.xz a4-6c88a9537ae829cd8a4b92312e115c311e6beb42.zip | |
fuzzy_find: for agents stuff
Diffstat (limited to 'lua/99/test')
| -rw-r--r-- | lua/99/test/agent.helpers_spec.lua | 52 | ||||
| -rw-r--r-- | lua/99/test/fill_in_function.cpp_spec.lua | 186 | ||||
| -rw-r--r-- | lua/99/test/fill_in_function_spec.lua | 148 | ||||
| -rw-r--r-- | lua/99/test/geo_spec.lua | 174 | ||||
| -rw-r--r-- | lua/99/test/implement-fn_spec-DO-NOT-USE-YET.lua | 62 | ||||
| -rw-r--r-- | lua/99/test/logger_spec.lua | 128 | ||||
| -rw-r--r-- | lua/99/test/marks_spec.lua | 228 | ||||
| -rw-r--r-- | lua/99/test/request_status_spec.lua | 18 | ||||
| -rw-r--r-- | lua/99/test/test_utils.lua | 98 | ||||
| -rw-r--r-- | lua/99/test/visual_spec.lua | 225 |
10 files changed, 682 insertions, 637 deletions
diff --git a/lua/99/test/agent.helpers_spec.lua b/lua/99/test/agent.helpers_spec.lua new file mode 100644 index 0000000..f59870a --- /dev/null +++ b/lua/99/test/agent.helpers_spec.lua @@ -0,0 +1,52 @@ +-- luacheck: globals describe it assert +local helpers = require("99.agents.helpers") +local eq = assert.are.same + +--- @param selected _99.Agents.FuzzyState.Selected[] +--- @return string[] +local function n(selected) + return vim.tbl_map(function(item) return item.name end, selected) +end + +local possible = { + "react-hooks", + "react-state", + "redux", + "recoil", + "rust-analyzer", +} + +describe("99.agents.helpers", function() + it("fuzzy matching", function() + local state = helpers.create_state(possible, false) + eq(5, #state.selected) + + state = helpers.fuzzy_match("rea", state) + eq({ "react-hooks", "react-state", }, n(state.selected)) + + state = helpers.fuzzy_match("rh", state) + eq({ "react-hooks" }, n(state.selected)) + + state = helpers.fuzzy_match("rst", state) + eq({ "react-state", "rust-analyzer" }, n(state.selected)) + + state = helpers.fuzzy_match("xyz", state) + eq({}, state.selected) + end) + + it("fuzzy matching iterative", function() + local state = helpers.create_state(possible, false) + + state = helpers.fuzzy_match("r", state) + eq(possible, n(state.selected)) + + state = helpers.fuzzy_match("re", state) + eq(possible, n(state.selected)) + + state = helpers.fuzzy_match("rea", state) + eq({ "react-hooks", "react-state", }, n(state.selected)) + + state = helpers.fuzzy_match("re", state) + eq(possible, n(state.selected)) + end) +end) diff --git a/lua/99/test/fill_in_function.cpp_spec.lua b/lua/99/test/fill_in_function.cpp_spec.lua index 9edf550..3cb67b5 100644 --- a/lua/99/test/fill_in_function.cpp_spec.lua +++ b/lua/99/test/fill_in_function.cpp_spec.lua @@ -12,122 +12,122 @@ local eq = assert.are.same --- @param lang string? --- @return _99.test.Provider, number local function setup(content, row, col, lang) - assert(lang, "lang must be provided") - local provider = test_utils.TestProvider.new() - _99.setup({ - provider = provider, - logger = { - error_cache_level = Levels.ERROR, - type = "print", - }, - }) + assert(lang, "lang must be provided") + local provider = test_utils.TestProvider.new() + _99.setup({ + provider = provider, + logger = { + error_cache_level = Levels.ERROR, + type = "print", + }, + }) - local buffer = test_utils.create_file(content, lang, row, col) - return provider, buffer + local buffer = test_utils.create_file(content, lang, row, col) + return provider, buffer end --- @param buffer number --- @return string[] local function read(buffer) - return vim.api.nvim_buf_get_lines(buffer, 0, -1, false) + return vim.api.nvim_buf_get_lines(buffer, 0, -1, false) end describe("fill_in_function", function() - it("fill in cpp function", function() - local cpp_content = { - "", - "uint32_t test() { }", - } - local provider, buffer = setup(cpp_content, 2, 5, "cpp") - local state = _99.__get_state() + it("fill in cpp function", function() + local cpp_content = { + "", + "uint32_t test() { }", + } + local provider, buffer = setup(cpp_content, 2, 5, "cpp") + local state = _99.__get_state() - _99.fill_in_function() + _99.fill_in_function() - eq(1, state:active_request_count()) - eq(cpp_content, read(buffer)) + eq(1, state:active_request_count()) + eq(cpp_content, read(buffer)) - provider:resolve("success", "uint32_t test() {\n return 42;\n}") - test_utils.next_frame() + provider:resolve("success", "uint32_t test() {\n return 42;\n}") + test_utils.next_frame() - local expected_state = { - "", - "uint32_t test() {", - " return 42;", - "}", - } - eq(expected_state, read(buffer)) - eq(0, state:active_request_count()) - end) + local expected_state = { + "", + "uint32_t test() {", + " return 42;", + "}", + } + eq(expected_state, read(buffer)) + eq(0, state:active_request_count()) + end) - it("fill in cpp concept with requires clause", function() - local cpp_content = { - "", - "template <typename T>", - "concept Callback = requires(T cb) {", - " // Invocation must return an int", - "};", - } + it("fill in cpp concept with requires clause", function() + local cpp_content = { + "", + "template <typename T>", + "concept Callback = requires(T cb) {", + " // Invocation must return an int", + "};", + } - local provider, buffer = setup(cpp_content, 3, 10, "cpp") - local state = _99.__get_state() + local provider, buffer = setup(cpp_content, 3, 10, "cpp") + local state = _99.__get_state() - _99.fill_in_function() + _99.fill_in_function() - eq(1, state:active_request_count()) - eq(cpp_content, read(buffer)) + eq(1, state:active_request_count()) + eq(cpp_content, read(buffer)) - provider:resolve( - "success", - "concept Callback = requires(T cb) {\n { cb() } -> std::same_as<int>;\n};" - ) - test_utils.next_frame() + provider:resolve( + "success", + "concept Callback = requires(T cb) {\n { cb() } -> std::same_as<int>;\n};" + ) + test_utils.next_frame() - local expected_state = { - "", - "template <typename T>", - "concept Callback = requires(T cb) {", - " { cb() } -> std::same_as<int>;", - "};", - } - eq(expected_state, read(buffer)) - eq(0, state:active_request_count()) - end) + local expected_state = { + "", + "template <typename T>", + "concept Callback = requires(T cb) {", + " { cb() } -> std::same_as<int>;", + "};", + } + eq(expected_state, read(buffer)) + eq(0, state:active_request_count()) + end) - it("fill in nested lambda inside a function", function() - local cpp_content = { - "", - "auto test() -> void", - "{", - " const auto say_42 = []() -> int {", - " // TODO: return 42", - " };", - "}", - } + it("fill in nested lambda inside a function", function() + local cpp_content = { + "", + "auto test() -> void", + "{", + " const auto say_42 = []() -> int {", + " // TODO: return 42", + " };", + "}", + } - local provider, buffer = setup(cpp_content, 4, 20, "cpp") - local state = _99.__get_state() + local provider, buffer = setup(cpp_content, 4, 20, "cpp") + local state = _99.__get_state() - _99.fill_in_function() + _99.fill_in_function() - eq(1, state:active_request_count()) - eq(cpp_content, read(buffer)) + eq(1, state:active_request_count()) + eq(cpp_content, read(buffer)) - provider:resolve( - "success", - "const auto say_42 = []() -> int {\n return 42;\n };" - ) - test_utils.next_frame() + provider:resolve( + "success", + "const auto say_42 = []() -> int {\n return 42;\n };" + ) + test_utils.next_frame() - local expected_state = { - "", - "auto test() -> void", - "{", - " const auto say_42 = []() -> int {", - " return 42;", - " };", - "}", - } - eq(expected_state, read(buffer)) - eq(0, state:active_request_count()) - end) + local expected_state = { + "", + "auto test() -> void", + "{", + " const auto say_42 = []() -> int {", + " return 42;", + " };", + "}", + } + eq(expected_state, read(buffer)) + eq(0, state:active_request_count()) + end) end) diff --git a/lua/99/test/fill_in_function_spec.lua b/lua/99/test/fill_in_function_spec.lua index 24cdcfe..cc356f1 100644 --- a/lua/99/test/fill_in_function_spec.lua +++ b/lua/99/test/fill_in_function_spec.lua @@ -10,109 +10,109 @@ local Levels = require("99.logger.level") --- @param lang string? --- @return _99.test.Provider, number local function setup(content, row, col, lang) - lang = lang or "lua" - local p = test_utils.TestProvider.new() - _99.setup({ - provider = p, - logger = { - error_cache_level = Levels.ERROR, - type = "print", - }, - }) + lang = lang or "lua" + local p = test_utils.TestProvider.new() + _99.setup({ + provider = p, + logger = { + error_cache_level = Levels.ERROR, + type = "print", + }, + }) - local buffer = test_utils.create_file(content, lang, row, col) - return p, buffer + local buffer = test_utils.create_file(content, lang, row, col) + return p, buffer end --- @param buffer number --- @return string[] local function r(buffer) - return vim.api.nvim_buf_get_lines(buffer, 0, -1, false) + return vim.api.nvim_buf_get_lines(buffer, 0, -1, false) end local content = { - "", - "local foo = function() end", + "", + "local foo = function() end", } describe("fill_in_function", function() - it("replace function contents", function() - local p, buffer = setup(content, 2, 12) - local state = _99.__get_state() + it("replace function contents", function() + local p, buffer = setup(content, 2, 12) + local state = _99.__get_state() - _99.fill_in_function() + _99.fill_in_function() - eq(1, state:active_request_count()) - eq(content, r(buffer)) + eq(1, state:active_request_count()) + eq(content, r(buffer)) - p:resolve("success", "function()\n return 42\nend") - test_utils.next_frame() + p:resolve("success", "function()\n return 42\nend") + test_utils.next_frame() - local expected_state = { - "", - "local foo = function()", - " return 42", - "end", - } - eq(expected_state, r(buffer)) - eq(0, state:active_request_count()) - end) + local expected_state = { + "", + "local foo = function()", + " return 42", + "end", + } + eq(expected_state, r(buffer)) + eq(0, state:active_request_count()) + end) - it("should test a typescript file", function() - local ts_content = { - "", - "const foo = function() {}", - } - local p, buffer = setup(ts_content, 2, 12, "typescript") - local state = _99.__get_state() + it("should test a typescript file", function() + local ts_content = { + "", + "const foo = function() {}", + } + local p, buffer = setup(ts_content, 2, 12, "typescript") + local state = _99.__get_state() - _99.fill_in_function() + _99.fill_in_function() - eq(1, state:active_request_count()) - eq(ts_content, r(buffer)) + eq(1, state:active_request_count()) + eq(ts_content, r(buffer)) - p:resolve("success", "function() {\n return 42;\n}") - test_utils.next_frame() + p:resolve("success", "function() {\n return 42;\n}") + test_utils.next_frame() - local expected_state = { - "", - "const foo = function() {", - " return 42;", - "}", - } - eq(expected_state, r(buffer)) - eq(0, state:active_request_count()) - end) + local expected_state = { + "", + "const foo = function() {", + " return 42;", + "}", + } + eq(expected_state, r(buffer)) + eq(0, state:active_request_count()) + end) - it("should cancel request when stop_all_requests is called", function() - local p, buffer = setup(content, 2, 12) - _99.fill_in_function() + it("should cancel request when stop_all_requests is called", function() + local p, buffer = setup(content, 2, 12) + _99.fill_in_function() - eq(content, r(buffer)) + eq(content, r(buffer)) - assert.is_false(p.request.request:is_cancelled()) - assert.is_not_nil(p.request) - assert.is_not_nil(p.request.request) + assert.is_false(p.request.request:is_cancelled()) + assert.is_not_nil(p.request) + assert.is_not_nil(p.request.request) - _99.stop_all_requests() - test_utils.next_frame() + _99.stop_all_requests() + test_utils.next_frame() - assert.is_true(p.request.request:is_cancelled()) + assert.is_true(p.request.request:is_cancelled()) - p:resolve("success", "function foo()\n return 42\nend") - test_utils.next_frame() + p:resolve("success", "function foo()\n return 42\nend") + test_utils.next_frame() - eq(content, r(buffer)) - end) + eq(content, r(buffer)) + end) - it("should handle error cases with graceful failures", function() - local p, buffer = setup(content, 2, 12) - _99.fill_in_function() + it("should handle error cases with graceful failures", function() + local p, buffer = setup(content, 2, 12) + _99.fill_in_function() - eq(content, r(buffer)) + eq(content, r(buffer)) - p:resolve("failed", "Something went wrong") - test_utils.next_frame() + p:resolve("failed", "Something went wrong") + test_utils.next_frame() - eq(content, r(buffer)) - end) + eq(content, r(buffer)) + end) end) diff --git a/lua/99/test/geo_spec.lua b/lua/99/test/geo_spec.lua index c8213a7..9dc107b 100644 --- a/lua/99/test/geo_spec.lua +++ b/lua/99/test/geo_spec.lua @@ -6,103 +6,103 @@ local test_utils = require("99.test.test_utils") local eq = assert.are.same describe("Range", function() - local buffer + local buffer - before_each(function() - buffer = test_utils.create_file({ - "function foo()", - " local x = 1", - " return x", - "end", - "", - "function bar()", - " return 42", - "end", - }, "lua", 1, 0) - end) + before_each(function() + buffer = test_utils.create_file({ + "function foo()", + " local x = 1", + " return x", + "end", + "", + "function bar()", + " return 42", + "end", + }, "lua", 1, 0) + end) - after_each(function() - test_utils.clean_files() - end) + after_each(function() + test_utils.clean_files() + end) - it("replace text", function() - local start_point = Point:new(2, 3) - local end_point = Point:new(3, 11) - local range = Range:new(buffer, start_point, end_point) - local original_text = range:to_text() - eq("local x = 1\n return x", original_text) + it("replace text", function() + local start_point = Point:new(2, 3) + local end_point = Point:new(3, 11) + local range = Range:new(buffer, start_point, end_point) + local original_text = range:to_text() + eq("local x = 1\n return x", original_text) - local replace_text = { "local y = 2" } - range:replace_text(replace_text) - local lines = vim.api.nvim_buf_get_lines(buffer, 0, -1, false) - eq({ - "function foo()", - " local y = 2", - "end", - "", - "function bar()", - " return 42", - "end", - }, lines) - end) + local replace_text = { "local y = 2" } + range:replace_text(replace_text) + local lines = vim.api.nvim_buf_get_lines(buffer, 0, -1, false) + eq({ + "function foo()", + " local y = 2", + "end", + "", + "function bar()", + " return 42", + "end", + }, lines) + end) - it("replace text single line into multi-line", function() - local start_point = Point:new(2, 3) - local end_point = Point:new(3, 11) - local range = Range:new(buffer, start_point, end_point) - local original_text = range:to_text() - eq("local x = 1\n return x", original_text) + it("replace text single line into multi-line", function() + local start_point = Point:new(2, 3) + local end_point = Point:new(3, 11) + local range = Range:new(buffer, start_point, end_point) + local original_text = range:to_text() + eq("local x = 1\n return x", original_text) - local replace_text = { - "local y = 2", - " local z = 3", - } - range:replace_text(replace_text) - local lines = vim.api.nvim_buf_get_lines(buffer, 0, -1, false) - eq({ - "function foo()", - " local y = 2", - " local z = 3", - "end", - "", - "function bar()", - " return 42", - "end", - }, lines) - end) + local replace_text = { + "local y = 2", + " local z = 3", + } + range:replace_text(replace_text) + local lines = vim.api.nvim_buf_get_lines(buffer, 0, -1, false) + eq({ + "function foo()", + " local y = 2", + " local z = 3", + "end", + "", + "function bar()", + " return 42", + "end", + }, lines) + end) - it( - "should be able to visual line select an empty line and return out an empty line of text", - function() - vim.api.nvim_win_set_cursor(0, { 5, 0 }) - vim.api.nvim_feedkeys("V", "x", false) + it( + "should be able to visual line select an empty line and return out an empty line of text", + function() + vim.api.nvim_win_set_cursor(0, { 5, 0 }) + vim.api.nvim_feedkeys("V", "x", false) - test_utils.next_frame() - vim.api.nvim_feedkeys( - vim.api.nvim_replace_termcodes("<Esc>", true, false, true), - "x", - false - ) + test_utils.next_frame() + vim.api.nvim_feedkeys( + vim.api.nvim_replace_termcodes("<Esc>", true, false, true), + "x", + false + ) - local range = Range.from_visual_selection() - local text = range:to_text() - eq("", text) - end - ) + local range = Range.from_visual_selection() + local text = range:to_text() + eq("", text) + end + ) - it("should create range from simple visual line selection", function() - vim.api.nvim_win_set_cursor(0, { 2, 0 }) - vim.api.nvim_feedkeys("V", "x", false) + it("should create range from simple visual line selection", function() + vim.api.nvim_win_set_cursor(0, { 2, 0 }) + vim.api.nvim_feedkeys("V", "x", false) - test_utils.next_frame() - vim.api.nvim_feedkeys( - vim.api.nvim_replace_termcodes("<Esc>", true, false, true), - "x", - false - ) + test_utils.next_frame() + vim.api.nvim_feedkeys( + vim.api.nvim_replace_termcodes("<Esc>", true, false, true), + "x", + false + ) - local range = Range.from_visual_selection() - local text = range:to_text() - eq(" local x = 1", text) - end) + local range = Range.from_visual_selection() + local text = range:to_text() + eq(" local x = 1", text) + end) end) diff --git a/lua/99/test/implement-fn_spec-DO-NOT-USE-YET.lua b/lua/99/test/implement-fn_spec-DO-NOT-USE-YET.lua index 317d270..66ee174 100644 --- a/lua/99/test/implement-fn_spec-DO-NOT-USE-YET.lua +++ b/lua/99/test/implement-fn_spec-DO-NOT-USE-YET.lua @@ -7,49 +7,49 @@ local test_content = require("99.test.test_content") --- @param content string[] --- @return _99.test.Provider, number local function setup(content) - local p = test_utils.TestProvider.new() - _99.setup({ - provider = p, - }) + local p = test_utils.TestProvider.new() + _99.setup({ + provider = p, + }) - local buffer = test_utils.create_file(content, "lua", 3, 3) - return p, buffer + local buffer = test_utils.create_file(content, "lua", 3, 3) + return p, buffer end --- @param buffer number --- @return string[] local function r(buffer) - return vim.api.nvim_buf_get_lines(buffer, 0, -1, false) + return vim.api.nvim_buf_get_lines(buffer, 0, -1, false) end local content = { - "function some_other_function() end", - "function foo()", - " bar()", - "end", - "", + "function some_other_function() end", + "function foo()", + " bar()", + "end", + "", } describe("implement_function", function() - it("basic call", function() - local p, buffer = setup(content) - _99.implement_fn() - eq(content, r(buffer)) + it("basic call", function() + local p, buffer = setup(content) + _99.implement_fn() + eq(content, r(buffer)) - p:resolve("success", "function bar()\n return 42\nend") - test_utils.next_frame() + p:resolve("success", "function bar()\n return 42\nend") + test_utils.next_frame() - local expected_state = { - "function some_other_function() end", - "function bar()", - " return 42", - "end", - "function foo()", - " bar()", - "end", - "", - } - eq(expected_state, r(buffer)) - end) + local expected_state = { + "function some_other_function() end", + "function bar()", + " return 42", + "end", + "function foo()", + " bar()", + "end", + "", + } + eq(expected_state, r(buffer)) + end) - it("should cancel request when stop_all_requests is called", function() end) + it("should cancel request when stop_all_requests is called", function() end) end) diff --git a/lua/99/test/logger_spec.lua b/lua/99/test/logger_spec.lua index a602dd5..c7bda84 100644 --- a/lua/99/test/logger_spec.lua +++ b/lua/99/test/logger_spec.lua @@ -5,7 +5,7 @@ local eq = assert.are.same local now = 0 time.now = function() - return now + return now end --- @class _99.Test.Logger.RequestLogs @@ -15,82 +15,82 @@ end --- @param all_logs string[][] --- @return _99.Test.Logger.RequestLogs local function l(all_logs) - local out = {} - for _, logs in ipairs(all_logs) do - local lines = {} - table.insert(out, lines) - for _, log_line in ipairs(logs) do - table.insert(lines, vim.json.decode(log_line)) - end + local out = {} + for _, logs in ipairs(all_logs) do + local lines = {} + table.insert(out, lines) + for _, log_line in ipairs(logs) do + table.insert(lines, vim.json.decode(log_line)) end - return out + end + return out end describe("Logger", function() - after_each(function() - Logger.reset() - now = 0 - Logger.set_max_cached_requests(2) - end) + after_each(function() + Logger.reset() + now = 0 + Logger.set_max_cached_requests(2) + end) - it("no caching of non ID'd logs. Global logs", function() - eq({}, Logger.logs()) + it("no caching of non ID'd logs. Global logs", function() + eq({}, Logger.logs()) - local ok = pcall(Logger.debug, Logger, "test log") - eq({}, Logger.logs()) - eq(ok, false) - end) + local ok = pcall(Logger.debug, Logger, "test log") + eq({}, Logger.logs()) + eq(ok, false) + end) - it("cache logs, keep max count", function() - eq({}, Logger.logs()) - local logger = Logger:set_id(69) + it("cache logs, keep max count", function() + eq({}, Logger.logs()) + local logger = Logger:set_id(69) - logger:debug("test log") + logger:debug("test log") - eq({ - { - { level = "DEBUG", id = 69, msg = "test log" }, - }, - }, l(Logger.logs())) + eq({ + { + { level = "DEBUG", id = 69, msg = "test log" }, + }, + }, l(Logger.logs())) - local logger2 = logger:set_id(420) - now = 1000 - logger2:error("error log") + local logger2 = logger:set_id(420) + now = 1000 + logger2:error("error log") - eq({ - { - { level = "ERROR", id = 420, msg = "error log" }, - }, - { - { level = "DEBUG", id = 69, msg = "test log" }, - }, - }, l(Logger.logs())) + eq({ + { + { level = "ERROR", id = 420, msg = "error log" }, + }, + { + { level = "DEBUG", id = 69, msg = "test log" }, + }, + }, l(Logger.logs())) - now = 1001 - logger:warn("warn log") + now = 1001 + logger:warn("warn log") - eq({ - { - { level = "DEBUG", id = 69, msg = "test log" }, - { level = "WARN", id = 69, msg = "warn log" }, - }, - { - { level = "ERROR", id = 420, msg = "error log" }, - }, - }, l(Logger.logs())) + eq({ + { + { level = "DEBUG", id = 69, msg = "test log" }, + { level = "WARN", id = 69, msg = "warn log" }, + }, + { + { level = "ERROR", id = 420, msg = "error log" }, + }, + }, l(Logger.logs())) - local logger3 = logger:set_id(1337) - now = 1002 - logger3:info("info log") + local logger3 = logger:set_id(1337) + now = 1002 + logger3:info("info log") - eq({ - { - { level = "INFO", id = 1337, msg = "info log" }, - }, - { - { level = "DEBUG", id = 69, msg = "test log" }, - { level = "WARN", id = 69, msg = "warn log" }, - }, - }, l(Logger.logs())) - end) + eq({ + { + { level = "INFO", id = 1337, msg = "info log" }, + }, + { + { level = "DEBUG", id = 69, msg = "test log" }, + { level = "WARN", id = 69, msg = "warn log" }, + }, + }, l(Logger.logs())) + end) end) diff --git a/lua/99/test/marks_spec.lua b/lua/99/test/marks_spec.lua index 3c28248..0b810f0 100644 --- a/lua/99/test/marks_spec.lua +++ b/lua/99/test/marks_spec.lua @@ -7,147 +7,143 @@ local test_utils = require("99.test.test_utils") local eq = assert.are.same describe("Mark", function() - local buffer + local buffer - before_each(function() - buffer = test_utils.create_file({ - "function foo()", - " local x = 1", - " return x", - "end", - "", - "function bar()", - " return 42", - "end", - }, "lua", 1, 0) - end) + before_each(function() + buffer = test_utils.create_file({ + "function foo()", + " local x = 1", + " return x", + "end", + "", + "function bar()", + " return 42", + "end", + }, "lua", 1, 0) + end) - after_each(function() - test_utils.clean_files() - end) + after_each(function() + test_utils.clean_files() + end) - it("should create a mark at a specific point", function() - local point = Point:new(2, 3) - local mark = Mark.mark_point(buffer, point) - local mark_point = Point.from_mark(mark) + it("should create a mark at a specific point", function() + local point = Point:new(2, 3) + local mark = Mark.mark_point(buffer, point) + local mark_point = Point.from_mark(mark) - eq(point, mark_point) + eq(point, mark_point) - mark:delete() - end) + mark:delete() + end) - it("marks range", function() - local start_point = Point:new(2, 3) - local end_point = Point:new(3, 10) - local range = Range:new(buffer, start_point, end_point) - local mark_start, mark_end = Mark.mark_range(range) - local actual_start = Point.from_mark(mark_start) - local actual_end = Point.from_mark(mark_end) + it("marks range", function() + local start_point = Point:new(2, 3) + local end_point = Point:new(3, 10) + local range = Range:new(buffer, start_point, end_point) + local mark_start, mark_end = Mark.mark_range(range) + local actual_start = Point.from_mark(mark_start) + local actual_end = Point.from_mark(mark_end) - eq(start_point, actual_start) - eq(end_point, actual_end) + eq(start_point, actual_start) + eq(end_point, actual_end) - mark_start:delete() - mark_end:delete() - end) + mark_start:delete() + mark_end:delete() + end) - it("should handle single-line ranges", function() - local start_point = Point:new(2, 3) - local end_point = Point:new(2, 10) - local range = Range:new(buffer, start_point, end_point) - local mark_start, mark_end = Mark.mark_range(range) - local actual_start = Point.from_mark(mark_start) - local actual_end = Point.from_mark(mark_end) + it("should handle single-line ranges", function() + local start_point = Point:new(2, 3) + local end_point = Point:new(2, 10) + local range = Range:new(buffer, start_point, end_point) + local mark_start, mark_end = Mark.mark_range(range) + local actual_start = Point.from_mark(mark_start) + local actual_end = Point.from_mark(mark_end) - eq(start_point, actual_start) - eq(end_point, actual_end) + eq(start_point, actual_start) + eq(end_point, actual_end) - mark_start:delete() - mark_end:delete() - end) + mark_start:delete() + mark_end:delete() + end) - it("should create mark one line above the range start", function() - local above_point = Point:new(2, 14) - local start_point = Point:new(3, 5) - local end_point = Point:new(4, 3) - local range = Range:new(buffer, start_point, end_point) - local mark = Mark.mark_above_range(range) - local mark_point = Point.from_mark(mark) + it("should create mark one line above the range start", function() + local above_point = Point:new(2, 14) + local start_point = Point:new(3, 5) + local end_point = Point:new(4, 3) + local range = Range:new(buffer, start_point, end_point) + local mark = Mark.mark_above_range(range) + local mark_point = Point.from_mark(mark) - eq(above_point, mark_point) + eq(above_point, mark_point) - mark:delete() - end) + mark:delete() + end) - it("should create mark at beginning when range starts at line 1", function() - local start_point = Point:new(1, 5) - local end_point = Point:new(2, 3) - local range = Range:new(buffer, start_point, end_point) - local mark = Mark.mark_above_range(range) - local mark_point = Point.from_mark(mark) + it("should create mark at beginning when range starts at line 1", function() + local start_point = Point:new(1, 5) + local end_point = Point:new(2, 3) + local range = Range:new(buffer, start_point, end_point) + local mark = Mark.mark_above_range(range) + local mark_point = Point.from_mark(mark) - local beginning_point = Point:new(1, 1) - eq(beginning_point, mark_point) - mark:delete() - end) + local beginning_point = Point:new(1, 1) + eq(beginning_point, mark_point) + mark:delete() + end) - it("should create mark at the end of the range", function() - local start_point = Point:new(2, 3) - local end_point = Point:new(3, 8) - local range = Range:new(buffer, start_point, end_point) - local mark = Mark.mark_end_of_range(buffer, range) - local mark_point = Point.from_mark(mark) - local expected_end_point = end_point:add(Point:new(0, 1)) + it("should create mark at the end of the range", function() + local start_point = Point:new(2, 3) + local end_point = Point:new(3, 8) + local range = Range:new(buffer, start_point, end_point) + local mark = Mark.mark_end_of_range(buffer, range) + local mark_point = Point.from_mark(mark) + local expected_end_point = end_point:add(Point:new(0, 1)) - eq(expected_end_point, mark_point) + eq(expected_end_point, mark_point) - mark:delete() - end) + mark:delete() + end) - it("should create mark above a function", function() - local func_start = Point:new(6, 1) - local func_end = Point:new(8, 4) - local func_range = Range:new(buffer, func_start, func_end) - local mock_func = { - function_range = func_range, - } + it("should create mark above a function", function() + local func_start = Point:new(6, 1) + local func_end = Point:new(8, 4) + local func_range = Range:new(buffer, func_start, func_end) + local mock_func = { + function_range = func_range, + } - local mark = Mark.mark_above_func(buffer, mock_func) - local mark_point = Point.from_mark(mark) - local expected_mark_point = func_start:sub(Point:new(1, 0)) + local mark = Mark.mark_above_func(buffer, mock_func) + local mark_point = Point.from_mark(mark) + local expected_mark_point = func_start:sub(Point:new(1, 0)) - eq(expected_mark_point, mark_point) - mark:delete() - end) + eq(expected_mark_point, mark_point) + mark:delete() + end) - it("should create mark at function body start", function() - local func_start = Point:new(6, 1) - local func_end = Point:new(8, 4) - local func_range = Range:new(buffer, func_start, func_end) - local mock_func = { - function_range = func_range, - } - local mark = Mark.mark_func_body(buffer, mock_func) - local mark_point = Point.from_mark(mark) + it("should create mark at function body start", function() + local func_start = Point:new(6, 1) + local func_end = Point:new(8, 4) + local func_range = Range:new(buffer, func_start, func_end) + local mock_func = { + function_range = func_range, + } + local mark = Mark.mark_func_body(buffer, mock_func) + local mark_point = Point.from_mark(mark) - eq(func_start, mark_point) + eq(func_start, mark_point) - mark:delete() - end) + mark:delete() + end) - it("should delete the extmark", function() - local point = Point:new(2, 3) - local mark = Mark.mark_point(buffer, point) - local mark_pos = Point.from_mark(mark) - eq(point, mark_pos) - mark:delete() + it("should delete the extmark", function() + local point = Point:new(2, 3) + local mark = Mark.mark_point(buffer, point) + local mark_pos = Point.from_mark(mark) + eq(point, mark_pos) + mark:delete() - local deleted_pos = vim.api.nvim_buf_get_extmark_by_id( - mark.buffer, - mark.nsid, - mark.id, - {} - ) - eq(0, #deleted_pos) - end) + local deleted_pos = + vim.api.nvim_buf_get_extmark_by_id(mark.buffer, mark.nsid, mark.id, {}) + eq(0, #deleted_pos) + end) end) diff --git a/lua/99/test/request_status_spec.lua b/lua/99/test/request_status_spec.lua index fadae04..90bb145 100644 --- a/lua/99/test/request_status_spec.lua +++ b/lua/99/test/request_status_spec.lua @@ -3,17 +3,17 @@ local eq = assert.are.same local RequestStatus = require("99.ops.request_status") describe("request_status", function() - it("setting lines and status line", function() - local status = RequestStatus.new(2000000, 3, "TITLE") - eq({ "⠙ TITLE" }, status:get()) + it("setting lines and status line", function() + local status = RequestStatus.new(2000000, 3, "TITLE") + eq({ "⠙ TITLE" }, status:get()) - status:push("foo") - status:push("bar") + status:push("foo") + status:push("bar") - eq({ "⠙ TITLE", "foo", "bar" }, status:get()) + eq({ "⠙ TITLE", "foo", "bar" }, status:get()) - status:push("baz") + status:push("baz") - eq({ "⠙ TITLE", "bar", "baz" }, status:get()) - end) + eq({ "⠙ TITLE", "bar", "baz" }, status:get()) + end) end) diff --git a/lua/99/test/test_utils.lua b/lua/99/test/test_utils.lua index 29b7344..2f60b86 100644 --- a/lua/99/test/test_utils.lua +++ b/lua/99/test/test_utils.lua @@ -1,14 +1,14 @@ local M = {} function M.next_frame() - local next = false - vim.schedule(function() - next = true - end) + local next = false + vim.schedule(function() + next = true + end) - vim.wait(1000, function() - return next - end) + vim.wait(1000, function() + return next + end) end M.created_files = {} @@ -25,64 +25,64 @@ local TestProvider = {} TestProvider.__index = TestProvider function TestProvider.new() - return setmetatable({}, TestProvider) + return setmetatable({}, TestProvider) end --- @param query string ---@param request _99.Request ---@param observer _99.ProviderObserver? function TestProvider:make_request(query, request, observer) - local logger = request.context.logger:set_area("TestProvider") - logger:debug("make_request", "tmp_file", request.context.tmp_file) - self.request = { - query = query, - request = request, - observer = observer, - logger = logger, - } + local logger = request.context.logger:set_area("TestProvider") + logger:debug("make_request", "tmp_file", request.context.tmp_file) + self.request = { + query = query, + request = request, + observer = observer, + logger = logger, + } end --- @param status _99.Request.ResponseState --- @param result string function TestProvider:resolve(status, result) - assert(self.request, "you cannot call resolve until make_request is called") - local obs = self.request.observer - if obs then - --- to match the behavior expected from the OpenCodeProvider - if self.request.request:is_cancelled() then - obs.on_complete("cancelled", result) - else - obs.on_complete(status, result) - end + assert(self.request, "you cannot call resolve until make_request is called") + local obs = self.request.observer + if obs then + --- to match the behavior expected from the OpenCodeProvider + if self.request.request:is_cancelled() then + obs.on_complete("cancelled", result) + else + obs.on_complete(status, result) end - self.request = nil + end + self.request = nil end --- @param line string function TestProvider:stdout(line) - assert(self.request, "you cannot call stdout until make_request is called") - local obs = self.request.observer - if obs then - obs.on_stdout(line) - end + assert(self.request, "you cannot call stdout until make_request is called") + local obs = self.request.observer + if obs then + obs.on_stdout(line) + end end --- @param line string function TestProvider:stderr(line) - assert(self.request, "you cannot call stderr until make_request is called") - local obs = self.request.observer - if obs then - obs.on_stderr(line) - end + assert(self.request, "you cannot call stderr until make_request is called") + local obs = self.request.observer + if obs then + obs.on_stderr(line) + end end M.TestProvider = TestProvider function M.clean_files() - for _, bufnr in ipairs(M.created_files) do - vim.api.nvim_buf_delete(bufnr, { force = true }) - end - M.created_files = {} + for _, bufnr in ipairs(M.created_files) do + vim.api.nvim_buf_delete(bufnr, { force = true }) + end + M.created_files = {} end ---@param contents string[] @@ -90,17 +90,17 @@ end ---@param row number? ---@param col number? function M.create_file(contents, file_type, row, col) - assert(type(contents) == "table", "contents must be a table of strings") - file_type = file_type or "lua" - local bufnr = vim.api.nvim_create_buf(false, false) + assert(type(contents) == "table", "contents must be a table of strings") + file_type = file_type or "lua" + local bufnr = vim.api.nvim_create_buf(false, false) - vim.api.nvim_set_current_buf(bufnr) - vim.bo[bufnr].ft = file_type - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, contents) - vim.api.nvim_win_set_cursor(0, { row or 1, col or 0 }) + vim.api.nvim_set_current_buf(bufnr) + vim.bo[bufnr].ft = file_type + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, contents) + vim.api.nvim_win_set_cursor(0, { row or 1, col or 0 }) - table.insert(M.created_files, bufnr) - return bufnr + table.insert(M.created_files, bufnr) + return bufnr end return M diff --git a/lua/99/test/visual_spec.lua b/lua/99/test/visual_spec.lua index bb02567..c4b1394 100644 --- a/lua/99/test/visual_spec.lua +++ b/lua/99/test/visual_spec.lua @@ -13,159 +13,156 @@ local Point = require("99.geo").Point --- @param end_col number --- @return _99.test.Provider, number, _99.Range local function setup(content, start_row, start_col, end_row, end_col) - local p = test_utils.TestProvider.new() - _99.setup({ - provider = p, - logger = { - error_cache_level = Levels.ERROR, - }, - }) + local p = test_utils.TestProvider.new() + _99.setup({ + provider = p, + logger = { + error_cache_level = Levels.ERROR, + }, + }) - local buffer = test_utils.create_file(content, "lua", start_row, start_col) + local buffer = test_utils.create_file(content, "lua", start_row, start_col) - -- Create a range for the visual selection - local start_point = Point:new(start_row, start_col) - local end_point = Point:new(end_row, end_col) - local range = Range:new(buffer, start_point, end_point) + -- Create a range for the visual selection + local start_point = Point:new(start_row, start_col) + local end_point = Point:new(end_row, end_col) + local range = Range:new(buffer, start_point, end_point) - return p, buffer, range + return p, buffer, range end --- @param buffer number --- @return string[] local function r(buffer) - return vim.api.nvim_buf_get_lines(buffer, 0, -1, false) + return vim.api.nvim_buf_get_lines(buffer, 0, -1, false) end local content = { - "local function foo()", - " -- TODO: implement", - "end", + "local function foo()", + " -- TODO: implement", + "end", } describe("visual", function() - it("should replace visual selection with AI response", function() - local p, buffer, range = setup(content, 2, 1, 2, 23) - local state = _99.__get_state() - local visual_fn = require("99.ops.over-range") + it("should replace visual selection with AI response", function() + local p, buffer, range = setup(content, 2, 1, 2, 23) + local state = _99.__get_state() + local visual_fn = require("99.ops.over-range") - local context = - require("99.request-context").from_current_buffer(state, 100) - visual_fn(context, range) + local context = + require("99.request-context").from_current_buffer(state, 100) + visual_fn(context, range) - eq(1, state:active_request_count()) - eq(content, r(buffer)) + eq(1, state:active_request_count()) + eq(content, r(buffer)) - p:resolve("success", " return 'implemented!'") - test_utils.next_frame() + p:resolve("success", " return 'implemented!'") + test_utils.next_frame() - local expected_state = { - "local function foo()", - " return 'implemented!'", - "end", - } - eq(expected_state, r(buffer)) - -- Note: Not checking active_request_count() == 0 due to logger bug with "id" key collision - end) + local expected_state = { + "local function foo()", + " return 'implemented!'", + "end", + } + eq(expected_state, r(buffer)) + -- Note: Not checking active_request_count() == 0 due to logger bug with "id" key collision + end) - it("should handle multi-line replacement", function() - local multi_line_content = { - "local function bar()", - " -- TODO: implement", - " -- more comments", - " -- even more", - "end", - } - local p, buffer, range = setup(multi_line_content, 2, 1, 4, 17) - local state = _99.__get_state() - local visual_fn = require("99.ops.over-range") + it("should handle multi-line replacement", function() + local multi_line_content = { + "local function bar()", + " -- TODO: implement", + " -- more comments", + " -- even more", + "end", + } + local p, buffer, range = setup(multi_line_content, 2, 1, 4, 17) + local state = _99.__get_state() + local visual_fn = require("99.ops.over-range") - local context = - require("99.request-context").from_current_buffer(state, 200) - visual_fn(context, range) + local context = + require("99.request-context").from_current_buffer(state, 200) + visual_fn(context, range) - eq(1, state:active_request_count()) - eq(multi_line_content, r(buffer)) + eq(1, state:active_request_count()) + eq(multi_line_content, r(buffer)) - p:resolve( - "success", - " local x = 1\n local y = 2\n return x + y" - ) - test_utils.next_frame() + p:resolve("success", " local x = 1\n local y = 2\n return x + y") + test_utils.next_frame() - local expected_state = { - "local function bar()", - " local x = 1", - " local y = 2", - " return x + y", - "end", - } - eq(expected_state, r(buffer)) - -- Note: Not checking active_request_count() == 0 due to logger bug with "id" key collision - end) + local expected_state = { + "local function bar()", + " local x = 1", + " local y = 2", + " return x + y", + "end", + } + eq(expected_state, r(buffer)) + -- Note: Not checking active_request_count() == 0 due to logger bug with "id" key collision + end) - it("should cancel request when stop_all_requests is called", function() - local p, buffer, range = setup(content, 2, 1, 2, 23) - local visual_fn = require("99.ops.over-range") - local state = _99.__get_state() - local context = - require("99.request-context").from_current_buffer(state, 300) + it("should cancel request when stop_all_requests is called", function() + local p, buffer, range = setup(content, 2, 1, 2, 23) + local visual_fn = require("99.ops.over-range") + local state = _99.__get_state() + local context = + require("99.request-context").from_current_buffer(state, 300) - visual_fn(context, range) + visual_fn(context, range) - eq(content, r(buffer)) + eq(content, r(buffer)) - assert.is_false(p.request.request:is_cancelled()) - assert.is_not_nil(p.request) - assert.is_not_nil(p.request.request) + assert.is_false(p.request.request:is_cancelled()) + assert.is_not_nil(p.request) + assert.is_not_nil(p.request.request) - _99.stop_all_requests() - test_utils.next_frame() + _99.stop_all_requests() + test_utils.next_frame() - assert.is_true(p.request.request:is_cancelled()) + assert.is_true(p.request.request:is_cancelled()) - p:resolve("success", " return 'should not appear'") - test_utils.next_frame() + p:resolve("success", " return 'should not appear'") + test_utils.next_frame() - -- Buffer should remain unchanged after cancellation - eq(content, r(buffer)) - end) + -- Buffer should remain unchanged after cancellation + eq(content, r(buffer)) + end) - it("should handle error cases with graceful failures", function() - local p, buffer, range = setup(content, 2, 1, 2, 23) - local visual_fn = require("99.ops.over-range") - local state = _99.__get_state() - local context = - require("99.request-context").from_current_buffer(state, 400) + it("should handle error cases with graceful failures", function() + local p, buffer, range = setup(content, 2, 1, 2, 23) + local visual_fn = require("99.ops.over-range") + local state = _99.__get_state() + local context = + require("99.request-context").from_current_buffer(state, 400) - visual_fn(context, range) + visual_fn(context, range) - eq(content, r(buffer)) + eq(content, r(buffer)) - p:resolve("failed", "Something went wrong") - test_utils.next_frame() + p:resolve("failed", "Something went wrong") + test_utils.next_frame() - -- Buffer should remain unchanged on failure - eq(content, r(buffer)) - end) + -- Buffer should remain unchanged on failure + eq(content, r(buffer)) + end) - it("should handle cancelled status gracefully", function() - local p, buffer, range = setup(content, 2, 1, 2, 23) - local visual_fn = require("99.ops.over-range") - local state = _99.__get_state() - local context = - require("99.request-context").from_current_buffer(state, 500) + it("should handle cancelled status gracefully", function() + local p, buffer, range = setup(content, 2, 1, 2, 23) + local visual_fn = require("99.ops.over-range") + local state = _99.__get_state() + local context = + require("99.request-context").from_current_buffer(state, 500) - visual_fn(context, range) + visual_fn(context, range) - eq(content, r(buffer)) + eq(content, r(buffer)) - -- Manually cancel and resolve as cancelled - p.request.request:cancel() - p:resolve("cancelled", "Request was cancelled") - test_utils.next_frame() + -- Manually cancel and resolve as cancelled + p.request.request:cancel() + p:resolve("cancelled", "Request was cancelled") + test_utils.next_frame() - -- Buffer should remain unchanged on cancellation - eq(content, r(buffer)) - end) + -- Buffer should remain unchanged on cancellation + eq(content, r(buffer)) + end) end) |
