repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
neovim/tests/std/map_spec.lua
Rawlocal map = require 'std.map'
describe( 'std.map', function ()
before_each( function ()
package.loaded['std.map'] = nil
map = require 'std.map'
end )
after_each( function ()
pcall( vim.keymap.del, 'n', '<test-map-keys>' )
pcall( vim.keymap.del, 'n', '<test-map-keys-2>' )
pcall( vim.keymap.del, 'i', 'k' )
pcall( vim.keymap.del, 'n', 'gd' )
pcall( vim.keymap.del, 'x', 'gd' )
pcall( vim.keymap.del, 'n', 'gx' )
end )
local function find_keymap( mode, lhs )
local keymaps = vim.api.nvim_get_keymap( mode )
for _, km in ipairs( keymaps ) do
if km.lhsraw == lhs then
return km
end
end
return nil
end
local function get_keymap( mode, lhs )
return assert( find_keymap( mode, lhs ) )
end
describe( 'mode aliases', function ()
it( 'should support "n" as alias for normal mode', function ()
local deleter = map.n { keys = '<test-map-keys>', command = 'echo "test"' }
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should support "normal" as explicit normal mode', function ()
local deleter = map.normal { keys = '<test-map-keys>', command = 'echo "test"' }
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should support "i" as alias for insert mode', function ()
local deleter = map.i { keys = 'k', command = 'echo "insert"' }
assert.is_function( deleter )
local mapping = get_keymap( 'i', 'k' )
assert.is_not_nil( mapping )
assert.equal( 'k', mapping.lhsraw )
end )
it( 'should support "insert" as explicit insert mode', function ()
local deleter = map.insert { keys = 'k', command = 'echo "insert"' }
assert.is_function( deleter )
local mapping = get_keymap( 'i', 'k' )
assert.is_not_nil( mapping )
assert.equal( 'k', mapping.lhsraw )
end )
it( 'should support "x" as alias for visual mode', function ()
local deleter = map.x { keys = '<test-map-keys>', command = 'echo "visual"' }
assert.is_function( deleter )
local mapping = get_keymap( 'x', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should support "visual" as explicit visual mode', function ()
local deleter = map.visual { keys = '<test-map-keys>', command = 'echo "visual"' }
assert.is_function( deleter )
local mapping = get_keymap( 'x', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should support "v" as alias for visual_select mode', function ()
local deleter = map.v { keys = '<test-map-keys>', command = 'echo "v"' }
assert.is_function( deleter )
local mapping = get_keymap( 'v', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should support "s" as alias for select mode', function ()
local deleter = map.s { keys = '<test-map-keys>', command = 'echo "s"' }
assert.is_function( deleter )
local mapping = get_keymap( 's', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should support "o" as alias for operator_pending mode', function ()
local deleter = map.o { keys = '<test-map-keys>', command = 'echo "o"' }
assert.is_function( deleter )
local mapping = get_keymap( 'o', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should support "c" as alias for command_line mode', function ()
local deleter = map.c { keys = '<test-map-keys>', command = 'echo "c"' }
assert.is_function( deleter )
local mapping = get_keymap( 'c', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should support "t" as alias for terminal mode', function ()
local deleter = map.t { keys = '<test-map-keys>', command = 'echo "t"' }
assert.is_function( deleter )
local mapping = get_keymap( 't', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
end )
describe( 'mode chaining', function ()
it( 'should chain normal and visual modes', function ()
local deleter = map.normal.visual { keys = 'gd', command = 'echo "chained"' }
assert.is_function( deleter )
local normal_mapping = get_keymap( 'n', 'gd' )
local visual_mapping = get_keymap( 'x', 'gd' )
assert.is_not_nil( normal_mapping )
assert.is_not_nil( visual_mapping )
end )
it( 'should chain multiple modes', function ()
local deleter = map.n.x.v { keys = 'gx', command = 'echo "multi"' }
assert.is_function( deleter )
local n_mapping = get_keymap( 'n', 'gx' )
local x_mapping = get_keymap( 'x', 'gx' )
local v_mapping = get_keymap( 'v', 'gx' )
assert.is_not_nil( n_mapping )
assert.is_not_nil( x_mapping )
assert.is_not_nil( v_mapping )
end )
it( 'should return self after adding mode for further chaining', function ()
local result = map.normal
assert.equal( map, result )
result = map.normal.visual
assert.equal( map, result )
end )
it( 'should not duplicate mode when same mode is chained multiple times', function ()
local m = map.normal.normal.normal
local modes = m.modes
local n_count = 0
for _, mode in ipairs( modes ) do
if mode == 'n' then n_count = n_count + 1 end
end
assert.equal( 1, n_count, 'mode "n" should appear exactly once in modes array before bind' )
end )
end )
describe( 'keys handling', function ()
it( 'should accept keys as string', function ()
local deleter = map.normal { keys = '<test-map-keys>', command = 'echo "string keys"' }
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( '<test-map-keys>', mapping.lhsraw )
end )
it( 'should accept keys as table (array of keys)', function ()
local deleter = map.normal { keys = { '<test-map-keys>', '<test-map-keys-2>' }, command = 'echo "table keys"' }
assert.is_function( deleter )
local mapping1 = get_keymap( 'n', '<test-map-keys>' )
local mapping2 = get_keymap( 'n', '<test-map-keys-2>' )
assert.is_not_nil( mapping1 )
assert.is_not_nil( mapping2 )
assert.equal( '<test-map-keys>', mapping1.lhsraw )
assert.equal( '<test-map-keys-2>', mapping2.lhsraw )
end )
end )
describe( 'command handling', function ()
it( 'should accept command as string', function ()
local deleter = map.normal { keys = '<test-map-keys>', command = 'echo "string command"' }
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( 'echo "string command"', mapping.rhs )
end )
it( 'should accept command as function', function ()
local called = false
local function test_func()
called = true
end
local deleter = map.normal { keys = '<test-map-keys>', command = test_func }
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.is_function( mapping.callback )
mapping.callback()
assert.is_true( called )
end )
end )
describe( 'options handling', function ()
it( 'should set silent=true by default', function ()
local deleter = map.normal { keys = '<test-map-keys>', command = 'echo "silent"' }
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.is_true( mapping.silent == 1 or mapping.silent == true )
end )
it( 'should concatenate category and description into desc', function ()
local deleter = map.normal {
keys = '<test-map-keys>',
command = 'echo "desc"',
category = 'TestCategory',
description = 'TestDescription',
}
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( 'TestCategory: TestDescription', mapping.desc )
end )
it( 'should use description alone when category is not present', function ()
local deleter = map.normal {
keys = '<test-map-keys>',
command = 'echo "desc"',
description = 'JustDescription',
}
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.equal( 'JustDescription', mapping.desc )
end )
it( 'should support buffer option for buffer-local keymap', function ()
vim.api.nvim_buf_set_lines( 0, 0, -1, true, { 'buffer test content' } )
local deleter = map.normal {
keys = '<test-map-keys>',
command = 'echo "buffer"',
buffer = 0,
}
assert.is_function( deleter )
local keymaps = vim.api.nvim_buf_get_keymap( 0, 'n' )
local found = false
for _, km in ipairs( keymaps ) do
if km.lhsraw == '<test-map-keys>' then
found = true
break
end
end
assert.is_true( found )
end )
it( 'should merge options field with defaults', function ()
local deleter = map.normal {
keys = '<test-map-keys>',
command = 'echo "merged"',
options = {
noremap = true,
},
}
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
assert.is_true( mapping.noremap == 1 or mapping.noremap == true )
end )
it( 'should support remap option', function ()
local deleter = map.normal {
keys = '<test-map-keys>',
command = 'echo "remap"',
remap = true,
}
assert.is_function( deleter )
local mapping = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping )
end )
end )
describe( 'cleanup function', function ()
it( 'should return a cleanup function (deleter)', function ()
local deleter = map.normal { keys = '<test-map-keys>', command = 'echo "delete"' }
assert.is_function( deleter )
local mapping_before = get_keymap( 'n', '<test-map-keys>' )
assert.is_not_nil( mapping_before )
deleter()
local mapping_after = find_keymap( 'n', '<test-map-keys>' )
assert.is_nil( mapping_after )
end )
it( 'should delete multiple keys when keys is a table', function ()
local deleter = map.normal {
keys = { '<test-map-keys>', '<test-map-keys-2>' },
command = 'echo "delete multiple"',
}
local mapping1_before = get_keymap( 'n', '<test-map-keys>' )
local mapping2_before = get_keymap( 'n', '<test-map-keys-2>' )
assert.is_not_nil( mapping1_before )
assert.is_not_nil( mapping2_before )
deleter()
local mapping1_after = find_keymap( 'n', '<test-map-keys>' )
local mapping2_after = find_keymap( 'n', '<test-map-keys-2>' )
assert.is_nil( mapping1_after )
assert.is_nil( mapping2_after )
end )
it( 'should delete buffer-local keymaps correctly', function ()
vim.api.nvim_buf_set_lines( 0, 0, -1, true, { 'buffer test content' } )
local deleter = map.normal {
keys = '<test-map-keys>',
command = 'echo "buffer delete"',
buffer = 0,
}
local keymaps_before = vim.api.nvim_buf_get_keymap( 0, 'n' )
local found_before = false
for _, km in ipairs( keymaps_before ) do
if km.lhsraw == '<test-map-keys>' then
found_before = true
break
end
end
assert(found_before, 'keymap should exist before deletion')
deleter()
local keymaps_after = vim.api.nvim_buf_get_keymap( 0, 'n' )
local found_after = false
for _, km in ipairs( keymaps_after ) do
if km.lhsraw == '<test-map-keys>' then
found_after = true
break
end
end
assert(not found_after, 'keymap should be deleted after calling deleter')
end )
end )
describe( 'default modes', function ()
it( 'should use normal_visual_select_operator_pending when no modes specified', function ()
local deleter = map { keys = '<test-map-keys>', command = 'echo "default modes"' }
assert.is_function( deleter )
local n_mapping = get_keymap( 'n', '<test-map-keys>' )
local x_mapping = get_keymap( 'x', '<test-map-keys>' )
local v_mapping = get_keymap( 'v', '<test-map-keys>' )
local o_mapping = get_keymap( 'o', '<test-map-keys>' )
assert.is_not_nil( n_mapping )
assert.is_not_nil( x_mapping )
assert.is_not_nil( v_mapping )
assert.is_not_nil( o_mapping )
end )
end )
describe( 'error handling', function ()
it( 'should error on unknown mode', function ()
assert.has_error( function ()
map.unknown_mode { keys = '<test-map-keys>', command = 'echo "error"' }
end, 'unknown keymap mode requested: unknown_mode' )
end )
it( 'should error when map.keys is not string or table', function ()
local invalid = 123
---@cast invalid any
local ok, err = pcall( function () map.normal { keys = invalid, command = 'echo "error"' } end )
assert.is_false( ok )
assert.is_not_nil( vim.split( tostring( err ), '\n' )[1]:match 'map.keys: expected' )
end )
it( 'should error when map.command is not function or string', function ()
local ok, err = pcall( function () map.normal { keys = '<test-map-keys>', command = nil } end )
assert.is_false( ok )
assert.is_not_nil( vim.split( tostring( err ), '\n' )[1]:match 'map.command: expected' )
end )
it( 'should error when map is not a table', function ()
local invalid = 123
---@cast invalid any
local ok, err = pcall( function () map( invalid ) end )
assert.is_false( ok )
assert.is_not_nil( vim.split( tostring( err ), '\n' )[1]:match 'map: expected' )
end )
it( 'should error on assignment to map', function ()
local ok, err = pcall( function () map.foo = 'bar' end )
assert.is_false( ok )
assert.is_not_nil( tostring( err ):match 'Assignments are not supported for std.map' )
end )
end )
end )