Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Tests
on:
push:
branches: [master, dev]
pull_request:
branches: [master, dev]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
nvim-version: ['v0.10.4', 'stable', 'nightly']
steps:
- uses: actions/checkout@v4
- uses: rhysd/action-setup-vim@v1
with:
neovim: true
version: ${{ matrix.nvim-version }}
- name: Run tests
run: make test
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Claude Code Instructions

## Git Commits
- Never add `Co-Authored-By` lines to commit messages
- The commit author should always be the repository owner
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
NVIM ?= nvim

.PHONY: test test-file

test:
$(NVIM) --headless -u tests/run_tests.lua

test-file:
$(NVIM) --headless -u tests/run_tests.lua -- $(FILE)
2,489 changes: 2,489 additions & 0 deletions deps/mini_test.lua

Large diffs are not rendered by default.

101 changes: 101 additions & 0 deletions tests/helpers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
-- Shared test utilities for smart-motion.nvim integration tests

local M = {}

--- Default test config that disables timing-dependent features
M.test_config = {
keys = "fjdksleirughtynm",
flow_state_timeout_ms = 0,
native_search = false,
auto_select_target = false,
dim_background = false,
presets = {},
}

--- Setup the plugin with optional config overrides
---@param overrides? table
function M.setup_plugin(overrides)
local config = vim.tbl_deep_extend("force", vim.deepcopy(M.test_config), overrides or {})
require("smart-motion").setup(config)
end

--- Create a scratch buffer with the given lines and set it as current
---@param lines string[]
---@return integer bufnr
function M.create_buf(lines)
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_current_buf(bufnr)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
vim.bo[bufnr].filetype = "text"
return bufnr
end

--- Set cursor position (1-indexed row, 0-indexed col)
---@param row integer
---@param col integer
function M.set_cursor(row, col)
vim.api.nvim_win_set_cursor(0, { row, col })
end

--- Get cursor position (1-indexed row, 0-indexed col)
---@return integer row, integer col
function M.get_cursor()
local pos = vim.api.nvim_win_get_cursor(0)
return pos[1], pos[2]
end

--- Get the contents of a register
---@param reg string
---@return string
function M.get_register(reg)
return vim.fn.getreg(reg)
end

--- Get all lines from the current buffer
---@return string[]
function M.get_buf_lines()
return vim.api.nvim_buf_get_lines(0, 0, -1, false)
end

--- Build a minimal SmartMotionContext
---@param overrides? table
---@return SmartMotionContext
function M.build_ctx(overrides)
local bufnr = vim.api.nvim_get_current_buf()
local winid = vim.api.nvim_get_current_win()
local cursor = vim.api.nvim_win_get_cursor(winid)
local last_line = vim.api.nvim_buf_line_count(bufnr)

local ctx = {
bufnr = bufnr,
winid = winid,
cursor_line = cursor[1] - 1, -- 0-indexed
cursor_col = cursor[2],
last_line = last_line,
}

if overrides then
ctx = vim.tbl_extend("force", ctx, overrides)
end

return ctx
end

--- Clean up all scratch buffers and reset plugin state
function M.cleanup()
-- Delete all scratch buffers
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_valid(bufnr) then
pcall(vim.api.nvim_buf_delete, bufnr, { force = true })
end
end

-- Clear relevant package.loaded entries for fresh state between test files
for key, _ in pairs(package.loaded) do
if key:match("^smart%-motion") then
package.loaded[key] = nil
end
end
end

return M
53 changes: 53 additions & 0 deletions tests/run_tests.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
-- Test runner entry point
-- Usage: nvim --headless -u tests/run_tests.lua
-- Or: make test

-- Determine project root from this script's location
local this_file = debug.getinfo(1, "S").source:sub(2)
local project_root = vim.fn.fnamemodify(this_file, ":h:h")

-- Add project to runtimepath so require("smart-motion") works
vim.opt.runtimepath:prepend(project_root)

-- Add deps/ to package.path so require("mini_test") works
package.path = project_root .. "/deps/?.lua;" .. package.path

-- Disable swap files and shada for test isolation
vim.o.swapfile = false
vim.o.shadafile = "NONE"

-- Load mini.test
local MiniTest = require("mini_test")

-- Collect test files: all tests/test_*.lua files
local test_dir = project_root .. "/tests"
local test_files = {}

-- Check if a specific file was passed via command line args
local cli_file = nil
for i, arg in ipairs(vim.v.argv) do
if arg == "--" and vim.v.argv[i + 1] then
cli_file = vim.v.argv[i + 1]
break
end
end

if cli_file then
table.insert(test_files, test_dir .. "/" .. cli_file)
else
local files = vim.fn.glob(test_dir .. "/test_*.lua", false, true)
table.sort(files)
test_files = files
end

-- Run tests with stdout reporter for headless
MiniTest.setup({
collect = {
find_files = function()
return test_files
end,
},
script_path = this_file,
})

MiniTest.run()
Loading
Loading