more test complexity
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1665,10 +1665,4 @@ function TestJustifyContent:testMultiLevelNestedModalJustifyContent()
|
||||
luaunit.assertEquals(footerRightFirstButton.x, expectedFooterRightStartX)
|
||||
end
|
||||
|
||||
-- Run the tests
|
||||
if arg and arg[0]:match("05_justify_content_tests%.lua$") then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
|
||||
return TestJustifyContent
|
||||
|
||||
luaunit.LuaUnit.run()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -131,7 +131,7 @@ function TestLayoutValidation:testMissingRequiredPropertiesDefaults()
|
||||
-- Test flex container with minimal properties
|
||||
local success2, flex_element = captureError(function()
|
||||
return Gui.new({
|
||||
positioning = Positioning.FLEX -- Only positioning specified
|
||||
positioning = Positioning.FLEX, -- Only positioning specified
|
||||
})
|
||||
end)
|
||||
luaunit.assertTrue(success2) -- Should not crash
|
||||
@@ -338,8 +338,909 @@ function TestLayoutValidation:testComplexNestedValidation()
|
||||
-- flex_grandchild positioning depends on FlexLove's behavior
|
||||
end
|
||||
|
||||
-- Run the tests
|
||||
print("=== Running Layout Validation Tests ===")
|
||||
luaunit.LuaUnit.run()
|
||||
-- ===================================
|
||||
-- COMPLEX VALIDATION STRUCTURE TESTS
|
||||
-- ===================================
|
||||
|
||||
return TestLayoutValidation
|
||||
-- Test 11: Complex Multi-Level Layout Validation
|
||||
function TestLayoutValidation:testComplexMultiLevelLayoutValidation()
|
||||
-- Test complex application-like structure with validation at every level
|
||||
local success, app = captureError(function()
|
||||
-- Main app container
|
||||
local app = Gui.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = 1200,
|
||||
h = 800,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 0,
|
||||
})
|
||||
|
||||
-- Header with complex validation scenarios
|
||||
local header = Gui.new({
|
||||
h = 60,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.SPACE_BETWEEN,
|
||||
alignItems = AlignItems.CENTER,
|
||||
gap = 20,
|
||||
padding = { top = 10, right = 20, bottom = 10, left = 20 },
|
||||
})
|
||||
header.parent = app
|
||||
table.insert(app.children, header)
|
||||
|
||||
-- Header navigation with potential edge cases
|
||||
local nav = Gui.new({
|
||||
w = 400,
|
||||
h = 40,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.CENTER,
|
||||
gap = 16,
|
||||
})
|
||||
nav.parent = header
|
||||
table.insert(header.children, nav)
|
||||
|
||||
-- Create nav items with extreme values
|
||||
for i = 1, 5 do
|
||||
local navItem = Gui.new({
|
||||
w = i == 3 and 0 or 80, -- One item with zero width
|
||||
h = i == 4 and -10 or 24, -- One item with negative height
|
||||
positioning = i == 5 and Positioning.ABSOLUTE or nil, -- Mixed positioning
|
||||
})
|
||||
navItem.parent = nav
|
||||
table.insert(nav.children, navItem)
|
||||
end
|
||||
|
||||
-- Header actions with validation edge cases
|
||||
local actions = Gui.new({
|
||||
w = 200,
|
||||
h = 40,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.FLEX_END,
|
||||
alignItems = AlignItems.CENTER,
|
||||
gap = 12,
|
||||
})
|
||||
actions.parent = header
|
||||
table.insert(header.children, actions)
|
||||
|
||||
-- Actions with extreme dimensions
|
||||
for i = 1, 3 do
|
||||
local action = Gui.new({
|
||||
w = i == 1 and 999999 or 32, -- Extremely large width
|
||||
h = i == 2 and 0.1 or 32, -- Fractional height
|
||||
x = i == 3 and -1000 or nil, -- Extreme negative position
|
||||
y = i == 3 and -1000 or nil,
|
||||
})
|
||||
action.parent = actions
|
||||
table.insert(actions.children, action)
|
||||
end
|
||||
|
||||
-- Main content with nested validation challenges
|
||||
local main = Gui.new({
|
||||
h = 740,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 0,
|
||||
})
|
||||
main.parent = app
|
||||
table.insert(app.children, main)
|
||||
|
||||
-- Sidebar with deep nesting and edge cases
|
||||
local sidebar = Gui.new({
|
||||
w = 250,
|
||||
h = 740,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 20,
|
||||
padding = { top = 20, right = 0, bottom = 20, left = 20 },
|
||||
})
|
||||
sidebar.parent = main
|
||||
table.insert(main.children, sidebar)
|
||||
|
||||
-- Sidebar sections with validation challenges
|
||||
for section = 1, 3 do
|
||||
local sideSection = Gui.new({
|
||||
h = section == 2 and -100 or 200, -- Negative height test
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 8,
|
||||
})
|
||||
sideSection.parent = sidebar
|
||||
table.insert(sidebar.children, sideSection)
|
||||
|
||||
-- Section items with extreme properties
|
||||
for item = 1, 4 do
|
||||
local sectionItem = Gui.new({
|
||||
h = 24,
|
||||
w = item == 2 and 0 or nil, -- Zero width test
|
||||
positioning = item == 4 and Positioning.ABSOLUTE or nil,
|
||||
x = item == 4 and 50 or nil,
|
||||
y = item == 4 and 50 or nil,
|
||||
gap = item == 3 and -5 or 0, -- Negative gap test
|
||||
})
|
||||
sectionItem.parent = sideSection
|
||||
table.insert(sideSection.children, sectionItem)
|
||||
|
||||
-- Nested items for deep validation
|
||||
if item <= 2 then
|
||||
for nested = 1, 2 do
|
||||
local nestedItem = Gui.new({
|
||||
w = nested == 1 and 999999 or 20, -- Extreme width
|
||||
h = 12,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.CENTER,
|
||||
alignItems = AlignItems.CENTER,
|
||||
})
|
||||
nestedItem.parent = sectionItem
|
||||
table.insert(sectionItem.children, nestedItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Content area with complex validation scenarios
|
||||
local content = Gui.new({
|
||||
w = 950,
|
||||
h = 740,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 0,
|
||||
})
|
||||
content.parent = main
|
||||
table.insert(main.children, content)
|
||||
|
||||
-- Content grid with wrapping and validation challenges
|
||||
local contentGrid = Gui.new({
|
||||
h = 600,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
flexWrap = FlexWrap.WRAP,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.FLEX_START,
|
||||
gap = 20,
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
})
|
||||
contentGrid.parent = content
|
||||
table.insert(content.children, contentGrid)
|
||||
|
||||
-- Grid items with validation edge cases
|
||||
for i = 1, 12 do
|
||||
local gridItem = Gui.new({
|
||||
w = i % 4 == 0 and 0 or 200, -- Some zero width items
|
||||
h = i % 3 == 0 and -50 or 150, -- Some negative height items
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.SPACE_BETWEEN,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = i % 5 == 0 and -10 or 12, -- Some negative gaps
|
||||
})
|
||||
gridItem.parent = contentGrid
|
||||
table.insert(contentGrid.children, gridItem)
|
||||
|
||||
-- Grid item content with extreme values
|
||||
for j = 1, 3 do
|
||||
local itemContent = Gui.new({
|
||||
h = j == 1 and 999999 or 40, -- Extreme height
|
||||
w = j == 2 and -100 or nil, -- Negative width
|
||||
positioning = j == 3 and Positioning.ABSOLUTE or nil,
|
||||
x = j == 3 and -500 or nil, -- Extreme negative position
|
||||
y = j == 3 and 1000000 or nil, -- Extreme positive position
|
||||
})
|
||||
itemContent.parent = gridItem
|
||||
table.insert(gridItem.children, itemContent)
|
||||
end
|
||||
end
|
||||
|
||||
-- Footer with final validation tests
|
||||
local footer = Gui.new({
|
||||
h = 140,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.SPACE_AROUND,
|
||||
alignItems = AlignItems.CENTER,
|
||||
gap = 0,
|
||||
padding = { top = 999999, right = -100, bottom = 0, left = 50 }, -- Extreme padding
|
||||
})
|
||||
footer.parent = content
|
||||
table.insert(content.children, footer)
|
||||
|
||||
-- Footer sections with final edge cases
|
||||
for i = 1, 4 do
|
||||
local footerSection = Gui.new({
|
||||
w = i == 1 and 0 or 200,
|
||||
h = i == 2 and -1000 or 100,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.CENTER,
|
||||
alignItems = AlignItems.CENTER,
|
||||
gap = i == 4 and 999999 or 8,
|
||||
})
|
||||
footerSection.parent = footer
|
||||
table.insert(footer.children, footerSection)
|
||||
end
|
||||
|
||||
return app
|
||||
end)
|
||||
|
||||
-- Should not crash despite extreme values
|
||||
luaunit.assertTrue(success)
|
||||
luaunit.assertIsTable(app)
|
||||
luaunit.assertEquals(#app.children, 2) -- header and main
|
||||
|
||||
-- Test layout calculation with extreme values
|
||||
local layoutSuccess = captureError(function()
|
||||
app:layoutChildren()
|
||||
end)
|
||||
luaunit.assertTrue(layoutSuccess) -- Layout should not crash
|
||||
|
||||
-- Verify structure integrity after layout
|
||||
luaunit.assertEquals(app.positioning, Positioning.FLEX)
|
||||
luaunit.assertEquals(#app.children, 2)
|
||||
luaunit.assertEquals(#app.children[1].children, 2) -- header nav and actions
|
||||
luaunit.assertEquals(#app.children[2].children, 2) -- sidebar and content
|
||||
|
||||
-- Test that extreme values are preserved but handled gracefully
|
||||
local nav = app.children[1].children[1]
|
||||
luaunit.assertEquals(#nav.children, 5) -- All nav items created
|
||||
|
||||
local actions = app.children[1].children[2]
|
||||
luaunit.assertEquals(actions.children[1].width, 999999) -- Extreme width preserved
|
||||
|
||||
local sidebar = app.children[2].children[1]
|
||||
luaunit.assertEquals(#sidebar.children, 3) -- All sidebar sections created
|
||||
|
||||
local content = app.children[2].children[2]
|
||||
luaunit.assertEquals(#content.children, 2) -- contentGrid and footer
|
||||
|
||||
local contentGrid = content.children[1]
|
||||
luaunit.assertEquals(#contentGrid.children, 12) -- All grid items created
|
||||
end
|
||||
|
||||
-- Test 12: Validation of Dynamic Property Changes in Complex Layouts
|
||||
function TestLayoutValidation:testComplexDynamicPropertyValidation()
|
||||
local success, result = captureError(function()
|
||||
-- Create complex dashboard layout
|
||||
local dashboard = Gui.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = 1000,
|
||||
h = 600,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 0,
|
||||
})
|
||||
|
||||
-- Metrics row that will be modified
|
||||
local metricsRow = Gui.new({
|
||||
h = 120,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
flexWrap = FlexWrap.WRAP,
|
||||
justifyContent = JustifyContent.SPACE_BETWEEN,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 20,
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
})
|
||||
metricsRow.parent = dashboard
|
||||
table.insert(dashboard.children, metricsRow)
|
||||
|
||||
-- Create initial metrics
|
||||
local metrics = {}
|
||||
for i = 1, 6 do
|
||||
local metric = Gui.new({
|
||||
w = 150,
|
||||
h = 80,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.SPACE_BETWEEN,
|
||||
alignItems = AlignItems.CENTER,
|
||||
gap = 8,
|
||||
})
|
||||
metric.parent = metricsRow
|
||||
table.insert(metricsRow.children, metric)
|
||||
metrics[i] = metric
|
||||
|
||||
-- Metric content
|
||||
for j = 1, 3 do
|
||||
local content = Gui.new({
|
||||
w = 100,
|
||||
h = 20,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.CENTER,
|
||||
alignItems = AlignItems.CENTER,
|
||||
})
|
||||
content.parent = metric
|
||||
table.insert(metric.children, content)
|
||||
end
|
||||
end
|
||||
|
||||
-- Content area that will receive dynamic changes
|
||||
local contentArea = Gui.new({
|
||||
h = 480,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 20,
|
||||
padding = { top = 0, right = 20, bottom = 20, left = 20 },
|
||||
})
|
||||
contentArea.parent = dashboard
|
||||
table.insert(dashboard.children, contentArea)
|
||||
|
||||
-- Left panel for modifications
|
||||
local leftPanel = Gui.new({
|
||||
w = 300,
|
||||
h = 460,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 16,
|
||||
})
|
||||
leftPanel.parent = contentArea
|
||||
table.insert(contentArea.children, leftPanel)
|
||||
|
||||
-- Right panel with nested complexity
|
||||
local rightPanel = Gui.new({
|
||||
w = 640,
|
||||
h = 460,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 12,
|
||||
})
|
||||
rightPanel.parent = contentArea
|
||||
table.insert(contentArea.children, rightPanel)
|
||||
|
||||
-- Create nested content for validation testing
|
||||
for i = 1, 3 do
|
||||
local section = Gui.new({
|
||||
h = 140,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
flexWrap = FlexWrap.WRAP,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.FLEX_START,
|
||||
gap = 12,
|
||||
padding = { top = 12, right = 12, bottom = 12, left = 12 },
|
||||
})
|
||||
section.parent = rightPanel
|
||||
table.insert(rightPanel.children, section)
|
||||
|
||||
-- Section items for modification testing
|
||||
for j = 1, 8 do
|
||||
local item = Gui.new({
|
||||
w = 80,
|
||||
h = 60,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.CENTER,
|
||||
alignItems = AlignItems.CENTER,
|
||||
gap = 4,
|
||||
})
|
||||
item.parent = section
|
||||
table.insert(section.children, item)
|
||||
end
|
||||
end
|
||||
|
||||
-- Initial layout
|
||||
dashboard:layoutChildren()
|
||||
|
||||
-- Test 1: Change flexDirection on main container
|
||||
dashboard.flexDirection = FlexDirection.HORIZONTAL
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 2: Modify metrics with extreme values
|
||||
metrics[1].width = 0
|
||||
metrics[2].width = -100
|
||||
metrics[3].width = 999999
|
||||
metrics[4].height = 0
|
||||
metrics[5].height = -200
|
||||
metrics[6].height = 1000000
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 3: Change flex wrap and justify properties
|
||||
metricsRow.flexWrap = FlexWrap.WRAP_REVERSE
|
||||
metricsRow.justifyContent = JustifyContent.CENTER
|
||||
metricsRow.alignItems = AlignItems.FLEX_END
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 4: Modify gap values with extremes
|
||||
metricsRow.gap = -50
|
||||
contentArea.gap = 999999
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 5: Change positioning types dynamically
|
||||
leftPanel.positioning = Positioning.ABSOLUTE
|
||||
leftPanel.x = -500
|
||||
leftPanel.y = 1000
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 6: Modify padding with extreme values
|
||||
rightPanel.padding = { top = -100, right = 999999, bottom = 0, left = -50 }
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 7: Change nested item properties
|
||||
local firstSection = rightPanel.children[1]
|
||||
firstSection.flexDirection = FlexDirection.VERTICAL
|
||||
firstSection.flexWrap = FlexWrap.WRAP_REVERSE
|
||||
firstSection.justifyContent = JustifyContent.SPACE_EVENLY
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 8: Modify individual items with extreme values
|
||||
local items = firstSection.children
|
||||
for i = 1, #items do
|
||||
items[i].width = i % 2 == 0 and 0 or 999999
|
||||
items[i].height = i % 3 == 0 and -100 or 200
|
||||
end
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 9: Add/remove children dynamically
|
||||
local newMetric = Gui.new({
|
||||
w = 0,
|
||||
h = -50,
|
||||
positioning = Positioning.ABSOLUTE,
|
||||
x = -1000,
|
||||
y = -1000,
|
||||
})
|
||||
newMetric.parent = metricsRow
|
||||
table.insert(metricsRow.children, newMetric)
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
-- Test 10: Remove children
|
||||
table.remove(metricsRow.children, 1)
|
||||
if metricsRow.children[1] then
|
||||
metricsRow.children[1].parent = nil
|
||||
end
|
||||
dashboard:layoutChildren() -- Should not crash
|
||||
|
||||
return {
|
||||
dashboard = dashboard,
|
||||
metricsRow = metricsRow,
|
||||
contentArea = contentArea,
|
||||
leftPanel = leftPanel,
|
||||
rightPanel = rightPanel,
|
||||
finalChildCount = #metricsRow.children,
|
||||
}
|
||||
end)
|
||||
|
||||
luaunit.assertTrue(success) -- Should not crash during any modifications
|
||||
luaunit.assertIsTable(result)
|
||||
luaunit.assertIsTable(result.dashboard)
|
||||
|
||||
-- Verify structure integrity after all modifications
|
||||
luaunit.assertEquals(result.dashboard.flexDirection, FlexDirection.HORIZONTAL)
|
||||
luaunit.assertEquals(result.metricsRow.flexWrap, FlexWrap.WRAP_REVERSE)
|
||||
luaunit.assertEquals(result.leftPanel.positioning, Positioning.ABSOLUTE)
|
||||
luaunit.assertEquals(result.finalChildCount, 6) -- 7 added - 1 removed = 6 remaining
|
||||
|
||||
-- Test final layout one more time
|
||||
local finalLayoutSuccess = captureError(function()
|
||||
result.dashboard:layoutChildren()
|
||||
end)
|
||||
luaunit.assertTrue(finalLayoutSuccess)
|
||||
end
|
||||
|
||||
-- Test 13: Validation of Circular Reference Prevention
|
||||
function TestLayoutValidation:testCircularReferenceValidation()
|
||||
local success, result = captureError(function()
|
||||
-- Create containers that could form circular references
|
||||
local container1 = Gui.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = 200,
|
||||
h = 200,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
})
|
||||
|
||||
local container2 = Gui.new({
|
||||
w = 180,
|
||||
h = 180,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
})
|
||||
|
||||
local container3 = Gui.new({
|
||||
w = 160,
|
||||
h = 160,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
})
|
||||
|
||||
-- Establish normal parent-child relationship
|
||||
container2.parent = container1
|
||||
table.insert(container1.children, container2)
|
||||
|
||||
container3.parent = container2
|
||||
table.insert(container2.children, container3)
|
||||
|
||||
-- Test layout works normally
|
||||
container1:layoutChildren()
|
||||
|
||||
-- Attempt to create circular reference (should be prevented or handled)
|
||||
-- Note: FlexLove should handle this gracefully or the test framework should catch it
|
||||
|
||||
-- Test case 1: Try to make parent a child of its own child
|
||||
local attemptSuccess1 = captureError(function()
|
||||
container1.parent = container3
|
||||
table.insert(container3.children, container1)
|
||||
container1:layoutChildren() -- This should either work or fail gracefully
|
||||
end)
|
||||
|
||||
-- Clean up potential circular reference
|
||||
container1.parent = nil
|
||||
if container3.children and #container3.children > 0 then
|
||||
for i = #container3.children, 1, -1 do
|
||||
if container3.children[i] == container1 then
|
||||
table.remove(container3.children, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Test case 2: Complex nested structure with potential circular refs
|
||||
local container4 = Gui.new({
|
||||
w = 140,
|
||||
h = 140,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
})
|
||||
|
||||
local container5 = Gui.new({
|
||||
w = 120,
|
||||
h = 120,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
})
|
||||
|
||||
-- Normal nesting first
|
||||
container4.parent = container3
|
||||
table.insert(container3.children, container4)
|
||||
|
||||
container5.parent = container4
|
||||
table.insert(container4.children, container5)
|
||||
|
||||
-- Test normal layout
|
||||
container1:layoutChildren()
|
||||
|
||||
-- Try to create deeper circular reference
|
||||
local attemptSuccess2 = captureError(function()
|
||||
container2.parent = container5
|
||||
table.insert(container5.children, container2)
|
||||
container1:layoutChildren()
|
||||
end)
|
||||
|
||||
return {
|
||||
container1 = container1,
|
||||
container2 = container2,
|
||||
container3 = container3,
|
||||
container4 = container4,
|
||||
container5 = container5,
|
||||
attempt1 = attemptSuccess1,
|
||||
attempt2 = attemptSuccess2,
|
||||
}
|
||||
end)
|
||||
|
||||
luaunit.assertTrue(success) -- Should not crash the test framework
|
||||
luaunit.assertIsTable(result)
|
||||
|
||||
-- Verify basic structure is maintained
|
||||
luaunit.assertIsTable(result.container1)
|
||||
luaunit.assertIsTable(result.container2)
|
||||
luaunit.assertIsTable(result.container3)
|
||||
|
||||
-- Test that final layout still works
|
||||
local finalLayoutSuccess = captureError(function()
|
||||
result.container1:layoutChildren()
|
||||
end)
|
||||
luaunit.assertTrue(finalLayoutSuccess)
|
||||
end
|
||||
|
||||
-- Test 14: Memory and Performance Validation with Large Structures
|
||||
function TestLayoutValidation:testLargeStructureValidation()
|
||||
local success, result = captureError(function()
|
||||
-- Create a large, complex structure to test memory handling
|
||||
local root = Gui.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = 2000,
|
||||
h = 1500,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.VERTICAL,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = 5,
|
||||
})
|
||||
|
||||
local itemCount = 0
|
||||
local maxDepth = 5
|
||||
local itemsPerLevel = 10
|
||||
|
||||
-- Recursive function to create deep, wide structure
|
||||
local function createLevel(parent, depth, items)
|
||||
if depth >= maxDepth then
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, items do
|
||||
local container = Gui.new({
|
||||
w = depth == 1 and 400 or 100,
|
||||
h = depth == 1 and 200 or 50,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = i % 2 == 0 and FlexDirection.HORIZONTAL or FlexDirection.VERTICAL,
|
||||
flexWrap = i % 3 == 0 and FlexWrap.WRAP or FlexWrap.NOWRAP,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.STRETCH,
|
||||
gap = depth,
|
||||
})
|
||||
container.parent = parent
|
||||
table.insert(parent.children, container)
|
||||
itemCount = itemCount + 1
|
||||
|
||||
-- Add leaf elements to some containers
|
||||
if depth >= 3 then
|
||||
for j = 1, 3 do
|
||||
local leaf = Gui.new({
|
||||
w = 20 + j * 5,
|
||||
h = 15 + j * 3,
|
||||
positioning = j == 3 and Positioning.ABSOLUTE or nil,
|
||||
x = j == 3 and j * 10 or nil,
|
||||
y = j == 3 and j * 10 or nil,
|
||||
})
|
||||
leaf.parent = container
|
||||
table.insert(container.children, leaf)
|
||||
itemCount = itemCount + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Recurse to next level
|
||||
createLevel(container, depth + 1, math.max(1, items - 2))
|
||||
end
|
||||
end
|
||||
|
||||
-- Create the large structure
|
||||
createLevel(root, 1, itemsPerLevel)
|
||||
|
||||
-- Test initial layout
|
||||
root:layoutChildren()
|
||||
|
||||
-- Modify properties across the structure
|
||||
local function modifyRandomly(container, depth)
|
||||
if depth > maxDepth then
|
||||
return
|
||||
end
|
||||
|
||||
-- Randomly modify properties
|
||||
if math.random() > 0.7 then
|
||||
container.gap = math.random(-10, 50)
|
||||
end
|
||||
|
||||
if math.random() > 0.8 then
|
||||
container.flexDirection = math.random() > 0.5 and FlexDirection.HORIZONTAL or FlexDirection.VERTICAL
|
||||
end
|
||||
|
||||
if math.random() > 0.9 then
|
||||
container.width = math.random(10, 500)
|
||||
container.height = math.random(10, 300)
|
||||
end
|
||||
|
||||
-- Recurse to children
|
||||
if container.children then
|
||||
for _, child in ipairs(container.children) do
|
||||
modifyRandomly(child, depth + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Apply random modifications
|
||||
for iteration = 1, 3 do
|
||||
modifyRandomly(root, 1)
|
||||
root:layoutChildren() -- Should handle large structure
|
||||
end
|
||||
|
||||
-- Test memory cleanup simulation
|
||||
local function clearSubtree(container)
|
||||
if container.children then
|
||||
for i = #container.children, 1, -1 do
|
||||
clearSubtree(container.children[i])
|
||||
container.children[i].parent = nil
|
||||
table.remove(container.children, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Clear half the structure
|
||||
if root.children then
|
||||
for i = math.ceil(#root.children / 2), #root.children do
|
||||
if root.children[i] then
|
||||
clearSubtree(root.children[i])
|
||||
root.children[i].parent = nil
|
||||
table.remove(root.children, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Test layout after cleanup
|
||||
root:layoutChildren()
|
||||
|
||||
return {
|
||||
root = root,
|
||||
itemCount = itemCount,
|
||||
finalChildCount = #root.children,
|
||||
}
|
||||
end)
|
||||
|
||||
luaunit.assertTrue(success) -- Should handle large structures without crashing
|
||||
luaunit.assertIsTable(result)
|
||||
luaunit.assertTrue(result.itemCount > 100) -- Should have created many items
|
||||
luaunit.assertTrue(result.finalChildCount > 0) -- Should have remaining children after cleanup
|
||||
|
||||
-- Test final layout works
|
||||
local finalLayoutSuccess = captureError(function()
|
||||
result.root:layoutChildren()
|
||||
end)
|
||||
luaunit.assertTrue(finalLayoutSuccess)
|
||||
end
|
||||
|
||||
-- Test 15: Validation of Edge Cases in Complex Flex Combinations
|
||||
function TestLayoutValidation:testComplexFlexCombinationValidation()
|
||||
local success, result = captureError(function()
|
||||
-- Test every possible combination of flex properties with edge cases
|
||||
local combinations = {}
|
||||
|
||||
local flexDirections = { FlexDirection.HORIZONTAL, FlexDirection.VERTICAL }
|
||||
local justifyContents = {
|
||||
JustifyContent.FLEX_START,
|
||||
JustifyContent.FLEX_END,
|
||||
JustifyContent.CENTER,
|
||||
JustifyContent.SPACE_BETWEEN,
|
||||
JustifyContent.SPACE_AROUND,
|
||||
JustifyContent.SPACE_EVENLY,
|
||||
}
|
||||
local alignItems = {
|
||||
AlignItems.FLEX_START,
|
||||
AlignItems.FLEX_END,
|
||||
AlignItems.CENTER,
|
||||
AlignItems.STRETCH,
|
||||
}
|
||||
local flexWraps = { FlexWrap.NOWRAP, FlexWrap.WRAP, FlexWrap.WRAP_REVERSE }
|
||||
|
||||
-- Main container for all combinations
|
||||
local mainContainer = Gui.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = 2400,
|
||||
h = 1800,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
flexWrap = FlexWrap.WRAP,
|
||||
justifyContent = JustifyContent.FLEX_START,
|
||||
alignItems = AlignItems.FLEX_START,
|
||||
gap = 20,
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
})
|
||||
|
||||
local combinationCount = 0
|
||||
|
||||
-- Test each combination
|
||||
for _, flexDir in ipairs(flexDirections) do
|
||||
for _, justify in ipairs(justifyContents) do
|
||||
for _, align in ipairs(alignItems) do
|
||||
for _, wrap in ipairs(flexWraps) do
|
||||
combinationCount = combinationCount + 1
|
||||
|
||||
local testContainer = Gui.new({
|
||||
w = 200,
|
||||
h = 150,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = flexDir,
|
||||
justifyContent = justify,
|
||||
alignItems = align,
|
||||
flexWrap = wrap,
|
||||
gap = 5,
|
||||
padding = { top = 5, right = 5, bottom = 5, left = 5 },
|
||||
})
|
||||
testContainer.parent = mainContainer
|
||||
table.insert(mainContainer.children, testContainer)
|
||||
|
||||
-- Add children with edge case properties
|
||||
for i = 1, 6 do
|
||||
local child = Gui.new({
|
||||
w = i == 1 and 0 or (i == 2 and -10 or (i == 6 and 999999 or 30)),
|
||||
h = i == 3 and 0 or (i == 4 and -5 or (i == 5 and 1000000 or 20)),
|
||||
positioning = i == 6 and Positioning.ABSOLUTE or nil,
|
||||
x = i == 6 and -100 or nil,
|
||||
y = i == 6 and 200 or nil,
|
||||
})
|
||||
child.parent = testContainer
|
||||
table.insert(testContainer.children, child)
|
||||
|
||||
-- Add nested content to some children
|
||||
if i <= 3 then
|
||||
local nested = Gui.new({
|
||||
w = 15,
|
||||
h = 10,
|
||||
positioning = Positioning.FLEX,
|
||||
flexDirection = FlexDirection.HORIZONTAL,
|
||||
justifyContent = JustifyContent.CENTER,
|
||||
alignItems = AlignItems.CENTER,
|
||||
})
|
||||
nested.parent = child
|
||||
table.insert(child.children, nested)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Test layout with all combinations
|
||||
mainContainer:layoutChildren()
|
||||
|
||||
-- Test dynamic property changes on all combinations
|
||||
for _, container in ipairs(mainContainer.children) do
|
||||
-- Change gap to extreme values
|
||||
container.gap = math.random() > 0.5 and -20 or 100
|
||||
|
||||
-- Change dimensions
|
||||
if math.random() > 0.7 then
|
||||
container.width = math.random() > 0.5 and 0 or 500
|
||||
container.height = math.random() > 0.5 and -50 or 300
|
||||
end
|
||||
|
||||
-- Modify children
|
||||
if container.children then
|
||||
for i, child in ipairs(container.children) do
|
||||
if math.random() > 0.8 then
|
||||
child.width = math.random() > 0.5 and 0 or 999999
|
||||
child.height = math.random() > 0.5 and -100 or 1000000
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Test layout after modifications
|
||||
mainContainer:layoutChildren()
|
||||
|
||||
return {
|
||||
mainContainer = mainContainer,
|
||||
combinationCount = combinationCount,
|
||||
finalContainerCount = #mainContainer.children,
|
||||
}
|
||||
end)
|
||||
|
||||
luaunit.assertTrue(success) -- Should handle all combinations without crashing
|
||||
luaunit.assertIsTable(result)
|
||||
|
||||
-- Should have tested many combinations
|
||||
local expectedCombinations = 2 * 6 * 4 * 3 -- 144 combinations
|
||||
luaunit.assertEquals(result.combinationCount, expectedCombinations)
|
||||
luaunit.assertEquals(result.finalContainerCount, expectedCombinations)
|
||||
|
||||
-- Test final layout works
|
||||
local finalLayoutSuccess = captureError(function()
|
||||
result.mainContainer:layoutChildren()
|
||||
end)
|
||||
luaunit.assertTrue(finalLayoutSuccess)
|
||||
end
|
||||
|
||||
luaunit.LuaUnit.run()
|
||||
|
||||
Reference in New Issue
Block a user