feat(test): test new auto-completion logic

This commit is contained in:
Barrett Ruth 2025-09-21 15:24:36 -04:00
parent 05968657f5
commit 18a747dd8a

View file

@ -380,4 +380,260 @@ describe('cp command parsing', function()
assert.is_true(error_logged)
end)
end)
describe('CP command completion', function()
local complete_fn
before_each(function()
-- Mock the command completion function
complete_fn = function(ArgLead, CmdLine, _)
local constants = require('cp.constants')
local platforms = constants.PLATFORMS
local actions = constants.ACTIONS
local args = vim.split(vim.trim(CmdLine), '%s+')
local num_args = #args
if CmdLine:sub(-1) == ' ' then
num_args = num_args + 1
end
if num_args == 2 then
local candidates = {}
local cp = require('cp')
local context = cp.get_current_context()
if context.platform and context.contest_id then
vim.list_extend(candidates, actions)
local cache = require('cp.cache')
cache.load()
local contest_data = cache.get_contest_data(context.platform, context.contest_id)
if contest_data and contest_data.problems then
for _, problem in ipairs(contest_data.problems) do
table.insert(candidates, problem.id)
end
end
else
vim.list_extend(candidates, platforms)
table.insert(candidates, 'cache')
table.insert(candidates, 'pick')
end
return vim.tbl_filter(function(cmd)
return cmd:find(ArgLead, 1, true) == 1
end, candidates)
elseif num_args == 3 then
if args[2] == 'cache' then
return vim.tbl_filter(function(cmd)
return cmd:find(ArgLead, 1, true) == 1
end, { 'clear' })
end
elseif num_args == 4 then
if args[2] == 'cache' and args[3] == 'clear' then
return vim.tbl_filter(function(cmd)
return cmd:find(ArgLead, 1, true) == 1
end, platforms)
elseif vim.tbl_contains(platforms, args[2]) then
local cache = require('cp.cache')
cache.load()
local contest_data = cache.get_contest_data(args[2], args[3])
if contest_data and contest_data.problems then
local candidates = {}
for _, problem in ipairs(contest_data.problems) do
table.insert(candidates, problem.id)
end
return vim.tbl_filter(function(cmd)
return cmd:find(ArgLead, 1, true) == 1
end, candidates)
end
end
end
return {}
end
-- Mock cp module
package.loaded['cp'] = {
get_current_context = function()
return { platform = nil, contest_id = nil }
end,
}
-- Mock cache module
package.loaded['cp.cache'] = {
load = function() end,
get_contest_data = function()
return nil
end,
}
end)
it('completes platforms and global actions when no contest context', function()
local result = complete_fn('', 'CP ', 3)
assert.is_table(result)
-- Should include platforms
local has_atcoder = false
local has_codeforces = false
local has_cses = false
-- Should include global actions
local has_cache = false
local has_pick = false
-- Should NOT include context-dependent actions
local has_run = false
local has_next = false
local has_prev = false
for _, item in ipairs(result) do
if item == 'atcoder' then
has_atcoder = true
end
if item == 'codeforces' then
has_codeforces = true
end
if item == 'cses' then
has_cses = true
end
if item == 'cache' then
has_cache = true
end
if item == 'pick' then
has_pick = true
end
if item == 'run' then
has_run = true
end
if item == 'next' then
has_next = true
end
if item == 'prev' then
has_prev = true
end
end
assert.is_true(has_atcoder)
assert.is_true(has_codeforces)
assert.is_true(has_cses)
assert.is_true(has_cache)
assert.is_true(has_pick)
assert.is_false(has_run)
assert.is_false(has_next)
assert.is_false(has_prev)
end)
it('completes all actions and problems when contest context exists', function()
-- Mock with contest context
package.loaded['cp'] = {
get_current_context = function()
return { platform = 'atcoder', contest_id = 'abc350' }
end,
}
package.loaded['cp.cache'] = {
load = function() end,
get_contest_data = function()
return {
problems = {
{ id = 'a' },
{ id = 'b' },
{ id = 'c' },
},
}
end,
}
local result = complete_fn('', 'CP ', 3)
assert.is_table(result)
local items = {}
for _, item in ipairs(result) do
items[item] = true
end
-- Should include all actions
assert.is_true(items['run'])
assert.is_true(items['next'])
assert.is_true(items['prev'])
assert.is_true(items['pick'])
assert.is_true(items['cache'])
-- Should include problems
assert.is_true(items['a'])
assert.is_true(items['b'])
assert.is_true(items['c'])
end)
it('completes cache subcommands', function()
local result = complete_fn('c', 'CP cache c', 10)
assert.is_table(result)
assert.equals(1, #result)
assert.equals('clear', result[1])
end)
it('completes cache subcommands with exact match', function()
local result = complete_fn('clear', 'CP cache clear', 14)
assert.is_table(result)
assert.equals(1, #result)
assert.equals('clear', result[1])
end)
it('completes platforms for cache clear', function()
local result = complete_fn('a', 'CP cache clear a', 16)
assert.is_table(result)
local has_atcoder = false
local has_cache = false
for _, item in ipairs(result) do
if item == 'atcoder' then
has_atcoder = true
end
if item == 'cache' then
has_cache = true
end
end
assert.is_true(has_atcoder)
assert.is_false(has_cache)
end)
it('filters completions based on current input', function()
local result = complete_fn('at', 'CP at', 5)
assert.is_table(result)
assert.equals(1, #result)
assert.equals('atcoder', result[1])
end)
it('returns empty array when no matches', function()
local result = complete_fn('xyz', 'CP xyz', 6)
assert.is_table(result)
assert.equals(0, #result)
end)
it('handles problem completion for platform contest', function()
-- Mock cache with contest problems
package.loaded['cp.cache'] = {
load = function() end,
get_contest_data = function(platform, contest)
if platform == 'atcoder' and contest == 'abc350' then
return {
problems = {
{ id = 'a' },
{ id = 'b' },
},
}
end
return nil
end,
}
local result = complete_fn('a', 'CP atcoder abc350 a', 18)
assert.is_table(result)
assert.equals(1, #result)
assert.equals('a', result[1])
end)
end)
end)