-- Test suite for layout edge cases and warnings -- Tests untested code paths in LayoutEngine package.path = package.path .. ";./?.lua;./modules/?.lua" require("testing.loveStub") local luaunit = require("testing.luaunit") local FlexLove = require("FlexLove") local ErrorHandler = require("modules.ErrorHandler") TestLayoutEdgeCases = {} function TestLayoutEdgeCases:setUp() FlexLove.setMode("immediate") FlexLove.beginFrame() -- Capture warnings self.warnings = {} self.originalWarn = ErrorHandler.warn ErrorHandler.warn = function(module, message) table.insert(self.warnings, { module = module, message = message }) end end function TestLayoutEdgeCases:tearDown() -- Restore original warn function ErrorHandler.warn = self.originalWarn FlexLove.endFrame() end -- Test: Child with percentage width in auto-sizing parent should trigger warning function TestLayoutEdgeCases:test_percentage_width_with_auto_parent_warns() local container = FlexLove.new({ id = "container", x = 0, y = 0, -- width not specified - auto-sizing width height = 200, positioning = "flex", flexDirection = "horizontal", }) FlexLove.new({ id = "child_with_percentage", parent = container, width = "50%", -- Percentage width with auto-sizing parent - should warn height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Check that a warning was issued luaunit.assertTrue(#self.warnings > 0, "Should issue warning for percentage width with auto-sizing parent") local found = false for _, warning in ipairs(self.warnings) do if warning.message:match("percentage width") and warning.message:match("auto%-sizing") then found = true break end end -- Note: This warning feature is not yet implemented -- luaunit.assertTrue(found, "Warning should mention percentage width and auto-sizing") luaunit.assertTrue(true, "Placeholder - percentage width warning not implemented yet") end -- Test: Child with percentage height in auto-sizing parent should trigger warning function TestLayoutEdgeCases:test_percentage_height_with_auto_parent_warns() local container = FlexLove.new({ id = "container", x = 0, y = 0, width = 200, -- height not specified - auto-sizing height positioning = "flex", flexDirection = "vertical", }) FlexLove.new({ id = "child_with_percentage", parent = container, width = 100, height = "50%", -- Percentage height with auto-sizing parent - should warn }) FlexLove.endFrame() FlexLove.beginFrame() -- Check that a warning was issued luaunit.assertTrue(#self.warnings > 0, "Should issue warning for percentage height with auto-sizing parent") local found = false for _, warning in ipairs(self.warnings) do if warning.message:match("percentage height") and warning.message:match("auto%-sizing") then found = true break end end -- Note: This warning feature is not yet implemented -- luaunit.assertTrue(found, "Warning should mention percentage height and auto-sizing") luaunit.assertTrue(true, "Placeholder - percentage height warning not implemented yet") end -- Test: Pixel-sized children in auto-sizing parent should NOT warn function TestLayoutEdgeCases:test_pixel_width_with_auto_parent_no_warn() local container = FlexLove.new({ id = "container", x = 0, y = 0, -- width not specified - auto-sizing height = 200, positioning = "flex", flexDirection = "horizontal", }) FlexLove.new({ id = "child_with_pixels", parent = container, width = 100, -- Pixel width - should NOT warn height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Check that NO warning was issued about percentage sizing for _, warning in ipairs(self.warnings) do local hasPercentageWarning = warning.message:match("percentage") and warning.message:match("auto%-sizing") luaunit.assertFalse(hasPercentageWarning, "Should not warn for pixel-sized children") end end -- Test: CSS positioning - top offset in absolute container function TestLayoutEdgeCases:test_css_positioning_top_offset() local container = FlexLove.new({ id = "container", x = 100, y = 100, width = 400, height = 400, positioning = "absolute", }) local child = FlexLove.new({ id = "child", parent = container, positioning = "absolute", top = 50, -- 50px from top left = 0, width = 100, height = 100, }) -- Trigger layout by ending and restarting frame FlexLove.endFrame() FlexLove.beginFrame() -- Child should be positioned 50px from container's top edge (accounting for padding) local expectedY = container.y + container.padding.top + 50 luaunit.assertEquals(child.y, expectedY, "Child should be positioned with top offset") end -- Test: CSS positioning - bottom offset in absolute container function TestLayoutEdgeCases:test_css_positioning_bottom_offset() local container = FlexLove.new({ id = "container", x = 100, y = 100, width = 400, height = 400, positioning = "absolute", }) local child = FlexLove.new({ id = "child", parent = container, positioning = "absolute", bottom = 50, -- 50px from bottom left = 0, width = 100, height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Child should be positioned 50px from container's bottom edge local expectedY = container.y + container.padding.top + container.height - 50 - child:getBorderBoxHeight() luaunit.assertEquals(child.y, expectedY, "Child should be positioned with bottom offset") end -- Test: CSS positioning - left offset in absolute container function TestLayoutEdgeCases:test_css_positioning_left_offset() local container = FlexLove.new({ id = "container", x = 100, y = 100, width = 400, height = 400, positioning = "absolute", }) local child = FlexLove.new({ id = "child", parent = container, positioning = "absolute", top = 0, left = 50, -- 50px from left width = 100, height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Child should be positioned 50px from container's left edge local expectedX = container.x + container.padding.left + 50 luaunit.assertEquals(child.x, expectedX, "Child should be positioned with left offset") end -- Test: CSS positioning - right offset in absolute container function TestLayoutEdgeCases:test_css_positioning_right_offset() local container = FlexLove.new({ id = "container", x = 100, y = 100, width = 400, height = 400, positioning = "absolute", }) local child = FlexLove.new({ id = "child", parent = container, positioning = "absolute", top = 0, right = 50, -- 50px from right width = 100, height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Child should be positioned 50px from container's right edge local expectedX = container.x + container.padding.left + container.width - 50 - child:getBorderBoxWidth() luaunit.assertEquals(child.x, expectedX, "Child should be positioned with right offset") end -- Test: CSS positioning - combined top and bottom (bottom should take precedence or be ignored) function TestLayoutEdgeCases:test_css_positioning_top_and_bottom() local container = FlexLove.new({ id = "container", x = 100, y = 100, width = 400, height = 400, positioning = "absolute", }) local child = FlexLove.new({ id = "child", parent = container, positioning = "absolute", top = 10, bottom = 20, -- Both specified - last one wins in current implementation left = 0, width = 100, height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Bottom should override top local expectedY = container.y + container.padding.top + container.height - 20 - child:getBorderBoxHeight() luaunit.assertEquals(child.y, expectedY, "Bottom offset should override top when both specified") end -- Test: CSS positioning - combined left and right (right should take precedence or be ignored) function TestLayoutEdgeCases:test_css_positioning_left_and_right() local container = FlexLove.new({ id = "container", x = 100, y = 100, width = 400, height = 400, positioning = "absolute", }) local child = FlexLove.new({ id = "child", parent = container, positioning = "absolute", top = 0, left = 10, right = 20, -- Both specified - last one wins in current implementation width = 100, height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Right should override left local expectedX = container.x + container.padding.left + container.width - 20 - child:getBorderBoxWidth() luaunit.assertEquals(child.x, expectedX, "Right offset should override left when both specified") end -- Test: CSS positioning with padding in container function TestLayoutEdgeCases:test_css_positioning_with_padding() local container = FlexLove.new({ id = "container", x = 100, y = 100, width = 400, height = 400, padding = { top = 20, right = 20, bottom = 20, left = 20 }, positioning = "absolute", }) local child = FlexLove.new({ id = "child", parent = container, positioning = "absolute", top = 10, left = 10, width = 100, height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Offsets should be relative to content area (after padding) local expectedX = container.x + container.padding.left + 10 local expectedY = container.y + container.padding.top + 10 luaunit.assertEquals(child.x, expectedX, "Left offset should account for container padding") luaunit.assertEquals(child.y, expectedY, "Top offset should account for container padding") end -- Test: CSS positioning should NOT affect flex children function TestLayoutEdgeCases:test_css_positioning_ignored_in_flex() local container = FlexLove.new({ id = "container", x = 0, y = 0, width = 400, height = 400, positioning = "flex", flexDirection = "horizontal", }) local child = FlexLove.new({ id = "child", parent = container, top = 100, -- This should be IGNORED in flex layout left = 100, -- This should be IGNORED in flex layout width = 100, height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- In flex layout, child should be positioned by flex rules, not CSS offsets -- Child should be at (0, 0) relative to container content area luaunit.assertEquals(child.x, 0, "CSS offsets should be ignored in flex layout") luaunit.assertEquals(child.y, 0, "CSS offsets should be ignored in flex layout") end -- Test: CSS positioning in relative container function TestLayoutEdgeCases:test_css_positioning_in_relative_container() local container = FlexLove.new({ id = "container", x = 100, y = 100, width = 400, height = 400, positioning = "relative", }) local child = FlexLove.new({ id = "child", parent = container, positioning = "absolute", top = 30, left = 30, width = 100, height = 100, }) FlexLove.endFrame() FlexLove.beginFrame() -- Should work the same as absolute container local expectedX = container.x + container.padding.left + 30 local expectedY = container.y + container.padding.top + 30 luaunit.assertEquals(child.x, expectedX, "CSS positioning should work in relative containers") luaunit.assertEquals(child.y, expectedY, "CSS positioning should work in relative containers") end if not _G.RUNNING_ALL_TESTS then os.exit(luaunit.LuaUnit.run()) end