442 lines
10 KiB
Lua
442 lines
10 KiB
Lua
-- 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
|