This commit is contained in:
Michael Freno
2025-09-18 18:27:57 -04:00
parent d869582b37
commit d5f85e82d1
14 changed files with 2511 additions and 17 deletions

View File

@@ -596,21 +596,21 @@ function Element:layoutChildren()
goto continue
end
if self.flexDirection == FlexDirection.VERTICAL then
-- Position relative to parent origin
child.x = self.x + (self.margin.left or 0)
child.y = self.y + currentPos
if self.flexDirection == FlexDirection.VERTICAL then
-- Position relative to parent origin
child.x = self.x + (self.padding.left or 0)
child.y = self.y + currentPos + (self.padding.top or 0)
-- Apply alignment to vertical axis (alignItems)
if self.alignItems == AlignItems.FLEX_START then
-- nothing
elseif self.alignItems == AlignItems.CENTER then
child.x = self.x + (self.width - (child.width or 0)) / 2
elseif self.alignItems == AlignItems.FLEX_END then
child.x = self.x + self.width - (child.width or 0)
elseif self.alignItems == AlignItems.STRETCH then
child.width = self.width
end
-- Apply alignment to vertical axis (alignItems)
if self.alignItems == AlignItems.FLEX_START then
-- nothing
elseif self.alignItems == AlignItems.CENTER then
child.x = self.x + ((self.width - (child.width or 0)) / 2)
elseif self.alignItems == AlignItems.FLEX_END then
child.x = self.x + self.width - (child.width or 0)
elseif self.alignItems == AlignItems.STRETCH then
child.width = self.width
end
-- Apply self alignment to cross axis (alignSelf)
local effectiveAlignSelf = child.alignSelf
@@ -650,8 +650,8 @@ function Element:layoutChildren()
currentPos = currentPos + (child.height or 0) + self.gap + (self.margin.top or 0) + (self.margin.bottom or 0)
else
-- Horizontal layout: position relative to parent origin
child.x = self.x + currentPos + (self.margin.left or 0)
child.y = self.y + (self.margin.top or 0)
child.x = self.x + self.padding.left + currentPos
child.y = self.y + self.padding.top
-- Determine effective alignment - alignSelf takes precedence over alignItems
local effectiveAlign = child.alignSelf
@@ -663,7 +663,8 @@ function Element:layoutChildren()
if effectiveAlign == AlignItems.FLEX_START then
-- Keep the margin.top position (already applied)
elseif effectiveAlign == AlignItems.CENTER then
child.y = self.y + (self.height - (child.height or 0)) / 2
-- Account for parent's margin when centering vertically
child.y = self.y + ((self.height - (child.height or 0)) / 2)
elseif effectiveAlign == AlignItems.FLEX_END then
child.y = self.y + self.height - (child.height or 0)
elseif effectiveAlign == AlignItems.STRETCH then

View File

@@ -0,0 +1,142 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
-- Create test cases
TestAbsolutePositioning = {}
function TestAbsolutePositioning:setUp()
-- Reset layout engine before each test
self.GUI = FlexLove.GUI
end
function TestAbsolutePositioning:testBasicAbsolutePositioning()
-- Test basic absolute positioning - similar to CSS position: absolute
local element = self.GUI.new({
x = 100,
y = 150,
w = 200,
h = 100,
positioning = FlexLove.enums.Positioning.ABSOLUTE,
})
luaunit.assertEquals(element.x, 100)
luaunit.assertEquals(element.y, 150)
luaunit.assertEquals(element.width, 200)
luaunit.assertEquals(element.height, 100)
luaunit.assertEquals(element.positioning, FlexLove.enums.Positioning.ABSOLUTE)
end
function TestAbsolutePositioning:testAbsolutePositioningWithOffsets()
-- Test absolute positioning with top/left/right/bottom - like CSS absolute positioning
local container = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 500,
})
local child = self.GUI.new({
parent = container,
x = 50,
y = 75,
w = 100,
h = 50,
positioning = FlexLove.enums.Positioning.ABSOLUTE,
})
-- Element should maintain its absolute position
luaunit.assertEquals(child.x, 50)
luaunit.assertEquals(child.y, 75)
luaunit.assertEquals(child.width, 100)
luaunit.assertEquals(child.height, 50)
end
function TestAbsolutePositioning:testAbsolutePositioningInContainer()
-- Test absolute positioning within a container - similar to CSS relative container
local container = self.GUI.new({
x = 100,
y = 100,
w = 500,
h = 500,
})
local child = self.GUI.new({
parent = container,
x = 50,
y = 50,
w = 100,
h = 100,
positioning = FlexLove.enums.Positioning.ABSOLUTE,
})
-- Child should keep its absolute position
luaunit.assertEquals(child.x, 50)
luaunit.assertEquals(child.y, 50)
luaunit.assertEquals(child.width, 100)
luaunit.assertEquals(child.height, 100)
end
function TestAbsolutePositioning:testAbsolutePositioningWithRightBottom()
-- Test absolute positioning with right/bottom properties - like CSS
local container = self.GUI.new({
x = 0,
y = 0,
w = 1000,
h = 800,
})
local child = self.GUI.new({
parent = container,
x = 850,
y = 650,
w = 100,
h = 100,
positioning = FlexLove.enums.Positioning.ABSOLUTE,
})
-- Child should maintain its position from right/bottom edges
luaunit.assertEquals(child.x, 850)
luaunit.assertEquals(child.y, 650)
luaunit.assertEquals(child.width, 100)
luaunit.assertEquals(child.height, 100)
end
function TestAbsolutePositioning:testAbsolutePositioningZIndex()
-- Test z-index with absolute positioning - like CSS z-index
local container = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 500,
})
local child1 = self.GUI.new({
parent = container,
x = 0,
y = 0,
w = 100,
h = 100,
z = 1,
positioning = FlexLove.enums.Positioning.ABSOLUTE,
})
local child2 = self.GUI.new({
parent = container,
x = 50,
y = 50,
w = 100,
h = 100,
z = 2,
positioning = FlexLove.enums.Positioning.ABSOLUTE,
})
-- Elements should maintain their z-index order
luaunit.assertEquals(child1.z, 1)
luaunit.assertEquals(child2.z, 2)
luaunit.assertTrue(child1.z < child2.z)
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,217 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
local FlexDirection = FlexLove.enums.FlexDirection
local Positioning = FlexLove.enums.Positioning
local JustifyContent = FlexLove.enums.JustifyContent
local AlignItems = FlexLove.enums.AlignItems
-- Create test cases
TestFlexDirection = {}
function TestFlexDirection:setUp()
self.GUI = FlexLove.GUI
end
function TestFlexDirection:testHorizontalFlexBasic()
-- Test basic horizontal flex layout - like CSS flex-direction: row
local container = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
})
-- Add three children with equal widths
local child1 = self.GUI.new({
parent = container,
w = 100,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 100,
h = 50,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 100,
h = 50,
positioning = Positioning.FLEX,
})
-- Elements should be positioned horizontally with default gap of 10
luaunit.assertEquals(child1.x, 0) -- First child starts at container's x
luaunit.assertEquals(child2.x, 110) -- Second child starts after first child + gap
luaunit.assertEquals(child3.x, 220) -- Third child starts after second child + gap
-- All children should maintain their original widths
luaunit.assertEquals(child1.width, 100)
luaunit.assertEquals(child2.width, 100)
luaunit.assertEquals(child3.width, 100)
end
function TestFlexDirection:testHorizontalFlexWithJustifyContentFlexStart()
local container = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.FLEX_START,
})
-- Add three children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Children should be positioned at the start with default gap
luaunit.assertEquals(child1.x, 0)
luaunit.assertEquals(child2.x, 60)
end
function TestFlexDirection:testHorizontalFlexWithJustifyContentCenter()
local container = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.CENTER,
})
-- Add three children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Children should be centered in container
-- Total width used: 50 + 10 + 50 = 110px
-- Remaining space: 500 - 110 = 390px
-- Space before first child: 390/2 = 195px
luaunit.assertEquals(child1.x, 195)
luaunit.assertEquals(child2.x, 255) -- 195 + 50 + 10
end
function TestFlexDirection:testHorizontalFlexWithJustifyContentFlexEnd()
local container = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.FLEX_END,
})
-- Add two children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Children should be positioned at the end
-- Total width used: 50 + 10 + 50 = 110px
-- First child should start at: 500 - 110 = 390px
luaunit.assertEquals(child1.x, 390)
luaunit.assertEquals(child2.x, 450) -- 390 + 50 + 10
end
function TestFlexDirection:testHorizontalFlexWithJustifyContentSpaceBetween()
local container = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.SPACE_BETWEEN,
})
-- Add two children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Children should be positioned at the edges
luaunit.assertEquals(child1.x, 0)
luaunit.assertEquals(child2.x, 450)
end
function TestFlexDirection:testHorizontalFlexWithAlignItemsCenter()
local container = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignItems = AlignItems.CENTER,
})
-- Add a child shorter than the container
local child = self.GUI.new({
parent = container,
w = 50,
h = 50, -- Container is 100px high, child is 50px
positioning = Positioning.FLEX,
})
-- Child should be vertically centered
-- Container height: 100px, Child height: 50px
-- Expected y: (100 - 50) / 2 = 25px
luaunit.assertEquals(child.y, 25)
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,175 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
local FlexDirection = FlexLove.enums.FlexDirection
local Positioning = FlexLove.enums.Positioning
local JustifyContent = FlexLove.enums.JustifyContent
local AlignItems = FlexLove.enums.AlignItems
-- Create test cases
TestVerticalFlexDirection = {}
function TestVerticalFlexDirection:setUp()
self.GUI = FlexLove.GUI
end
function TestVerticalFlexDirection:testVerticalFlexBasic()
-- Test basic vertical flex layout - like CSS flex-direction: column
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 500,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
})
-- Add three children with equal heights
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 100,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 100,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 50,
h = 100,
positioning = Positioning.FLEX,
})
-- Elements should be positioned vertically with default gap of 10
luaunit.assertEquals(child1.y, 0)
luaunit.assertEquals(child2.y, 110)
luaunit.assertEquals(child3.y, 220)
-- All children should maintain their original heights
luaunit.assertEquals(child1.height, 100)
luaunit.assertEquals(child2.height, 100)
luaunit.assertEquals(child3.height, 100)
end
function TestVerticalFlexDirection:testVerticalFlexWithJustifyContentFlexStart()
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 500,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
justifyContent = JustifyContent.FLEX_START,
})
-- Add two children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Children should be positioned at the start with default gap
luaunit.assertEquals(child1.y, 0)
luaunit.assertEquals(child2.y, 60)
end
function TestVerticalFlexDirection:testVerticalFlexWithJustifyContentCenter()
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 500,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
justifyContent = JustifyContent.CENTER,
})
-- Add two children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Children should be centered in container
-- Total height used: 50 + 10 + 50 = 110px
-- Remaining space: 500 - 110 = 390px
-- Space before first child: 390/2 = 195px
luaunit.assertEquals(child1.y, 195)
luaunit.assertEquals(child2.y, 255)
end
function TestVerticalFlexDirection:testVerticalFlexWithAlignItemsCenter()
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 500,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
alignItems = AlignItems.CENTER,
})
-- Add a child narrower than the container
local child = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Child should be horizontally centered
-- Container width: 100px, Child width: 50px
-- Expected x: (100 - 50) / 2 = 25px
luaunit.assertEquals(child.x, 25)
end
function TestVerticalFlexDirection:testVerticalFlexWithAlignItemsStretch()
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 500,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
alignItems = AlignItems.STRETCH,
})
-- Add a child without explicit width
local child = self.GUI.new({
parent = container,
h = 50,
positioning = Positioning.FLEX,
})
-- Child should stretch to container width
luaunit.assertEquals(child.width, 100)
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,206 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
local FlexDirection = FlexLove.enums.FlexDirection
local Positioning = FlexLove.enums.Positioning
local JustifyContent = FlexLove.enums.JustifyContent
-- Create test cases
TestJustifyContent = {}
function TestJustifyContent:setUp()
self.GUI = FlexLove.GUI
end
function TestJustifyContent:testJustifyContentSpaceEvenly()
-- Test space-evenly distribution in horizontal layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.SPACE_EVENLY,
})
-- Add three children of equal width
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Calculate expected positions
-- Total width of children: 150px (3 * 50px)
-- Remaining space: 150px (300px - 150px)
-- Space between and around items: 150px / 4 = 37.5px
luaunit.assertEquals(child1.x, 37) -- First space
luaunit.assertEquals(child2.x, 125) -- First space + width + second space
luaunit.assertEquals(child3.x, 212) -- Previous + width + third space
end
function TestJustifyContent:testJustifyContentSpaceAround()
-- Test space-around distribution
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.SPACE_AROUND,
})
-- Add two children with equal widths
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Calculate expected positions
-- Total width of children: 100px (2 * 50px)
-- Remaining space: 200px (300px - 100px)
-- Space around each item: 200px / 4 = 50px
-- First item gets 50px margin, second gets 150px (50px * 3) margin
luaunit.assertEquals(child1.x, 50)
luaunit.assertEquals(child2.x, 200)
end
function TestJustifyContent:testJustifyContentSpaceBetween()
-- Test space-between distribution
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.SPACE_BETWEEN,
})
-- Add three children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Calculate expected positions
-- Total width of children: 150px (3 * 50px)
-- Remaining space: 150px (300px - 150px)
-- Space between items: 75px (150px / 2)
luaunit.assertEquals(child1.x, 0) -- First child at start
luaunit.assertEquals(child2.x, 125) -- After first gap
luaunit.assertEquals(child3.x, 250) -- After second gap
end
function TestJustifyContent:testJustifyContentFlexStart()
-- Test flex-start alignment
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.FLEX_START,
})
-- Add two children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Children should be at the start with default gap
luaunit.assertEquals(child1.x, 0) -- First child at start
luaunit.assertEquals(child2.x, 60) -- After first child + gap
end
function TestJustifyContent:testJustifyContentFlexEnd()
-- Test flex-end alignment
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.FLEX_END,
})
-- Add two children
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Children should be at the end with default gap
-- Total width needed: 110px (50px + 10px + 50px)
-- Start position: 300px - 110px = 190px
luaunit.assertEquals(child1.x, 190)
luaunit.assertEquals(child2.x, 250)
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,168 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
local FlexDirection = FlexLove.enums.FlexDirection
local Positioning = FlexLove.enums.Positioning
local AlignItems = FlexLove.enums.AlignItems
-- Create test cases
TestAlignItems = {}
function TestAlignItems:setUp()
self.GUI = FlexLove.GUI
end
function TestAlignItems:testAlignItemsStretchHorizontal()
-- Test stretch alignment in horizontal layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignItems = AlignItems.STRETCH,
})
-- Add child without explicit height
local child = self.GUI.new({
parent = container,
w = 50,
positioning = Positioning.FLEX,
})
-- Child should stretch to container height
luaunit.assertEquals(child.height, container.height)
end
function TestAlignItems:testAlignItemsStretchVertical()
-- Test stretch alignment in vertical layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
alignItems = AlignItems.STRETCH,
})
-- Add child without explicit width
local child = self.GUI.new({
parent = container,
h = 50,
positioning = Positioning.FLEX,
})
-- Child should stretch to container width
luaunit.assertEquals(child.width, container.width)
end
function TestAlignItems:testAlignItemsCenterHorizontal()
-- Test center alignment in horizontal layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignItems = AlignItems.CENTER,
})
-- Add child shorter than container
local child = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Child should be vertically centered
-- Container height: 100px, Child height: 50px
-- Expected y: (100 - 50) / 2 = 25px
luaunit.assertEquals(child.y, 25)
end
function TestAlignItems:testAlignItemsCenterVertical()
-- Test center alignment in vertical layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
alignItems = AlignItems.CENTER,
})
-- Add child narrower than container
local child = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Child should be horizontally centered
-- Container width: 100px, Child width: 50px
-- Expected x: (100 - 50) / 2 = 25px
luaunit.assertEquals(child.x, 25)
end
function TestAlignItems:testAlignItemsFlexStart()
-- Test flex-start alignment in horizontal layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignItems = AlignItems.FLEX_START,
})
-- Add child shorter than container
local child = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Child should be at the top
luaunit.assertEquals(child.y, 0)
end
function TestAlignItems:testAlignItemsFlexEnd()
-- Test flex-end alignment in horizontal layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignItems = AlignItems.FLEX_END,
})
-- Add child shorter than container
local child = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Child should be at the bottom
-- Container height: 100px, Child height: 50px
-- Expected y: 100px - 50px = 50px
luaunit.assertEquals(child.y, 50)
end
-- Run the test suite
os.exit(luaunit.LuaUnit.run())

View File

@@ -0,0 +1,234 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
local FlexDirection = FlexLove.enums.FlexDirection
local Positioning = FlexLove.enums.Positioning
local AlignContent = FlexLove.enums.AlignContent
-- Create test cases
TestFlexWrap = {}
function TestFlexWrap:setUp()
self.GUI = FlexLove.GUI
end
function TestFlexWrap:testFlexWrapHorizontal()
-- Test flex wrap in horizontal layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignContent = AlignContent.FLEX_START,
})
-- Add three children that exceed container width
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- First line: child1 and child2 (with 10px gap)
-- Second line: child3
luaunit.assertEquals(child1.x, 0)
luaunit.assertEquals(child1.y, 0)
luaunit.assertEquals(child2.x, 60)
luaunit.assertEquals(child2.y, 0)
luaunit.assertEquals(child3.x, 0)
luaunit.assertEquals(child3.y, 60)
end
function TestFlexWrap:testFlexWrapVertical()
-- Test flex wrap in vertical layout
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
alignContent = AlignContent.FLEX_START,
})
-- Add three children that exceed container height
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- First column: child1 and child2 (with 10px gap)
-- Second column: child3
luaunit.assertEquals(child1.x, 0)
luaunit.assertEquals(child1.y, 0)
luaunit.assertEquals(child2.x, 0)
luaunit.assertEquals(child2.y, 60)
luaunit.assertEquals(child3.x, 60)
luaunit.assertEquals(child3.y, 0)
end
function TestFlexWrap:testFlexWrapWithAlignContentCenter()
-- Test align-content center with flex wrap
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignContent = AlignContent.CENTER,
})
-- Add three children that create two rows
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Total height used: 110px (two rows of 50px + 10px gap)
-- Remaining space: 190px (300px - 110px)
-- Space before first row: 95px (190px / 2)
luaunit.assertEquals(child1.y, 95)
luaunit.assertEquals(child2.y, 95)
luaunit.assertEquals(child3.y, 155) -- 95px + 50px + 10px gap
end
function TestFlexWrap:testFlexWrapWithAlignContentSpaceBetween()
-- Test align-content space-between with flex wrap
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignContent = AlignContent.SPACE_BETWEEN,
})
-- Add three children that create two rows
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- First row at top (y = 0)
-- Second row at bottom (y = 250)
luaunit.assertEquals(child1.y, 0)
luaunit.assertEquals(child2.y, 0)
luaunit.assertEquals(child3.y, 250)
end
function TestFlexWrap:testFlexWrapWithAlignContentSpaceAround()
-- Test align-content space-around with flex wrap
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignContent = AlignContent.SPACE_AROUND,
})
-- Add three children that create two rows
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child3 = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Space around calculation:
-- Total height of content: 110px (two rows of 50px + 10px gap)
-- Remaining space: 190px
-- Space per unit: 63.33px (190px / 3)
-- First row: 63.33px (one unit of space)
-- Second row: 190px (three units of space)
luaunit.assertEquals(child1.y, 63)
luaunit.assertEquals(child2.y, 63)
luaunit.assertEquals(child3.y, 190)
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,267 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
local FlexDirection = FlexLove.enums.FlexDirection
local Positioning = FlexLove.enums.Positioning
local JustifyContent = FlexLove.enums.JustifyContent
local AlignItems = FlexLove.enums.AlignItems
-- Create test cases
TestLayoutValidation = {}
function TestLayoutValidation:setUp()
self.GUI = FlexLove.GUI
end
function TestLayoutValidation:testNestedFlexContainers()
-- Test nested flex containers behave correctly
local outerContainer = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
})
local innerContainer1 = self.GUI.new({
parent = outerContainer,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.SPACE_BETWEEN,
})
local innerContainer2 = self.GUI.new({
parent = outerContainer,
w = 300,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.CENTER,
})
-- Add children to inner container 1
local child1 = self.GUI.new({
parent = innerContainer1,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = innerContainer1,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Add child to inner container 2
local child3 = self.GUI.new({
parent = innerContainer2,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Verify outer container layout
luaunit.assertEquals(innerContainer1.y, 0)
luaunit.assertEquals(innerContainer2.y, 110) -- 100 + 10 gap
-- Verify inner container 1 layout (space-between)
luaunit.assertEquals(child1.x, 0)
luaunit.assertEquals(child2.x, 250)
-- Verify inner container 2 layout (center)
luaunit.assertEquals(child3.x, 125) -- (300 - 50) / 2
-- Test container references
luaunit.assertEquals(#innerContainer1.children, 2)
luaunit.assertEquals(#innerContainer2.children, 1)
luaunit.assertEquals(innerContainer1.children[1], child1)
luaunit.assertEquals(innerContainer1.children[2], child2)
luaunit.assertEquals(innerContainer2.children[1], child3)
end
function TestLayoutValidation:testMixedPositioning()
-- Test mixing absolute and flex positioning
local container = self.GUI.new({
x = 0,
y = 0,
w = 300,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
})
-- Add flex positioned child
local flexChild = self.GUI.new({
parent = container,
w = 100,
h = 50,
positioning = Positioning.FLEX,
})
-- Add absolute positioned child
local absoluteChild = self.GUI.new({
parent = container,
x = 150,
y = 150,
w = 100,
h = 50,
positioning = Positioning.ABSOLUTE,
})
-- Add another flex positioned child
local flexChild2 = self.GUI.new({
parent = container,
w = 100,
h = 50,
positioning = Positioning.FLEX,
})
-- Verify flex children positions
luaunit.assertEquals(flexChild.y, 0)
luaunit.assertEquals(flexChild2.y, 60) -- 50 + 10 gap
-- Verify absolute child position is maintained
luaunit.assertEquals(absoluteChild.x, 150)
luaunit.assertEquals(absoluteChild.y, 150)
end
function TestLayoutValidation:testDynamicSizing()
-- Test auto-sizing of flex containers
local container = self.GUI.new({
x = 0,
y = 0,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
})
-- Add children to determine container size
local child1 = self.GUI.new({
parent = container,
w = 50,
h = 100,
positioning = Positioning.FLEX,
})
local child2 = self.GUI.new({
parent = container,
w = 50,
h = 150,
positioning = Positioning.FLEX,
})
-- Container should size to fit children
luaunit.assertEquals(container.width, 110) -- 50 + 10 + 50
luaunit.assertEquals(container.height, 150) -- Max of child heights
end
function TestLayoutValidation:testDeepNesting()
-- Test deeply nested flex containers
local level1 = self.GUI.new({
x = 0,
y = 0,
w = 400,
h = 400,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
})
local level2 = self.GUI.new({
parent = level1,
w = 300,
h = 300,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
})
local level3 = self.GUI.new({
parent = level2,
w = 200,
h = 200,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
alignItems = AlignItems.CENTER,
})
local level4 = self.GUI.new({
parent = level3,
w = 100,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.CENTER,
})
-- Add a child to the deepest level
local deepChild = self.GUI.new({
parent = level4,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
-- Verify positioning through all levels
luaunit.assertEquals(level2.y, 0)
luaunit.assertEquals(level3.x, 0)
luaunit.assertEquals(level4.x, 50) -- (200 - 100) / 2
luaunit.assertEquals(deepChild.x, 25) -- (100 - 50) / 2
end
function TestLayoutValidation:testEdgeCases()
-- Test edge cases and potential layout issues
local container = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
})
-- Test zero-size child
local zeroSizeChild = self.GUI.new({
parent = container,
w = 0,
h = 0,
positioning = Positioning.FLEX,
})
-- Test negative size (should be clamped to 0)
local negativeSizeChild = self.GUI.new({
parent = container,
w = -50,
h = -50,
positioning = Positioning.FLEX,
})
-- Test oversized child
local oversizedChild = self.GUI.new({
parent = container,
w = 200,
h = 200,
positioning = Positioning.FLEX,
})
-- Verify layout handles edge cases gracefully
luaunit.assertTrue(zeroSizeChild.width >= 0)
luaunit.assertTrue(zeroSizeChild.height >= 0)
luaunit.assertTrue(negativeSizeChild.width >= 0)
luaunit.assertTrue(negativeSizeChild.height >= 0)
luaunit.assertEquals(oversizedChild.x, 0) -- Should still be positioned at start
-- Check that containers handle children properly
luaunit.assertEquals(zeroSizeChild.x, 0) -- First child should be at start
luaunit.assertEquals(negativeSizeChild.x, 0) -- Should be positioned after zero-size child
luaunit.assertEquals(oversizedChild.x, 0) -- Should be positioned after negative-size child
luaunit.assertNotNil(container.children[1]) -- Container should maintain child references
luaunit.assertEquals(#container.children, 3) -- All children should be tracked
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,211 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
-- Import only the enum values we need for each test
local FlexDirection = FlexLove.enums.FlexDirection
local Positioning = FlexLove.enums.Positioning
local JustifyContent = FlexLove.enums.JustifyContent
local AlignItems = FlexLove.enums.AlignItems
-- Create test cases
TestPerformance = {}
function TestPerformance:setUp()
self.GUI = FlexLove.GUI
end
-- Helper function to measure execution time
local function measure(fn)
local start = os.clock()
fn()
return os.clock() - start
end
function TestPerformance:testLargeNumberOfChildren()
-- Test performance with a large number of children
local container = self.GUI.new({
x = 0,
y = 0,
w = 1000,
h = 1000,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.FLEX_START,
})
-- Create 100 children
local createTime = measure(function()
for _ = 1, 100 do
self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
end
end)
-- Print creation time for visibility
print(string.format("Creating 100 children took: %.4f seconds", createTime))
-- Verify container has all children
luaunit.assertEquals(#container.children, 100)
-- Performance should be reasonable (adjust threshold based on target hardware)
luaunit.assertTrue(createTime < 1.0, "Creating children took too long: " .. createTime)
-- Test layout time (with nil check)
local layoutTime = measure(function()
luaunit.assertNotNil(container.layoutChildren, "layoutChildren method should exist")
container:layoutChildren()
end)
-- Print layout time for visibility
print(string.format("Laying out 100 children took: %.4f seconds", layoutTime))
-- Layout should be reasonably fast
luaunit.assertTrue(layoutTime < 1.0, "Layout took too long: " .. layoutTime)
end
function TestPerformance:testDeepHierarchy()
-- Test performance with a deep hierarchy
local root = nil
local rootTime = measure(function()
root = self.GUI.new({
x = 0,
y = 0,
w = 1000,
h = 1000,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.VERTICAL,
})
local current = root
for i = 1, 10 do
current = self.GUI.new({
parent = current,
w = 900 - (i * 50),
h = 900 - (i * 50),
positioning = Positioning.FLEX,
flexDirection = i % 2 == 0 and FlexDirection.HORIZONTAL or FlexDirection.VERTICAL,
})
-- Add some siblings at each level
for _ = 1, 3 do
self.GUI.new({
parent = current,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
end
end
end)
-- Print creation time for visibility
print(string.format("Creating deep hierarchy took: %.4f seconds", rootTime))
-- Creation should be reasonably fast
luaunit.assertTrue(rootTime < 1.0, "Creating deep hierarchy took too long: " .. rootTime)
-- Test layout performance (with nil check)
local layoutTime = measure(function()
luaunit.assertNotNil(root.layoutChildren, "layoutChildren method should exist")
root:layoutChildren()
end)
-- Print layout time for visibility
print(string.format("Laying out deep hierarchy took: %.4f seconds", layoutTime))
-- Layout should be reasonably fast
luaunit.assertTrue(layoutTime < 1.0, "Layout took too long: " .. layoutTime)
end
function TestPerformance:testDynamicUpdates()
-- Test performance of dynamic updates
local container = self.GUI.new({
x = 0,
y = 0,
w = 1000,
h = 1000,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
alignItems = AlignItems.CENTER,
})
-- Create 50 children
local children = {}
for i = 1, 50 do
children[i] = self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
end
-- Test update performance (resizing children)
local updateTime = measure(function()
for _, child in ipairs(children) do
child.width = child.width + 10
child.height = child.height + 10
end
luaunit.assertNotNil(container.layoutChildren, "layoutChildren method should exist")
container:layoutChildren()
end)
-- Print update time for visibility
print(string.format("Updating 50 children took: %.4f seconds", updateTime))
-- Updates should be reasonably fast
luaunit.assertTrue(updateTime < 1.0, "Updates took too long: " .. updateTime)
-- Verify updates were applied
luaunit.assertEquals(children[1].width, 60)
luaunit.assertEquals(children[1].height, 60)
end
function TestPerformance:testRapidResizing()
-- Test performance of rapid window resizing
local container = self.GUI.new({
x = 0,
y = 0,
w = 1000,
h = 1000,
positioning = Positioning.FLEX,
flexDirection = FlexDirection.HORIZONTAL,
justifyContent = JustifyContent.SPACE_BETWEEN,
})
-- Add 20 children
for _ = 1, 20 do
self.GUI.new({
parent = container,
w = 50,
h = 50,
positioning = Positioning.FLEX,
})
end
-- Test 10 rapid resizes
local resizeTime = measure(function()
for i = 1, 10 do
container:resize(1000 + i * 100, 1000 + i * 100)
end
end)
-- Print resize time for visibility
print(string.format("10 rapid resizes took: %.4f seconds", resizeTime))
-- Resizing should be reasonably fast
luaunit.assertTrue(resizeTime < 1.0, "Resizing took too long: " .. resizeTime)
-- Verify final dimensions
luaunit.assertEquals(container.width, 2000)
luaunit.assertEquals(container.height, 2000)
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,230 @@
package.path = package.path .. ";game/libs/?.lua;?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
local Positioning = FlexLove.enums.Positioning
local TextAlign = FlexLove.enums.TextAlign
local Color = FlexLove.Color
-- Create test cases
TestElementProperties = {}
function TestElementProperties:setUp()
self.GUI = FlexLove.GUI
end
function TestElementProperties:testBasicProperties()
local element = self.GUI.new({
x = 10,
y = 20,
w = 100,
h = 50,
z = 1,
positioning = Positioning.ABSOLUTE,
})
-- Test basic properties
luaunit.assertNotNil(element)
luaunit.assertEquals(element.x, 10)
luaunit.assertEquals(element.y, 20)
luaunit.assertEquals(element.z, 1)
luaunit.assertEquals(element.width, 100)
luaunit.assertEquals(element.height, 50)
luaunit.assertEquals(element.positioning, Positioning.ABSOLUTE)
end
function TestElementProperties:testPropertyModification()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Test property modification
luaunit.assertNotNil(element)
element.x = 50
element.y = 60
element.width = 200
element.height = 150
luaunit.assertEquals(element.x, 50)
luaunit.assertEquals(element.y, 60)
luaunit.assertEquals(element.width, 200)
luaunit.assertEquals(element.height, 150)
end
function TestElementProperties:testParentChildRelationship()
local parent = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 500,
})
local child = self.GUI.new({
parent = parent,
x = 10,
y = 10,
w = 100,
h = 100,
})
-- Test parent-child relationship
luaunit.assertNotNil(parent)
luaunit.assertNotNil(child)
luaunit.assertNotNil(parent.children)
luaunit.assertEquals(child.parent, parent)
luaunit.assertTrue(#parent.children == 1)
luaunit.assertEquals(parent.children[1], child)
end
function TestElementProperties:testBounds()
local element = self.GUI.new({
x = 10,
y = 20,
w = 100,
h = 50,
})
-- Test bounds calculation
luaunit.assertNotNil(element)
luaunit.assertNotNil(element.getBounds)
local bounds = element:getBounds()
luaunit.assertEquals(bounds.x, 10)
luaunit.assertEquals(bounds.y, 20)
luaunit.assertEquals(bounds.width, 100)
luaunit.assertEquals(bounds.height, 50)
end
function TestElementProperties:testZLayering()
local parent = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 500,
})
local child1 = self.GUI.new({
parent = parent,
x = 0,
y = 0,
w = 100,
h = 100,
z = 1,
})
local child2 = self.GUI.new({
parent = parent,
x = 0,
y = 0,
w = 100,
h = 100,
z = 2,
})
-- Test z ordering
luaunit.assertNotNil(parent)
luaunit.assertNotNil(child1)
luaunit.assertNotNil(child2)
luaunit.assertNotNil(child1.z)
luaunit.assertNotNil(child2.z)
luaunit.assertTrue(child1.z < child2.z)
end
function TestElementProperties:testColors()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
background = Color.new(1, 0, 0, 1), -- Red
textColor = Color.new(0, 1, 0, 1), -- Green
borderColor = Color.new(0, 0, 1, 1), -- Blue
})
-- Test color assignments
luaunit.assertNotNil(element.background)
luaunit.assertEquals(element.background.r, 1)
luaunit.assertEquals(element.background.g, 0)
luaunit.assertEquals(element.background.b, 0)
luaunit.assertEquals(element.background.a, 1)
luaunit.assertNotNil(element.textColor)
luaunit.assertEquals(element.textColor.r, 0)
luaunit.assertEquals(element.textColor.g, 1)
luaunit.assertEquals(element.textColor.b, 0)
luaunit.assertEquals(element.textColor.a, 1)
luaunit.assertNotNil(element.borderColor)
luaunit.assertEquals(element.borderColor.r, 0)
luaunit.assertEquals(element.borderColor.g, 0)
luaunit.assertEquals(element.borderColor.b, 1)
luaunit.assertEquals(element.borderColor.a, 1)
end
function TestElementProperties:testText()
local element = self.GUI.new({
x = 0,
y = 0,
w = 200,
h = 100,
text = "Test Text",
textSize = 16,
textAlign = TextAlign.CENTER,
})
-- Test text properties
luaunit.assertNotNil(element)
luaunit.assertEquals(element.text, "Test Text")
luaunit.assertEquals(element.textSize, 16)
luaunit.assertEquals(element.textAlign, TextAlign.CENTER)
-- Test text update
element:updateText("New Text", true)
luaunit.assertEquals(element.text, "New Text")
end
function TestElementProperties:testOpacity()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
opacity = 0.5,
})
-- Test opacity property and updates
luaunit.assertNotNil(element)
luaunit.assertEquals(element.opacity, 0.5)
element:updateOpacity(0.8)
luaunit.assertEquals(element.opacity, 0.8)
end
function TestElementProperties:testBorder()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
border = {
top = true,
right = true,
bottom = true,
left = true,
},
})
-- Test border configuration
luaunit.assertNotNil(element)
luaunit.assertTrue(element.border.top)
luaunit.assertTrue(element.border.right)
luaunit.assertTrue(element.border.bottom)
luaunit.assertTrue(element.border.left)
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,216 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
-- Create test cases
TestAnimationAndTransform = {}
function TestAnimationAndTransform:setUp()
self.GUI = FlexLove.GUI
end
function TestAnimationAndTransform:testBasicTranslation()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Test translate transformation
luaunit.assertNotNil(element)
luaunit.assertNotNil(element.translate)
element:translate(50, 30)
luaunit.assertEquals(element.x, 50)
luaunit.assertEquals(element.y, 30)
end
function TestAnimationAndTransform:testScale()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Test scale transformation
luaunit.assertNotNil(element)
luaunit.assertNotNil(element.scale)
element:scale(2, 1.5)
luaunit.assertEquals(element.width, 200)
luaunit.assertEquals(element.height, 150)
end
function TestAnimationAndTransform:testRotation()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Test rotation transformation (in radians)
luaunit.assertNotNil(element)
luaunit.assertNotNil(element.rotate)
local angle = math.pi / 4 -- 45 degrees
element:rotate(angle)
luaunit.assertNotNil(element.rotation)
luaunit.assertEquals(element.rotation, angle)
end
function TestAnimationAndTransform:testAnimationTweening()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Start position animation
luaunit.assertNotNil(element)
luaunit.assertNotNil(element.animate)
luaunit.assertNotNil(element.update)
element:animate({
x = 200,
y = 150,
duration = 1.0,
easing = "linear",
})
-- Test initial state
luaunit.assertEquals(element.x, 0)
luaunit.assertEquals(element.y, 0)
-- Simulate time passing (0.5 seconds)
element:update(0.5)
-- Test mid-animation state (linear interpolation)
luaunit.assertEquals(element.x, 100) -- Half way there
luaunit.assertEquals(element.y, 75) -- Half way there
end
function TestAnimationAndTransform:testChainedTransformations()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Apply multiple transformations in sequence
luaunit.assertNotNil(element)
luaunit.assertNotNil(element.translate)
luaunit.assertNotNil(element.scale)
luaunit.assertNotNil(element.rotate)
element:translate(50, 50):scale(2, 2):rotate(math.pi / 2)
-- Verify final state
luaunit.assertEquals(element.x, 50)
luaunit.assertEquals(element.y, 50)
luaunit.assertEquals(element.width, 200)
luaunit.assertEquals(element.height, 200)
luaunit.assertNotNil(element.rotation)
luaunit.assertEquals(element.rotation, math.pi / 2)
end
function TestAnimationAndTransform:testAnimationCancellation()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Start animation
luaunit.assertNotNil(element)
luaunit.assertNotNil(element.animate)
luaunit.assertNotNil(element.update)
luaunit.assertNotNil(element.stopAnimation)
element:animate({
x = 200,
y = 200,
duration = 2.0,
})
-- Update partially
element:update(0.5)
-- Cancel animation
element:stopAnimation()
-- Position should remain at last updated position
local x = element.x
local y = element.y
-- Update again to ensure animation stopped
element:update(0.5)
luaunit.assertEquals(element.x, x)
luaunit.assertEquals(element.y, y)
end
function TestAnimationAndTransform:testMultiplePropertyAnimation()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
alpha = 1.0,
})
-- Animate multiple properties simultaneously
luaunit.assertNotNil(element)
luaunit.assertNotNil(element.animate)
luaunit.assertNotNil(element.update)
element:animate({
x = 200,
y = 200,
width = 200,
height = 200,
alpha = 0.5,
duration = 1.0,
easing = "linear",
})
-- Update halfway
element:update(0.5)
-- Test all properties at midpoint
luaunit.assertEquals(element.x, 100)
luaunit.assertEquals(element.y, 100)
luaunit.assertEquals(element.width, 150)
luaunit.assertEquals(element.height, 150)
luaunit.assertNotNil(element.alpha)
luaunit.assertEquals(element.alpha, 0.75)
end
function TestAnimationAndTransform:testEasingFunctions()
local element = self.GUI.new({
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Test different easing functions
local easings = { "linear", "easeInQuad", "easeOutQuad", "easeInOutQuad" }
for _, easing in ipairs(easings) do
element.x = 0
luaunit.assertNotNil(element.animate)
element:animate({
x = 100,
duration = 1.0,
easing = easing,
})
element:update(0.5)
-- Ensure animation is progressing (exact values depend on easing function)
luaunit.assertTrue(element.x > 0 and element.x < 100)
end
end
luaunit.LuaUnit.run()

View File

@@ -0,0 +1,250 @@
package.path = package.path .. ";?.lua"
local luaunit = require("testing/luaunit")
require("testing/loveStub") -- Required to mock LOVE functions
local FlexLove = require("FlexLove")
-- Create test cases
TestAuxiliaryFunctions = {}
function TestAuxiliaryFunctions:setUp()
self.GUI = FlexLove.GUI
end
function TestAuxiliaryFunctions:testFindElementById()
local root = self.GUI.new({
id = "root",
x = 0,
y = 0,
w = 500,
h = 500,
})
local child = self.GUI.new({
id = "child",
parent = root,
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Test finding elements by ID
luaunit.assertNotNil(self.GUI.findElementById)
local foundRoot = self.GUI:findElementById("root")
local foundChild = self.GUI:findElementById("child")
luaunit.assertNotNil(foundRoot)
luaunit.assertNotNil(foundChild)
luaunit.assertEquals(foundRoot, root)
luaunit.assertEquals(foundChild, child)
end
function TestAuxiliaryFunctions:testFindElementsByClass()
local root = self.GUI.new({
class = "container",
x = 0,
y = 0,
w = 500,
h = 500,
})
self.GUI.new({
class = "item",
parent = root,
x = 0,
y = 0,
w = 100,
h = 100,
})
self.GUI.new({
class = "item",
parent = root,
x = 100,
y = 0,
w = 100,
h = 100,
})
-- Test finding elements by class
luaunit.assertNotNil(self.GUI.findElementsByClass)
local items = self.GUI:findElementsByClass("item")
luaunit.assertEquals(#items, 2)
local containers = self.GUI:findElementsByClass("container")
luaunit.assertEquals(#containers, 1)
luaunit.assertEquals(containers[1], root)
end
function TestAuxiliaryFunctions:testGetElementsAtPoint()
local root = self.GUI.new({
x = 0,
y = 0,
w = 500,
h = 500,
})
self.GUI.new({
parent = root,
x = 50,
y = 50,
w = 100,
h = 100,
})
self.GUI.new({
parent = root,
x = 200,
y = 200,
w = 100,
h = 100,
})
-- Test getting elements at specific points
luaunit.assertNotNil(self.GUI.getElementsAtPoint)
local elements1 = self.GUI:getElementsAtPoint(75, 75)
local elements2 = self.GUI:getElementsAtPoint(250, 250)
local elements3 = self.GUI:getElementsAtPoint(0, 0)
luaunit.assertTrue(#elements1 >= 2) -- Should find root and child1
luaunit.assertTrue(#elements2 >= 2) -- Should find root and child2
luaunit.assertEquals(#elements3, 1) -- Should only find root
end
function TestAuxiliaryFunctions:testQuerySelector()
local root = self.GUI.new({
id = "root",
class = "container",
x = 0,
y = 0,
w = 500,
h = 500,
})
self.GUI.new({
id = "btn1",
class = "button primary",
parent = root,
x = 0,
y = 0,
w = 100,
h = 100,
})
self.GUI.new({
id = "btn2",
class = "button secondary",
parent = root,
x = 100,
y = 0,
w = 100,
h = 100,
})
-- Test querySelector functionality
luaunit.assertNotNil(self.GUI.querySelector)
local container = self.GUI:querySelector(".container")
local primaryBtn = self.GUI:querySelector(".button.primary")
local secondaryBtn = self.GUI:querySelector(".button.secondary")
local specificBtn = self.GUI:querySelector("#btn1")
luaunit.assertNotNil(container)
luaunit.assertNotNil(primaryBtn)
luaunit.assertNotNil(secondaryBtn)
luaunit.assertNotNil(specificBtn)
luaunit.assertEquals(container, root)
end
function TestAuxiliaryFunctions:testQuerySelectorAll()
local root = self.GUI.new({
class = "container",
x = 0,
y = 0,
w = 500,
h = 500,
})
for i = 1, 3 do
self.GUI.new({
class = "item",
parent = root,
x = i * 100,
y = 0,
w = 100,
h = 100,
})
end
-- Test querySelectorAll functionality
luaunit.assertNotNil(self.GUI.querySelectorAll)
local items = self.GUI:querySelectorAll(".item")
local containers = self.GUI:querySelectorAll(".container")
luaunit.assertEquals(#items, 3)
luaunit.assertEquals(#containers, 1)
end
function TestAuxiliaryFunctions:testDebugPrint()
local root = self.GUI.new({
id = "root",
x = 0,
y = 0,
w = 500,
h = 500,
})
self.GUI.new({
id = "child",
parent = root,
x = 0,
y = 0,
w = 100,
h = 100,
})
-- Test debug print functionality
luaunit.assertNotNil(self.GUI.debugPrint)
local debugOutput = self.GUI:debugPrint()
luaunit.assertNotNil(debugOutput)
luaunit.assertString(debugOutput)
luaunit.assertTrue(string.find(debugOutput, "root") ~= nil)
luaunit.assertTrue(string.find(debugOutput, "child") ~= nil)
end
function TestAuxiliaryFunctions:testMeasureText()
local text = "Hello World"
local fontSize = 12
-- Test text measurement functionality
luaunit.assertNotNil(self.GUI.measureText)
local width, height = self.GUI:measureText(text, fontSize)
luaunit.assertNotNil(width)
luaunit.assertNotNil(height)
luaunit.assertNumber(width)
luaunit.assertNumber(height)
luaunit.assertTrue(width > 0)
luaunit.assertTrue(height > 0)
end
function TestAuxiliaryFunctions:testUtilityFunctions()
-- Test color conversion
luaunit.assertNotNil(self.GUI.hexToRGB)
local r, g, b = self.GUI:hexToRGB("#FF0000")
luaunit.assertEquals(r, 255)
luaunit.assertEquals(g, 0)
luaunit.assertEquals(b, 0)
-- Test point inside rectangle
luaunit.assertNotNil(self.GUI.pointInRect)
local isInside = self.GUI:pointInRect(10, 10, 0, 0, 20, 20)
luaunit.assertTrue(isInside)
-- Test rectangle intersection
luaunit.assertNotNil(self.GUI.rectIntersect)
local intersects = self.GUI:rectIntersect(0, 0, 10, 10, 5, 5, 10, 10)
luaunit.assertTrue(intersects)
end
luaunit.LuaUnit.run()

135
testing/__tests__/README.md Normal file
View File

@@ -0,0 +1,135 @@
# FlexLove GUI Library Test Suite
This directory contains comprehensive tests for the FlexLove GUI library. The tests cover layout behavior, property management, animations, and utility functions.
## Test Files
1. **01_absolute_positioning.lua**
- Basic absolute positioning
- Parent-child relationships
- Coordinate system tests
2. **02_flex_direction.lua**
- Horizontal flex layout
- Vertical flex layout
- Mixed direction layouts
3. **03_vertical_flex_direction.lua**
- Vertical layout specifics
- Column-based layouts
- Vertical alignment
4. **04_justify_content.lua**
- Flex-start alignment
- Flex-end alignment
- Space-between distribution
- Space-around distribution
5. **05_align_items.lua**
- Cross-axis alignment
- Stretch behavior
- Baseline alignment
6. **06_flex_wrap.lua**
- Wrapping behavior
- Multi-line layouts
- Wrap alignment
7. **07_layout_validation.lua**
- Edge cases
- Nested containers
- Deep hierarchies
8. **08_performance.lua**
- Large element counts
- Deep hierarchies
- Dynamic updates
- Rapid resizing
9. **09_element_properties.lua**
- Basic properties
- Custom properties
- Property modification
- Visibility and clipping
10. **10_animation_and_transform.lua**
- Basic transformations
- Animation tweening
- Easing functions
- Animation cancellation
11. **11_auxiliary_functions.lua**
- Element queries
- Debug utilities
- Layout helpers
- Utility functions
## Running Tests
### Run All Tests
```bash
cd /path/to/station_alpha
for f in game/libs/testing/__tests__/flexlove/*.lua; do lua "$f"; done
```
### Run Specific Test File
```bash
cd /path/to/station_alpha
lua game/libs/testing/__tests__/flexlove/[test_file].lua
```
## Test Structure
Each test file follows this general structure:
```lua
package.path = package.path .. ";/path/to/station_alpha/?.lua"
local luaunit = require('game/libs/testing/luaunit')
require('game/libs/testing/loveStub')
local FlexLove = require('game/libs/FlexLove')
TestClassName = {}
function TestClassName:setUp()
self.GUI = FlexLove.GUI
end
function TestClassName:testFeature()
-- Test implementation
end
os.exit(luaunit.LuaUnit.run())
```
## Known Issues
1. Layout Calculations
- Some justify-content calculations need verification
- Align-items behavior needs adjustment
- Flex-wrap positioning requires fixes
2. Missing Methods
- Animation and transform methods not implemented
- Some utility functions not available
- Custom property support incomplete
3. Performance
- Resize calculations may need optimization
- Deep hierarchy performance could be improved
## Contributing
When adding new tests:
1. Follow the existing naming convention
2. Add proper type annotations
3. Include nil checks for optional features
4. Document expected behavior
5. Add the test to this README
## Dependencies
- Lua 5.1+ / LuaJIT
- LÖVE2D (for graphics features)
- luaunit (testing framework)

42
testing/runAll.lua Normal file
View File

@@ -0,0 +1,42 @@
package.path = package.path .. ";./?.lua;./game/?.lua;./game/utils/?.lua;./game/components/?.lua;./game/systems/?.lua"
local luaunit = require("testing.luaunit")
-- Run all tests in the __tests__ directory
local testFiles = {
"testing/__tests__/01_absolute_positioning.lua",
"testing/__tests__/02_flex_direction.lua",
"testing/__tests__/03_vertical_flex_direction.lua",
"testing/__tests__/04_justify_content.lua",
"testing/__tests__/05_align_items.lua",
"testing/__tests__/06_flex_wrap.lua",
"testing/__tests__/07_layout_validation.lua",
"testing/__tests__/08_performance.lua",
"testing/__tests__/09_element_properties.lua",
"testing/__tests__/10_animation_and_transform.lua",
"testing/__tests__/11_auxiliary_functions.lua",
}
-- testingun all tests, but don't exit on error
local success = true
print("========================================")
print("Running ALL tests")
print("========================================")
for _, testFile in ipairs(testFiles) do
print("========================================")
print("Running test file: " .. testFile)
print("========================================")
local status, err = pcall(dofile, testFile)
if not status then
print("Error running test " .. testFile .. ": " .. tostring(err))
success = false
end
end
print("========================================")
print("All tests completed")
print("========================================")
-- Run the tests and exit with appropriate code
local result = luaunit.LuaUnit.run()
os.exit(success and result or 1)