diff options
| author | TJ DeVries <devries.timothyj@gmail.com> | 2022-08-04 16:00:30 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-04 16:00:30 -0400 |
| commit | 4725867ec66b9a0f5e5ad95a1fd94c2f97fa2d2c (patch) | |
| tree | f4dcf668bb66469273e630f69eebe123d390f2c0 /lua/telescope/testharness | |
| parent | 75a5e5065376d9103fc4bafc3ae6327304cee6e9 (diff) | |
fix: restore testing framework to actually work (#2070)
after refactor to some new asynchronous items for finders,
the tests stopped actually doing anything.
now they do things again.
Diffstat (limited to 'lua/telescope/testharness')
| -rw-r--r-- | lua/telescope/testharness/helpers.lua | 56 | ||||
| -rw-r--r-- | lua/telescope/testharness/init.lua | 112 | ||||
| -rw-r--r-- | lua/telescope/testharness/runner.lua | 156 |
3 files changed, 324 insertions, 0 deletions
diff --git a/lua/telescope/testharness/helpers.lua b/lua/telescope/testharness/helpers.lua new file mode 100644 index 0000000..5296c45 --- /dev/null +++ b/lua/telescope/testharness/helpers.lua @@ -0,0 +1,56 @@ +local test_helpers = {} + +test_helpers.get_picker = function() + local state = require "telescope.state" + return state.get_status(vim.api.nvim_get_current_buf()).picker +end + +test_helpers.get_results_bufnr = function() + local state = require "telescope.state" + return state.get_status(vim.api.nvim_get_current_buf()).results_bufnr +end + +test_helpers.get_file = function() + return vim.fn.fnamemodify(vim.api.nvim_buf_get_name(0), ":t") +end + +test_helpers.get_prompt = function() + return vim.api.nvim_buf_get_lines(0, 0, -1, false)[1] +end + +test_helpers.get_results = function() + return vim.api.nvim_buf_get_lines(test_helpers.get_results_bufnr(), 0, -1, false) +end + +test_helpers.get_best_result = function() + local results = test_helpers.get_results() + local picker = test_helpers.get_picker() + + if picker.sorting_strategy == "ascending" then + return results[1] + else + return results[#results] + end +end + +test_helpers.get_selection = function() + local state = require "telescope.state" + return state.get_global_key "selected_entry" +end + +test_helpers.get_selection_value = function() + return test_helpers.get_selection().value +end + +test_helpers.make_globals = function() + GetFile = test_helpers.get_file -- luacheck: globals GetFile + GetPrompt = test_helpers.get_prompt -- luacheck: globals GetPrompt + + GetResults = test_helpers.get_results -- luacheck: globals GetResults + GetBestResult = test_helpers.get_best_result -- luacheck: globals GetBestResult + + GetSelection = test_helpers.get_selection -- luacheck: globals GetSelection + GetSelectionValue = test_helpers.get_selection_value -- luacheck: globals GetSelectionValue +end + +return test_helpers diff --git a/lua/telescope/testharness/init.lua b/lua/telescope/testharness/init.lua new file mode 100644 index 0000000..9a8e707 --- /dev/null +++ b/lua/telescope/testharness/init.lua @@ -0,0 +1,112 @@ +local assert = require "luassert" + +local Path = require "plenary.path" + +local tester = {} +tester.debug = false + +local get_results_from_contents = function(content) + local nvim = vim.fn.jobstart( + { "nvim", "--noplugin", "-u", "scripts/minimal_init.vim", "--headless", "--embed" }, + { rpc = true } + ) + + local result = vim.fn.rpcrequest(nvim, "nvim_exec_lua", content, {}) + assert.are.same(true, result[1], vim.inspect(result)) + + local count = 0 + while + vim.fn.rpcrequest(nvim, "nvim_exec_lua", "return require('telescope.testharness.runner').state.done", {}) ~= true + do + count = count + 1 + vim.wait(100) + + -- TODO: Could maybe wait longer, but it's annoying to wait if the test is going to timeout. + if count > 100 then + break + end + end + + local state = vim.fn.rpcrequest(nvim, "nvim_exec_lua", "return require('telescope.testharness.runner').state", {}) + vim.fn.jobstop(nvim) + + assert.are.same(true, state.done, vim.inspect(state)) + + local result_table = {} + for _, v in ipairs(state.results) do + table.insert(result_table, v) + end + + return result_table, state +end + +local check_results = function(results, state) + assert(state, "Must pass state") + + for _, v in ipairs(results) do + local assertion + if not v._type or v._type == "are" or v._type == "_default" then + assertion = assert.are.same + else + assertion = assert.are_not.same + end + + -- TODO: I think it would be nice to be able to see the state, + -- but it clutters up the test output so much here. + -- + -- So we would have to consider how to do that I think. + assertion(v.expected, v.actual, string.format("Test Case: %s // %s", v.location, v.case)) + end +end + +tester.run_string = function(contents) + contents = [[ + return (function() + local tester = require('telescope.testharness') + local runner = require('telescope.testharness.runner') + local helper = require('telescope.testharness.helpers') + helper.make_globals() + local ok, msg = pcall(function() + runner.log("Loading Test") + ]] .. contents .. [[ + end) + return {ok, msg or runner.state} + end)() + ]] + + check_results(get_results_from_contents(contents)) +end + +tester.run_file = function(filename) + local file = "./lua/tests/pickers/" .. filename .. ".lua" + local path = Path:new(file) + + if not path:exists() then + assert.are.same("<An existing file>", file) + end + + local contents = string.format( + [[ + return (function() + local runner = require('telescope.testharness.runner') + local helper = require('telescope.testharness.helpers') + helper.make_globals() + local ok, msg = pcall(function() + runner.log("Loading Test") + return loadfile("%s")() + end) + return {ok, msg or runner.state} + end)() + ]], + path:absolute() + ) + + check_results(get_results_from_contents(contents)) +end + +tester.not_ = function(val) + val._type = "are_not" + return val +end + +return tester diff --git a/lua/telescope/testharness/runner.lua b/lua/telescope/testharness/runner.lua new file mode 100644 index 0000000..af1bf30 --- /dev/null +++ b/lua/telescope/testharness/runner.lua @@ -0,0 +1,156 @@ +local builtin = require "telescope.builtin" + +local DELAY = vim.g.telescope_test_delay or 50 +local runner = {} + +-- State is test variable +runner.state = { + done = false, + results = {}, + msgs = {}, +} + +local writer = function(val) + table.insert(runner.state.results, val) +end + +local invalid_test_case = function(k) + error { case = k, expected = "<a valid key>", actual = k } +end + +local _VALID_KEYS = { + post_typed = true, + post_close = true, +} + +local replace_terms = function(input) + return vim.api.nvim_replace_termcodes(input, true, false, true) +end + +runner.nvim_feed = function(text, feed_opts) + feed_opts = feed_opts or "m" + + vim.api.nvim_feedkeys(text, feed_opts, true) +end + +local end_test_cases = function() + runner.state.done = true +end + +local execute_test_case = function(location, key, spec) + local ok, actual = pcall(spec[2]) + + if not ok then + writer { + location = "Error: " .. location, + case = key, + expected = "To succeed and return: " .. tostring(spec[1]), + actual = actual, + + _type = spec._type, + } + + end_test_cases() + else + writer { + location = location, + case = key, + expected = spec[1], + actual = actual, + + _type = spec._type, + } + end + + return ok +end + +runner.log = function(msg) + table.insert(runner.state.msgs, msg) +end + +runner.picker = function(picker_name, input, test_cases, opts) + opts = opts or {} + + for k, _ in pairs(test_cases) do + if not _VALID_KEYS[k] then + return invalid_test_case(k) + end + end + + opts.on_complete = { + runner.create_on_complete(input, test_cases), + } + + opts._on_error = function(self, msg) + runner.state.done = true + writer { + location = "Error while running on complete", + expected = "To Work", + actual = msg, + } + end + + runner.log "Starting picker" + builtin[picker_name](opts) + runner.log "Called picker" +end + +runner.create_on_complete = function(input, test_cases) + input = replace_terms(input) + + local actions = {} + for i = 1, #input do + local char = input:sub(i, i) + table.insert(actions, { + cb = function() + runner.log("Inserting char: " .. char) + runner.nvim_feed(char, "") + end, + char = char, + }) + end + + return function() + local action + + repeat + action = table.remove(actions, 1) + if action then + action.cb() + end + until not action or string.match(action.char, "%g") + + if #actions > 0 then + return + end + + vim.defer_fn(function() + if test_cases.post_typed then + for k, v in ipairs(test_cases.post_typed) do + if not execute_test_case("post_typed", k, v) then + return + end + end + end + + vim.defer_fn(function() + runner.nvim_feed(replace_terms "<CR>", "") + + vim.defer_fn(function() + if test_cases.post_close then + for k, v in ipairs(test_cases.post_close) do + if not execute_test_case("post_close", k, v) then + return + end + end + end + + vim.defer_fn(end_test_cases, DELAY) + end, DELAY) + end, DELAY) + end, DELAY) + end +end + +return runner |
