Files
FlexLove/testing/__tests__/16_event_system_tests.lua
2025-11-09 12:00:42 -05:00

370 lines
9.8 KiB
Lua

-- Event System Tests
-- Tests for the enhanced callback system with InputEvent objects
package.path = package.path .. ";?.lua"
local lu = require("testing.luaunit")
require("testing.loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
local Gui = FlexLove.Gui
TestEventSystem = {}
function TestEventSystem:setUp()
-- Clear all keyboard modifier states at start of each test
love.keyboard.setDown("lshift", false)
love.keyboard.setDown("rshift", false)
love.keyboard.setDown("lctrl", false)
love.keyboard.setDown("rctrl", false)
love.keyboard.setDown("lalt", false)
love.keyboard.setDown("ralt", false)
love.keyboard.setDown("lgui", false)
love.keyboard.setDown("rgui", false)
Gui.init({ baseScale = { width = 1920, height = 1080 } })
love.window.setMode(1920, 1080)
Gui.resize(1920, 1080) -- Recalculate scale factors after setMode
end
function TestEventSystem:tearDown()
-- Clean up after each test
Gui.destroy()
-- Reset keyboard state
love.keyboard.setDown("lshift", false)
love.keyboard.setDown("rshift", false)
love.keyboard.setDown("lctrl", false)
love.keyboard.setDown("rctrl", false)
love.keyboard.setDown("lalt", false)
love.keyboard.setDown("ralt", false)
love.keyboard.setDown("lgui", false)
love.keyboard.setDown("rgui", false)
end
-- Test 1: Event object structure
function TestEventSystem:test_event_object_has_required_fields()
local eventReceived = nil
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
eventReceived = event
end,
})
-- Simulate mouse press and release
love.mouse.setPosition(150, 150)
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
-- Verify event object structure
lu.assertNotNil(eventReceived, "Event should be received")
lu.assertNotNil(eventReceived.type, "Event should have type field")
lu.assertNotNil(eventReceived.button, "Event should have button field")
lu.assertNotNil(eventReceived.x, "Event should have x field")
lu.assertNotNil(eventReceived.y, "Event should have y field")
lu.assertNotNil(eventReceived.modifiers, "Event should have modifiers field")
lu.assertNotNil(eventReceived.clickCount, "Event should have clickCount field")
lu.assertNotNil(eventReceived.timestamp, "Event should have timestamp field")
end
-- Test 2: Left click event
function TestEventSystem:test_left_click_generates_click_event()
local eventsReceived = {}
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
table.insert(eventsReceived, { type = event.type, button = event.button })
end,
})
-- Simulate left click
love.mouse.setPosition(150, 150)
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
-- Should receive press, click, and release events
lu.assertTrue(#eventsReceived >= 2, "Should receive at least 2 events")
-- Check for click event
local hasClickEvent = false
for _, evt in ipairs(eventsReceived) do
if evt.type == "click" and evt.button == 1 then
hasClickEvent = true
break
end
end
lu.assertTrue(hasClickEvent, "Should receive click event for left button")
end
-- Test 3: Right click event
function TestEventSystem:test_right_click_generates_rightclick_event()
local eventsReceived = {}
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
table.insert(eventsReceived, { type = event.type, button = event.button })
end,
})
-- Simulate right click
love.mouse.setPosition(150, 150)
love.mouse.setDown(2, true)
button:update(0.016)
love.mouse.setDown(2, false)
button:update(0.016)
-- Check for rightclick event
local hasRightClickEvent = false
for _, evt in ipairs(eventsReceived) do
if evt.type == "rightclick" and evt.button == 2 then
hasRightClickEvent = true
break
end
end
lu.assertTrue(hasRightClickEvent, "Should receive rightclick event for right button")
end
-- Test 4: Middle click event
function TestEventSystem:test_middle_click_generates_middleclick_event()
local eventsReceived = {}
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
table.insert(eventsReceived, { type = event.type, button = event.button })
end,
})
-- Simulate middle click
love.mouse.setPosition(150, 150)
love.mouse.setDown(3, true)
button:update(0.016)
love.mouse.setDown(3, false)
button:update(0.016)
-- Check for middleclick event
local hasMiddleClickEvent = false
for _, evt in ipairs(eventsReceived) do
if evt.type == "middleclick" and evt.button == 3 then
hasMiddleClickEvent = true
break
end
end
lu.assertTrue(hasMiddleClickEvent, "Should receive middleclick event for middle button")
end
-- Test 5: Modifier keys detection
function TestEventSystem:test_modifier_keys_are_detected()
local eventReceived = nil
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
if event.type == "click" then
eventReceived = event
end
end,
})
-- Simulate shift + click
love.keyboard.setDown("lshift", true)
love.mouse.setPosition(150, 150)
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
lu.assertNotNil(eventReceived, "Should receive click event")
lu.assertTrue(eventReceived.modifiers.shift, "Shift modifier should be detected")
end
-- Test 6: Double click detection
function TestEventSystem:test_double_click_increments_click_count()
local clickEvents = {}
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
if event.type == "click" then
table.insert(clickEvents, event.clickCount)
end
end,
})
-- Simulate first click
love.mouse.setPosition(150, 150)
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
-- Simulate second click quickly (double-click)
love.timer.setTime(love.timer.getTime() + 0.1) -- 100ms later
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
lu.assertEquals(#clickEvents, 2, "Should receive 2 click events")
lu.assertEquals(clickEvents[1], 1, "First click should have clickCount = 1")
lu.assertEquals(clickEvents[2], 2, "Second click should have clickCount = 2")
end
-- Test 7: Press and release events
function TestEventSystem:test_press_and_release_events_are_fired()
local eventsReceived = {}
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
table.insert(eventsReceived, event.type)
end,
})
-- Simulate click
love.mouse.setPosition(150, 150)
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
-- Should receive press, click, and release
lu.assertTrue(#eventsReceived >= 2, "Should receive multiple events")
local hasPress = false
local hasRelease = false
for _, eventType in ipairs(eventsReceived) do
if eventType == "press" then
hasPress = true
end
if eventType == "release" then
hasRelease = true
end
end
lu.assertTrue(hasPress, "Should receive press event")
lu.assertTrue(hasRelease, "Should receive release event")
end
-- Test 8: Mouse position in event
function TestEventSystem:test_event_contains_mouse_position()
local eventReceived = nil
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
if event.type == "click" then
eventReceived = event
end
end,
})
-- Simulate click at specific position
local mouseX, mouseY = 175, 125
love.mouse.setPosition(mouseX, mouseY)
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
lu.assertNotNil(eventReceived, "Should receive click event")
lu.assertEquals(eventReceived.x, mouseX, "Event should contain correct mouse X position")
lu.assertEquals(eventReceived.y, mouseY, "Event should contain correct mouse Y position")
end
-- Test 9: No callback when mouse outside element
function TestEventSystem:test_no_callback_when_clicking_outside_element()
local callbackCalled = false
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
callbackCalled = true
end,
})
-- Click outside element
love.mouse.setPosition(50, 50)
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
lu.assertFalse(callbackCalled, "Callback should not be called when clicking outside element")
end
-- Test 10: Multiple modifiers
function TestEventSystem:test_multiple_modifiers_detected()
local eventReceived = nil
local button = Gui.new({
x = 100,
y = 100,
width = 200,
height = 100,
callback = function(element, event)
if event.type == "click" then
eventReceived = event
end
end,
})
-- Simulate shift + ctrl + click
love.keyboard.setDown("lshift", true)
love.keyboard.setDown("lctrl", true)
love.mouse.setPosition(150, 150)
love.mouse.setDown(1, true)
button:update(0.016)
love.mouse.setDown(1, false)
button:update(0.016)
lu.assertNotNil(eventReceived, "Should receive click event")
lu.assertTrue(eventReceived.modifiers.shift, "Shift modifier should be detected")
lu.assertTrue(eventReceived.modifiers.ctrl, "Ctrl modifier should be detected")
end
print("Running Event System Tests...")
lu.LuaUnit.run()