This commit is contained in:
Michael Freno
2025-11-05 16:39:43 -05:00
parent 619e1a7393
commit c77d93fdee
6 changed files with 489 additions and 26 deletions

View File

@@ -0,0 +1,332 @@
-- ====================
-- StateManager Module Tests
-- ====================
local luaunit = require("testing.luaunit")
require("testing.loveStub") -- Required to mock LOVE functions
local StateManager = require("modules.StateManager")
TestStateManager = {}
function TestStateManager:setUp()
-- Reset StateManager before each test
StateManager.clearAllStates()
end
function TestStateManager:tearDown()
-- Clean up after each test
StateManager.clearAllStates()
end
-- ====================
-- Basic State Operations
-- ====================
function TestStateManager:test_getState_createsNewState()
local state = StateManager.getState("test-element")
luaunit.assertNotNil(state)
luaunit.assertEquals(state.hover, false)
luaunit.assertEquals(state.pressed, false)
luaunit.assertEquals(state.focused, false)
luaunit.assertEquals(state.disabled, false)
luaunit.assertEquals(state.active, false)
end
function TestStateManager:test_getState_returnsExistingState()
local state1 = StateManager.getState("test-element")
state1.hover = true
local state2 = StateManager.getState("test-element")
luaunit.assertEquals(state2.hover, true)
luaunit.assertTrue(state1 == state2) -- Same reference
end
function TestStateManager:test_updateState_modifiesState()
StateManager.updateState("test-element", {
hover = true,
pressed = false,
})
local state = StateManager.getState("test-element")
luaunit.assertEquals(state.hover, true)
luaunit.assertEquals(state.pressed, false)
end
function TestStateManager:test_updateState_mergesPartialState()
StateManager.updateState("test-element", { hover = true })
StateManager.updateState("test-element", { pressed = true })
local state = StateManager.getState("test-element")
luaunit.assertEquals(state.hover, true)
luaunit.assertEquals(state.pressed, true)
end
function TestStateManager:test_clearState_removesState()
StateManager.updateState("test-element", { hover = true })
StateManager.clearState("test-element")
local state = StateManager.getState("test-element")
luaunit.assertEquals(state.hover, false) -- New state created with defaults
end
-- ====================
-- Scrollbar State Tests
-- ====================
function TestStateManager:test_scrollbarStates_initialization()
local state = StateManager.getState("test-element")
luaunit.assertEquals(state.scrollbarHoveredVertical, false)
luaunit.assertEquals(state.scrollbarHoveredHorizontal, false)
luaunit.assertEquals(state.scrollbarDragging, false)
luaunit.assertNil(state.hoveredScrollbar)
luaunit.assertEquals(state.scrollbarDragOffset, 0)
end
function TestStateManager:test_scrollbarStates_updates()
StateManager.updateState("test-element", {
scrollbarHoveredVertical = true,
scrollbarDragging = true,
hoveredScrollbar = "vertical",
scrollbarDragOffset = 25,
})
local state = StateManager.getState("test-element")
luaunit.assertEquals(state.scrollbarHoveredVertical, true)
luaunit.assertEquals(state.scrollbarDragging, true)
luaunit.assertEquals(state.hoveredScrollbar, "vertical")
luaunit.assertEquals(state.scrollbarDragOffset, 25)
end
-- ====================
-- Frame Management Tests
-- ====================
function TestStateManager:test_frameNumber_increments()
local frame1 = StateManager.getFrameNumber()
StateManager.incrementFrame()
local frame2 = StateManager.getFrameNumber()
luaunit.assertEquals(frame2, frame1 + 1)
end
function TestStateManager:test_updateState_updatesFrameNumber()
StateManager.incrementFrame()
StateManager.incrementFrame()
local currentFrame = StateManager.getFrameNumber()
StateManager.updateState("test-element", { hover = true })
local state = StateManager.getState("test-element")
luaunit.assertEquals(state.lastUpdateFrame, currentFrame)
end
-- ====================
-- Cleanup Tests
-- ====================
function TestStateManager:test_cleanup_removesStaleStates()
-- Configure short retention
StateManager.configure({ stateRetentionFrames = 5 })
-- Create state
StateManager.updateState("test-element", { hover = true })
-- Advance frames beyond retention
for i = 1, 10 do
StateManager.incrementFrame()
end
-- Cleanup should remove the state
local cleanedCount = StateManager.cleanup()
luaunit.assertEquals(cleanedCount, 1)
-- Reset config
StateManager.configure({ stateRetentionFrames = 60 })
end
function TestStateManager:test_cleanup_keepsActiveStates()
StateManager.configure({ stateRetentionFrames = 5 })
StateManager.updateState("test-element", { hover = true })
-- Update state within retention period
for i = 1, 3 do
StateManager.incrementFrame()
StateManager.updateState("test-element", { hover = true })
end
local cleanedCount = StateManager.cleanup()
luaunit.assertEquals(cleanedCount, 0) -- Should not clean active state
StateManager.configure({ stateRetentionFrames = 60 })
end
function TestStateManager:test_forceCleanupIfNeeded_activatesWhenOverLimit()
StateManager.configure({ maxStateEntries = 5 })
-- Create more states than limit
for i = 1, 10 do
StateManager.updateState("element-" .. i, { hover = true })
end
-- Advance frames
for i = 1, 15 do
StateManager.incrementFrame()
end
local cleanedCount = StateManager.forceCleanupIfNeeded()
luaunit.assertTrue(cleanedCount > 0)
StateManager.configure({ maxStateEntries = 1000 })
end
-- ====================
-- State Count Tests
-- ====================
function TestStateManager:test_getStateCount_returnsCorrectCount()
luaunit.assertEquals(StateManager.getStateCount(), 0)
StateManager.getState("element-1")
StateManager.getState("element-2")
StateManager.getState("element-3")
luaunit.assertEquals(StateManager.getStateCount(), 3)
end
-- ====================
-- Active State Tests
-- ====================
function TestStateManager:test_getActiveState_returnsOnlyActiveProperties()
StateManager.updateState("test-element", {
hover = true,
pressed = false,
focused = true,
})
local activeState = StateManager.getActiveState("test-element")
luaunit.assertEquals(activeState.hover, true)
luaunit.assertEquals(activeState.pressed, false)
luaunit.assertEquals(activeState.focused, true)
luaunit.assertNil(activeState.lastUpdateFrame) -- Should not include frame tracking
end
-- ====================
-- Helper Function Tests
-- ====================
function TestStateManager:test_isHovered_returnsTrueWhenHovered()
StateManager.updateState("test-element", { hover = true })
luaunit.assertTrue(StateManager.isHovered("test-element"))
end
function TestStateManager:test_isHovered_returnsFalseWhenNotHovered()
StateManager.updateState("test-element", { hover = false })
luaunit.assertFalse(StateManager.isHovered("test-element"))
end
function TestStateManager:test_isPressed_returnsTrueWhenPressed()
StateManager.updateState("test-element", { pressed = true })
luaunit.assertTrue(StateManager.isPressed("test-element"))
end
function TestStateManager:test_isFocused_returnsTrueWhenFocused()
StateManager.updateState("test-element", { focused = true })
luaunit.assertTrue(StateManager.isFocused("test-element"))
end
function TestStateManager:test_isDisabled_returnsTrueWhenDisabled()
StateManager.updateState("test-element", { disabled = true })
luaunit.assertTrue(StateManager.isDisabled("test-element"))
end
function TestStateManager:test_isActive_returnsTrueWhenActive()
StateManager.updateState("test-element", { active = true })
luaunit.assertTrue(StateManager.isActive("test-element"))
end
-- ====================
-- State Change Events Tests
-- ====================
function TestStateManager:test_subscribe_receivesStateChangeEvents()
local callbackInvoked = false
local receivedId = nil
local receivedProperty = nil
local receivedOldValue = nil
local receivedNewValue = nil
local callback = function(id, property, oldValue, newValue)
callbackInvoked = true
receivedId = id
receivedProperty = property
receivedOldValue = oldValue
receivedNewValue = newValue
end
StateManager.subscribe("test-element", callback)
StateManager.updateState("test-element", { hover = true })
luaunit.assertTrue(callbackInvoked)
luaunit.assertEquals(receivedId, "test-element")
luaunit.assertEquals(receivedProperty, "hover")
luaunit.assertEquals(receivedOldValue, false)
luaunit.assertEquals(receivedNewValue, true)
end
function TestStateManager:test_subscribe_multipleListeners()
local callback1Invoked = false
local callback2Invoked = false
StateManager.subscribe("test-element", function() callback1Invoked = true end)
StateManager.subscribe("test-element", function() callback2Invoked = true end)
StateManager.updateState("test-element", { hover = true })
luaunit.assertTrue(callback1Invoked)
luaunit.assertTrue(callback2Invoked)
end
function TestStateManager:test_unsubscribe_removesListener()
local callbackInvoked = false
local callback = function() callbackInvoked = true end
StateManager.subscribe("test-element", callback)
StateManager.unsubscribe("test-element", callback)
StateManager.updateState("test-element", { hover = true })
luaunit.assertFalse(callbackInvoked)
end
-- ====================
-- Configuration Tests
-- ====================
function TestStateManager:test_configure_updatesSettings()
StateManager.configure({
stateRetentionFrames = 30,
maxStateEntries = 500,
})
-- Test that configuration was applied by creating many states
-- and checking cleanup behavior (indirect test)
for i = 1, 10 do
StateManager.updateState("element-" .. i, { hover = true })
end
luaunit.assertEquals(StateManager.getStateCount(), 10)
-- Reset to defaults
StateManager.configure({
stateRetentionFrames = 60,
maxStateEntries = 1000,
})
end
return TestStateManager

View File

@@ -35,6 +35,7 @@ local testFiles = {
"testing/__tests__/29_drag_event_tests.lua",
"testing/__tests__/30_scrollbar_features_tests.lua",
"testing/__tests__/31_immediate_mode_basic_tests.lua",
"testing/__tests__/32_state_manager_tests.lua",
}
local success = true