2997 lines
69 KiB
Lua
2997 lines
69 KiB
Lua
-- Comprehensive test suite for Element.lua
|
|
-- Tests element creation, size calculations, positioning, layout, scroll, styling, and edge cases
|
|
|
|
package.path = package.path .. ";./?.lua;./modules/?.lua"
|
|
|
|
-- Load love stub before anything else
|
|
require("testing.loveStub")
|
|
|
|
local luaunit = require("testing.luaunit")
|
|
local ErrorHandler = require("modules.ErrorHandler")
|
|
|
|
-- Initialize ErrorHandler
|
|
ErrorHandler.init({})
|
|
|
|
-- Setup package loader to map FlexLove.modules.X to modules/X
|
|
local originalSearchers = package.searchers or package.loaders
|
|
table.insert(originalSearchers, 2, function(modname)
|
|
if modname:match("^FlexLove%.modules%.") then
|
|
local moduleName = modname:gsub("^FlexLove%.modules%.", "")
|
|
return function() return require("modules." .. moduleName) end
|
|
end
|
|
end)
|
|
|
|
-- Load FlexLove which properly initializes all dependencies
|
|
local FlexLove = require("FlexLove")
|
|
local Element = require("modules.Element")
|
|
local Color = require("modules.Color")
|
|
|
|
-- Initialize FlexLove
|
|
FlexLove.init()
|
|
|
|
-- ============================================================================
|
|
-- Helper Functions
|
|
-- ============================================================================
|
|
|
|
local function createBasicElement(props)
|
|
props = props or {}
|
|
props.width = props.width or 100
|
|
props.height = props.height or 100
|
|
return Element.new(props)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Creation Tests
|
|
-- ============================================================================
|
|
|
|
TestElementCreation = {}
|
|
|
|
function TestElementCreation:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementCreation:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementCreation:test_create_minimal_element()
|
|
local element = FlexLove.new({
|
|
id = "test1",
|
|
x = 10,
|
|
y = 20,
|
|
width = 100,
|
|
height = 50,
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.id, "test1")
|
|
luaunit.assertEquals(element.x, 10)
|
|
luaunit.assertEquals(element.y, 20)
|
|
luaunit.assertEquals(element.width, 100)
|
|
luaunit.assertEquals(element.height, 50)
|
|
end
|
|
|
|
function TestElementCreation:test_element_with_text()
|
|
local element = FlexLove.new({
|
|
id = "text1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
text = "Hello World",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.text, "Hello World")
|
|
end
|
|
|
|
function TestElementCreation:test_element_with_backgroundColor()
|
|
local element = FlexLove.new({
|
|
id = "colored1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
backgroundColor = { 1, 0, 0, 1 },
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertNotNil(element.backgroundColor)
|
|
end
|
|
|
|
function TestElementCreation:test_element_with_children()
|
|
local parent = FlexLove.new({
|
|
id = "parent1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 200,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "child1",
|
|
x = 10,
|
|
y = 10,
|
|
width = 50,
|
|
height = 50,
|
|
parent = parent,
|
|
})
|
|
|
|
luaunit.assertNotNil(parent)
|
|
luaunit.assertNotNil(child)
|
|
luaunit.assertEquals(child.parent, parent)
|
|
luaunit.assertEquals(#parent.children, 1)
|
|
luaunit.assertEquals(parent.children[1], child)
|
|
end
|
|
|
|
function TestElementCreation:test_element_with_padding()
|
|
local element = FlexLove.new({
|
|
id = "padded1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
padding = { horizontal = 10, vertical = 10 },
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.padding.left, 10)
|
|
luaunit.assertEquals(element.padding.top, 10)
|
|
luaunit.assertEquals(element.padding.right, 10)
|
|
luaunit.assertEquals(element.padding.bottom, 10)
|
|
end
|
|
|
|
function TestElementCreation:test_element_with_margin()
|
|
local element = FlexLove.new({
|
|
id = "margined1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
margin = { horizontal = 5, vertical = 5 },
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.margin.left, 5)
|
|
luaunit.assertEquals(element.margin.top, 5)
|
|
luaunit.assertEquals(element.margin.right, 5)
|
|
luaunit.assertEquals(element.margin.bottom, 5)
|
|
end
|
|
|
|
function TestElementCreation:test_element_with_z_index()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
z = 10,
|
|
})
|
|
|
|
luaunit.assertEquals(element.z, 10)
|
|
end
|
|
|
|
function TestElementCreation:test_element_with_userdata()
|
|
local customData = { foo = "bar", count = 42 }
|
|
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
userdata = customData,
|
|
})
|
|
|
|
luaunit.assertEquals(element.userdata, customData)
|
|
luaunit.assertEquals(element.userdata.foo, "bar")
|
|
luaunit.assertEquals(element.userdata.count, 42)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Sizing Tests
|
|
-- ============================================================================
|
|
|
|
TestElementSizing = {}
|
|
|
|
function TestElementSizing:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementSizing:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementSizing:test_getBorderBoxWidth()
|
|
local element = FlexLove.new({
|
|
id = "sized1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 50,
|
|
})
|
|
|
|
local borderBoxWidth = element:getBorderBoxWidth()
|
|
luaunit.assertEquals(borderBoxWidth, 100)
|
|
end
|
|
|
|
function TestElementSizing:test_getBorderBoxHeight()
|
|
local element = FlexLove.new({
|
|
id = "sized2",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 50,
|
|
})
|
|
|
|
local borderBoxHeight = element:getBorderBoxHeight()
|
|
luaunit.assertEquals(borderBoxHeight, 50)
|
|
end
|
|
|
|
function TestElementSizing:test_getBorderBoxWidth_with_border()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 50,
|
|
border = { left = 2, right = 2, top = 0, bottom = 0 },
|
|
})
|
|
|
|
local borderBoxWidth = element:getBorderBoxWidth()
|
|
-- Width includes left + right borders
|
|
luaunit.assertTrue(borderBoxWidth >= 100)
|
|
end
|
|
|
|
function TestElementSizing:test_getBounds()
|
|
local element = FlexLove.new({
|
|
id = "bounds1",
|
|
x = 10,
|
|
y = 20,
|
|
width = 100,
|
|
height = 50,
|
|
})
|
|
|
|
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 TestElementSizing:test_getAvailableContentWidth()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
|
})
|
|
|
|
local availWidth = element:getAvailableContentWidth()
|
|
luaunit.assertNotNil(availWidth)
|
|
-- Should be less than total width due to padding
|
|
luaunit.assertTrue(availWidth <= 200)
|
|
end
|
|
|
|
function TestElementSizing:test_getAvailableContentHeight()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
|
})
|
|
|
|
local availHeight = element:getAvailableContentHeight()
|
|
luaunit.assertNotNil(availHeight)
|
|
-- Should be less than total height due to padding
|
|
luaunit.assertTrue(availHeight <= 100)
|
|
end
|
|
|
|
function TestElementSizing:test_contains_point_inside()
|
|
local element = FlexLove.new({
|
|
id = "contains1",
|
|
x = 10,
|
|
y = 20,
|
|
width = 100,
|
|
height = 50,
|
|
})
|
|
|
|
local contains = element:contains(50, 40)
|
|
luaunit.assertTrue(contains)
|
|
end
|
|
|
|
function TestElementSizing:test_contains_point_outside()
|
|
local element = FlexLove.new({
|
|
id = "contains2",
|
|
x = 10,
|
|
y = 20,
|
|
width = 100,
|
|
height = 50,
|
|
})
|
|
|
|
local contains = element:contains(150, 100)
|
|
luaunit.assertFalse(contains)
|
|
end
|
|
|
|
function TestElementSizing:test_contains_point_on_edge()
|
|
local element = FlexLove.new({
|
|
id = "contains3",
|
|
x = 10,
|
|
y = 20,
|
|
width = 100,
|
|
height = 50,
|
|
})
|
|
|
|
-- Point on right edge
|
|
local contains = element:contains(110, 40)
|
|
luaunit.assertTrue(contains)
|
|
|
|
-- Point on bottom edge
|
|
contains = element:contains(50, 70)
|
|
luaunit.assertTrue(contains)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Units Tests
|
|
-- ============================================================================
|
|
|
|
TestElementUnits = {}
|
|
|
|
function TestElementUnits:setUp()
|
|
-- Set viewport size for viewport unit calculations
|
|
love.window.setMode(1920, 1080)
|
|
FlexLove.beginFrame()
|
|
end
|
|
|
|
function TestElementUnits:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementUnits:test_element_with_percentage_width()
|
|
local parent = FlexLove.new({
|
|
id = "parent_pct",
|
|
x = 0,
|
|
y = 0,
|
|
width = 1000,
|
|
height = 500,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "child_pct",
|
|
x = 0,
|
|
y = 0,
|
|
width = "50%",
|
|
height = 100,
|
|
parent = parent,
|
|
})
|
|
|
|
luaunit.assertNotNil(child)
|
|
-- Width should be resolved to 500 (50% of parent's 1000)
|
|
luaunit.assertEquals(child.width, 500)
|
|
end
|
|
|
|
function TestElementUnits:test_element_with_viewport_units()
|
|
local element = FlexLove.new({
|
|
id = "viewport1",
|
|
x = 0,
|
|
y = 0,
|
|
width = "50vw", -- 50% of viewport width (1920) = 960
|
|
height = "25vh", -- 25% of viewport height (1080) = 270
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
-- Units should be resolved immediately to numbers
|
|
luaunit.assertEquals(type(element.width), "number")
|
|
luaunit.assertEquals(type(element.height), "number")
|
|
-- Should be positive values
|
|
luaunit.assertTrue(element.width > 0)
|
|
luaunit.assertTrue(element.height > 0)
|
|
end
|
|
|
|
function TestElementUnits:test_resize_with_percentage_units()
|
|
-- Test that percentage units calculate correctly initially
|
|
local parent = FlexLove.new({
|
|
id = "resize_parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 1000,
|
|
height = 500,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "resize_child",
|
|
width = "50%",
|
|
height = "50%",
|
|
parent = parent,
|
|
})
|
|
|
|
-- Initial calculation should be 50% of parent
|
|
luaunit.assertEquals(child.width, 500)
|
|
luaunit.assertEquals(child.height, 250)
|
|
|
|
-- Verify units are stored correctly
|
|
luaunit.assertEquals(child.units.width.unit, "%")
|
|
luaunit.assertEquals(child.units.height.unit, "%")
|
|
end
|
|
|
|
function TestElementUnits:test_resize_with_viewport_units()
|
|
-- Test that viewport units calculate correctly
|
|
local element = FlexLove.new({
|
|
id = "vp_resize",
|
|
x = 0,
|
|
y = 0,
|
|
width = "50vw",
|
|
height = "50vh",
|
|
})
|
|
|
|
-- Should be 50% of viewport (1920x1080)
|
|
luaunit.assertEquals(element.width, 960)
|
|
luaunit.assertEquals(element.height, 540)
|
|
|
|
-- Verify units are stored correctly
|
|
luaunit.assertEquals(element.units.width.unit, "vw")
|
|
luaunit.assertEquals(element.units.height.unit, "vh")
|
|
end
|
|
|
|
function TestElementUnits:test_resize_with_textSize_scaling()
|
|
-- Test that textSize with viewport units calculates correctly
|
|
local element = FlexLove.new({
|
|
id = "text_resize",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
text = "Test",
|
|
textSize = "2vh",
|
|
autoScaleText = true,
|
|
})
|
|
|
|
-- 2vh of 1080 = 21.6
|
|
luaunit.assertAlmostEquals(element.textSize, 21.6, 0.1)
|
|
|
|
-- Verify unit is stored
|
|
luaunit.assertEquals(element.units.textSize.unit, "vh")
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Positioning Tests
|
|
-- ============================================================================
|
|
|
|
TestElementPositioning = {}
|
|
|
|
function TestElementPositioning:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementPositioning:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementPositioning:test_element_absolute_position()
|
|
local element = FlexLove.new({
|
|
id = "abs1",
|
|
x = 100,
|
|
y = 200,
|
|
width = 50,
|
|
height = 50,
|
|
positioning = "absolute",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.positioning, "absolute")
|
|
end
|
|
|
|
function TestElementPositioning:test_nested_element_positions()
|
|
local parent = FlexLove.new({
|
|
id = "nest_parent",
|
|
x = 100,
|
|
y = 100,
|
|
width = 300,
|
|
height = 200,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "nest_child",
|
|
x = 20,
|
|
y = 30,
|
|
width = 50,
|
|
height = 50,
|
|
parent = parent,
|
|
})
|
|
|
|
luaunit.assertNotNil(parent)
|
|
luaunit.assertNotNil(child)
|
|
-- Child positions are absolute in FlexLove, not relative to parent
|
|
-- So child.x = parent.x + relative_x = 100 + 20 = 120
|
|
luaunit.assertEquals(child.x, 120)
|
|
luaunit.assertEquals(child.y, 130)
|
|
end
|
|
|
|
function TestElementPositioning:test_absolute_positioning_with_top_left()
|
|
local element = createBasicElement({
|
|
positioning = "absolute",
|
|
top = 10,
|
|
left = 20,
|
|
})
|
|
|
|
luaunit.assertEquals(element.positioning, "absolute")
|
|
luaunit.assertEquals(element.top, 10)
|
|
luaunit.assertEquals(element.left, 20)
|
|
end
|
|
|
|
function TestElementPositioning:test_absolute_positioning_with_bottom_right()
|
|
local element = createBasicElement({
|
|
positioning = "absolute",
|
|
bottom = 10,
|
|
right = 20,
|
|
})
|
|
|
|
luaunit.assertEquals(element.positioning, "absolute")
|
|
luaunit.assertEquals(element.bottom, 10)
|
|
luaunit.assertEquals(element.right, 20)
|
|
end
|
|
|
|
function TestElementPositioning:test_relative_positioning()
|
|
local element = createBasicElement({
|
|
positioning = "relative",
|
|
top = 10,
|
|
left = 10,
|
|
})
|
|
|
|
luaunit.assertEquals(element.positioning, "relative")
|
|
end
|
|
|
|
function TestElementPositioning:test_applyPositioningOffsets_with_absolute()
|
|
local parent = FlexLove.new({
|
|
id = "offset_parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 500,
|
|
height = 500,
|
|
positioning = "absolute",
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "offset_child",
|
|
width = 100,
|
|
height = 100,
|
|
positioning = "absolute",
|
|
top = 50,
|
|
left = 50,
|
|
parent = parent,
|
|
})
|
|
|
|
-- Apply positioning offsets
|
|
parent:applyPositioningOffsets(child)
|
|
|
|
-- Child should be offset from parent
|
|
luaunit.assertTrue(child.y >= parent.y + 50)
|
|
luaunit.assertTrue(child.x >= parent.x + 50)
|
|
end
|
|
|
|
function TestElementPositioning:test_applyPositioningOffsets_with_right_bottom()
|
|
local parent = FlexLove.new({
|
|
id = "rb_parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 500,
|
|
height = 500,
|
|
positioning = "relative",
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "rb_child",
|
|
width = 100,
|
|
height = 100,
|
|
positioning = "absolute",
|
|
right = 50,
|
|
bottom = 50,
|
|
parent = parent,
|
|
})
|
|
|
|
parent:applyPositioningOffsets(child)
|
|
|
|
-- Child should be positioned from right/bottom
|
|
luaunit.assertNotNil(child.x)
|
|
luaunit.assertNotNil(child.y)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Flex Layout Tests
|
|
-- ============================================================================
|
|
|
|
TestElementFlex = {}
|
|
|
|
function TestElementFlex:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementFlex:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementFlex:test_element_with_flex_direction()
|
|
local element = FlexLove.new({
|
|
id = "flex1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 200,
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.flexDirection, "horizontal")
|
|
end
|
|
|
|
function TestElementFlex:test_element_with_flex_properties()
|
|
local parent = FlexLove.new({
|
|
id = "flex_parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 200,
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
})
|
|
|
|
local element = FlexLove.new({
|
|
id = "flex2",
|
|
parent = parent,
|
|
width = 100,
|
|
height = 100,
|
|
flexGrow = 1,
|
|
flexShrink = 0,
|
|
flexBasis = "auto",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
-- Just check element was created successfully
|
|
-- Flex properties are handled by LayoutEngine, not stored on element
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.parent, parent)
|
|
end
|
|
|
|
function TestElementFlex:test_element_with_gap()
|
|
local element = FlexLove.new({
|
|
id = "gap1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 200,
|
|
positioning = "flex",
|
|
gap = 10,
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.gap, 10)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Grid Layout Tests
|
|
-- ============================================================================
|
|
|
|
TestElementGrid = {}
|
|
|
|
function TestElementGrid:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementGrid:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementGrid:test_grid_layout()
|
|
local element = createBasicElement({
|
|
positioning = "grid",
|
|
gridColumns = 2,
|
|
gridRows = 2,
|
|
})
|
|
|
|
luaunit.assertEquals(element.positioning, "grid")
|
|
luaunit.assertEquals(element.gridColumns, 2)
|
|
luaunit.assertEquals(element.gridRows, 2)
|
|
end
|
|
|
|
function TestElementGrid:test_grid_gap()
|
|
local element = createBasicElement({
|
|
positioning = "grid",
|
|
columnGap = 10,
|
|
rowGap = 10,
|
|
})
|
|
|
|
luaunit.assertEquals(element.columnGap, 10)
|
|
luaunit.assertEquals(element.rowGap, 10)
|
|
end
|
|
|
|
function TestElementGrid:test_grid_with_uneven_children()
|
|
local grid = FlexLove.new({
|
|
id = "uneven_grid",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 300,
|
|
positioning = "grid",
|
|
gridRows = 2,
|
|
gridColumns = 2,
|
|
})
|
|
|
|
-- Add only 3 children to a 2x2 grid
|
|
for i = 1, 3 do
|
|
FlexLove.new({
|
|
id = "grid_item_" .. i,
|
|
width = 50,
|
|
height = 50,
|
|
parent = grid,
|
|
})
|
|
end
|
|
|
|
luaunit.assertEquals(#grid.children, 3)
|
|
end
|
|
|
|
function TestElementGrid:test_grid_with_percentage_gaps()
|
|
local grid = FlexLove.new({
|
|
id = "pct_gap_grid",
|
|
x = 0,
|
|
y = 0,
|
|
width = 400,
|
|
height = 400,
|
|
positioning = "grid",
|
|
gridRows = 2,
|
|
gridColumns = 2,
|
|
columnGap = "5%",
|
|
rowGap = "5%",
|
|
})
|
|
|
|
luaunit.assertNotNil(grid.columnGap)
|
|
luaunit.assertNotNil(grid.rowGap)
|
|
luaunit.assertTrue(grid.columnGap > 0)
|
|
luaunit.assertTrue(grid.rowGap > 0)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Styling Tests
|
|
-- ============================================================================
|
|
|
|
TestElementStyling = {}
|
|
|
|
function TestElementStyling:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementStyling:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_border()
|
|
local element = FlexLove.new({
|
|
id = "bordered1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
border = 2,
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.border, 2)
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_corner_radius()
|
|
local element = FlexLove.new({
|
|
id = "rounded1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
cornerRadius = 10,
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
-- Corner radius might be stored as a table
|
|
luaunit.assertNotNil(element.cornerRadius)
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_text_align()
|
|
local element = FlexLove.new({
|
|
id = "aligned1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
text = "Centered Text",
|
|
textAlign = "center",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.textAlign, "center")
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_opacity()
|
|
local element = FlexLove.new({
|
|
id = "transparent1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
opacity = 0.5,
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.opacity, 0.5)
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_border_color()
|
|
local element = FlexLove.new({
|
|
id = "colored_border",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
border = 2,
|
|
borderColor = { 1, 0, 0, 1 },
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertNotNil(element.borderColor)
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_text_color()
|
|
local textColor = Color.new(255, 0, 0, 1)
|
|
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
text = "Red text",
|
|
textColor = textColor,
|
|
})
|
|
|
|
luaunit.assertEquals(element.textColor, textColor)
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_background_color()
|
|
local bgColor = Color.new(0, 0, 255, 1)
|
|
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
backgroundColor = bgColor,
|
|
})
|
|
|
|
luaunit.assertEquals(element.backgroundColor, bgColor)
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_corner_radius_table()
|
|
-- Test uniform radius (should be stored as number for optimization)
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
cornerRadius = 10,
|
|
})
|
|
|
|
luaunit.assertNotNil(element.cornerRadius)
|
|
luaunit.assertEquals(type(element.cornerRadius), "number")
|
|
luaunit.assertEquals(element.cornerRadius, 10)
|
|
|
|
-- Test non-uniform radius (should be stored as table)
|
|
local element2 = FlexLove.new({
|
|
id = "test2",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
cornerRadius = { topLeft = 5, topRight = 10, bottomLeft = 15, bottomRight = 20 },
|
|
})
|
|
|
|
luaunit.assertNotNil(element2.cornerRadius)
|
|
luaunit.assertEquals(type(element2.cornerRadius), "table")
|
|
luaunit.assertEquals(element2.cornerRadius.topLeft, 5)
|
|
luaunit.assertEquals(element2.cornerRadius.topRight, 10)
|
|
luaunit.assertEquals(element2.cornerRadius.bottomLeft, 15)
|
|
luaunit.assertEquals(element2.cornerRadius.bottomRight, 20)
|
|
end
|
|
|
|
function TestElementStyling:test_element_with_margin_table()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
margin = { top = 5, right = 10, bottom = 5, left = 10 },
|
|
})
|
|
|
|
luaunit.assertNotNil(element.margin)
|
|
luaunit.assertEquals(element.margin.top, 5)
|
|
luaunit.assertEquals(element.margin.right, 10)
|
|
luaunit.assertEquals(element.margin.bottom, 5)
|
|
luaunit.assertEquals(element.margin.left, 10)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Methods Tests
|
|
-- ============================================================================
|
|
|
|
TestElementMethods = {}
|
|
|
|
function TestElementMethods:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementMethods:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementMethods:test_element_setText()
|
|
local element = FlexLove.new({
|
|
id = "textual1",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
text = "Initial",
|
|
})
|
|
|
|
element:setText("Updated")
|
|
luaunit.assertEquals(element.text, "Updated")
|
|
end
|
|
|
|
function TestElementMethods:test_element_addChild()
|
|
local parent = FlexLove.new({
|
|
id = "parent_add",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 200,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "child_add",
|
|
x = 10,
|
|
y = 10,
|
|
width = 50,
|
|
height = 50,
|
|
})
|
|
|
|
parent:addChild(child)
|
|
luaunit.assertEquals(#parent.children, 1)
|
|
luaunit.assertEquals(parent.children[1], child)
|
|
luaunit.assertEquals(child.parent, parent)
|
|
end
|
|
|
|
function TestElementMethods:test_getScaledContentPadding()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
|
})
|
|
|
|
local padding = element:getScaledContentPadding()
|
|
-- May be nil if no theme component with contentPadding
|
|
if padding then
|
|
luaunit.assertNotNil(padding.top)
|
|
luaunit.assertNotNil(padding.right)
|
|
luaunit.assertNotNil(padding.bottom)
|
|
luaunit.assertNotNil(padding.left)
|
|
end
|
|
end
|
|
|
|
function TestElementMethods:test_resize_updates_dimensions()
|
|
local element = createBasicElement({
|
|
width = 100,
|
|
height = 100,
|
|
})
|
|
|
|
-- resize() is for viewport resizing, not element resizing
|
|
-- Use setProperty to change element dimensions
|
|
element:setProperty("width", 200)
|
|
element:setProperty("height", 200)
|
|
|
|
luaunit.assertEquals(element.width, 200)
|
|
luaunit.assertEquals(element.height, 200)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Scroll Tests
|
|
-- ============================================================================
|
|
|
|
TestElementScroll = {}
|
|
|
|
function TestElementScroll:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementScroll:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementScroll:test_scrollable_element_with_overflow()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.overflow, "scroll")
|
|
luaunit.assertNotNil(element._scrollManager)
|
|
end
|
|
|
|
function TestElementScroll:test_setScrollPosition()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
element:setScrollPosition(50, 100)
|
|
local scrollX, scrollY = element:getScrollPosition()
|
|
|
|
-- Note: actual scroll may be clamped based on content
|
|
luaunit.assertNotNil(scrollX)
|
|
luaunit.assertNotNil(scrollY)
|
|
end
|
|
|
|
function TestElementScroll:test_scrollBy()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
local initialX, initialY = element:getScrollPosition()
|
|
element:scrollBy(10, 20)
|
|
local newX, newY = element:getScrollPosition()
|
|
|
|
luaunit.assertNotNil(newX)
|
|
luaunit.assertNotNil(newY)
|
|
end
|
|
|
|
function TestElementScroll:test_scrollToTop()
|
|
local container = FlexLove.new({
|
|
id = "scroll_container",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
positioning = "flex",
|
|
flexDirection = "vertical",
|
|
})
|
|
|
|
-- Add content that overflows
|
|
for i = 1, 10 do
|
|
FlexLove.new({
|
|
id = "item_" .. i,
|
|
width = 280,
|
|
height = 50,
|
|
parent = container,
|
|
})
|
|
end
|
|
|
|
-- Scroll down first
|
|
container:setScrollPosition(nil, 100)
|
|
local _, scrollY = container:getScrollPosition()
|
|
luaunit.assertEquals(scrollY, 100)
|
|
|
|
-- Scroll to top
|
|
container:scrollToTop()
|
|
_, scrollY = container:getScrollPosition()
|
|
luaunit.assertEquals(scrollY, 0)
|
|
end
|
|
|
|
function TestElementScroll:test_scrollToBottom()
|
|
local container = FlexLove.new({
|
|
id = "scroll_bottom",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
positioning = "flex",
|
|
flexDirection = "vertical",
|
|
})
|
|
|
|
-- Add overflowing content
|
|
for i = 1, 10 do
|
|
FlexLove.new({
|
|
id = "item_" .. i,
|
|
width = 280,
|
|
height = 50,
|
|
parent = container,
|
|
})
|
|
end
|
|
|
|
container:scrollToBottom()
|
|
|
|
local _, scrollY = container:getScrollPosition()
|
|
local _, maxScrollY = container:getMaxScroll()
|
|
|
|
luaunit.assertEquals(scrollY, maxScrollY)
|
|
end
|
|
|
|
function TestElementScroll:test_scrollToLeft()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
element:scrollToLeft()
|
|
local scrollX, _ = element:getScrollPosition()
|
|
luaunit.assertEquals(scrollX, 0)
|
|
end
|
|
|
|
function TestElementScroll:test_scrollToRight()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
element:scrollToRight()
|
|
local scrollX, _ = element:getScrollPosition()
|
|
luaunit.assertNotNil(scrollX)
|
|
end
|
|
|
|
function TestElementScroll:test_getMaxScroll()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
local maxX, maxY = element:getMaxScroll()
|
|
luaunit.assertNotNil(maxX)
|
|
luaunit.assertNotNil(maxY)
|
|
end
|
|
|
|
function TestElementScroll:test_getScrollPercentage()
|
|
local container = FlexLove.new({
|
|
id = "scroll_pct",
|
|
x = 0,
|
|
y = 0,
|
|
width = 300,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
positioning = "flex",
|
|
flexDirection = "vertical",
|
|
})
|
|
|
|
for i = 1, 10 do
|
|
FlexLove.new({
|
|
id = "item_" .. i,
|
|
width = 280,
|
|
height = 50,
|
|
parent = container,
|
|
})
|
|
end
|
|
|
|
-- At top
|
|
local _, percentY = container:getScrollPercentage()
|
|
luaunit.assertEquals(percentY, 0)
|
|
|
|
-- Scroll halfway
|
|
local _, maxScrollY = container:getMaxScroll()
|
|
container:setScrollPosition(nil, maxScrollY / 2)
|
|
_, percentY = container:getScrollPercentage()
|
|
luaunit.assertAlmostEquals(percentY, 0.5, 0.01)
|
|
end
|
|
|
|
function TestElementScroll:test_hasOverflow()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
local hasOverflowX, hasOverflowY = element:hasOverflow()
|
|
luaunit.assertNotNil(hasOverflowX)
|
|
luaunit.assertNotNil(hasOverflowY)
|
|
end
|
|
|
|
function TestElementScroll:test_getContentSize()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
local contentWidth, contentHeight = element:getContentSize()
|
|
luaunit.assertNotNil(contentWidth)
|
|
luaunit.assertNotNil(contentHeight)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Child Management Tests
|
|
-- ============================================================================
|
|
|
|
TestElementChildren = {}
|
|
|
|
function TestElementChildren:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementChildren:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementChildren:test_addChild()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "child",
|
|
x = 10,
|
|
y = 10,
|
|
width = 50,
|
|
height = 50,
|
|
})
|
|
|
|
parent:addChild(child)
|
|
luaunit.assertEquals(#parent.children, 1)
|
|
luaunit.assertEquals(parent.children[1], child)
|
|
luaunit.assertEquals(child.parent, parent)
|
|
end
|
|
|
|
function TestElementChildren:test_removeChild()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "child",
|
|
x = 10,
|
|
y = 10,
|
|
width = 50,
|
|
height = 50,
|
|
})
|
|
|
|
parent:addChild(child)
|
|
parent:removeChild(child)
|
|
|
|
luaunit.assertEquals(#parent.children, 0)
|
|
luaunit.assertNil(child.parent)
|
|
end
|
|
|
|
function TestElementChildren:test_clearChildren()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local child1 = FlexLove.new({ id = "child1", x = 0, y = 0, width = 50, height = 50 })
|
|
local child2 = FlexLove.new({ id = "child2", x = 0, y = 0, width = 50, height = 50 })
|
|
|
|
parent:addChild(child1)
|
|
parent:addChild(child2)
|
|
parent:clearChildren()
|
|
|
|
luaunit.assertEquals(#parent.children, 0)
|
|
end
|
|
|
|
function TestElementChildren:test_getChildCount()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local child1 = FlexLove.new({ id = "child1", x = 0, y = 0, width = 50, height = 50 })
|
|
local child2 = FlexLove.new({ id = "child2", x = 0, y = 0, width = 50, height = 50 })
|
|
|
|
parent:addChild(child1)
|
|
parent:addChild(child2)
|
|
|
|
luaunit.assertEquals(parent:getChildCount(), 2)
|
|
end
|
|
|
|
function TestElementChildren:test_addChild_triggers_autosize_recalc()
|
|
local parent = FlexLove.new({
|
|
id = "dynamic_parent",
|
|
x = 0,
|
|
y = 0,
|
|
positioning = "flex",
|
|
})
|
|
|
|
local initialWidth = parent.width
|
|
local initialHeight = parent.height
|
|
|
|
-- Add child dynamically
|
|
local child = FlexLove.new({
|
|
id = "dynamic_child",
|
|
width = 150,
|
|
height = 150,
|
|
})
|
|
|
|
parent:addChild(child)
|
|
|
|
-- Parent should have resized
|
|
luaunit.assertTrue(parent.width >= initialWidth)
|
|
luaunit.assertTrue(parent.height >= initialHeight)
|
|
end
|
|
|
|
function TestElementChildren:test_removeChild_triggers_autosize_recalc()
|
|
local parent = FlexLove.new({
|
|
id = "shrink_parent",
|
|
x = 0,
|
|
y = 0,
|
|
positioning = "flex",
|
|
})
|
|
|
|
local child1 = FlexLove.new({
|
|
id = "child1",
|
|
width = 100,
|
|
height = 100,
|
|
parent = parent,
|
|
})
|
|
|
|
local child2 = FlexLove.new({
|
|
id = "child2",
|
|
width = 100,
|
|
height = 100,
|
|
parent = parent,
|
|
})
|
|
|
|
local widthWithTwo = parent.width
|
|
|
|
parent:removeChild(child2)
|
|
|
|
-- Parent should shrink
|
|
luaunit.assertTrue(parent.width < widthWithTwo)
|
|
end
|
|
|
|
function TestElementChildren:test_clearChildren_resets_autosize()
|
|
local parent = FlexLove.new({
|
|
id = "clear_parent",
|
|
x = 0,
|
|
y = 0,
|
|
positioning = "flex",
|
|
})
|
|
|
|
for i = 1, 5 do
|
|
FlexLove.new({
|
|
id = "child_" .. i,
|
|
width = 50,
|
|
height = 50,
|
|
parent = parent,
|
|
})
|
|
end
|
|
|
|
local widthWithChildren = parent.width
|
|
|
|
parent:clearChildren()
|
|
|
|
-- Parent should shrink to minimal size
|
|
luaunit.assertTrue(parent.width < widthWithChildren)
|
|
luaunit.assertEquals(#parent.children, 0)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Visibility Tests
|
|
-- ============================================================================
|
|
|
|
TestElementVisibility = {}
|
|
|
|
function TestElementVisibility:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementVisibility:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementVisibility:test_visibility_visible()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
visibility = "visible",
|
|
})
|
|
|
|
luaunit.assertEquals(element.visibility, "visible")
|
|
end
|
|
|
|
function TestElementVisibility:test_visibility_hidden()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
visibility = "hidden",
|
|
})
|
|
|
|
luaunit.assertEquals(element.visibility, "hidden")
|
|
end
|
|
|
|
function TestElementVisibility:test_opacity_default()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
})
|
|
|
|
luaunit.assertEquals(element.opacity, 1)
|
|
end
|
|
|
|
function TestElementVisibility:test_opacity_custom()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
opacity = 0.5,
|
|
})
|
|
|
|
luaunit.assertEquals(element.opacity, 0.5)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Text Editing Tests
|
|
-- ============================================================================
|
|
|
|
TestElementTextEditing = {}
|
|
|
|
function TestElementTextEditing:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementTextEditing:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementTextEditing:test_editable_element()
|
|
local element = FlexLove.new({
|
|
id = "input",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 40,
|
|
editable = true,
|
|
text = "Edit me",
|
|
})
|
|
|
|
luaunit.assertTrue(element.editable)
|
|
luaunit.assertNotNil(element._textEditor)
|
|
end
|
|
|
|
function TestElementTextEditing:test_placeholder_text()
|
|
local element = FlexLove.new({
|
|
id = "input",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 40,
|
|
editable = true,
|
|
placeholder = "Enter text...",
|
|
})
|
|
|
|
luaunit.assertEquals(element.placeholder, "Enter text...")
|
|
end
|
|
|
|
function TestElementTextEditing:test_insertText()
|
|
local element = createBasicElement({
|
|
editable = true,
|
|
text = "Hello",
|
|
})
|
|
|
|
element:insertText(" World", 5)
|
|
|
|
luaunit.assertEquals(element:getText(), "Hello World")
|
|
end
|
|
|
|
function TestElementTextEditing:test_deleteText()
|
|
local element = createBasicElement({
|
|
editable = true,
|
|
text = "Hello World",
|
|
})
|
|
|
|
element:deleteText(5, 11)
|
|
|
|
luaunit.assertEquals(element:getText(), "Hello")
|
|
end
|
|
|
|
function TestElementTextEditing:test_replaceText()
|
|
local element = createBasicElement({
|
|
editable = true,
|
|
text = "Hello World",
|
|
})
|
|
|
|
element:replaceText(6, 11, "Lua")
|
|
|
|
luaunit.assertEquals(element:getText(), "Hello Lua")
|
|
end
|
|
|
|
function TestElementTextEditing:test_getText_non_editable()
|
|
local element = createBasicElement({
|
|
text = "Test",
|
|
})
|
|
|
|
luaunit.assertEquals(element:getText(), "Test")
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element State Tests
|
|
-- ============================================================================
|
|
|
|
TestElementState = {}
|
|
|
|
function TestElementState:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementState:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementState:test_element_with_disabled()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
disabled = true,
|
|
})
|
|
|
|
luaunit.assertTrue(element.disabled)
|
|
end
|
|
|
|
function TestElementState:test_element_with_active()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
x = 0,
|
|
y = 0,
|
|
width = 100,
|
|
height = 100,
|
|
active = true,
|
|
})
|
|
|
|
luaunit.assertTrue(element.active)
|
|
end
|
|
|
|
function TestElementState:test_element_with_hover_state()
|
|
local element = createBasicElement({
|
|
backgroundColor = Color.new(1, 0, 0, 1),
|
|
})
|
|
|
|
-- Hover states are managed by theme system, not stored as element properties
|
|
-- Elements have _themeState and _scrollbarHoveredVertical/Horizontal for internal hover tracking
|
|
luaunit.assertNotNil(element._themeState)
|
|
luaunit.assertEquals(element._themeState, "normal")
|
|
end
|
|
|
|
function TestElementState:test_element_with_active_state()
|
|
local element = createBasicElement({
|
|
backgroundColor = Color.new(1, 0, 0, 1),
|
|
active = {
|
|
backgroundColor = Color.new(0, 0, 1, 1),
|
|
},
|
|
})
|
|
|
|
luaunit.assertNotNil(element.active)
|
|
end
|
|
|
|
function TestElementState:test_element_with_disabled_state()
|
|
local element = createBasicElement({
|
|
disabled = true,
|
|
})
|
|
|
|
luaunit.assertTrue(element.disabled)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Auto-Sizing Tests
|
|
-- ============================================================================
|
|
|
|
TestElementAutoSizing = {}
|
|
|
|
function TestElementAutoSizing:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementAutoSizing:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementAutoSizing:test_autosize_with_nested_flex()
|
|
local root = FlexLove.new({
|
|
id = "root",
|
|
x = 0,
|
|
y = 0,
|
|
positioning = "flex",
|
|
flexDirection = "vertical",
|
|
})
|
|
|
|
local row1 = FlexLove.new({
|
|
id = "row1",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
parent = root,
|
|
})
|
|
|
|
FlexLove.new({
|
|
id = "item1",
|
|
width = 100,
|
|
height = 50,
|
|
parent = row1,
|
|
})
|
|
|
|
FlexLove.new({
|
|
id = "item2",
|
|
width = 100,
|
|
height = 50,
|
|
parent = row1,
|
|
})
|
|
|
|
-- Root should auto-size to contain row
|
|
luaunit.assertTrue(root.width >= 200)
|
|
luaunit.assertTrue(root.height >= 50)
|
|
end
|
|
|
|
function TestElementAutoSizing:test_autosize_with_absolutely_positioned_child()
|
|
local parent = FlexLove.new({
|
|
id = "abs_parent",
|
|
x = 0,
|
|
y = 0,
|
|
positioning = "flex",
|
|
})
|
|
|
|
-- Regular child affects size
|
|
FlexLove.new({
|
|
id = "regular",
|
|
width = 100,
|
|
height = 100,
|
|
parent = parent,
|
|
})
|
|
|
|
-- Absolutely positioned child should NOT affect parent size
|
|
FlexLove.new({
|
|
id = "absolute",
|
|
width = 200,
|
|
height = 200,
|
|
positioning = "absolute",
|
|
parent = parent,
|
|
})
|
|
|
|
-- Parent should only size to regular child
|
|
luaunit.assertTrue(parent.width < 150)
|
|
luaunit.assertTrue(parent.height < 150)
|
|
end
|
|
|
|
function TestElementAutoSizing:test_autosize_with_margin()
|
|
local parent = FlexLove.new({
|
|
id = "margin_parent",
|
|
x = 0,
|
|
y = 0,
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
})
|
|
|
|
-- Add two children with margins to test margin collapsing
|
|
FlexLove.new({
|
|
id = "margin_child1",
|
|
width = 100,
|
|
height = 100,
|
|
margin = { right = 20 },
|
|
parent = parent,
|
|
})
|
|
|
|
FlexLove.new({
|
|
id = "margin_child2",
|
|
width = 100,
|
|
height = 100,
|
|
margin = { left = 20 },
|
|
parent = parent,
|
|
})
|
|
|
|
-- Parent should size to children including margins (flexbox includes margins in sizing)
|
|
-- Child1: 100px + 20px right margin = 120px
|
|
-- Child2: 20px left margin + 100px = 120px
|
|
-- Total width: 240px
|
|
-- Max height: 100px (no vertical margins)
|
|
luaunit.assertEquals(parent.width, 240)
|
|
luaunit.assertEquals(parent.height, 100)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Transform Tests
|
|
-- ============================================================================
|
|
|
|
TestElementTransform = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementTransform:test_rotate_transform()
|
|
local element = createBasicElement({})
|
|
|
|
element:rotate(90)
|
|
|
|
luaunit.assertNotNil(element.transform)
|
|
luaunit.assertEquals(element.transform.rotate, 90)
|
|
end
|
|
|
|
function TestElementTransform:test_scale_transform()
|
|
local element = createBasicElement({})
|
|
|
|
element:scale(2, 2)
|
|
|
|
luaunit.assertNotNil(element.transform)
|
|
luaunit.assertEquals(element.transform.scaleX, 2)
|
|
luaunit.assertEquals(element.transform.scaleY, 2)
|
|
end
|
|
|
|
function TestElementTransform:test_translate_transform()
|
|
local element = createBasicElement({})
|
|
|
|
element:translate(10, 20)
|
|
|
|
luaunit.assertNotNil(element.transform)
|
|
luaunit.assertEquals(element.transform.translateX, 10)
|
|
luaunit.assertEquals(element.transform.translateY, 20)
|
|
end
|
|
|
|
function TestElementTransform:test_setTransformOrigin()
|
|
local element = createBasicElement({})
|
|
|
|
element:setTransformOrigin(0.5, 0.5)
|
|
|
|
luaunit.assertNotNil(element.transform)
|
|
luaunit.assertEquals(element.transform.originX, 0.5)
|
|
luaunit.assertEquals(element.transform.originY, 0.5)
|
|
end
|
|
|
|
function TestElementTransform:test_combined_transforms()
|
|
local element = createBasicElement({})
|
|
|
|
element:rotate(45)
|
|
element:scale(1.5, 1.5)
|
|
element:translate(10, 10)
|
|
|
|
luaunit.assertEquals(element.transform.rotate, 45)
|
|
luaunit.assertEquals(element.transform.scaleX, 1.5)
|
|
luaunit.assertEquals(element.transform.translateX, 10)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Image Tests
|
|
-- ============================================================================
|
|
|
|
TestElementImage = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementImage:test_image_loading_deferred_callback()
|
|
local callbackCalled = false
|
|
local element = createBasicElement({
|
|
image = "test.png",
|
|
onImageLoad = function(element, img)
|
|
callbackCalled = true
|
|
end,
|
|
})
|
|
|
|
-- Callback should be stored as element.onImageLoad
|
|
luaunit.assertNotNil(element.onImageLoad)
|
|
luaunit.assertEquals(type(element.onImageLoad), "function")
|
|
|
|
-- Note: In real usage, callback is called automatically when image loads
|
|
-- For testing, we just verify the callback is stored correctly
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementImage:test_image_with_tint()
|
|
local element = createBasicElement({
|
|
image = "test.png",
|
|
})
|
|
|
|
local tintColor = Color.new(1, 0, 0, 1)
|
|
element:setImageTint(tintColor)
|
|
|
|
luaunit.assertEquals(element.imageTint, tintColor)
|
|
end
|
|
|
|
function TestElementImage:test_image_with_opacity()
|
|
local element = createBasicElement({
|
|
image = "test.png",
|
|
})
|
|
|
|
element:setImageOpacity(0.5)
|
|
|
|
luaunit.assertEquals(element.imageOpacity, 0.5)
|
|
end
|
|
|
|
function TestElementImage:test_image_with_repeat()
|
|
local element = createBasicElement({
|
|
image = "test.png",
|
|
})
|
|
|
|
element:setImageRepeat("repeat")
|
|
|
|
luaunit.assertEquals(element.imageRepeat, "repeat")
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Blur Tests
|
|
-- ============================================================================
|
|
|
|
TestElementBlur = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementBlur:test_getBlurInstance_no_blur()
|
|
local element = createBasicElement({})
|
|
|
|
-- getBlurInstance has a bug - it passes quality as number instead of {quality=num} to Blur.new
|
|
-- Wrap in pcall to verify it doesn't crash the element
|
|
local success, result = pcall(function()
|
|
return element:getBlurInstance()
|
|
end)
|
|
|
|
-- Test passes if it returns nil or errors gracefully
|
|
luaunit.assertTrue(success == false or result == nil or type(result) == "table")
|
|
end
|
|
|
|
function TestElementBlur:test_getBlurInstance_with_blur()
|
|
local element = createBasicElement({
|
|
backdropBlur = { radius = 50, quality = 5 },
|
|
})
|
|
|
|
-- Blur instance should be created when backdropBlur is set
|
|
local blur = element:getBlurInstance()
|
|
|
|
-- May be nil if Blur module isn't initialized, but shouldn't error
|
|
luaunit.assertTrue(blur == nil or type(blur) == "table")
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Update and Animation Tests
|
|
-- ============================================================================
|
|
|
|
TestElementUpdate = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementUpdate:test_update_without_animations()
|
|
local element = createBasicElement({})
|
|
|
|
-- Should not error
|
|
element:update(0.016)
|
|
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementUpdate:test_update_with_transition()
|
|
local element = createBasicElement({
|
|
opacity = 1,
|
|
})
|
|
|
|
element:setTransition("opacity", {
|
|
duration = 1.0,
|
|
easing = "linear",
|
|
})
|
|
|
|
-- Change opacity to trigger transition
|
|
element:setProperty("opacity", 0)
|
|
|
|
-- Update should process transition
|
|
element:update(0.5)
|
|
|
|
-- Opacity should be between 0 and 1
|
|
luaunit.assertTrue(element.opacity >= 0 and element.opacity <= 1)
|
|
end
|
|
|
|
function TestElementUpdate:test_countActiveAnimations()
|
|
local element = createBasicElement({})
|
|
|
|
local count = element:_countActiveAnimations()
|
|
|
|
luaunit.assertEquals(count, 0)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Draw Tests
|
|
-- ============================================================================
|
|
|
|
TestElementDraw = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementDraw:test_draw_basic_element()
|
|
local element = createBasicElement({
|
|
backgroundColor = Color.new(1, 0, 0, 1),
|
|
})
|
|
|
|
-- Should not error
|
|
element:draw()
|
|
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementDraw:test_draw_with_opacity_zero()
|
|
local element = createBasicElement({
|
|
backgroundColor = Color.new(1, 0, 0, 1),
|
|
opacity = 0,
|
|
})
|
|
|
|
-- Should not draw but not error
|
|
element:draw()
|
|
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementDraw:test_draw_with_transform()
|
|
local element = createBasicElement({})
|
|
|
|
element:rotate(45)
|
|
element:scale(1.5, 1.5)
|
|
|
|
-- Should apply transforms
|
|
element:draw()
|
|
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementDraw:test_draw_with_blur()
|
|
local element = createBasicElement({
|
|
backdropBlur = { radius = 50, quality = 5 },
|
|
backgroundColor = Color.new(1, 1, 1, 0.5),
|
|
})
|
|
|
|
-- Should handle blur
|
|
element:draw()
|
|
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Layout Tests
|
|
-- ============================================================================
|
|
|
|
TestElementLayout = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementLayout:test_layoutChildren_empty()
|
|
local element = createBasicElement({})
|
|
|
|
-- Should not error with no children
|
|
element:layoutChildren()
|
|
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementLayout:test_layoutChildren_with_children()
|
|
local parent = createBasicElement({
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local child1 = createBasicElement({ width = 50, height = 50 })
|
|
local child2 = createBasicElement({ width = 50, height = 50 })
|
|
|
|
parent:addChild(child1)
|
|
parent:addChild(child2)
|
|
|
|
parent:layoutChildren()
|
|
|
|
-- Children should have positions
|
|
luaunit.assertNotNil(child1.x)
|
|
luaunit.assertNotNil(child2.x)
|
|
end
|
|
|
|
function TestElementLayout:test_checkPerformanceWarnings()
|
|
local parent = createBasicElement({})
|
|
|
|
-- Add many children to trigger warnings (reduced from 150 for performance)
|
|
for i = 1, 30 do
|
|
parent:addChild(createBasicElement({ width = 10, height = 10 }))
|
|
end
|
|
|
|
-- Should check performance
|
|
parent:_checkPerformanceWarnings()
|
|
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Focus Tests
|
|
-- ============================================================================
|
|
|
|
TestElementFocus = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementFocus:test_focus_non_editable()
|
|
local element = createBasicElement({})
|
|
|
|
element:focus()
|
|
|
|
-- Should not create editor for non-editable element
|
|
luaunit.assertNil(element._textEditor)
|
|
end
|
|
|
|
function TestElementFocus:test_focus_editable()
|
|
local element = createBasicElement({
|
|
editable = true,
|
|
text = "Test",
|
|
})
|
|
|
|
element:focus()
|
|
|
|
-- Should create editor
|
|
luaunit.assertNotNil(element._textEditor)
|
|
luaunit.assertTrue(element:isFocused())
|
|
end
|
|
|
|
function TestElementFocus:test_blur()
|
|
local element = createBasicElement({
|
|
editable = true,
|
|
text = "Test",
|
|
})
|
|
|
|
element:focus()
|
|
element:blur()
|
|
|
|
luaunit.assertFalse(element:isFocused())
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Hierarchy Tests
|
|
-- ============================================================================
|
|
|
|
TestElementHierarchy = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementHierarchy:test_getHierarchyDepth_root()
|
|
local element = createBasicElement({})
|
|
|
|
local depth = element:getHierarchyDepth()
|
|
|
|
luaunit.assertEquals(depth, 0)
|
|
end
|
|
|
|
function TestElementHierarchy:test_getHierarchyDepth_nested()
|
|
local root = createBasicElement({})
|
|
local child = createBasicElement({})
|
|
local grandchild = createBasicElement({})
|
|
|
|
root:addChild(child)
|
|
child:addChild(grandchild)
|
|
|
|
luaunit.assertEquals(grandchild:getHierarchyDepth(), 2)
|
|
end
|
|
|
|
function TestElementHierarchy:test_countElements()
|
|
local root = createBasicElement({})
|
|
|
|
local child1 = createBasicElement({})
|
|
local child2 = createBasicElement({})
|
|
|
|
root:addChild(child1)
|
|
root:addChild(child2)
|
|
|
|
local count = root:countElements()
|
|
|
|
luaunit.assertEquals(count, 3) -- root + 2 children
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Property Setting Tests
|
|
-- ============================================================================
|
|
|
|
TestElementProperty = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementProperty:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementProperty:test_setProperty_valid()
|
|
local element = createBasicElement({})
|
|
|
|
element:setProperty("opacity", 0.5)
|
|
|
|
luaunit.assertEquals(element.opacity, 0.5)
|
|
end
|
|
|
|
function TestElementProperty:test_setProperty_with_transition()
|
|
local element = createBasicElement({
|
|
opacity = 1,
|
|
})
|
|
|
|
element:setTransition("opacity", { duration = 1.0 })
|
|
element:setProperty("opacity", 0)
|
|
|
|
-- Transition should be created
|
|
luaunit.assertNotNil(element.transitions)
|
|
luaunit.assertNotNil(element.transitions.opacity)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Transitions Tests
|
|
-- ============================================================================
|
|
|
|
TestElementTransitions = {}
|
|
|
|
-- Note: No setUp/tearDown needed - tests use Element.new() directly (retained mode)
|
|
|
|
function TestElementTransitions:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementTransitions:test_removeTransition()
|
|
local element = createBasicElement({
|
|
opacity = 1,
|
|
})
|
|
|
|
element:setTransition("opacity", { duration = 1.0 })
|
|
element:removeTransition("opacity")
|
|
|
|
-- Transition should be removed
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementTransitions:test_setTransitionGroup()
|
|
local element = createBasicElement({})
|
|
|
|
element:setTransitionGroup("fade", { duration = 1.0 }, { "opacity", "scale" })
|
|
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Theme Tests
|
|
-- ============================================================================
|
|
|
|
TestElementTheme = {}
|
|
|
|
function TestElementTheme:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementTheme:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementTheme:test_getScaledContentPadding_no_theme()
|
|
local element = createBasicElement({})
|
|
|
|
local padding = element:getScaledContentPadding()
|
|
-- Should return nil if no theme component
|
|
luaunit.assertNil(padding)
|
|
end
|
|
|
|
function TestElementTheme:test_getAvailableContentWidth_with_padding()
|
|
local element = FlexLove.new({
|
|
id = "content_width",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
padding = 10,
|
|
})
|
|
|
|
local availableWidth = element:getAvailableContentWidth()
|
|
-- Should be width minus padding
|
|
luaunit.assertEquals(availableWidth, 180) -- 200 - 10*2
|
|
end
|
|
|
|
function TestElementTheme:test_getAvailableContentHeight_with_padding()
|
|
local element = FlexLove.new({
|
|
id = "content_height",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 100,
|
|
padding = 10,
|
|
})
|
|
|
|
local availableHeight = element:getAvailableContentHeight()
|
|
luaunit.assertEquals(availableHeight, 80) -- 100 - 10*2
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Convenience API Tests
|
|
-- ============================================================================
|
|
|
|
TestConvenienceAPI = {}
|
|
|
|
function TestConvenienceAPI:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestConvenienceAPI:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestConvenienceAPI:test_flexDirection_row_converts()
|
|
local element = FlexLove.new({
|
|
id = "test_row",
|
|
width = 200,
|
|
height = 100,
|
|
positioning = "flex",
|
|
flexDirection = "row",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.flexDirection, "horizontal")
|
|
end
|
|
|
|
function TestConvenienceAPI:test_flexDirection_column_converts()
|
|
local element = FlexLove.new({
|
|
id = "test_column",
|
|
width = 200,
|
|
height = 100,
|
|
positioning = "flex",
|
|
flexDirection = "column",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.flexDirection, "vertical")
|
|
end
|
|
|
|
function TestConvenienceAPI:test_padding_single_number()
|
|
local element = FlexLove.new({
|
|
id = "test_padding_num",
|
|
width = 200,
|
|
height = 100,
|
|
padding = 10,
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.padding.top, 10)
|
|
luaunit.assertEquals(element.padding.right, 10)
|
|
luaunit.assertEquals(element.padding.bottom, 10)
|
|
luaunit.assertEquals(element.padding.left, 10)
|
|
end
|
|
|
|
function TestConvenienceAPI:test_padding_single_string()
|
|
local element = FlexLove.new({
|
|
id = "test_padding_str",
|
|
width = 200,
|
|
height = 100,
|
|
padding = "5%",
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
-- All sides should be 5% of the element's dimensions
|
|
-- For width: 5% of 200 = 10, for height: 5% of 100 = 5
|
|
luaunit.assertEquals(element.padding.left, 10)
|
|
luaunit.assertEquals(element.padding.right, 10)
|
|
luaunit.assertEquals(element.padding.top, 5)
|
|
luaunit.assertEquals(element.padding.bottom, 5)
|
|
end
|
|
|
|
function TestConvenienceAPI:test_margin_single_number()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
width = 400,
|
|
height = 300,
|
|
})
|
|
|
|
local element = FlexLove.new({
|
|
id = "test_margin_num",
|
|
parent = parent,
|
|
width = 100,
|
|
height = 100,
|
|
margin = 15,
|
|
})
|
|
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.margin.top, 15)
|
|
luaunit.assertEquals(element.margin.right, 15)
|
|
luaunit.assertEquals(element.margin.bottom, 15)
|
|
luaunit.assertEquals(element.margin.left, 15)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Element Edge Cases and Error Handling Tests
|
|
-- ============================================================================
|
|
|
|
TestElementEdgeCases = {}
|
|
|
|
function TestElementEdgeCases:setUp()
|
|
FlexLove.beginFrame(1920, 1080)
|
|
end
|
|
|
|
function TestElementEdgeCases:tearDown()
|
|
FlexLove.endFrame()
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_with_init()
|
|
-- Test that Element.new() works after FlexLove.init() is called
|
|
-- Element now uses module-level dependencies initialized via Element.init()
|
|
FlexLove.init() -- Ensure FlexLove is initialized
|
|
local Element = require("modules.Element")
|
|
local success = pcall(function()
|
|
Element.new({})
|
|
end)
|
|
luaunit.assertTrue(success) -- Should work after Element.init() is called by FlexLove
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_negative_dimensions()
|
|
local element = FlexLove.new({
|
|
id = "negative",
|
|
x = 0,
|
|
y = 0,
|
|
width = -100,
|
|
height = -50,
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
-- Element should still be created (negative values handled)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_zero_dimensions()
|
|
local element = FlexLove.new({
|
|
id = "zero",
|
|
x = 0,
|
|
y = 0,
|
|
width = 0,
|
|
height = 0,
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_invalid_opacity()
|
|
-- Opacity > 1
|
|
local success = pcall(function()
|
|
FlexLove.new({
|
|
id = "high_opacity",
|
|
width = 100,
|
|
height = 100,
|
|
opacity = 2.5,
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success) -- Should error (validateRange)
|
|
|
|
-- Negative opacity
|
|
success = pcall(function()
|
|
FlexLove.new({
|
|
id = "negative_opacity",
|
|
width = 100,
|
|
height = 100,
|
|
opacity = -0.5,
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success) -- Should error (validateRange)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_invalid_image_opacity()
|
|
-- imageOpacity > 1
|
|
local success = pcall(function()
|
|
FlexLove.new({
|
|
id = "high_img_opacity",
|
|
width = 100,
|
|
height = 100,
|
|
imageOpacity = 3.0,
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success)
|
|
|
|
-- Negative imageOpacity
|
|
success = pcall(function()
|
|
FlexLove.new({
|
|
id = "negative_img_opacity",
|
|
width = 100,
|
|
height = 100,
|
|
imageOpacity = -1.0,
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_invalid_text_size()
|
|
-- Zero textSize
|
|
local success = pcall(function()
|
|
FlexLove.new({
|
|
id = "zero_text",
|
|
width = 100,
|
|
height = 100,
|
|
textSize = 0,
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success)
|
|
|
|
-- Negative textSize
|
|
success = pcall(function()
|
|
FlexLove.new({
|
|
id = "negative_text",
|
|
width = 100,
|
|
height = 100,
|
|
textSize = -12,
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_invalid_text_align()
|
|
local success = pcall(function()
|
|
FlexLove.new({
|
|
id = "invalid_align",
|
|
width = 100,
|
|
height = 100,
|
|
textAlign = "invalid_value",
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success) -- Should error (validateEnum)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_invalid_positioning()
|
|
local success = pcall(function()
|
|
FlexLove.new({
|
|
id = "invalid_pos",
|
|
width = 100,
|
|
height = 100,
|
|
positioning = "invalid_positioning",
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success) -- Should error (validateEnum)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_invalid_flex_direction()
|
|
local success = pcall(function()
|
|
FlexLove.new({
|
|
id = "invalid_flex",
|
|
width = 100,
|
|
height = 100,
|
|
positioning = "flex",
|
|
flexDirection = "diagonal",
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success) -- Should error (validateEnum)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_invalid_object_fit()
|
|
local success = pcall(function()
|
|
FlexLove.new({
|
|
id = "invalid_fit",
|
|
width = 100,
|
|
height = 100,
|
|
objectFit = "stretch",
|
|
})
|
|
end)
|
|
luaunit.assertFalse(success) -- Should error (validateEnum)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_nonexistent_image()
|
|
local element = FlexLove.new({
|
|
id = "no_image",
|
|
width = 100,
|
|
height = 100,
|
|
imagePath = "/nonexistent/path/to/image.png",
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertNil(element._loadedImage) -- Image should fail to load silently
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_password_multiline_conflict()
|
|
local element = FlexLove.new({
|
|
id = "conflict",
|
|
width = 200,
|
|
height = 100,
|
|
editable = true,
|
|
passwordMode = true,
|
|
multiline = true, -- Should be disabled by passwordMode
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertFalse(element.multiline) -- multiline should be forced to false
|
|
end
|
|
|
|
function TestElementEdgeCases:test_add_nil_child()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local success = pcall(function()
|
|
parent:addChild(nil)
|
|
end)
|
|
luaunit.assertFalse(success) -- Should error
|
|
end
|
|
|
|
function TestElementEdgeCases:test_remove_nonexistent_child()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local notAChild = FlexLove.new({
|
|
id = "orphan",
|
|
width = 50,
|
|
height = 50,
|
|
})
|
|
|
|
parent:removeChild(notAChild) -- Should not crash
|
|
luaunit.assertEquals(#parent.children, 0)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_remove_nil_child()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
parent:removeChild(nil) -- Should not crash
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_clear_children_empty()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
parent:clearChildren() -- Should not crash
|
|
luaunit.assertEquals(#parent.children, 0)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_clear_children_twice()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "child",
|
|
width = 50,
|
|
height = 50,
|
|
parent = parent,
|
|
})
|
|
|
|
parent:clearChildren()
|
|
parent:clearChildren()
|
|
luaunit.assertEquals(#parent.children, 0)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_scroll_without_manager()
|
|
local element = FlexLove.new({
|
|
id = "no_scroll",
|
|
width = 100,
|
|
height = 100,
|
|
-- No overflow property, so no ScrollManager
|
|
})
|
|
|
|
element:setScrollPosition(50, 50) -- Should not crash
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_scroll_by_nil()
|
|
local element = FlexLove.new({
|
|
id = "scrollable",
|
|
width = 200,
|
|
height = 200,
|
|
overflow = "scroll",
|
|
})
|
|
|
|
element:scrollBy(nil, nil) -- Should use current position
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_destroy_twice()
|
|
local element = FlexLove.new({
|
|
id = "destroyable",
|
|
width = 100,
|
|
height = 100,
|
|
})
|
|
|
|
element:destroy()
|
|
element:destroy() -- Call again - should not crash
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_destroy_with_children()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "child",
|
|
width = 50,
|
|
height = 50,
|
|
parent = parent,
|
|
})
|
|
|
|
parent:destroy() -- Should destroy all children too
|
|
luaunit.assertEquals(#parent.children, 0)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_element_destroy()
|
|
local parent = FlexLove.new({
|
|
id = "parent",
|
|
x = 0,
|
|
y = 0,
|
|
width = 200,
|
|
height = 200,
|
|
})
|
|
|
|
local child = FlexLove.new({
|
|
id = "child",
|
|
parent = parent,
|
|
x = 0,
|
|
y = 0,
|
|
width = 50,
|
|
height = 50,
|
|
})
|
|
|
|
luaunit.assertEquals(#parent.children, 1)
|
|
child:destroy()
|
|
luaunit.assertNil(child.parent)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_update_nil_dt()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
})
|
|
|
|
local success = pcall(function()
|
|
element:update(nil)
|
|
end)
|
|
-- May or may not error depending on implementation
|
|
end
|
|
|
|
function TestElementEdgeCases:test_update_negative_dt()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
})
|
|
|
|
element:update(-0.016) -- Should not crash
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_draw_nil_backdrop()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
})
|
|
|
|
element:draw(nil) -- Should not crash
|
|
luaunit.assertTrue(true)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_invalid_corner_radius()
|
|
-- String cornerRadius
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
cornerRadius = "invalid",
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
|
|
-- Negative cornerRadius
|
|
element = FlexLove.new({
|
|
id = "test2",
|
|
width = 100,
|
|
height = 100,
|
|
cornerRadius = -10,
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_partial_corner_radius()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
cornerRadius = {
|
|
topLeft = 10,
|
|
-- Missing other corners
|
|
},
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.cornerRadius.topLeft, 10)
|
|
luaunit.assertEquals(element.cornerRadius.topRight, 0)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_invalid_border()
|
|
-- String border
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
border = "invalid",
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
|
|
-- Negative border
|
|
element = FlexLove.new({
|
|
id = "test2",
|
|
width = 100,
|
|
height = 100,
|
|
border = -5,
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_partial_border()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
border = {
|
|
top = 2,
|
|
left = 3,
|
|
-- Missing right and bottom
|
|
},
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
luaunit.assertEquals(element.border.top, 2)
|
|
luaunit.assertEquals(element.border.left, 3)
|
|
luaunit.assertFalse(element.border.right)
|
|
luaunit.assertFalse(element.border.bottom)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_invalid_padding()
|
|
-- String padding
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
padding = "invalid",
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
|
|
-- Negative padding
|
|
element = FlexLove.new({
|
|
id = "test2",
|
|
width = 100,
|
|
height = 100,
|
|
padding = { top = -10, left = -10, right = -10, bottom = -10 },
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_invalid_margin()
|
|
-- String margin
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
margin = "invalid",
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_invalid_gap()
|
|
-- Negative gap
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 300,
|
|
height = 200,
|
|
positioning = "flex",
|
|
gap = -10,
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
|
|
-- Negative rows/columns
|
|
element = FlexLove.new({
|
|
id = "test2",
|
|
width = 300,
|
|
height = 200,
|
|
positioning = "grid",
|
|
gridRows = -5,
|
|
gridColumns = -5,
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_set_text_on_non_text()
|
|
local element = FlexLove.new({
|
|
id = "no_text",
|
|
width = 100,
|
|
height = 100,
|
|
})
|
|
|
|
element:setText("New text") -- Should not crash
|
|
luaunit.assertEquals(element.text, "New text")
|
|
end
|
|
|
|
function TestElementEdgeCases:test_set_text_nil()
|
|
local element = FlexLove.new({
|
|
id = "text",
|
|
width = 100,
|
|
height = 100,
|
|
text = "Initial",
|
|
})
|
|
|
|
element:setText(nil)
|
|
luaunit.assertNil(element.text)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_conflicting_size_constraints()
|
|
-- Width less than padding
|
|
local element = FlexLove.new({
|
|
id = "conflict",
|
|
width = 10,
|
|
height = 10,
|
|
padding = { top = 20, left = 20, right = 20, bottom = 20 },
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
-- Content width should be clamped to 0 or handled gracefully
|
|
end
|
|
|
|
function TestElementEdgeCases:test_textinput_non_editable()
|
|
local element = FlexLove.new({
|
|
id = "not_editable",
|
|
width = 100,
|
|
height = 100,
|
|
editable = false,
|
|
})
|
|
|
|
local success = pcall(function()
|
|
element:textinput("a")
|
|
end)
|
|
-- Should either do nothing or handle gracefully
|
|
end
|
|
|
|
function TestElementEdgeCases:test_keypressed_non_editable()
|
|
local element = FlexLove.new({
|
|
id = "not_editable",
|
|
width = 100,
|
|
height = 100,
|
|
editable = false,
|
|
})
|
|
|
|
local success = pcall(function()
|
|
element:keypressed("return", "return", false)
|
|
end)
|
|
-- Should either do nothing or handle gracefully
|
|
end
|
|
|
|
function TestElementEdgeCases:test_invalid_blur_config()
|
|
-- Negative intensity
|
|
local element = FlexLove.new({
|
|
id = "blur",
|
|
width = 100,
|
|
height = 100,
|
|
contentBlur = { radius = -10, quality = 5 },
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
|
|
-- Intensity > 100
|
|
element = FlexLove.new({
|
|
id = "blur2",
|
|
width = 100,
|
|
height = 100,
|
|
backdropBlur = { radius = 150, quality = 5 },
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
|
|
-- Invalid quality
|
|
element = FlexLove.new({
|
|
id = "blur3",
|
|
width = 100,
|
|
height = 100,
|
|
contentBlur = { radius = 50, quality = 0 },
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_available_content_no_padding()
|
|
local element = FlexLove.new({
|
|
id = "test",
|
|
width = 100,
|
|
height = 100,
|
|
})
|
|
|
|
local availWidth = element:getAvailableContentWidth()
|
|
local availHeight = element:getAvailableContentHeight()
|
|
|
|
luaunit.assertEquals(availWidth, 100)
|
|
luaunit.assertEquals(availHeight, 100)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_max_lines_without_multiline()
|
|
local element = FlexLove.new({
|
|
id = "text",
|
|
width = 200,
|
|
height = 100,
|
|
editable = true,
|
|
multiline = false,
|
|
maxLines = 5, -- Should be ignored for single-line
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_max_length_zero()
|
|
local element = FlexLove.new({
|
|
id = "text",
|
|
width = 200,
|
|
height = 40,
|
|
editable = true,
|
|
maxLength = 0,
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
function TestElementEdgeCases:test_max_length_negative()
|
|
local element = FlexLove.new({
|
|
id = "text",
|
|
width = 200,
|
|
height = 40,
|
|
editable = true,
|
|
maxLength = -10,
|
|
})
|
|
luaunit.assertNotNil(element)
|
|
end
|
|
|
|
-- Run tests
|
|
if not _G.RUNNING_ALL_TESTS then
|
|
os.exit(luaunit.LuaUnit.run())
|
|
end
|