364 lines
9.9 KiB
Lua
364 lines
9.9 KiB
Lua
describe('run panel state integration', function()
|
|
local cp
|
|
local logged_messages
|
|
local mock_vim_api_calls
|
|
local mock_vim_cmd_calls
|
|
|
|
before_each(function()
|
|
logged_messages = {}
|
|
mock_vim_api_calls = {}
|
|
mock_vim_cmd_calls = {}
|
|
|
|
local mock_logger = {
|
|
log = function(msg, level)
|
|
table.insert(logged_messages, { msg = msg, level = level })
|
|
end,
|
|
set_config = function() end,
|
|
}
|
|
|
|
local mock_cache = {
|
|
load = function() end,
|
|
get_test_cases = function()
|
|
return nil
|
|
end,
|
|
set_test_cases = function() end,
|
|
get_contest_data = function(platform, contest_id)
|
|
if platform == 'atcoder' and contest_id == 'abc123' then
|
|
return {
|
|
problems = {
|
|
{ id = 'a', name = 'Problem A' },
|
|
{ id = 'b', name = 'Problem B' },
|
|
{ id = 'c', name = 'Problem C' },
|
|
},
|
|
}
|
|
end
|
|
return nil
|
|
end,
|
|
set_file_state = function() end,
|
|
get_file_state = function()
|
|
return nil
|
|
end,
|
|
}
|
|
|
|
local mock_scrape = {
|
|
scrape_contest_metadata = function()
|
|
return { success = false, error = 'mocked disabled' }
|
|
end,
|
|
scrape_problem = function()
|
|
return { success = false, error = 'mocked disabled' }
|
|
end,
|
|
}
|
|
|
|
local mock_problem = {
|
|
create_context = function(platform, contest_id, problem_id, config, language)
|
|
return {
|
|
platform = platform,
|
|
contest_id = contest_id,
|
|
problem_id = problem_id,
|
|
source_file = '/tmp/test.cpp',
|
|
problem_name = problem_id or contest_id,
|
|
}
|
|
end,
|
|
}
|
|
|
|
local mock_snippets = {
|
|
setup = function() end,
|
|
}
|
|
|
|
local mock_run = {
|
|
load_test_cases = function()
|
|
return false
|
|
end,
|
|
get_run_panel_state = function()
|
|
return { test_cases = {}, current_index = 1 }
|
|
end,
|
|
run_all_test_cases = function() end,
|
|
handle_compilation_failure = function() end,
|
|
}
|
|
|
|
local mock_execute = {
|
|
compile_problem = function()
|
|
return { success = true }
|
|
end,
|
|
}
|
|
|
|
local mock_run_render = {
|
|
setup_highlights = function() end,
|
|
render_test_list = function()
|
|
return {}, {}
|
|
end,
|
|
}
|
|
|
|
local mock_vim = {
|
|
fn = {
|
|
has = function()
|
|
return 1
|
|
end,
|
|
mkdir = function() end,
|
|
expand = function(str)
|
|
if str == '%:t:r' then
|
|
return 'test'
|
|
end
|
|
if str == '%:p' then
|
|
return '/tmp/test.cpp'
|
|
end
|
|
return str
|
|
end,
|
|
tempname = function()
|
|
return '/tmp/test_session'
|
|
end,
|
|
delete = function() end,
|
|
},
|
|
cmd = {
|
|
e = function() end,
|
|
split = function() end,
|
|
vsplit = function() end,
|
|
startinsert = function() end,
|
|
stopinsert = function() end,
|
|
diffthis = function() end,
|
|
},
|
|
api = {
|
|
nvim_get_current_buf = function()
|
|
return 1
|
|
end,
|
|
nvim_get_current_win = function()
|
|
return 1
|
|
end,
|
|
nvim_create_buf = function()
|
|
return 2
|
|
end,
|
|
nvim_set_option_value = function(opt, val, opts)
|
|
table.insert(mock_vim_api_calls, { 'set_option_value', opt, val, opts })
|
|
end,
|
|
nvim_get_option_value = function(opt, opts)
|
|
if opt == 'readonly' then
|
|
return false
|
|
end
|
|
if opt == 'filetype' then
|
|
return 'cpp'
|
|
end
|
|
return nil
|
|
end,
|
|
nvim_win_set_buf = function() end,
|
|
nvim_buf_set_lines = function() end,
|
|
nvim_buf_get_lines = function()
|
|
return { '' }
|
|
end,
|
|
nvim_win_set_cursor = function() end,
|
|
nvim_win_get_cursor = function()
|
|
return { 1, 0 }
|
|
end,
|
|
nvim_create_namespace = function()
|
|
return 1
|
|
end,
|
|
nvim_win_close = function() end,
|
|
nvim_buf_delete = function() end,
|
|
nvim_win_call = function(win, fn)
|
|
fn()
|
|
end,
|
|
},
|
|
keymap = {
|
|
set = function() end,
|
|
},
|
|
schedule = function(fn)
|
|
fn()
|
|
end,
|
|
log = {
|
|
levels = {
|
|
ERROR = 1,
|
|
WARN = 2,
|
|
INFO = 3,
|
|
},
|
|
},
|
|
tbl_contains = function(tbl, val)
|
|
for _, v in ipairs(tbl) do
|
|
if v == val then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end,
|
|
tbl_map = function(fn, tbl)
|
|
local result = {}
|
|
for i, v in ipairs(tbl) do
|
|
result[i] = fn(v)
|
|
end
|
|
return result
|
|
end,
|
|
tbl_filter = function(fn, tbl)
|
|
local result = {}
|
|
for _, v in ipairs(tbl) do
|
|
if fn(v) then
|
|
table.insert(result, v)
|
|
end
|
|
end
|
|
return result
|
|
end,
|
|
split = function(str, sep)
|
|
local result = {}
|
|
for token in string.gmatch(str, '[^' .. sep .. ']+') do
|
|
table.insert(result, token)
|
|
end
|
|
return result
|
|
end,
|
|
}
|
|
|
|
package.loaded['cp.log'] = mock_logger
|
|
package.loaded['cp.cache'] = mock_cache
|
|
package.loaded['cp.scrape'] = mock_scrape
|
|
package.loaded['cp.problem'] = mock_problem
|
|
package.loaded['cp.snippets'] = mock_snippets
|
|
package.loaded['cp.run'] = mock_run
|
|
package.loaded['cp.execute'] = mock_execute
|
|
package.loaded['cp.run_render'] = mock_run_render
|
|
|
|
_G.vim = mock_vim
|
|
|
|
mock_vim.cmd = function(cmd_str)
|
|
table.insert(mock_vim_cmd_calls, cmd_str)
|
|
if cmd_str == 'silent only' then
|
|
-- Simulate closing all windows
|
|
end
|
|
end
|
|
|
|
cp = require('cp')
|
|
cp.setup({
|
|
contests = {
|
|
atcoder = {
|
|
default_language = 'cpp',
|
|
cpp = { extension = 'cpp' },
|
|
},
|
|
},
|
|
scrapers = {}, -- Disable scrapers for testing
|
|
run_panel = {
|
|
diff_mode = 'vim',
|
|
toggle_diff_key = 'd',
|
|
next_test_key = 'j',
|
|
prev_test_key = 'k',
|
|
ansi = false,
|
|
},
|
|
})
|
|
end)
|
|
|
|
after_each(function()
|
|
package.loaded['cp.log'] = nil
|
|
package.loaded['cp.cache'] = nil
|
|
package.loaded['cp.scrape'] = nil
|
|
package.loaded['cp.problem'] = nil
|
|
package.loaded['cp.snippets'] = nil
|
|
package.loaded['cp.run'] = nil
|
|
package.loaded['cp.execute'] = nil
|
|
package.loaded['cp.run_render'] = nil
|
|
_G.vim = nil
|
|
end)
|
|
|
|
describe('run panel state bug fix', function()
|
|
it('properly resets run panel state after navigation', function()
|
|
-- Setup: configure a contest with problems
|
|
cp.handle_command({ fargs = { 'atcoder', 'abc123', 'a' } })
|
|
|
|
-- Clear previous messages
|
|
logged_messages = {}
|
|
mock_vim_cmd_calls = {}
|
|
|
|
-- Step 1: Run cp run to open the test panel
|
|
cp.handle_command({ fargs = { 'run' } })
|
|
|
|
-- Verify panel would be opened (no test cases means it logs a warning but state is set)
|
|
local panel_opened = false
|
|
for _, log in ipairs(logged_messages) do
|
|
if log.msg:match('no test cases found') then
|
|
panel_opened = true -- Panel was attempted to open
|
|
break
|
|
end
|
|
end
|
|
assert.is_true(panel_opened, 'First run command should attempt to open panel')
|
|
|
|
-- Clear messages and cmd calls for next step
|
|
logged_messages = {}
|
|
mock_vim_cmd_calls = {}
|
|
|
|
-- Step 2: Run cp next to navigate to next problem
|
|
cp.handle_command({ fargs = { 'next' } })
|
|
|
|
-- Verify that 'silent only' was called (which closes windows)
|
|
local silent_only_called = false
|
|
for _, cmd in ipairs(mock_vim_cmd_calls) do
|
|
if cmd == 'silent only' then
|
|
silent_only_called = true
|
|
break
|
|
end
|
|
end
|
|
assert.is_true(silent_only_called, 'Navigation should close all windows')
|
|
|
|
-- Clear messages for final step
|
|
logged_messages = {}
|
|
|
|
-- Step 3: Run cp run again - this should try to OPEN the panel, not close it
|
|
cp.handle_command({ fargs = { 'run' } })
|
|
|
|
-- Verify panel would be opened again (not closed)
|
|
local panel_opened_again = false
|
|
for _, log in ipairs(logged_messages) do
|
|
if log.msg:match('no test cases found') then
|
|
panel_opened_again = true -- Panel was attempted to open again
|
|
break
|
|
end
|
|
end
|
|
assert.is_true(
|
|
panel_opened_again,
|
|
'Second run command should attempt to open panel, not close it'
|
|
)
|
|
|
|
-- Verify no "test panel closed" message
|
|
local panel_closed = false
|
|
for _, log in ipairs(logged_messages) do
|
|
if log.msg:match('test panel closed') then
|
|
panel_closed = true
|
|
break
|
|
end
|
|
end
|
|
assert.is_false(panel_closed, 'Second run command should not close panel')
|
|
end)
|
|
|
|
it('handles navigation to previous problem correctly', function()
|
|
-- Setup: configure a contest starting with problem b
|
|
cp.handle_command({ fargs = { 'atcoder', 'abc123', 'b' } })
|
|
|
|
-- Clear messages
|
|
logged_messages = {}
|
|
mock_vim_cmd_calls = {}
|
|
|
|
-- Open test panel
|
|
cp.handle_command({ fargs = { 'run' } })
|
|
|
|
-- Navigate to previous problem (should go to 'a')
|
|
logged_messages = {}
|
|
mock_vim_cmd_calls = {}
|
|
cp.handle_command({ fargs = { 'prev' } })
|
|
|
|
-- Verify 'silent only' was called
|
|
local silent_only_called = false
|
|
for _, cmd in ipairs(mock_vim_cmd_calls) do
|
|
if cmd == 'silent only' then
|
|
silent_only_called = true
|
|
break
|
|
end
|
|
end
|
|
assert.is_true(silent_only_called, 'Previous navigation should also close all windows')
|
|
|
|
-- Run again - should open panel
|
|
logged_messages = {}
|
|
cp.handle_command({ fargs = { 'run' } })
|
|
|
|
local panel_opened = false
|
|
for _, log in ipairs(logged_messages) do
|
|
if log.msg:match('no test cases found') then
|
|
panel_opened = true
|
|
break
|
|
end
|
|
end
|
|
assert.is_true(panel_opened, 'After previous navigation, run should open panel')
|
|
end)
|
|
end)
|
|
end)
|