diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f43a44819..7f5bdd050 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,16 +26,6 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} # CLI arguments args: --check lua/ tests/ - - name: Install Plenary - uses: actions/checkout@v2 - with: - repository: nvim-lua/plenary.nvim - path: plenary.nvim - - name: Install Treesitter - uses: actions/checkout@v2 - with: - repository: nvim-treesitter/nvim-treesitter - path: nvim-treesitter - name: Install Neovim uses: rhysd/action-setup-vim@v1 id: neovim diff --git a/.gitignore b/.gitignore index 1da12dac2..415c8794d 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,5 @@ luac.out *.x86_64 *.hex -plenary.nvim/ -nvim-treesitter/ -mini.nvim/ +# Directory containing testing dependencies downloaded during test run +.deps/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 93f9cb0ee..803c4a1c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,13 +25,17 @@ Please document any new code you add with [emmylua annotations](https://emmylua. ### Tests - To run tests, [plenary.nvim](https://github.com/nvim-lua/plenary.nvim) and [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) must be present in the nvim-orgmode directory: + To run tests run `make test` in the nvim-orgmode directory: ``` -git clone https://github.com/nvim-treesitter/nvim-treesitter -git clone https://github.com/nvim-lua/plenary.nvim make test ``` +To run a specific test you can set a `FILE` environment variable to a specific +spec you want to test. Example: +``` +make test FILE=./tests/plenary/api/api_spec.lua +``` + ### Formatting Formatting is done via [StyLua](https://github.com/JohnnyMorganz/StyLua). To format everything run: diff --git a/Makefile b/Makefile index 2315b16a2..61e7121f5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ +clean: + nvim --headless --clean -n -c "lua vim.fn.delete('./tests/.deps', 'rf')" +q test: - nvim --headless --clean -u tests/minimal_init.vim -c "TSUpdateSync org" -c "PlenaryBustedDirectory tests/plenary/ {minimal_init = 'tests/minimal_init.vim'}" -testfile: - nvim --headless --clean -u tests/minimal_init.vim -c "TSUpdateSync org" -c "PlenaryBustedDirectory $(FILE) {minimal_init = 'tests/minimal_init.vim'}" + nvim --headless --clean -u tests/test.lua "$(FILE)" docs: md2vim -desc "*orgmode* *orgmode.nvim*\n* NOTE: This file is autogenerated from DOCS.md file" DOCS.md doc/orgmode.txt api_docs: diff --git a/tests/minimal_init.lua b/tests/minimal_init.lua new file mode 100644 index 000000000..0c37302a8 --- /dev/null +++ b/tests/minimal_init.lua @@ -0,0 +1,101 @@ +local M = {} +--- +---@class MinPlugin A plugin to download and register on the package path +---@alias PluginName string The plugin name, will be used as part of the git clone destination +---@alias PluginUrl string The git url at which a plugin is located, can be a path. See https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols for details +---@alias MinPlugins table + +-- Gets the current directory of this file +local base_root_path = vim.fn.fnamemodify(debug.getinfo(1, 'S').source:sub(2), ':p:h') +---Gets the root directory of the minimal init and if path is specified appends the given path to the root allowing for +---subdirectories within the current cwd +---@param path string? The additional path to append to the root, not required +---@return string root The root path suffixed with the path provided or an empty suffix if none was given +function M.root(path) + return base_root_path .. '/.deps/' .. (path or '') +end + +---Downloads a plugin from a given url and registers it on the 'runtimepath' +---@param plugin_name PluginName +---@param plugin_url PluginUrl +function M.load_plugin(plugin_name, plugin_url) + local package_root = M.root('plugins/') + local install_destination = package_root .. plugin_name + vim.opt.runtimepath:append(install_destination) + + if not vim.loop.fs_stat(package_root) then + vim.fn.mkdir(package_root, 'p') + end + + -- If the plugin install path already exists, we don't need to clone it again. + if not vim.loop.fs_stat(install_destination) then + print(string.format('>> Downloading plugin "%s" to "%s"', plugin_name, install_destination)) + vim.fn.system({ + 'git', + 'clone', + '--depth=1', + plugin_url, + install_destination, + }) + if vim.v.shell_error > 0 then + error( + string.format('>> Failed to clone plugin: "%s" to "%s"!', plugin_name, install_destination), + vim.log.levels.ERROR + ) + end + end +end + +---Do the initial setup. Downloads plugins, ensures the minimal init does not pollute the filesystem by keeping +---everything self contained to the CWD of the minimal init file. Run prior to running tests, reproducing issues, etc. +---@param plugins? MinPlugins +function M.setup(plugins) + vim.opt.packpath = {} -- Empty the package path so we use only the plugins specified + vim.opt.runtimepath:append(M.root('.min')) -- Ensure the runtime detects the root min dir + + -- Install required plugins + if plugins ~= nil then + for plugin_name, plugin_url in pairs(plugins) do + M.load_plugin(plugin_name, plugin_url) + end + end + + vim.env.XDG_CONFIG_HOME = M.root('xdg/config') + vim.env.XDG_DATA_HOME = M.root('xdg/data') + vim.env.XDG_STATE_HOME = M.root('xdg/state') + vim.env.XDG_CACHE_HOME = M.root('xdg/cache') + + -- NOTE: Cleanup the xdg cache on exit so new runs of the minimal init doesn't share any previous state, e.g. shada + vim.api.nvim_create_autocmd('VimLeave', { + callback = function() + vim.fn.delete(M.root('xdg'), 'rf') + end, + }) +end + +M.setup({ + plenary = 'https://github.com/nvim-lua/plenary.nvim.git', + treesitter = 'https://github.com/nvim-treesitter/nvim-treesitter', +}) +-- WARN: Do all plugin setup, test runs, reproductions, etc. AFTER calling setup with a list of plugins! +-- Basically, do all that stuff AFTER this line. + +--## Set proper settings ## +-- Register Orgmode on the runtimepath, base_root_path is the directory where this file exists +vim.opt.runtimepath:prepend(vim.fn.fnamemodify(base_root_path, ':h')) +vim.opt.termguicolors = true +vim.opt.swapfile = false +vim.cmd.language('en_US.utf-8') +vim.env.TZ = 'Europe/London' +vim.g.mapleader = ',' + +require('orgmode').setup_ts_grammar() +require('nvim-treesitter.configs').setup({ + ensure_installed = { 'org' }, + sync_install = true, +}) + +require('orgmode').setup({ + org_agenda_files = { base_root_path .. '/plenary/fixtures/*' }, + org_default_notes_file = base_root_path .. '/plenary/fixtures/refile.org', +}) diff --git a/tests/minimal_init.vim b/tests/minimal_init.vim deleted file mode 100644 index e5d7e82d7..000000000 --- a/tests/minimal_init.vim +++ /dev/null @@ -1,21 +0,0 @@ -set rtp+=. -set rtp+=./plenary.nvim -set rtp+=./nvim-treesitter -set termguicolors -set noswapfile -language en_US.utf-8 -runtime plugin/plenary.vim -runtime plugin/nvim-treesitter.lua -let mapleader = ',' -set shada="NONE" -call setenv('TZ', 'Europe/London') - -lua << EOF -require('orgmode').setup_ts_grammar() -require('nvim-treesitter.configs').setup({}) - -require('orgmode').setup({ - org_agenda_files = { vim.fn.getcwd() .. '/tests/plenary/fixtures/*' }, - org_default_notes_file = vim.fn.getcwd() .. '/tests/plenary/fixtures/refile.org', -}) -EOF diff --git a/tests/test.lua b/tests/test.lua new file mode 100644 index 000000000..b17d65b69 --- /dev/null +++ b/tests/test.lua @@ -0,0 +1,14 @@ +require('tests.minimal_init') +---@type string +local test_file = vim.v.argv[#vim.v.argv] +if test_file == '' or not test_file:find('tests/plenary/', nil, true) then + test_file = 'tests/plenary' +else + print('Individual Test File/Directory provided: ' .. test_file) + print('Running all tests at ' .. test_file) +end + +require('plenary.test_harness').test_directory(test_file, { + minimal_init = 'tests/minimal_init.lua', + sequential = true, +})