more tests, fixed theme validation

This commit is contained in:
Michael Freno
2025-11-14 21:54:01 -05:00
parent 1dab1a197e
commit 48d44a1a11
12 changed files with 2380 additions and 169 deletions

View File

@@ -0,0 +1,441 @@
-- Integration tests for LayoutEngine.lua
-- Tests actual layout calculations with mock element structures
package.path = package.path .. ";./?.lua;./modules/?.lua"
-- Load love stub before anything else
require("testing.loveStub")
local luaunit = require("testing.luaunit")
local LayoutEngine = require("modules.LayoutEngine")
local Units = require("modules.Units")
local utils = require("modules.utils")
-- Mock dependencies
local mockContext = {
getScaleFactors = function()
return 1, 1
end,
baseScale = 1,
_cachedViewport = { width = 1920, height = 1080 },
}
local mockErrorHandler = {
error = function(module, msg) end,
warn = function(module, msg) end,
}
local mockGrid = {
layoutGridItems = function(element) end,
}
local deps = {
utils = utils,
Grid = mockGrid,
Units = Units,
Context = mockContext,
ErrorHandler = mockErrorHandler,
}
-- Helper function to create mock element
local function createMockElement(props)
return {
id = props.id or "mock",
x = props.x or 0,
y = props.y or 0,
width = props.width or 100,
height = props.height or 100,
absoluteX = props.absoluteX or 0,
absoluteY = props.absoluteY or 0,
marginLeft = props.marginLeft or 0,
marginTop = props.marginTop or 0,
marginRight = props.marginRight or 0,
marginBottom = props.marginBottom or 0,
children = props.children or {},
parent = props.parent,
isHidden = props.isHidden or false,
flexGrow = props.flexGrow or 0,
flexShrink = props.flexShrink or 1,
flexBasis = props.flexBasis or "auto",
alignSelf = props.alignSelf,
minWidth = props.minWidth,
maxWidth = props.maxWidth,
minHeight = props.minHeight,
maxHeight = props.maxHeight,
text = props.text,
_layout = nil,
recalculateUnits = function() end,
layoutChildren = function() end,
}
end
-- Test suite for layoutChildren with flex layout
TestLayoutChildrenFlex = {}
function TestLayoutChildrenFlex:test_layoutChildren_horizontal_flex_start()
local props = {
positioning = utils.enums.Positioning.FLEX,
flexDirection = utils.enums.FlexDirection.HORIZONTAL,
justifyContent = utils.enums.JustifyContent.FLEX_START,
alignItems = utils.enums.AlignItems.FLEX_START,
gap = 10,
}
local layout = LayoutEngine.new(props, deps)
local parent = createMockElement({
id = "parent",
width = 300,
height = 100,
})
local child1 = createMockElement({
id = "child1",
width = 50,
height = 30,
parent = parent,
})
local child2 = createMockElement({
id = "child2",
width = 60,
height = 40,
parent = parent,
})
parent.children = { child1, child2 }
parent._layout = layout
layout:initialize(parent)
layout:layoutChildren()
-- Verify layout was calculated (children positions should be set)
-- Child1 should be at (0, 0)
luaunit.assertEquals(child1.x, 0)
luaunit.assertEquals(child1.y, 0)
-- Child2 should be at (50 + gap, 0) = (60, 0)
luaunit.assertEquals(child2.x, 60)
luaunit.assertEquals(child2.y, 0)
end
function TestLayoutChildrenFlex:test_layoutChildren_vertical_flex_start()
local props = {
positioning = utils.enums.Positioning.FLEX,
flexDirection = utils.enums.FlexDirection.VERTICAL,
justifyContent = utils.enums.JustifyContent.FLEX_START,
alignItems = utils.enums.AlignItems.FLEX_START,
gap = 5,
}
local layout = LayoutEngine.new(props, deps)
local parent = createMockElement({
id = "parent",
width = 100,
height = 200,
})
local child1 = createMockElement({
id = "child1",
width = 50,
height = 30,
parent = parent,
})
local child2 = createMockElement({
id = "child2",
width = 60,
height = 40,
parent = parent,
})
parent.children = { child1, child2 }
parent._layout = layout
layout:initialize(parent)
layout:layoutChildren()
-- Verify layout was calculated
luaunit.assertEquals(child1.x, 0)
luaunit.assertEquals(child1.y, 0)
-- Child2 should be below child1 with gap
luaunit.assertEquals(child2.x, 0)
luaunit.assertEquals(child2.y, 35) -- 30 + 5
end
function TestLayoutChildrenFlex:test_layoutChildren_with_margins()
local props = {
positioning = utils.enums.Positioning.FLEX,
flexDirection = utils.enums.FlexDirection.HORIZONTAL,
justifyContent = utils.enums.JustifyContent.FLEX_START,
gap = 0,
}
local layout = LayoutEngine.new(props, deps)
local parent = createMockElement({
id = "parent",
width = 300,
height = 100,
})
local child1 = createMockElement({
id = "child1",
width = 50,
height = 30,
marginLeft = 10,
marginRight = 5,
parent = parent,
})
parent.children = { child1 }
parent._layout = layout
layout:initialize(parent)
layout:layoutChildren()
-- Child should be offset by left margin
luaunit.assertEquals(child1.x, 10)
end
function TestLayoutChildrenFlex:test_layoutChildren_with_hidden_children()
local props = {
positioning = utils.enums.Positioning.FLEX,
flexDirection = utils.enums.FlexDirection.HORIZONTAL,
gap = 10,
}
local layout = LayoutEngine.new(props, deps)
local parent = createMockElement({
id = "parent",
width = 300,
height = 100,
})
local child1 = createMockElement({
id = "child1",
width = 50,
height = 30,
parent = parent,
})
local child2 = createMockElement({
id = "child2",
width = 60,
height = 40,
isHidden = true,
parent = parent,
})
local child3 = createMockElement({
id = "child3",
width = 70,
height = 35,
parent = parent,
})
parent.children = { child1, child2, child3 }
parent._layout = layout
layout:initialize(parent)
layout:layoutChildren()
-- Child2 should be skipped, so child3 should be positioned after child1
luaunit.assertEquals(child1.x, 0)
luaunit.assertEquals(child3.x, 60) -- 50 + gap (10)
end
function TestLayoutChildrenFlex:test_layoutChildren_center()
local props = {
positioning = utils.enums.Positioning.FLEX,
flexDirection = utils.enums.FlexDirection.HORIZONTAL,
justifyContent = utils.enums.JustifyContent.CENTER,
alignItems = utils.enums.AlignItems.CENTER,
gap = 10,
}
local layout = LayoutEngine.new(props, deps)
local parent = createMockElement({
id = "parent",
width = 300,
height = 100,
})
local child1 = createMockElement({
id = "child1",
width = 50,
height = 30,
parent = parent,
})
local child2 = createMockElement({
id = "child2",
width = 60,
height = 40,
parent = parent,
})
parent.children = { child1, child2 }
parent._layout = layout
layout:initialize(parent)
layout:layoutChildren()
-- Children should be centered
-- Total width needed: 50 + 10 + 60 = 120
-- Remaining space: 300 - 120 = 180
-- Center offset: 180 / 2 = 90
luaunit.assertEquals(child1.x, 90)
luaunit.assertEquals(child2.x, 150) -- 90 + 50 + 10
-- Vertical centering
-- Child1 height 30, container 100, offset = (100-30)/2 = 35
luaunit.assertEquals(child1.y, 35)
-- Child2 height 40, offset = (100-40)/2 = 30
luaunit.assertEquals(child2.y, 30)
end
function TestLayoutChildrenFlex:test_layoutChildren_space_between()
local props = {
positioning = utils.enums.Positioning.FLEX,
flexDirection = utils.enums.FlexDirection.HORIZONTAL,
justifyContent = utils.enums.JustifyContent.SPACE_BETWEEN,
gap = 0,
}
local layout = LayoutEngine.new(props, deps)
local parent = createMockElement({
id = "parent",
width = 300,
height = 100,
})
local child1 = createMockElement({
id = "child1",
width = 50,
height = 30,
parent = parent,
})
local child2 = createMockElement({
id = "child2",
width = 60,
height = 40,
parent = parent,
})
parent.children = { child1, child2 }
parent._layout = layout
layout:initialize(parent)
layout:layoutChildren()
-- First child at start
luaunit.assertEquals(child1.x, 0)
-- Last child at end: 300 - 60 = 240
luaunit.assertEquals(child2.x, 240)
end
-- Test suite for applyPositioningOffsets
TestApplyPositioningOffsets = {}
function TestApplyPositioningOffsets:test_applyPositioningOffsets_relative()
local props = {
positioning = utils.enums.Positioning.FLEX,
}
local layout = LayoutEngine.new(props, deps)
local parent = createMockElement({
id = "parent",
x = 100,
y = 50,
})
local child = createMockElement({
id = "child",
x = 20,
y = 30,
parent = parent,
})
layout:initialize(parent)
layout:applyPositioningOffsets(child)
-- Relative positioning: child keeps its x, y
luaunit.assertEquals(child.x, 20)
luaunit.assertEquals(child.y, 30)
end
function TestApplyPositioningOffsets:test_applyPositioningOffsets_absolute()
local props = {
positioning = utils.enums.Positioning.ABSOLUTE,
}
local layout = LayoutEngine.new(props, deps)
local parent = createMockElement({
id = "parent",
absoluteX = 100,
absoluteY = 50,
width = 300,
height = 200,
})
local child = createMockElement({
id = "child",
x = 20,
y = 30,
parent = parent,
})
layout:initialize(parent)
layout:applyPositioningOffsets(child)
-- Absolute positioning: child.x, child.y are relative to parent
luaunit.assertEquals(child.absoluteX, 120) -- 100 + 20
luaunit.assertEquals(child.absoluteY, 80) -- 50 + 30
end
-- Test suite for grid layout
TestLayoutChildrenGrid = {}
function TestLayoutChildrenGrid:test_layoutChildren_grid_delegates_to_Grid()
local gridCalled = false
local mockGridForTest = {
layoutGridItems = function(element)
gridCalled = true
end,
}
local depsWithMockGrid = {
utils = utils,
Grid = mockGridForTest,
Units = Units,
Context = mockContext,
ErrorHandler = mockErrorHandler,
}
local props = {
positioning = utils.enums.Positioning.GRID,
gridRows = 2,
gridColumns = 2,
}
local layout = LayoutEngine.new(props, depsWithMockGrid)
local parent = createMockElement({
id = "parent",
width = 300,
height = 200,
})
parent._layout = layout
layout:initialize(parent)
layout:layoutChildren()
-- Verify Grid.layoutGridItems was called
luaunit.assertTrue(gridCalled)
end
-- Run tests if this file is executed directly
if not _G.RUNNING_ALL_TESTS then
os.exit(luaunit.LuaUnit.run())
end