Files
Axel Meyer e3b5f3bd11 test(command-test): cheap-fill M3 gap + Coverage Statements (Test-Cov Phase 2.6)
3 mutations tested. 2 caught, 1 uncaught (M3: cancel_all with 2+ simultaneous commands).
Cheap-fill: added 2-unit simultaneous cancel_all scenario with both-nil assertions.
2026-05-16 02:38:25 +02:00

96 lines
3.7 KiB
Lua

-- lib-core.command-test — pure-state assertions via engine.test.
-- See meta/docs/superpowers/specs/2026-05-14-p3-7-lib-command-design.md §5.
local command = require("lib-core.command")
local T = engine.test
local M = {}
function M.run_tests(ctx)
-- Mocked-Unit Helper: closure-state simulates a module's unit-state.
local function make_unit(x0, y0, speed)
local state = { x = x0, y = y0 }
local h = command.register(
function() return { x = state.x, y = state.y } end,
function(nx, ny) state.x = nx; state.y = ny end,
speed
)
return h, state
end
-- Register / Unregister (3)
local h1, s1 = make_unit(0, 0, 100)
T.assert(h1 ~= nil and h1 >= 1, "register returns positive handle")
T.equals(command.count_registered(), 1, "count_registered after register")
command.unregister(h1)
T.equals(command.count_registered(), 0, "count_registered after unregister")
-- Re-register for further tests
local h2, s2 = make_unit(0, 0, 100)
local h3, s3 = make_unit(0, 0, 200)
-- Move-Issue + State-Query (3)
command.move_to({h2}, 100, 0)
local cur = command.current(h2)
T.assert(cur ~= nil and cur.type == "move"
and cur.target_x == 100 and cur.target_y == 0,
"current returns move-command data after move_to")
T.assert(command.is_moving(h2), "is_moving true after move_to")
T.assert(not command.is_moving(h3), "is_moving false for idle unit")
-- State-Query bei idle (2)
T.assert(command.current(h3) == nil, "current returns nil for idle unit")
T.assert(not command.is_moving(99999), "is_moving false for unknown handle")
-- Update-step (2): unit moves toward target
s2.x, s2.y = 0, 0 -- reset
command.move_to({h2}, 100, 0)
command.update(0.1) -- 100 px/s * 0.1s = 10 px step
T.equals(s2.x, 10, "update moves 10px in 0.1s @ 100 px/s")
T.equals(s2.y, 0, "y unchanged for horizontal move")
-- Arrival-snap (2): step >= dist clears + snaps
s2.x, s2.y = 0, 0
command.move_to({h2}, 5, 0)
command.update(0.1) -- step = 10 >= dist = 5 → snap + clear
T.equals(s2.x, 5, "arrival snap to target.x")
T.assert(command.current(h2) == nil, "arrival clears active command")
-- Cancel + cancel_all (5)
s2.x, s2.y = 0, 0
command.move_to({h2, h3}, 1000, 0)
command.cancel(h2)
T.assert(command.current(h2) == nil, "cancel clears command on h2")
T.assert(command.current(h3) ~= nil, "cancel doesn't affect h3")
command.cancel_all()
T.assert(command.current(h3) == nil, "cancel_all clears remaining")
command.move_to({h2, h3}, 500, 0)
command.cancel_all()
T.assert(command.current(h2) == nil, "cancel_all clears h2 of 2-unit batch")
T.assert(command.current(h3) == nil, "cancel_all clears h3 of 2-unit batch")
-- Speed-Setter (2)
T.equals(command.speed(h2), 100, "speed from register")
command.set_speed(h2, 250)
T.equals(command.speed(h2), 250, "set_speed updates")
-- Arrive-Threshold + Enabled (3)
T.equals(command.arrive_threshold(), 2, "default threshold = 2")
command.set_arrive_threshold(5)
T.equals(command.arrive_threshold(), 5, "set_arrive_threshold writes")
T.assert(command.enabled(), "enabled default true")
command.set_enabled(false)
T.assert(not command.enabled(), "set_enabled(false) writes")
command.set_enabled(true)
-- Error-Handling (2)
local ok1 = pcall(function()
command.register("not a function", function() end, 100)
end)
T.assert(not ok1, "register with non-function errors")
local ok2 = pcall(function() command.move_to({99999}, 0, 0) end)
T.assert(not ok2, "move_to with unknown handle errors")
end
return M