cleaned up rendering mode swapping
This commit is contained in:
400
testing/__tests__/mixed_mode_children_test.lua
Normal file
400
testing/__tests__/mixed_mode_children_test.lua
Normal file
@@ -0,0 +1,400 @@
|
||||
-- Test retained children persisting when immediate parents recreate
|
||||
package.path = package.path .. ";./?.lua;./modules/?.lua"
|
||||
|
||||
-- Load love stub before anything else
|
||||
require("testing.loveStub")
|
||||
|
||||
local luaunit = require("testing.luaunit")
|
||||
local FlexLove = require("FlexLove")
|
||||
|
||||
TestMixedModeChildren = {}
|
||||
|
||||
function TestMixedModeChildren:setUp()
|
||||
FlexLove.init({ immediateMode = true })
|
||||
FlexLove.setMode("immediate")
|
||||
end
|
||||
|
||||
function TestMixedModeChildren:tearDown()
|
||||
FlexLove._defaultDependencies.StateManager.reset()
|
||||
FlexLove.topElements = {}
|
||||
FlexLove._currentFrameElements = {}
|
||||
FlexLove._frameStarted = false
|
||||
end
|
||||
|
||||
-- Test 1: Retained child persists when immediate parent recreates
|
||||
function TestMixedModeChildren:testRetainedChildPersistsWithImmediateParent()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
-- Frame 1: Create immediate parent with retained child
|
||||
local parent1 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
local retainedChild = FlexLove.new({
|
||||
id = "retained_child",
|
||||
mode = "retained",
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
parent1:addChild(retainedChild)
|
||||
|
||||
luaunit.assertEquals(#parent1.children, 1, "Parent should have 1 child")
|
||||
luaunit.assertEquals(parent1.children[1], retainedChild, "Child should be the retained element")
|
||||
luaunit.assertEquals(retainedChild.parent, parent1, "Child's parent should be set")
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2: Recreate immediate parent, retained child should persist
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent2 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
-- The retained child should be automatically restored
|
||||
luaunit.assertEquals(#parent2.children, 1, "Parent should still have 1 child after recreation")
|
||||
luaunit.assertEquals(parent2.children[1], retainedChild, "Child should be the same retained element")
|
||||
luaunit.assertEquals(retainedChild.parent, parent2, "Child's parent reference should be updated")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test 2: Multiple retained children persist
|
||||
function TestMixedModeChildren:testMultipleRetainedChildrenPersist()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent1 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
local child1 = FlexLove.new({
|
||||
id = "child1",
|
||||
mode = "retained",
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
local child2 = FlexLove.new({
|
||||
id = "child2",
|
||||
mode = "retained",
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
local child3 = FlexLove.new({
|
||||
id = "child3",
|
||||
mode = "retained",
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
parent1:addChild(child1)
|
||||
parent1:addChild(child2)
|
||||
parent1:addChild(child3)
|
||||
|
||||
luaunit.assertEquals(#parent1.children, 3, "Parent should have 3 children")
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent2 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
luaunit.assertEquals(#parent2.children, 3, "Parent should still have 3 children")
|
||||
luaunit.assertEquals(parent2.children[1], child1, "First child should persist")
|
||||
luaunit.assertEquals(parent2.children[2], child2, "Second child should persist")
|
||||
luaunit.assertEquals(parent2.children[3], child3, "Third child should persist")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test 3: Immediate children do NOT persist (only retained children)
|
||||
function TestMixedModeChildren:testImmediateChildrenDoNotPersist()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent1 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
local immediateChild = FlexLove.new({
|
||||
id = "immediate_child",
|
||||
mode = "immediate",
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
local retainedChild = FlexLove.new({
|
||||
id = "retained_child",
|
||||
mode = "retained",
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
parent1:addChild(immediateChild)
|
||||
parent1:addChild(retainedChild)
|
||||
|
||||
luaunit.assertEquals(#parent1.children, 2, "Parent should have 2 children")
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent2 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
-- Only retained child should persist
|
||||
luaunit.assertEquals(#parent2.children, 1, "Parent should only have 1 child (retained)")
|
||||
luaunit.assertEquals(parent2.children[1], retainedChild, "Only retained child should persist")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test 4: Top-level retained element persists in immediate mode
|
||||
function TestMixedModeChildren:testTopLevelRetainedElementPersists()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local retainedElement = FlexLove.new({
|
||||
id = "top_retained",
|
||||
mode = "retained",
|
||||
width = 100,
|
||||
height = 100,
|
||||
})
|
||||
|
||||
luaunit.assertEquals(#FlexLove.topElements, 1, "Should have 1 top-level element")
|
||||
luaunit.assertEquals(FlexLove.topElements[1], retainedElement, "Top element should be retained element")
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2
|
||||
FlexLove.beginFrame()
|
||||
|
||||
-- Retained element should still be in topElements
|
||||
luaunit.assertEquals(#FlexLove.topElements, 1, "Retained element should persist in topElements")
|
||||
luaunit.assertEquals(FlexLove.topElements[1], retainedElement, "Should be same retained element")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test 5: Mixed top-level elements (immediate and retained)
|
||||
function TestMixedModeChildren:testMixedTopLevelElements()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local immediateElement1 = FlexLove.new({
|
||||
id = "immediate1",
|
||||
mode = "immediate",
|
||||
width = 100,
|
||||
height = 100,
|
||||
})
|
||||
|
||||
local retainedElement = FlexLove.new({
|
||||
id = "retained",
|
||||
mode = "retained",
|
||||
width = 100,
|
||||
height = 100,
|
||||
})
|
||||
|
||||
luaunit.assertEquals(#FlexLove.topElements, 2, "Should have 2 top-level elements")
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local immediateElement2 = FlexLove.new({
|
||||
id = "immediate2",
|
||||
mode = "immediate",
|
||||
width = 100,
|
||||
height = 100,
|
||||
})
|
||||
|
||||
-- Should have retained element + new immediate element
|
||||
luaunit.assertEquals(#FlexLove.topElements, 2, "Should have 2 top-level elements")
|
||||
|
||||
-- Find retained element in topElements
|
||||
local foundRetained = false
|
||||
for _, elem in ipairs(FlexLove.topElements) do
|
||||
if elem == retainedElement then
|
||||
foundRetained = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
luaunit.assertTrue(foundRetained, "Retained element should still be in topElements")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test 6: Retained child cleanup on parent destroy
|
||||
function TestMixedModeChildren:testRetainedChildCleanupOnDestroy()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
local retainedChild = FlexLove.new({
|
||||
id = "retained_child",
|
||||
mode = "retained",
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
parent:addChild(retainedChild)
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Destroy parent (simulating explicit cleanup)
|
||||
parent:destroy()
|
||||
|
||||
-- Frame 2: Create new parent with same ID
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent2 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
-- Since parent was destroyed, retained children should be cleared
|
||||
luaunit.assertEquals(#parent2.children, 0, "Parent should have no children after destroy")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test 7: Nested mixed-mode tree (immediate -> retained -> immediate)
|
||||
function TestMixedModeChildren:testNestedMixedModeTree()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local immediateParent = FlexLove.new({
|
||||
id = "immediate_parent",
|
||||
mode = "immediate",
|
||||
width = 300,
|
||||
height = 300,
|
||||
})
|
||||
|
||||
local retainedMiddle = FlexLove.new({
|
||||
id = "retained_middle",
|
||||
mode = "retained",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
local immediateGrandchild = FlexLove.new({
|
||||
id = "immediate_grandchild",
|
||||
mode = "immediate",
|
||||
width = 100,
|
||||
height = 100,
|
||||
})
|
||||
|
||||
immediateParent:addChild(retainedMiddle)
|
||||
retainedMiddle:addChild(immediateGrandchild)
|
||||
|
||||
luaunit.assertEquals(#immediateParent.children, 1, "Immediate parent should have 1 child")
|
||||
luaunit.assertEquals(#retainedMiddle.children, 1, "Retained middle should have 1 child")
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2: Recreate immediate parent
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local immediateParent2 = FlexLove.new({
|
||||
id = "immediate_parent",
|
||||
mode = "immediate",
|
||||
width = 300,
|
||||
height = 300,
|
||||
})
|
||||
|
||||
-- Retained middle should persist
|
||||
luaunit.assertEquals(#immediateParent2.children, 1, "Immediate parent should still have retained child")
|
||||
luaunit.assertEquals(immediateParent2.children[1], retainedMiddle, "Retained middle should persist")
|
||||
|
||||
-- Immediate grandchild should also persist (as child of retained middle)
|
||||
luaunit.assertEquals(#retainedMiddle.children, 1, "Retained middle should still have its child")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test 8: Prevent duplicate creation of retained children
|
||||
function TestMixedModeChildren:testPreventDuplicateRetainedChildren()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
-- Frame 1: Create immediate parent with retained child
|
||||
local parent1 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
local retainedChild = FlexLove.new({
|
||||
id = "unique_child",
|
||||
mode = "retained",
|
||||
parent = parent1,
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
luaunit.assertEquals(#parent1.children, 1, "Parent should have 1 child")
|
||||
local originalChild = parent1.children[1]
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2: Recreate parent and try to create child again
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent2 = FlexLove.new({
|
||||
id = "parent",
|
||||
mode = "immediate",
|
||||
width = 200,
|
||||
height = 200,
|
||||
})
|
||||
|
||||
-- Try to create the same retained child again
|
||||
local duplicateAttempt = FlexLove.new({
|
||||
id = "unique_child",
|
||||
mode = "retained",
|
||||
parent = parent2,
|
||||
width = 50,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
-- Should return the existing child, not create a new one
|
||||
luaunit.assertEquals(duplicateAttempt, originalChild, "Should return existing child instead of creating duplicate")
|
||||
luaunit.assertEquals(duplicateAttempt, retainedChild, "Should be the same retained child instance")
|
||||
luaunit.assertEquals(#parent2.children, 1, "Parent should still have only 1 child")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Run tests
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
@@ -16,7 +16,9 @@ local originalSearchers = package.searchers or package.loaders
|
||||
table.insert(originalSearchers, 2, function(modname)
|
||||
if modname:match("^FlexLove%.modules%.") then
|
||||
local moduleName = modname:gsub("^FlexLove%.modules%.", "")
|
||||
return function() return require("modules." .. moduleName) end
|
||||
return function()
|
||||
return require("modules." .. moduleName)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -41,17 +43,17 @@ end
|
||||
function TestMixedModeEvents:test_immediateChildOfRetainedParentHandlesEvents()
|
||||
local eventFired = false
|
||||
local eventType = nil
|
||||
|
||||
|
||||
-- Create retained parent
|
||||
local parent = FlexLove.new({
|
||||
mode = "retained",
|
||||
width = 800,
|
||||
height = 600,
|
||||
})
|
||||
|
||||
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
|
||||
-- Create immediate child with event handler
|
||||
local child = FlexLove.new({
|
||||
mode = "immediate",
|
||||
@@ -66,19 +68,19 @@ function TestMixedModeEvents:test_immediateChildOfRetainedParentHandlesEvents()
|
||||
eventType = event.type
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
|
||||
-- Verify child is positioned correctly
|
||||
luaunit.assertEquals(child.x, 0)
|
||||
luaunit.assertEquals(child.y, 0)
|
||||
|
||||
|
||||
-- Manually call the event handler (simulating event processing)
|
||||
-- In the real app, this would be triggered by mousepressed/released
|
||||
if child.onEvent then
|
||||
child.onEvent(child, { type = "release", x = 50, y = 25, button = 1 })
|
||||
end
|
||||
|
||||
|
||||
-- Verify event was handled
|
||||
luaunit.assertTrue(eventFired)
|
||||
luaunit.assertEquals(eventType, "release")
|
||||
@@ -87,17 +89,17 @@ end
|
||||
-- Test that hover state is tracked for immediate children
|
||||
function TestMixedModeEvents:test_immediateChildOfRetainedParentTracksHover()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
|
||||
-- Create retained parent
|
||||
local parent = FlexLove.new({
|
||||
mode = "retained",
|
||||
width = 800,
|
||||
height = 600,
|
||||
})
|
||||
|
||||
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
|
||||
-- Create immediate child
|
||||
local child = FlexLove.new({
|
||||
mode = "immediate",
|
||||
@@ -108,12 +110,12 @@ function TestMixedModeEvents:test_immediateChildOfRetainedParentTracksHover()
|
||||
width = 100,
|
||||
height = 50,
|
||||
})
|
||||
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
|
||||
-- Child should have event handler module
|
||||
luaunit.assertNotNil(child._eventHandler)
|
||||
|
||||
|
||||
-- Verify child can track hover state (stored in StateManager for immediate mode)
|
||||
-- The actual hover detection happens in Element's event processing
|
||||
luaunit.assertEquals(child._elementMode, "immediate")
|
||||
@@ -123,9 +125,9 @@ end
|
||||
function TestMixedModeEvents:test_multipleImmediateChildrenHandleEventsIndependently()
|
||||
local button1Clicked = false
|
||||
local button2Clicked = false
|
||||
|
||||
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
|
||||
-- Create retained parent
|
||||
local parent = FlexLove.new({
|
||||
mode = "retained",
|
||||
@@ -135,10 +137,10 @@ function TestMixedModeEvents:test_multipleImmediateChildrenHandleEventsIndepende
|
||||
flexDirection = "horizontal",
|
||||
gap = 10,
|
||||
})
|
||||
|
||||
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
|
||||
-- Create two immediate button children
|
||||
local button1 = FlexLove.new({
|
||||
mode = "immediate",
|
||||
@@ -152,7 +154,7 @@ function TestMixedModeEvents:test_multipleImmediateChildrenHandleEventsIndepende
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
local button2 = FlexLove.new({
|
||||
mode = "immediate",
|
||||
id = "button2",
|
||||
@@ -165,28 +167,31 @@ function TestMixedModeEvents:test_multipleImmediateChildrenHandleEventsIndepende
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
|
||||
-- Verify buttons are positioned correctly
|
||||
luaunit.assertEquals(button1.x, 0)
|
||||
luaunit.assertEquals(button2.x, 110) -- 100 + 10 gap
|
||||
|
||||
|
||||
-- Simulate clicking button1
|
||||
if button1.onEvent then
|
||||
button1.onEvent(button1, { type = "release", x = 50, y = 25, button = 1 })
|
||||
end
|
||||
|
||||
|
||||
luaunit.assertTrue(button1Clicked)
|
||||
luaunit.assertFalse(button2Clicked)
|
||||
|
||||
|
||||
-- Simulate clicking button2
|
||||
if button2.onEvent then
|
||||
button2.onEvent(button2, { type = "release", x = 150, y = 25, button = 1 })
|
||||
end
|
||||
|
||||
|
||||
luaunit.assertTrue(button1Clicked)
|
||||
luaunit.assertTrue(button2Clicked)
|
||||
end
|
||||
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
-- Run tests
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
|
||||
193
testing/__tests__/retained_in_immediate_test.lua
Normal file
193
testing/__tests__/retained_in_immediate_test.lua
Normal file
@@ -0,0 +1,193 @@
|
||||
--[[
|
||||
Test: Retained Elements in Immediate Mode (No Duplication)
|
||||
|
||||
This test verifies that retained-mode elements don't get recreated
|
||||
when the overall application is in immediate mode.
|
||||
]]
|
||||
|
||||
package.path = package.path .. ";./?.lua;./modules/?.lua"
|
||||
|
||||
require("testing.loveStub")
|
||||
|
||||
local luaunit = require("testing.luaunit")
|
||||
local FlexLove = require("FlexLove")
|
||||
local Color = require("modules.Color")
|
||||
|
||||
TestRetainedInImmediateMode = {}
|
||||
|
||||
function TestRetainedInImmediateMode:setUp()
|
||||
-- Initialize in IMMEDIATE mode
|
||||
FlexLove.init({ immediateMode = true })
|
||||
end
|
||||
|
||||
function TestRetainedInImmediateMode:tearDown()
|
||||
if FlexLove.getMode() == "immediate" then
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
FlexLove.init({ immediateMode = false })
|
||||
end
|
||||
|
||||
-- Test that top-level retained elements persist across frames
|
||||
function TestRetainedInImmediateMode:test_topLevelRetainedElementPersists()
|
||||
-- Helper function that creates elements (simulates user code called each frame)
|
||||
local function createUI()
|
||||
local backdrop = FlexLove.new({
|
||||
mode = "retained",
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
backgroundColor = Color.new(0.1, 0.2, 0.3, 0.5),
|
||||
})
|
||||
return backdrop
|
||||
end
|
||||
|
||||
FlexLove.beginFrame()
|
||||
|
||||
-- Frame 1: Create a retained element (no explicit ID)
|
||||
local backdrop = createUI()
|
||||
|
||||
local backdropId = backdrop.id
|
||||
luaunit.assertNotNil(backdropId, "Backdrop should have auto-generated ID")
|
||||
luaunit.assertEquals(backdrop._elementMode, "retained")
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2: Call createUI() again (same function, same line numbers)
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local backdrop2 = createUI()
|
||||
|
||||
-- Should return the SAME element, not create a new one
|
||||
luaunit.assertEquals(backdrop2.id, backdropId, "Should return existing element with same ID")
|
||||
luaunit.assertEquals(backdrop2, backdrop, "Should return exact same element instance")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test that retained elements with explicit IDs can be recreated
|
||||
function TestRetainedInImmediateMode:test_explicitIdAllowsNewElements()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
-- Create element with explicit ID
|
||||
local element1 = FlexLove.new({
|
||||
id = "my_custom_id",
|
||||
mode = "retained",
|
||||
width = 100,
|
||||
height = 100,
|
||||
backgroundColor = Color.new(1, 0, 0, 1),
|
||||
})
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
FlexLove.beginFrame()
|
||||
|
||||
-- Create another element with SAME explicit ID but different properties
|
||||
-- This should create a NEW element (user controls uniqueness)
|
||||
local element2 = FlexLove.new({
|
||||
id = "my_custom_id",
|
||||
mode = "retained",
|
||||
width = 200, -- Different properties
|
||||
height = 200,
|
||||
backgroundColor = Color.new(0, 1, 0, 1),
|
||||
})
|
||||
|
||||
-- With explicit IDs, we allow duplicates (user responsibility)
|
||||
luaunit.assertEquals(element2.id, "my_custom_id")
|
||||
-- Properties should match NEW element, not old
|
||||
luaunit.assertEquals(element2.width, 200)
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test that multiple retained elements persist independently
|
||||
function TestRetainedInImmediateMode:test_multipleRetainedElementsPersist()
|
||||
local function createUI()
|
||||
local backdrop = FlexLove.new({
|
||||
mode = "retained",
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
})
|
||||
|
||||
local window = FlexLove.new({
|
||||
mode = "retained",
|
||||
width = "90%",
|
||||
height = "90%",
|
||||
})
|
||||
|
||||
return backdrop, window
|
||||
end
|
||||
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local backdrop, window = createUI()
|
||||
|
||||
local backdropId = backdrop.id
|
||||
local windowId = window.id
|
||||
|
||||
luaunit.assertNotEquals(backdropId, windowId, "Different elements should have different IDs")
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local backdrop2, window2 = createUI()
|
||||
|
||||
-- Both should return existing elements
|
||||
luaunit.assertEquals(backdrop2.id, backdropId)
|
||||
luaunit.assertEquals(window2.id, windowId)
|
||||
luaunit.assertEquals(backdrop2, backdrop)
|
||||
luaunit.assertEquals(window2, window)
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test that retained children of retained parents persist
|
||||
function TestRetainedInImmediateMode:test_retainedChildOfRetainedParentPersists()
|
||||
local function createUI()
|
||||
local parent = FlexLove.new({
|
||||
mode = "retained",
|
||||
width = 400,
|
||||
height = 400,
|
||||
})
|
||||
|
||||
local child = FlexLove.new({
|
||||
mode = "retained",
|
||||
parent = parent,
|
||||
width = 100,
|
||||
height = 100,
|
||||
})
|
||||
|
||||
return parent, child
|
||||
end
|
||||
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent, child = createUI()
|
||||
|
||||
local parentId = parent.id
|
||||
local childId = child.id
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local parent2, child2 = createUI()
|
||||
|
||||
-- Parent should be the same
|
||||
luaunit.assertEquals(parent2.id, parentId)
|
||||
luaunit.assertEquals(parent2, parent)
|
||||
|
||||
-- Child should also be the same instance
|
||||
luaunit.assertEquals(child2.id, childId, "Child ID should match")
|
||||
luaunit.assertEquals(child2, child, "Child should be same instance")
|
||||
|
||||
-- Child should still exist in parent's children
|
||||
luaunit.assertEquals(#parent2.children, 1, "Parent should have exactly 1 child")
|
||||
luaunit.assertEquals(parent2.children[1].id, childId)
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Run tests
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
184
testing/__tests__/retained_prop_stability_test.lua
Normal file
184
testing/__tests__/retained_prop_stability_test.lua
Normal file
@@ -0,0 +1,184 @@
|
||||
--[[
|
||||
Test: Retained Elements with Varying Props (ID Stability)
|
||||
|
||||
This test verifies that retained-mode elements return the same instance
|
||||
across frames even when props vary slightly (e.g., different Color instances).
|
||||
]]
|
||||
|
||||
package.path = package.path .. ";./?.lua;./modules/?.lua"
|
||||
|
||||
require("testing.loveStub")
|
||||
|
||||
local luaunit = require("testing.luaunit")
|
||||
local FlexLove = require("FlexLove")
|
||||
local Color = require("modules.Color")
|
||||
|
||||
TestRetainedPropStability = {}
|
||||
|
||||
function TestRetainedPropStability:setUp()
|
||||
-- Initialize in IMMEDIATE mode
|
||||
FlexLove.init({ immediateMode = true })
|
||||
end
|
||||
|
||||
function TestRetainedPropStability:tearDown()
|
||||
if FlexLove.getMode() == "immediate" then
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
FlexLove.init({ immediateMode = false })
|
||||
end
|
||||
|
||||
-- Test that retained elements persist despite creating new Color instances
|
||||
function TestRetainedPropStability:test_retainedElementIgnoresColorInstanceChanges()
|
||||
FlexLove.beginFrame()
|
||||
|
||||
-- Frame 1: Create retained element with Color instance
|
||||
local backdrop1 = FlexLove.new({
|
||||
mode = "retained",
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
backgroundColor = Color.new(1, 1, 1, 0.1), -- NEW Color instance
|
||||
})
|
||||
|
||||
local id1 = backdrop1.id
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2: Same props but NEW Color instance (common pattern in user code)
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local backdrop2 = FlexLove.new({
|
||||
mode = "retained",
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
backgroundColor = Color.new(1, 1, 1, 0.1), -- NEW Color instance (different table)
|
||||
})
|
||||
|
||||
-- Should return SAME element despite different Color instance
|
||||
luaunit.assertEquals(backdrop2.id, id1, "ID should be stable across frames")
|
||||
luaunit.assertEquals(backdrop2, backdrop1, "Should return same element instance")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test that retained elements with complex props persist
|
||||
function TestRetainedPropStability:test_retainedElementWithComplexProps()
|
||||
local function createWindow()
|
||||
return FlexLove.new({
|
||||
mode = "retained",
|
||||
z = 100,
|
||||
x = "5%",
|
||||
y = "5%",
|
||||
width = "90%",
|
||||
height = "90%",
|
||||
themeComponent = "framev3",
|
||||
positioning = "flex",
|
||||
flexDirection = "vertical",
|
||||
justifySelf = "center",
|
||||
justifyContent = "flex-start",
|
||||
alignItems = "center",
|
||||
scaleCorners = 3,
|
||||
padding = { horizontal = "5%", vertical = "3%" },
|
||||
gap = 10,
|
||||
})
|
||||
end
|
||||
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local window1 = createWindow()
|
||||
local id1 = window1.id
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2: Same function, same props
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local window2 = createWindow()
|
||||
|
||||
-- Should return same element
|
||||
luaunit.assertEquals(window2.id, id1)
|
||||
luaunit.assertEquals(window2, window1)
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test that retained elements with backdrop blur persist
|
||||
function TestRetainedPropStability:test_retainedElementWithBackdropBlur()
|
||||
local function createBackdrop()
|
||||
return FlexLove.new({
|
||||
mode = "retained",
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
backdropBlur = { radius = 10 }, -- Table prop
|
||||
backgroundColor = Color.new(1, 1, 1, 0.1),
|
||||
})
|
||||
end
|
||||
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local backdrop1 = createBackdrop()
|
||||
local id1 = backdrop1.id
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local backdrop2 = createBackdrop()
|
||||
|
||||
-- Should return same element
|
||||
luaunit.assertEquals(backdrop2.id, id1)
|
||||
luaunit.assertEquals(backdrop2, backdrop1)
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test that multiple retained elements persist independently
|
||||
function TestRetainedPropStability:test_multipleRetainedElementsWithVaryingProps()
|
||||
local function createUI()
|
||||
local backdrop = FlexLove.new({
|
||||
mode = "retained",
|
||||
z = 50,
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
backdropBlur = { radius = 10 },
|
||||
backgroundColor = Color.new(1, 1, 1, 0.1),
|
||||
})
|
||||
|
||||
local window = FlexLove.new({
|
||||
mode = "retained",
|
||||
z = 100,
|
||||
x = "5%",
|
||||
y = "5%",
|
||||
width = "90%",
|
||||
height = "90%",
|
||||
themeComponent = "framev3",
|
||||
padding = { horizontal = "5%", vertical = "3%" },
|
||||
})
|
||||
|
||||
return backdrop, window
|
||||
end
|
||||
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local backdrop1, window1 = createUI()
|
||||
local backdropId = backdrop1.id
|
||||
local windowId = window1.id
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
-- Frame 2: New Color instances, new table instances for props
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local backdrop2, window2 = createUI()
|
||||
|
||||
-- Both should return existing elements
|
||||
luaunit.assertEquals(backdrop2.id, backdropId)
|
||||
luaunit.assertEquals(window2.id, windowId)
|
||||
luaunit.assertEquals(backdrop2, backdrop1)
|
||||
luaunit.assertEquals(window2, window1)
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Run tests
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
@@ -46,6 +46,9 @@ local testFiles = {
|
||||
"testing/__tests__/image_scaler_test.lua",
|
||||
"testing/__tests__/input_event_test.lua",
|
||||
"testing/__tests__/layout_engine_test.lua",
|
||||
"testing/__tests__/mixed_mode_events_test.lua",
|
||||
"testing/__tests__/mixed_mode_children_test.lua",
|
||||
"testing/__tests__/retained_in_immediate_test.lua",
|
||||
"testing/__tests__/module_loader_test.lua",
|
||||
"testing/__tests__/ninepatch_test.lua",
|
||||
"testing/__tests__/performance_test.lua",
|
||||
@@ -58,7 +61,7 @@ local testFiles = {
|
||||
"testing/__tests__/utils_test.lua",
|
||||
"testing/__tests__/calc_test.lua",
|
||||
-- Feature/Integration tests
|
||||
--"testing/__tests__/critical_failures_test.lua",
|
||||
"testing/__tests__/critical_failures_test.lua",
|
||||
"testing/__tests__/flexlove_test.lua",
|
||||
"testing/__tests__/touch_events_test.lua",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user