package.path = package.path .. ";?.lua" local luaunit = require("testing.luaunit") require("testing.loveStub") local FlexLove = require("FlexLove") local Gui, Color, enums = FlexLove.Gui, FlexLove.Color, FlexLove.enums TestAuxiliaryFunctions = {} function TestAuxiliaryFunctions:setUp() -- Clear any existing GUI elements Gui.destroy() end function TestAuxiliaryFunctions:tearDown() -- Clean up after each test Gui.destroy() end -- ============================================ -- Color Utility Functions Tests -- ============================================ function TestAuxiliaryFunctions:testColorNewBasic() local color = Color.new(1, 0.5, 0.2, 0.8) luaunit.assertEquals(color.r, 1) luaunit.assertEquals(color.g, 0.5) luaunit.assertEquals(color.b, 0.2) luaunit.assertEquals(color.a, 0.8) end function TestAuxiliaryFunctions:testColorNewDefaults() -- Test default values when parameters are nil or missing local color = Color.new() luaunit.assertEquals(color.r, 0) luaunit.assertEquals(color.g, 0) luaunit.assertEquals(color.b, 0) luaunit.assertEquals(color.a, 1) -- Alpha defaults to 1 end function TestAuxiliaryFunctions:testColorNewPartialDefaults() local color = Color.new(0.7, 0.3) luaunit.assertEquals(color.r, 0.7) luaunit.assertEquals(color.g, 0.3) luaunit.assertEquals(color.b, 0) luaunit.assertEquals(color.a, 1) end function TestAuxiliaryFunctions:testColorFromHex6Digit() local color = Color.fromHex("#FF8040") -- Note: Color.fromHex actually returns values in 0-255 range, not 0-1 luaunit.assertEquals(color.r, 255) luaunit.assertEquals(color.g, 128) luaunit.assertEquals(color.b, 64) luaunit.assertEquals(color.a, 1) end function TestAuxiliaryFunctions:testColorFromHex8Digit() local color = Color.fromHex("#FF8040CC") luaunit.assertEquals(color.r, 255) luaunit.assertEquals(color.g, 128) luaunit.assertEquals(color.b, 64) luaunit.assertAlmostEquals(color.a, 204 / 255, 0.01) -- CC hex = 204 decimal end function TestAuxiliaryFunctions:testColorFromHexWithoutHash() local color = Color.fromHex("FF8040") luaunit.assertEquals(color.r, 255) luaunit.assertEquals(color.g, 128) luaunit.assertEquals(color.b, 64) luaunit.assertEquals(color.a, 1) end function TestAuxiliaryFunctions:testColorFromHexInvalid() luaunit.assertError(function() Color.fromHex("#INVALID") end) luaunit.assertError(function() Color.fromHex("#FF80") -- Too short end) luaunit.assertError(function() Color.fromHex("#FF8040CC99") -- Too long end) end function TestAuxiliaryFunctions:testColorToRGBA() local color = Color.new(0.8, 0.6, 0.4, 0.9) local r, g, b, a = color:toRGBA() luaunit.assertEquals(r, 0.8) luaunit.assertEquals(g, 0.6) luaunit.assertEquals(b, 0.4) luaunit.assertEquals(a, 0.9) end -- ============================================ -- Element Calculation Utility Tests -- ============================================ function TestAuxiliaryFunctions:testCalculateTextWidthWithText() local element = Gui.new({ text = "Test Text", textSize = 16, }) local width = element:calculateTextWidth() print("Text: '" .. (element.text or "nil") .. "', TextSize: " .. (element.textSize or "nil") .. ", Width: " .. width) luaunit.assertTrue(width > 0, "Text width should be greater than 0, got: " .. width) end function TestAuxiliaryFunctions:testCalculateTextWidthNoText() local element = Gui.new({}) local width = element:calculateTextWidth() luaunit.assertEquals(width, 0, "Text width should be 0 when no text") end function TestAuxiliaryFunctions:testCalculateTextHeightWithSize() local element = Gui.new({ text = "Test", textSize = 24, }) local height = element:calculateTextHeight() luaunit.assertTrue(height > 0, "Text height should be greater than 0") end function TestAuxiliaryFunctions:testCalculateAutoWidthNoChildren() local element = Gui.new({ text = "Hello", }) local width = element:calculateAutoWidth() local textWidth = element:calculateTextWidth() luaunit.assertEquals(width, textWidth, "Auto width should equal text width when no children") end function TestAuxiliaryFunctions:testCalculateAutoWidthWithChildren() local parent = Gui.new({ positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.HORIZONTAL, gap = 5, -- Add gap to test gap calculation }) local child1 = Gui.new({ parent = parent, width = 50, height = 30, }) local child2 = Gui.new({ parent = parent, width = 40, height = 25, }) local width = parent:calculateAutoWidth() luaunit.assertTrue(width > 90, "Auto width should account for children and gaps") end function TestAuxiliaryFunctions:testCalculateAutoHeightNoChildren() local element = Gui.new({ text = "Hello", }) local height = element:calculateAutoHeight() local textHeight = element:calculateTextHeight() luaunit.assertEquals(height, textHeight, "Auto height should equal text height when no children") end function TestAuxiliaryFunctions:testCalculateAutoHeightWithChildren() local parent = Gui.new({ positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.VERTICAL, gap = 5, -- Add gap to test gap calculation }) local child1 = Gui.new({ parent = parent, width = 50, height = 30, }) local child2 = Gui.new({ parent = parent, width = 40, height = 25, }) local height = parent:calculateAutoHeight() luaunit.assertTrue(height > 55, "Auto height should account for children and gaps") end -- ============================================ -- Element Utility Methods Tests -- ============================================ function TestAuxiliaryFunctions:testGetBounds() local element = Gui.new({ x = 10, y = 20, width = 100, height = 80, }) local bounds = element:getBounds() luaunit.assertEquals(bounds.x, 10) luaunit.assertEquals(bounds.y, 20) luaunit.assertEquals(bounds.width, 100) luaunit.assertEquals(bounds.height, 80) end function TestAuxiliaryFunctions:testUpdateText() local element = Gui.new({ text = "Original Text", width = 100, height = 50, }) element:updateText("New Text") luaunit.assertEquals(element.text, "New Text") luaunit.assertEquals(element.width, 100) -- Should not change without autoresize luaunit.assertEquals(element.height, 50) end function TestAuxiliaryFunctions:testUpdateTextWithAutoresize() local element = Gui.new({ text = "Short", textSize = 16, }) local originalWidth = element.width element:updateText("Much Longer Text That Should Change Width", true) -- Debug: let's see what the values are -- print("Original width: " .. originalWidth .. ", New width: " .. element.width) luaunit.assertEquals(element.text, "Much Longer Text That Should Change Width") luaunit.assertTrue( element.width > originalWidth, "Width should increase with longer text and autoresize. Original: " .. originalWidth .. ", New: " .. element.width ) end function TestAuxiliaryFunctions:testUpdateTextKeepOriginalWhenNil() local element = Gui.new({ text = "Original Text", }) element:updateText(nil) luaunit.assertEquals(element.text, "Original Text", "Text should remain unchanged when nil is passed") end function TestAuxiliaryFunctions:testUpdateOpacitySingle() local element = Gui.new({ opacity = 1.0, }) element:updateOpacity(0.5) luaunit.assertEquals(element.opacity, 0.5) end function TestAuxiliaryFunctions:testUpdateOpacityPropagateToChildren() local parent = Gui.new({ opacity = 1.0, }) local child1 = Gui.new({ parent = parent, opacity = 1.0, }) local child2 = Gui.new({ parent = parent, opacity = 1.0, }) parent:updateOpacity(0.3) luaunit.assertEquals(parent.opacity, 0.3) luaunit.assertEquals(child1.opacity, 0.3) luaunit.assertEquals(child2.opacity, 0.3) end -- ============================================ -- Animation Utility Functions Tests -- ============================================ function TestAuxiliaryFunctions:testAnimationFadeFactory() local fadeAnim = Gui.Animation.fade(2.0, 1.0, 0.0) luaunit.assertEquals(fadeAnim.duration, 2.0) luaunit.assertEquals(fadeAnim.start.opacity, 1.0) luaunit.assertEquals(fadeAnim.final.opacity, 0.0) luaunit.assertNotNil(fadeAnim.transform) luaunit.assertNotNil(fadeAnim.transition) end function TestAuxiliaryFunctions:testAnimationScaleFactory() local scaleAnim = Gui.Animation.scale(1.5, { width = 100, height = 50 }, { width = 200, height = 100 }) luaunit.assertEquals(scaleAnim.duration, 1.5) luaunit.assertEquals(scaleAnim.start.width, 100) luaunit.assertEquals(scaleAnim.start.height, 50) luaunit.assertEquals(scaleAnim.final.width, 200) luaunit.assertEquals(scaleAnim.final.height, 100) end function TestAuxiliaryFunctions:testAnimationInterpolation() local fadeAnim = Gui.Animation.fade(1.0, 1.0, 0.0) fadeAnim.elapsed = 0.5 -- 50% through animation local result = fadeAnim:interpolate() luaunit.assertAlmostEquals(result.opacity, 0.5, 0.01) -- Should be halfway end function TestAuxiliaryFunctions:testAnimationUpdate() local fadeAnim = Gui.Animation.fade(1.0, 1.0, 0.0) -- Animation should not be finished initially local finished = fadeAnim:update(0.5) luaunit.assertFalse(finished) luaunit.assertEquals(fadeAnim.elapsed, 0.5) -- Animation should be finished after full duration finished = fadeAnim:update(0.6) -- Total 1.1 seconds > 1.0 duration luaunit.assertTrue(finished) end function TestAuxiliaryFunctions:testAnimationApplyToElement() local element = Gui.new({ width = 100, height = 50, }) local fadeAnim = Gui.Animation.fade(1.0, 1.0, 0.0) fadeAnim:apply(element) luaunit.assertEquals(element.animation, fadeAnim) end function TestAuxiliaryFunctions:testAnimationReplaceExisting() local element = Gui.new({ width = 100, height = 50, }) local fadeAnim1 = Gui.Animation.fade(1.0, 1.0, 0.0) local fadeAnim2 = Gui.Animation.fade(2.0, 0.5, 1.0) fadeAnim1:apply(element) fadeAnim2:apply(element) luaunit.assertEquals(element.animation, fadeAnim2, "Second animation should replace the first") end -- ============================================ -- GUI Management Utility Tests -- ============================================ function TestAuxiliaryFunctions:testGuiDestroyEmptyState() -- Should not error when destroying empty GUI Gui.destroy() luaunit.assertEquals(#Gui.topElements, 0) end function TestAuxiliaryFunctions:testGuiDestroyWithElements() local element1 = Gui.new({ x = 10, y = 10, width = 100, height = 50, }) local element2 = Gui.new({ x = 20, y = 20, width = 80, height = 40, }) luaunit.assertEquals(#Gui.topElements, 2) Gui.destroy() luaunit.assertEquals(#Gui.topElements, 0) end function TestAuxiliaryFunctions:testGuiDestroyWithNestedElements() local parent = Gui.new({ width = 200, height = 100, }) local child1 = Gui.new({ parent = parent, width = 50, height = 30, }) local child2 = Gui.new({ parent = parent, width = 40, height = 25, }) luaunit.assertEquals(#Gui.topElements, 1) luaunit.assertEquals(#parent.children, 2) Gui.destroy() luaunit.assertEquals(#Gui.topElements, 0) end function TestAuxiliaryFunctions:testElementDestroyRemovesFromParent() local parent = Gui.new({ width = 200, height = 100, }) local child = Gui.new({ parent = parent, width = 50, height = 30, }) luaunit.assertEquals(#parent.children, 1) child:destroy() luaunit.assertEquals(#parent.children, 0) luaunit.assertNil(child.parent) end function TestAuxiliaryFunctions:testElementDestroyRemovesFromTopElements() local element = Gui.new({ x = 10, y = 10, width = 100, height = 50, }) luaunit.assertEquals(#Gui.topElements, 1) element:destroy() luaunit.assertEquals(#Gui.topElements, 0) end function TestAuxiliaryFunctions:testElementDestroyNestedChildren() local parent = Gui.new({ width = 200, height = 150, }) local child = Gui.new({ parent = parent, width = 100, height = 75, }) local grandchild = Gui.new({ parent = child, width = 50, height = 30, }) luaunit.assertEquals(#parent.children, 1) luaunit.assertEquals(#child.children, 1) parent:destroy() luaunit.assertEquals(#Gui.topElements, 0) luaunit.assertEquals(#child.children, 0, "Grandchildren should be destroyed") end -- ============================================ -- Edge Cases and Error Handling Tests -- ============================================ function TestAuxiliaryFunctions:testColorFromHexEmptyString() luaunit.assertError(function() Color.fromHex("") end) end function TestAuxiliaryFunctions:testColorFromHexNoHashInvalidLength() luaunit.assertError(function() Color.fromHex("FF80") end) end function TestAuxiliaryFunctions:testAnimationInterpolationAtBoundaries() local scaleAnim = Gui.Animation.scale(1.0, { width = 100, height = 50 }, { width = 200, height = 100 }) -- At start (elapsed = 0) scaleAnim.elapsed = 0 scaleAnim._resultDirty = true -- Mark dirty after changing elapsed local result = scaleAnim:interpolate() luaunit.assertEquals(result.width, 100) luaunit.assertEquals(result.height, 50) -- At end (elapsed = duration) scaleAnim.elapsed = 1.0 scaleAnim._resultDirty = true -- Mark dirty after changing elapsed result = scaleAnim:interpolate() luaunit.assertEquals(result.width, 200) luaunit.assertEquals(result.height, 100) -- Beyond end (elapsed > duration) - should clamp to end values scaleAnim.elapsed = 1.5 scaleAnim._resultDirty = true -- Mark dirty after changing elapsed result = scaleAnim:interpolate() luaunit.assertEquals(result.width, 200) luaunit.assertEquals(result.height, 100) end function TestAuxiliaryFunctions:testAutoSizingWithZeroChildren() local element = Gui.new({ text = "", }) local width = element:calculateAutoWidth() local height = element:calculateAutoHeight() luaunit.assertTrue(width >= 0, "Auto width should be non-negative") luaunit.assertTrue(height >= 0, "Auto height should be non-negative") end function TestAuxiliaryFunctions:testUpdateOpacityBoundaryValues() local element = Gui.new({ opacity = 0.5, }) -- Test minimum boundary element:updateOpacity(0.0) luaunit.assertEquals(element.opacity, 0.0) -- Test maximum boundary element:updateOpacity(1.0) luaunit.assertEquals(element.opacity, 1.0) -- Test beyond boundaries (should still work, implementation may clamp) element:updateOpacity(1.5) luaunit.assertEquals(element.opacity, 1.5) -- FlexLove doesn't appear to clamp element:updateOpacity(-0.2) luaunit.assertEquals(element.opacity, -0.2) -- FlexLove doesn't appear to clamp end -- ============================================ -- Test 11: Complex Color Management System -- ============================================ function TestAuxiliaryFunctions:testComplexColorManagementSystem() print("\n=== Test 11: Complex Color Management System ===") -- Create color management system for UI theming local theme_colors = {} local color_variations = {} -- Test comprehensive color creation and conversion local base_colors = { { name = "primary", hex = "#2563EB", r = 0.145, g = 0.388, b = 0.922 }, { name = "secondary", hex = "#7C3AED", r = 0.486, g = 0.227, b = 0.929 }, { name = "success", hex = "#10B981", r = 0.063, g = 0.725, b = 0.506 }, { name = "warning", hex = "#F59E0B", r = 0.961, g = 0.619, b = 0.043 }, { name = "danger", hex = "#EF4444", r = 0.937, g = 0.267, b = 0.267 }, } -- Test color creation from hex and manual RGB for _, color_def in ipairs(base_colors) do local hex_color = Color.fromHex(color_def.hex) local manual_color = Color.new(color_def.r, color_def.g, color_def.b, 1.0) theme_colors[color_def.name] = { hex = hex_color, manual = manual_color, name = color_def.name, } -- Verify hex parsing (FlexLove uses 0-255 range) luaunit.assertAlmostEquals(hex_color.r / 255, color_def.r, 0.01, string.format("%s hex red component mismatch", color_def.name)) luaunit.assertAlmostEquals(hex_color.g / 255, color_def.g, 0.01, string.format("%s hex green component mismatch", color_def.name)) luaunit.assertAlmostEquals(hex_color.b / 255, color_def.b, 0.01, string.format("%s hex blue component mismatch", color_def.name)) end -- Test color variations (opacity, brightness adjustments) local opacities = { 0.1, 0.25, 0.5, 0.75, 0.9 } for color_name, color_set in pairs(theme_colors) do color_variations[color_name] = {} -- Create opacity variations for _, opacity in ipairs(opacities) do local variant_color = Color.new(color_set.manual.r, color_set.manual.g, color_set.manual.b, opacity) color_variations[color_name]["alpha_" .. tostring(opacity)] = variant_color luaunit.assertEquals(variant_color.a, opacity, string.format("%s opacity variant should have correct alpha", color_name)) end -- Create brightness variations local brightness_factors = { 0.3, 0.6, 1.0, 1.4, 1.8 } for _, factor in ipairs(brightness_factors) do local bright_r = math.min(1.0, color_set.manual.r * factor) local bright_g = math.min(1.0, color_set.manual.g * factor) local bright_b = math.min(1.0, color_set.manual.b * factor) local bright_color = Color.new(bright_r, bright_g, bright_b, 1.0) color_variations[color_name]["bright_" .. tostring(factor)] = bright_color luaunit.assertTrue(bright_r <= 1.0 and bright_g <= 1.0 and bright_b <= 1.0, "Brightness variations should not exceed 1.0") end end -- Test color application to complex UI structure local ui_container = Gui.new({ width = 800, height = 600, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.VERTICAL, gap = 10, }) -- Apply theme colors to different UI components local component_types = { "header", "content", "sidebar", "footer", "modal" } for i, comp_type in ipairs(component_types) do local component = Gui.new({ width = 780, height = 100, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.HORIZONTAL, justifyContent = enums.JustifyContent.SPACE_BETWEEN, alignItems = enums.AlignItems.CENTER, gap = 8, }) component.parent = ui_container table.insert(ui_container.children, component) -- Apply color based on component type local color_name = base_colors[((i - 1) % #base_colors) + 1].name component.backgroundColor = theme_colors[color_name].manual component.textColor = Color.new(1, 1, 1, 1) -- White text -- Add sub-components with color variations for j = 1, 4 do local sub_component = Gui.new({ width = 150, height = 80, positioning = enums.Positioning.FLEX, justifyContent = enums.JustifyContent.CENTER, alignItems = enums.AlignItems.CENTER, }) sub_component.parent = component table.insert(component.children, sub_component) -- Apply color variation local opacity_key = "alpha_" .. tostring(opacities[((j - 1) % #opacities) + 1]) sub_component.backgroundColor = color_variations[color_name][opacity_key] end end -- Verify color system integrity ui_container:layoutChildren() luaunit.assertEquals(#ui_container.children, 5, "Should have 5 themed components") -- Count theme_colors (it's a table with string keys, not an array) local theme_color_count = 0 for _ in pairs(theme_colors) do theme_color_count = theme_color_count + 1 end luaunit.assertEquals(theme_color_count, 5, "Should have 5 base theme colors") local total_variations = 0 for _, variations in pairs(color_variations) do for _ in pairs(variations) do total_variations = total_variations + 1 end end luaunit.assertTrue(total_variations >= 50, "Should have created numerous color variations") print(string.format("Color Management System: %d base colors, %d variations, %d UI components", #base_colors, total_variations, #ui_container.children)) end -- ============================================ -- Test 12: Advanced Text and Auto-sizing Complex System -- ============================================ function TestAuxiliaryFunctions:testAdvancedTextAndAutoSizingSystem() print("\n=== Test 12: Advanced Text and Auto-sizing System ===") -- Create dynamic text content management system local content_manager = { dynamic_texts = {}, auto_sized_containers = {}, text_metrics = {}, } -- Test complex multi-language text scenarios local text_scenarios = { { id = "english_short", content = "Hello World", size = 14, expected_behavior = "compact", }, { id = "english_long", content = "This is a much longer text that should demonstrate text wrapping and auto-sizing capabilities in various scenarios", size = 16, expected_behavior = "expanding", }, { id = "mixed_content", content = "Product: Widget Pro™\nPrice: $299.99\nAvailability: In Stock ✓", size = 12, expected_behavior = "multiline", }, { id = "special_chars", content = "Spéciál Chàracters: αβγδε • ★ ♦ ♠ → ∞", size = 18, expected_behavior = "unicode", }, { id = "numbers_symbols", content = "Data: 123,456.78 | Progress: 85% | Status: [●●●○○]", size = 13, expected_behavior = "data_display", }, } -- Create dynamic text containers with auto-sizing local main_container = Gui.new({ width = 1000, height = 800, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.VERTICAL, gap = 15, }) for _, scenario in ipairs(text_scenarios) do local text_container = Gui.new({ width = 900, height = 100, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.HORIZONTAL, justifyContent = enums.JustifyContent.SPACE_BETWEEN, alignItems = enums.AlignItems.FLEX_START, gap = 20, }) text_container.parent = main_container table.insert(main_container.children, text_container) -- Create auto-sized text element local text_element = Gui.new({ text = scenario.content, textSize = scenario.size, width = 0, height = 0, -- Start with zero size for auto-sizing }) text_element.parent = text_container table.insert(text_container.children, text_element) -- Calculate auto dimensions local auto_width = text_element:calculateAutoWidth() local auto_height = text_element:calculateAutoHeight() local text_width = text_element:calculateTextWidth() local text_height = text_element:calculateTextHeight() -- Store metrics content_manager.text_metrics[scenario.id] = { auto_width = auto_width, auto_height = auto_height, text_width = text_width, text_height = text_height, char_count = string.len(scenario.content), content = scenario.content, } -- Verify text calculations luaunit.assertTrue(auto_width >= 0, string.format("%s: Auto width should be non-negative", scenario.id)) luaunit.assertTrue(auto_height >= 0, string.format("%s: Auto height should be non-negative", scenario.id)) luaunit.assertTrue(text_width >= 0, string.format("%s: Text width should be non-negative", scenario.id)) luaunit.assertTrue(text_height >= 0, string.format("%s: Text height should be non-negative", scenario.id)) -- For single-line text, auto width should roughly match text width if not string.find(scenario.content, "\n") then luaunit.assertAlmostEquals( auto_width, text_width, text_width * 0.1, string.format("%s: Auto width should approximate text width for single-line", scenario.id) ) end -- Apply auto-sizing text_element.w = auto_width text_element.h = auto_height content_manager.auto_sized_containers[scenario.id] = text_element -- Create comparison elements with fixed sizes local fixed_element = Gui.new({ text = scenario.content, textSize = scenario.size, width = 200, height = 50, -- Fixed size }) fixed_element.parent = text_container table.insert(text_container.children, fixed_element) -- Create adaptive element that changes based on content length local adaptive_element = Gui.new({ text = scenario.content, textSize = scenario.size, width = math.max(150, auto_width * 0.8), height = math.max(30, auto_height * 1.2), }) adaptive_element.parent = text_container table.insert(text_container.children, adaptive_element) end -- Test dynamic text updates with auto-resizing local dynamic_updates = { { target = "english_short", new_text = "Updated: Hello Universe!", autoresize = true }, { target = "english_long", new_text = "Shortened text", autoresize = true }, { target = "mixed_content", new_text = "Status: SOLD OUT ❌", autoresize = false }, { target = "numbers_symbols", new_text = "Final Results: 999,999.99 | Complete: 100% | Status: [●●●●●]", autoresize = true, }, } for _, update in ipairs(dynamic_updates) do local element = content_manager.auto_sized_containers[update.target] if element then local original_width = element.w local original_height = element.h element:updateText(update.new_text, update.autoresize) if update.autoresize then -- With autoresize, dimensions should potentially change local new_auto_width = element:calculateAutoWidth() local new_auto_height = element:calculateAutoHeight() luaunit.assertEquals(element.text, update.new_text, string.format("%s: Text should be updated", update.target)) -- If autoresize is working, element dimensions should match auto calculations if new_auto_width ~= original_width or new_auto_height ~= original_height then content_manager.text_metrics[update.target .. "_updated"] = { auto_width = new_auto_width, auto_height = new_auto_height, original_width = original_width, original_height = original_height, text_changed = true, } end else -- Without autoresize, dimensions should remain the same luaunit.assertEquals(element.w, original_width, string.format("%s: Width should not change without autoresize", update.target)) luaunit.assertEquals(element.h, original_height, string.format("%s: Height should not change without autoresize", update.target)) end end end -- Test complex auto-sizing with nested structures local nested_container = Gui.new({ width = 800, height = 200, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.VERTICAL, gap = 10, }) nested_container.parent = main_container table.insert(main_container.children, nested_container) -- Create nested structure with auto-sizing children local prev_container = nested_container for level = 1, 3 do local level_container = Gui.new({ width = 750 - (level * 50), height = 60, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.HORIZONTAL, justifyContent = enums.JustifyContent.SPACE_AROUND, gap = 5, }) level_container.parent = prev_container table.insert(prev_container.children, level_container) prev_container = level_container for item = 1, 4 do local item_text = string.format("L%d-Item%d: %s", level, item, string.rep("Text ", level)) local text_item = Gui.new({ text = item_text, textSize = 14 - level, width = 0, height = 0, }) text_item.parent = level_container table.insert(level_container.children, text_item) -- Apply auto-sizing text_item.w = text_item:calculateAutoWidth() text_item.h = text_item:calculateAutoHeight() end end -- Perform layout and verify main_container:layoutChildren() luaunit.assertEquals(#main_container.children, #text_scenarios + 1, "Should have scenario containers plus nested container") -- Count text_metrics (it's a table with string keys, not an array) local metrics_count = 0 for _ in pairs(content_manager.text_metrics) do metrics_count = metrics_count + 1 end luaunit.assertTrue(metrics_count >= #text_scenarios, "Should have metrics for all scenarios") print(string.format("Text Management System: %d scenarios, %d metrics, %d updates", #text_scenarios, #content_manager.text_metrics, #dynamic_updates)) end -- ============================================ -- Test 13: Comprehensive Animation Engine Testing -- ============================================ function TestAuxiliaryFunctions:testComprehensiveAnimationEngine() print("\n=== Test 13: Comprehensive Animation Engine ===") -- Create animation test environment local animation_system = { active_animations = {}, completed_animations = {}, animation_chains = {}, performance_metrics = {}, } -- Create container for animated elements local animation_container = Gui.new({ width = 1200, height = 800, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.VERTICAL, gap = 20, }) -- Test various animation types and combinations local animation_test_cases = { { name = "fade_animations", elements = 8, animation_type = "fade", duration_range = { 0.5, 2.0 }, properties = { opacity = { from = 1.0, to = 0.0 } }, }, { name = "scale_animations", elements = 6, animation_type = "scale", duration_range = { 1.0, 3.0 }, properties = { width = { from = 100, to = 200 }, height = { from = 50, to = 100 }, }, }, { name = "complex_mixed", elements = 10, animation_type = "mixed", duration_range = { 0.8, 2.5 }, properties = { opacity = { from = 0.2, to = 1.0 }, width = { from = 80, to = 150 }, height = { from = 40, to = 80 }, }, }, } -- Create and configure animations for each test case for case_idx, test_case in ipairs(animation_test_cases) do local case_container = Gui.new({ width = 1180, height = 200, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.HORIZONTAL, flexWrap = enums.FlexWrap.WRAP, justifyContent = enums.JustifyContent.SPACE_AROUND, gap = 15, }) case_container.parent = animation_container table.insert(animation_container.children, case_container) animation_system.animation_chains[test_case.name] = {} for elem_idx = 1, test_case.elements do local element = Gui.new({ width = test_case.properties.width and test_case.properties.width.from or 120, height = test_case.properties.height and test_case.properties.height.from or 60, opacity = test_case.properties.opacity and test_case.properties.opacity.from or 1.0, }) element.parent = case_container table.insert(case_container.children, element) -- Create animation based on type local duration = test_case.duration_range[1] + (math.random() * (test_case.duration_range[2] - test_case.duration_range[1])) local animation if test_case.animation_type == "fade" then animation = Gui.Animation.fade(duration, test_case.properties.opacity.from, test_case.properties.opacity.to) elseif test_case.animation_type == "scale" then animation = Gui.Animation.scale(duration, { width = test_case.properties.width.from, height = test_case.properties.height.from, }, { width = test_case.properties.width.to, height = test_case.properties.height.to, }) elseif test_case.animation_type == "mixed" then -- Create complex animation with multiple properties animation = { duration = duration, elapsed = 0, start = {}, final = {}, element = element, properties = {}, } -- Set up start and final values for all properties for prop, values in pairs(test_case.properties) do animation.start[prop] = values.from animation.final[prop] = values.to animation.properties[prop] = true end -- Add interpolation method animation.interpolate = function(self) local progress = math.min(1.0, self.elapsed / self.duration) local result = {} for prop in pairs(self.properties) do local start_val = self.start[prop] local final_val = self.final[prop] result[prop] = start_val + (final_val - start_val) * progress end return result end -- Add update method animation.update = function(self, dt) self.elapsed = self.elapsed + dt local finished = self.elapsed >= self.duration if finished then self.elapsed = self.duration end -- Apply interpolated values to element local values = self:interpolate() for prop, value in pairs(values) do if prop == "opacity" then self.element.opacity = value elseif prop == "width" then self.element.w = value elseif prop == "height" then self.element.h = value end end return finished end -- Add apply method animation.apply = function(self, element) self.element = element element.animation = self end end -- Verify animation creation luaunit.assertNotNil(animation, string.format("Animation should be created for %s", test_case.name)) luaunit.assertTrue(animation.duration > 0, "Animation should have positive duration") luaunit.assertNotNil(animation.start, "Animation should have start properties") luaunit.assertNotNil(animation.final, "Animation should have final properties") -- Apply animation to element animation:apply(element) animation_system.active_animations[test_case.name .. "_" .. elem_idx] = { animation = animation, element = element, start_time = 0, test_case = test_case.name, } table.insert(animation_system.animation_chains[test_case.name], animation) end end -- Simulate animation updates over time local total_simulation_time = 4.0 -- 4 seconds local dt = 1 / 60 -- 60 FPS local frame_count = 0 local active_count_over_time = {} for sim_time = 0, total_simulation_time, dt do frame_count = frame_count + 1 local active_count = 0 local completed_this_frame = {} -- Update all active animations for anim_id, anim_data in pairs(animation_system.active_animations) do if anim_data.animation then local finished = anim_data.animation:update(dt) if finished then table.insert(completed_this_frame, anim_id) animation_system.completed_animations[anim_id] = { animation = anim_data.animation, completion_time = sim_time, total_frames = frame_count, } else active_count = active_count + 1 end end end -- Remove completed animations for _, anim_id in ipairs(completed_this_frame) do animation_system.active_animations[anim_id] = nil end active_count_over_time[frame_count] = active_count -- Test interpolation at specific progress points if frame_count % 60 == 0 then -- Every second for anim_id, anim_data in pairs(animation_system.active_animations) do if anim_data.animation.interpolate then local progress = anim_data.animation.elapsed / anim_data.animation.duration local interpolated = anim_data.animation:interpolate() luaunit.assertTrue(progress >= 0 and progress <= 1, string.format("Animation progress should be 0-1, got %.3f", progress)) luaunit.assertNotNil(interpolated, "Interpolation should return values") end end end end -- Analyze animation performance and correctness local total_animations = 0 local total_completed = 0 for test_case_name, animations in pairs(animation_system.animation_chains) do total_animations = total_animations + #animations end for _ in pairs(animation_system.completed_animations) do total_completed = total_completed + 1 end animation_system.performance_metrics = { total_animations = total_animations, completed_animations = total_completed, completion_rate = total_completed / total_animations, simulation_frames = frame_count, simulation_time = total_simulation_time, } -- Verify animation system functionality luaunit.assertTrue(total_animations > 20, "Should have created substantial number of animations") luaunit.assertTrue(total_completed > 0, "Some animations should have completed") luaunit.assertTrue(animation_system.performance_metrics.completion_rate > 0.5, "Majority of animations should complete within simulation time") -- Test animation chaining and sequencing local chain_element = Gui.new({ width = 100, height = 50, opacity = 1.0 }) chain_element.parent = animation_container table.insert(animation_container.children, chain_element) -- Create animation chain: fade out -> scale up -> fade in local chain_animations = { Gui.Animation.fade(0.5, 1.0, 0.0), Gui.Animation.scale(0.8, { width = 100, height = 50 }, { width = 200, height = 100 }), Gui.Animation.fade(0.5, 0.0, 1.0), } -- Test each animation in the chain for i, chain_anim in ipairs(chain_animations) do luaunit.assertNotNil(chain_anim, string.format("Chain animation %d should exist", i)) luaunit.assertTrue(chain_anim.duration > 0, string.format("Chain animation %d should have duration", i)) -- Apply and test first few frames chain_anim:apply(chain_element) for frame = 1, 5 do local finished = chain_anim:update(0.1) if frame < 5 then luaunit.assertFalse(finished, string.format("Chain animation %d should not finish in %d frames", i, frame)) end end end -- Perform final layout animation_container:layoutChildren() luaunit.assertEquals(#animation_container.children, #animation_test_cases + 1, "Should have containers for each test case plus chain element") print( string.format( "Animation Engine: %d total animations, %d completed (%.1f%%), %d frames simulated", animation_system.performance_metrics.total_animations, animation_system.performance_metrics.completed_animations, animation_system.performance_metrics.completion_rate * 100, animation_system.performance_metrics.simulation_frames ) ) end -- ============================================ -- Test 14: Advanced GUI Management and Cleanup System -- ============================================ function TestAuxiliaryFunctions:testAdvancedGUIManagementAndCleanup() print("\n=== Test 14: Advanced GUI Management and Cleanup ===") -- Create complex GUI hierarchy for testing management local gui_manager = { element_registry = {}, destruction_log = {}, memory_snapshots = {}, hierarchy_metrics = {}, } -- Test complex nested structure creation and management local application_structure = { { type = "main_window", children = { { type = "header", children = { { type = "logo", children = {} }, { type = "nav_menu", children = { { type = "nav_item", children = {} }, { type = "nav_item", children = {} }, { type = "nav_item", children = {} }, }, }, { type = "user_area", children = { { type = "avatar", children = {} }, { type = "dropdown", children = { { type = "menu_item", children = {} }, { type = "menu_item", children = {} }, { type = "divider", children = {} }, { type = "menu_item", children = {} }, }, }, }, }, }, }, { type = "main_content", children = { { type = "sidebar", children = { { type = "sidebar_section", children = { { type = "section_header", children = {} }, { type = "section_item", children = {} }, { type = "section_item", children = {} }, { type = "section_item", children = {} }, }, }, { type = "sidebar_section", children = { { type = "section_header", children = {} }, { type = "section_item", children = {} }, { type = "section_item", children = {} }, }, }, }, }, { type = "content_area", children = { { type = "content_header", children = { { type = "breadcrumb", children = {} }, { type = "actions", children = { { type = "action_button", children = {} }, { type = "action_button", children = {} }, { type = "action_dropdown", children = {} }, }, }, }, }, { type = "content_body", children = { { type = "data_grid", children = { { type = "grid_header", children = {} }, { type = "grid_row", children = { { type = "grid_cell", children = {} }, { type = "grid_cell", children = {} }, { type = "grid_cell", children = {} }, }, }, { type = "grid_row", children = { { type = "grid_cell", children = {} }, { type = "grid_cell", children = {} }, { type = "grid_cell", children = {} }, }, }, }, }, }, }, }, }, }, }, { type = "footer", children = { { type = "footer_links", children = {} }, { type = "footer_info", children = {} }, }, }, }, }, } -- Recursive function to create GUI structure local function createGUIHierarchy(structure, parent, level) level = level or 1 local created_elements = {} for _, item in ipairs(structure) do local element = Gui.new({ width = math.max(100, 300 - level * 20), height = math.max(30, 80 - level * 5), positioning = enums.Positioning.FLEX, flexDirection = level % 2 == 0 and enums.FlexDirection.HORIZONTAL or enums.FlexDirection.VERTICAL, justifyContent = enums.JustifyContent.FLEX_START, alignItems = enums.AlignItems.STRETCH, gap = math.max(2, 10 - level), }) if parent then element.parent = parent table.insert(parent.children, element) end -- Register element in management system local element_id = item.type .. "_" .. tostring(level) .. "_" .. tostring(#created_elements + 1) gui_manager.element_registry[element_id] = { element = element, type = item.type, level = level, parent_id = parent and "parent_of_" .. element_id or nil, children_count = #item.children, } table.insert(created_elements, { id = element_id, element = element }) -- Recursively create children if #item.children > 0 then local child_elements = createGUIHierarchy(item.children, element, level + 1) gui_manager.element_registry[element_id].child_elements = child_elements end end return created_elements end -- Create the complex structure local root_elements = createGUIHierarchy(application_structure) local root_element = root_elements[1].element -- Take initial memory snapshot gui_manager.memory_snapshots.initial = { element_count = 0, registry_size = 0, } for _ in pairs(gui_manager.element_registry) do gui_manager.memory_snapshots.initial.element_count = gui_manager.memory_snapshots.initial.element_count + 1 end gui_manager.memory_snapshots.initial.registry_size = #gui_manager.element_registry gui_manager.memory_snapshots.initial.top_elements = #Gui.topElements -- Perform layout to establish structure root_element:layoutChildren() -- Calculate hierarchy metrics local function calculateHierarchyMetrics(element, depth) depth = depth or 1 local metrics = { max_depth = depth, total_elements = 1, elements_by_level = {}, } metrics.elements_by_level[depth] = 1 for _, child in ipairs(element.children) do local child_metrics = calculateHierarchyMetrics(child, depth + 1) metrics.max_depth = math.max(metrics.max_depth, child_metrics.max_depth) metrics.total_elements = metrics.total_elements + child_metrics.total_elements for level, count in pairs(child_metrics.elements_by_level) do metrics.elements_by_level[level] = (metrics.elements_by_level[level] or 0) + count end end return metrics end gui_manager.hierarchy_metrics = calculateHierarchyMetrics(root_element) -- Test selective destruction (remove sidebar while keeping other elements) local sidebar_element = nil for element_id, element_data in pairs(gui_manager.element_registry) do if element_data.type == "sidebar" then sidebar_element = element_data.element break end end if sidebar_element then local sidebar_children_count = #sidebar_element.children local sidebar_parent = sidebar_element.parent local original_parent_children = sidebar_parent and #sidebar_parent.children or 0 -- Destroy sidebar and track the process local destruction_start = os.clock() sidebar_element:destroy() local destruction_time = os.clock() - destruction_start gui_manager.destruction_log.sidebar = { destruction_time = destruction_time, children_destroyed = sidebar_children_count, parent_children_after = sidebar_parent and #sidebar_parent.children or 0, } -- Verify destruction luaunit.assertNil(sidebar_element.parent, "Destroyed element should have no parent") luaunit.assertEquals(#sidebar_element.children, 0, "Destroyed element should have no children") if sidebar_parent then luaunit.assertEquals(#sidebar_parent.children, original_parent_children - 1, "Parent should have one fewer child after destruction") end end -- Test mass destruction and recreation cycle local destruction_cycles = 3 for cycle = 1, destruction_cycles do -- Take pre-destruction snapshot gui_manager.memory_snapshots["pre_cycle_" .. cycle] = { top_elements = #Gui.topElements, registry_size = #gui_manager.element_registry, } -- Destroy all GUI elements local destruction_start = os.clock() Gui.destroy() local destruction_time = os.clock() - destruction_start -- Take post-destruction snapshot gui_manager.memory_snapshots["post_destruction_" .. cycle] = { top_elements = #Gui.topElements, destruction_time = destruction_time, } -- Verify complete destruction luaunit.assertEquals(#Gui.topElements, 0, string.format("Cycle %d: All top elements should be destroyed", cycle)) -- Force garbage collection collectgarbage("collect") -- Recreate simplified structure for next cycle if cycle < destruction_cycles then local simple_structure = { { type = "test_container", children = { { type = "test_item", children = {} }, { type = "test_item", children = {} }, { type = "test_item", children = {} }, }, }, } local recreation_start = os.clock() createGUIHierarchy(simple_structure) local recreation_time = os.clock() - recreation_start gui_manager.memory_snapshots["post_recreation_" .. cycle] = { top_elements = #Gui.topElements, recreation_time = recreation_time, } end end -- Test complex element retrieval and manipulation local final_container = Gui.new({ width = 400, height = 300, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.VERTICAL, }) -- Create elements with specific IDs for retrieval testing local managed_elements = {} for i = 1, 10 do local element = Gui.new({ width = 350, height = 25, text = "Managed Element " .. i, textSize = 12, }) element.parent = final_container table.insert(final_container.children, element) managed_elements["element_" .. i] = element end -- Test bounds calculation for all elements for element_id, element in pairs(managed_elements) do local bounds = element:getBounds() luaunit.assertNotNil(bounds, string.format("%s: Bounds should be calculable", element_id)) luaunit.assertTrue(bounds.width > 0, string.format("%s: Bounds width should be positive", element_id)) luaunit.assertTrue(bounds.height > 0, string.format("%s: Bounds height should be positive", element_id)) luaunit.assertTrue(bounds.x >= 0, string.format("%s: Bounds x should be non-negative", element_id)) luaunit.assertTrue(bounds.y >= 0, string.format("%s: Bounds y should be non-negative", element_id)) end -- Test opacity management across hierarchy for element_id, element_pair in pairs(managed_elements) do -- Extract number from "element_N" key local num = tonumber(element_id:match("%d+")) if num and num % 2 == 0 then element_pair:updateOpacity(0.5) luaunit.assertEquals(element_pair.opacity, 0.5, "Even elements should have 0.5 opacity") end end -- Perform final layout final_container:layoutChildren() -- Verify final GUI state luaunit.assertTrue(#Gui.topElements >= 1, "Should have at least final container") luaunit.assertEquals(#final_container.children, 10, "Final container should have 10 managed elements") luaunit.assertTrue(gui_manager.hierarchy_metrics.max_depth >= 4, "Original hierarchy should have been deep") luaunit.assertTrue(gui_manager.hierarchy_metrics.total_elements >= 20, "Should have created substantial hierarchy") print( string.format( "GUI Management: %d elements, %d max depth, %d destruction cycles, %d managed elements", gui_manager.hierarchy_metrics.total_elements, gui_manager.hierarchy_metrics.max_depth, destruction_cycles, #managed_elements ) ) end -- ============================================ -- Test 15: Extreme Edge Cases and Error Resilience -- ============================================ function TestAuxiliaryFunctions:testExtremeEdgeCasesAndErrorResilience() print("\n=== Test 15: Extreme Edge Cases and Error Resilience ===") -- Test boundary conditions and error handling local edge_case_results = { color_tests = {}, text_tests = {}, animation_tests = {}, hierarchy_tests = {}, performance_tests = {}, } -- Extreme color value testing local extreme_color_tests = { { name = "negative_values", r = -1.0, g = -0.5, b = -2.0, a = -0.3 }, { name = "huge_values", r = 999.0, g = 1000.0, b = 50000.0, a = 100.0 }, { name = "zero_values", r = 0.0, g = 0.0, b = 0.0, a = 0.0 }, { name = "fractional_extremes", r = 0.0001, g = 0.9999, b = 0.00001, a = 0.99999 }, { name = "infinity_values", r = math.huge, g = -math.huge, b = 1 / 0, a = -1 / 0 }, } for _, test in ipairs(extreme_color_tests) do local success, result = pcall(function() local color = Color.new(test.r, test.g, test.b, test.a) return { created = true, r = color.r, g = color.g, b = color.b, a = color.a, rgba = { color:toRGBA() }, } end) edge_case_results.color_tests[test.name] = { success = success, result = result, expected_error = test.name == "infinity_values", } if test.name ~= "infinity_values" then luaunit.assertTrue(success, string.format("Color creation should handle %s", test.name)) end end -- Extreme hex color testing local extreme_hex_tests = { { hex = "", should_error = true }, { hex = "#", should_error = true }, { hex = "#FF", should_error = true }, { hex = "#FFFF", should_error = true }, { hex = "#FFFFFF", should_error = false }, { hex = "#FFFFFFFF", should_error = false }, { hex = "#FFFFFFFFFF", should_error = true }, { hex = "#GGGGGG", should_error = true }, { hex = "#123456789", should_error = true }, { hex = "FFFFFF", should_error = false }, -- without # { hex = "#ffffff", should_error = false }, -- lowercase { hex = "#FfFfFf", should_error = false }, -- mixed case } for _, test in ipairs(extreme_hex_tests) do local success, result = pcall(function() return Color.fromHex(test.hex) end) if test.should_error then luaunit.assertFalse(success, string.format("Hex '%s' should cause error", test.hex)) else luaunit.assertTrue(success, string.format("Hex '%s' should be valid", test.hex)) end end -- Extreme text and sizing tests local extreme_text_tests = { { name = "empty_string", text = "" }, { name = "single_char", text = "A" }, { name = "very_long", text = string.rep("Very long text that goes on and on and on. ", 100) }, { name = "unicode_heavy", text = "🎉🚀⭐️🌟💫✨🎨🎯🎪🎭🎬🎮🎲🎳🎸🎹🎺🎻🥁🎤🎧🎼🎵🎶", }, { name = "special_chars", text = "\n\t\r\b\f\v\\\"'`~!@#$%^&*()_+-=[]{}|;:,.<>?" }, { name = "mixed_newlines", text = "Line 1\nLine 2\r\nLine 3\rLine 4\n\nLine 6" }, { name = "numbers_symbols", text = "0123456789!@#$%^&*()_+-=[]{}|\\:;\";'<>?,./`~" }, } for _, test in ipairs(extreme_text_tests) do local element = Gui.new({ text = test.text, textSize = 14, width = 0, height = 0, }) local text_width = element:calculateTextWidth() local text_height = element:calculateTextHeight() local auto_width = element:calculateAutoWidth() local auto_height = element:calculateAutoHeight() edge_case_results.text_tests[test.name] = { text_width = text_width, text_height = text_height, auto_width = auto_width, auto_height = auto_height, char_count = string.len(test.text), } -- All calculations should return non-negative values luaunit.assertTrue(text_width >= 0, string.format("%s: Text width should be non-negative", test.name)) luaunit.assertTrue(text_height >= 0, string.format("%s: Text height should be non-negative", test.name)) luaunit.assertTrue(auto_width >= 0, string.format("%s: Auto width should be non-negative", test.name)) luaunit.assertTrue(auto_height >= 0, string.format("%s: Auto height should be non-negative", test.name)) -- Test text updates with extreme values local success = pcall(function() element:updateText(test.text, true) element:updateText(nil) -- Should preserve existing text element:updateText("") -- Should set to empty end) luaunit.assertTrue(success, string.format("%s: Text updates should not crash", test.name)) end -- Extreme animation testing local extreme_animation_tests = { { name = "zero_duration", duration = 0 }, { name = "negative_duration", duration = -1.0 }, { name = "huge_duration", duration = 999999.0 }, { name = "tiny_duration", duration = 0.001 }, { name = "infinity_duration", duration = math.huge }, } for _, test in ipairs(extreme_animation_tests) do local success, result = pcall(function() local animation = Gui.Animation.fade(test.duration, 1.0, 0.0) return { created = true, duration = animation.duration, interpolated = animation:interpolate(), } end) edge_case_results.animation_tests[test.name] = { success = success, result = result, } -- Most duration values should be handled gracefully if test.name ~= "infinity_duration" then luaunit.assertTrue(success, string.format("Animation with %s should be created", test.name)) end end -- Extreme hierarchy testing local max_depth = 20 local extreme_hierarchy_element = Gui.new({ width = 1000, height = 800 }) local current_parent = extreme_hierarchy_element -- Create extremely deep hierarchy for depth = 1, max_depth do local child = Gui.new({ width = math.max(50, 1000 - depth * 45), height = math.max(30, 800 - depth * 35), positioning = enums.Positioning.FLEX, flexDirection = depth % 2 == 0 and enums.FlexDirection.HORIZONTAL or enums.FlexDirection.VERTICAL, }) child.parent = current_parent table.insert(current_parent.children, child) current_parent = child end -- Test layout performance with extreme depth local deep_layout_start = os.clock() local layout_success = pcall(function() extreme_hierarchy_element:layoutChildren() end) local deep_layout_time = os.clock() - deep_layout_start edge_case_results.hierarchy_tests.extreme_depth = { success = layout_success, depth = max_depth, layout_time = deep_layout_time, } luaunit.assertTrue(layout_success, "Extremely deep hierarchy should layout without crashing") luaunit.assertTrue(deep_layout_time < 5.0, "Deep hierarchy layout should complete in reasonable time") -- Test extreme width hierarchy (many siblings) local wide_container = Gui.new({ width = 2000, height = 200, positioning = enums.Positioning.FLEX, flexDirection = enums.FlexDirection.HORIZONTAL, flexWrap = enums.FlexWrap.WRAP, gap = 2, }) local max_siblings = 500 for i = 1, max_siblings do local sibling = Gui.new({ width = 30, height = 25 }) sibling.parent = wide_container table.insert(wide_container.children, sibling) end local wide_layout_start = os.clock() local wide_layout_success = pcall(function() wide_container:layoutChildren() end) local wide_layout_time = os.clock() - wide_layout_start edge_case_results.hierarchy_tests.extreme_width = { success = wide_layout_success, siblings = max_siblings, layout_time = wide_layout_time, } luaunit.assertTrue(wide_layout_success, "Extremely wide hierarchy should layout without crashing") luaunit.assertTrue(wide_layout_time < 10.0, "Wide hierarchy layout should complete in reasonable time") -- Test massive cleanup operations local cleanup_elements = {} for i = 1, 1000 do local element = Gui.new({ width = 50, height = 30 }) table.insert(cleanup_elements, element) end local cleanup_start = os.clock() local cleanup_success = pcall(function() Gui.destroy() end) local cleanup_time = os.clock() - cleanup_start edge_case_results.performance_tests.massive_cleanup = { success = cleanup_success, elements = #cleanup_elements, cleanup_time = cleanup_time, } luaunit.assertTrue(cleanup_success, "Massive cleanup should complete without crashing") luaunit.assertTrue(cleanup_time < 5.0, "Massive cleanup should complete in reasonable time") luaunit.assertEquals(#Gui.topElements, 0, "All elements should be cleaned up") -- Test opacity boundary resilience local opacity_element = Gui.new({ width = 100, height = 50, opacity = 0.5 }) local extreme_opacities = { -999, -1, 0, 0.5, 1, 2, 999, math.huge, -math.huge } for _, opacity in ipairs(extreme_opacities) do local success = pcall(function() opacity_element:updateOpacity(opacity) end) luaunit.assertTrue(success, string.format("Opacity update with value %s should not crash", tostring(opacity))) end -- Summary of edge case testing local total_tests = 0 local successful_tests = 0 for category, tests in pairs(edge_case_results) do for test_name, result in pairs(tests) do total_tests = total_tests + 1 if result.success ~= false then successful_tests = successful_tests + 1 end end end print(string.format("Edge Case Testing: %d/%d tests handled gracefully (%.1f%%)", successful_tests, total_tests, (successful_tests / total_tests) * 100)) luaunit.assertTrue(successful_tests / total_tests > 0.8, "Should handle majority of edge cases gracefully") end luaunit.LuaUnit.run()