fixes to run individual

This commit is contained in:
Michael Freno
2025-12-12 20:46:16 -05:00
parent 1d6ad6018f
commit e9b532b8f8
28 changed files with 508 additions and 951 deletions

View File

@@ -1,285 +0,0 @@
-- Touch Interaction Examples for FlexLöve
-- Demonstrates multi-touch gestures, scrolling, and touch events
package.path = package.path .. ";../?.lua;../modules/?.lua"
local FlexLove = require("FlexLove")
local lv = love
FlexLove.init({
theme = "metal",
baseScale = { width = 800, height = 600 },
})
-- Application state
local app = {
touchPoints = {}, -- Active touch points for visualization
gestureLog = {}, -- Recent gestures
selectedTab = "basic", -- Current tab: basic, gestures, scroll
}
-- Helper to add gesture to log
local function logGesture(gestureName, details)
table.insert(app.gestureLog, 1, {
name = gestureName,
details = details or "",
time = lv.timer.getTime(),
})
-- Keep only last 5 gestures
while #app.gestureLog > 5 do
table.remove(app.gestureLog)
end
end
-- Create main container
function lv.load()
-- Tab buttons container
local tabContainer = FlexLove.new({
flexDirection = "row",
gap = 10,
padding = { top = 10, left = 10, right = 10, bottom = 10 },
width = "100vw",
})
-- Tab buttons
local tabs = { "basic", "gestures", "scroll" }
for _, tabName in ipairs(tabs) do
FlexLove.new({
parent = tabContainer,
text = tabName:upper(),
padding = { top = 10, left = 20, right = 20, bottom = 10 },
backgroundColor = app.selectedTab == tabName and { 0.3, 0.6, 0.8, 1 } or { 0.2, 0.2, 0.2, 1 },
color = { 1, 1, 1, 1 },
onEvent = function(el, event)
if event.type == "click" or event.type == "touchrelease" then
app.selectedTab = tabName
lv.load() -- Reload UI
end
end,
})
end
-- Content area based on selected tab
if app.selectedTab == "basic" then
createBasicTouchDemo()
elseif app.selectedTab == "gestures" then
createGesturesDemo()
elseif app.selectedTab == "scroll" then
createScrollDemo()
end
-- Touch visualization overlay (always visible)
createTouchVisualization()
end
-- Basic touch event demo
function createBasicTouchDemo()
local container = FlexLove.new({
width = "100vw",
height = "80vh",
padding = 20,
gap = 10,
flexDirection = "column",
})
FlexLove.new({
parent = container,
text = "Touch Events Demo",
fontSize = 24,
color = { 1, 1, 1, 1 },
})
local touchInfo = {
lastEvent = "None",
touchId = "None",
position = { x = 0, y = 0 },
}
local touchArea = FlexLove.new({
parent = container,
width = "90vw",
height = 300,
backgroundColor = { 0.2, 0.2, 0.3, 1 },
justifyContent = "center",
alignItems = "center",
onEvent = function(el, event)
if event.type == "touchpress" then
touchInfo.lastEvent = "Touch Press"
touchInfo.touchId = event.touchId or "unknown"
touchInfo.position = { x = event.x, y = event.y }
logGesture("Touch Press", string.format("ID: %s", touchInfo.touchId))
elseif event.type == "touchmove" then
touchInfo.lastEvent = "Touch Move"
touchInfo.position = { x = event.x, y = event.y }
elseif event.type == "touchrelease" then
touchInfo.lastEvent = "Touch Release"
logGesture("Touch Release", string.format("ID: %s", touchInfo.touchId))
end
end,
})
FlexLove.new({
parent = touchArea,
text = "Touch or click this area",
color = { 0.7, 0.7, 0.7, 1 },
fontSize = 18,
})
-- Info display
FlexLove.new({
parent = container,
text = string.format("Last Event: %s", touchInfo.lastEvent),
color = { 1, 1, 1, 1 },
})
FlexLove.new({
parent = container,
text = string.format("Touch ID: %s", touchInfo.touchId),
color = { 1, 1, 1, 1 },
})
FlexLove.new({
parent = container,
text = string.format("Position: (%.0f, %.0f)", touchInfo.position.x, touchInfo.position.y),
color = { 1, 1, 1, 1 },
})
end
-- Gesture recognition demo
function createGesturesDemo()
local container = FlexLove.new({
width = "100vw",
height = "80vh",
padding = 20,
gap = 10,
flexDirection = "column",
})
FlexLove.new({
parent = container,
text = "Gesture Recognition Demo",
fontSize = 24,
color = { 1, 1, 1, 1 },
})
FlexLove.new({
parent = container,
text = "Try: Tap, Double-tap, Long-press, Swipe",
fontSize = 14,
color = { 0.7, 0.7, 0.7, 1 },
})
local gestureArea = FlexLove.new({
parent = container,
width = "90vw",
height = 300,
backgroundColor = { 0.2, 0.3, 0.2, 1 },
justifyContent = "center",
alignItems = "center",
})
FlexLove.new({
parent = gestureArea,
text = "Perform gestures here",
color = { 0.7, 0.7, 0.7, 1 },
fontSize = 18,
})
-- Gesture log display
FlexLove.new({
parent = container,
text = "Recent Gestures:",
fontSize = 16,
color = { 1, 1, 1, 1 },
})
for i, gesture in ipairs(app.gestureLog) do
FlexLove.new({
parent = container,
text = string.format("%d. %s - %s", i, gesture.name, gesture.details),
fontSize = 12,
color = { 0.8, 0.8, 0.8, 1 },
})
end
end
-- Scrollable content demo
function createScrollDemo()
local container = FlexLove.new({
width = "100vw",
height = "80vh",
padding = 20,
gap = 10,
flexDirection = "column",
})
FlexLove.new({
parent = container,
text = "Touch Scrolling Demo",
fontSize = 24,
color = { 1, 1, 1, 1 },
})
FlexLove.new({
parent = container,
text = "Touch and drag to scroll • Momentum scrolling enabled",
fontSize = 14,
color = { 0.7, 0.7, 0.7, 1 },
})
local scrollContainer = FlexLove.new({
parent = container,
width = "90vw",
height = 400,
backgroundColor = { 0.15, 0.15, 0.2, 1 },
overflow = "auto",
padding = 10,
gap = 5,
})
-- Add many items to make it scrollable
for i = 1, 50 do
FlexLove.new({
parent = scrollContainer,
text = string.format("Scrollable Item #%d - Touch and drag to scroll", i),
padding = { top = 15, left = 10, right = 10, bottom = 15 },
backgroundColor = i % 2 == 0 and { 0.2, 0.2, 0.3, 1 } or { 0.25, 0.25, 0.35, 1 },
color = { 1, 1, 1, 1 },
width = "100%",
})
end
end
-- Touch visualization overlay
function createTouchVisualization()
-- This would need custom drawing in lv.draw() to show active touch points
end
function lv.update(dt)
FlexLove.update(dt)
-- Update active touch points for visualization
app.touchPoints = {}
local touches = lv.touch.getTouches()
for _, id in ipairs(touches) do
local x, y = lv.touch.getPosition(id)
table.insert(app.touchPoints, { x = x, y = y, id = tostring(id) })
end
end
function lv.draw()
FlexLove.draw()
-- Draw touch point visualization
for _, touch in ipairs(app.touchPoints) do
lv.graphics.setColor(1, 0, 0, 0.5)
lv.graphics.circle("fill", touch.x, touch.y, 30)
lv.graphics.setColor(1, 1, 1, 1)
lv.graphics.circle("line", touch.x, touch.y, 30)
-- Draw touch ID
lv.graphics.setColor(1, 1, 1, 1)
lv.graphics.print(touch.id, touch.x - 10, touch.y - 40)
end
end

View File

@@ -1,124 +0,0 @@
-- Example: Varying Border Widths
-- Demonstrates how to use different border widths on each side of an element
local FlexLove = require("FlexLove")
function love.load()
FlexLove.init({
baseScale = { width = 1920, height = 1080 },
})
-- Example 1: Different width on each side
FlexLove.Element.new({
x = 50,
y = 50,
width = 200,
height = 150,
backgroundColor = FlexLove.Color.new(0.95, 0.95, 0.95, 1),
border = {
top = 1, -- Thin top border
right = 2, -- Medium right border
bottom = 3, -- Thick bottom border
left = 4, -- Very thick left border
},
borderColor = FlexLove.Color.new(0.2, 0.4, 0.8, 1),
text = "Different width\non each side",
textSize = 16,
textAlign = "center",
padding = 20,
})
-- Example 2: Using boolean values (true = 1px)
FlexLove.Element.new({
x = 300,
y = 50,
width = 200,
height = 150,
backgroundColor = FlexLove.Color.new(0.95, 0.95, 0.95, 1),
border = {
top = true, -- true becomes 1px
right = 8, -- Thick border
bottom = true,-- true becomes 1px
left = false, -- No border
},
borderColor = FlexLove.Color.new(0.8, 0.2, 0.2, 1),
text = "Boolean borders\ntrue = 1px\nfalse = none",
textSize = 16,
textAlign = "center",
padding = 20,
})
-- Example 3: Uniform border with single number
FlexLove.Element.new({
x = 550,
y = 50,
width = 200,
height = 150,
backgroundColor = FlexLove.Color.new(0.95, 0.95, 0.95, 1),
border = 5, -- All sides 5px
borderColor = FlexLove.Color.new(0.2, 0.8, 0.2, 1),
cornerRadius = 10,
text = "Uniform 5px\nall around\nwith rounded\ncorners",
textSize = 16,
textAlign = "center",
padding = 20,
})
-- Example 4: Decorative card with emphasis on one side
FlexLove.Element.new({
x = 50,
y = 250,
width = 700,
height = 100,
backgroundColor = FlexLove.Color.new(1, 1, 1, 1),
border = {
top = 1,
right = 1,
bottom = 1,
left = 8, -- Thick accent border on left
},
borderColor = FlexLove.Color.new(0.9, 0.5, 0.1, 1),
text = "Card with accent border on the left side",
textSize = 18,
padding = { left = 20, top = 10, right = 10, bottom = 10 },
})
-- Instructions
FlexLove.Element.new({
x = 50,
y = 400,
width = 700,
height = "auto",
backgroundColor = FlexLove.Color.new(0.1, 0.1, 0.1, 0.8),
text = "Border Width Options:\n• Use numbers for specific pixel widths (1, 2, 3, etc.)\n• Use true for 1px border\n• Use false for no border\n• Use a single number for uniform borders on all sides\n• Combine with cornerRadius for rounded uniform borders",
textSize = 14,
textColor = FlexLove.Color.new(1, 1, 1, 1),
padding = 20,
cornerRadius = 5,
})
end
function love.draw()
love.graphics.clear(0.15, 0.15, 0.2, 1)
FlexLove.draw()
end
function love.update(dt)
FlexLove.update(dt)
end
function love.mousepressed(x, y, button)
FlexLove.mousepressed(x, y, button)
end
function love.mousereleased(x, y, button)
FlexLove.mousereleased(x, y, button)
end
function love.mousemoved(x, y, dx, dy)
FlexLove.mousemoved(x, y, dx, dy)
end
function love.wheelmoved(x, y)
FlexLove.wheelmoved(x, y)
end

View File

@@ -1,29 +1,18 @@
-- Comprehensive test suite for Animation.lua
-- Consolidates all animation testing including core functionality, easing, properties, and keyframes
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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 local originalSearchers = package.searchers or package.loaders
table.insert(originalSearchers, 2, function(modname) table.insert(originalSearchers, 2, function(modname)
if modname:match("^FlexLove%.modules%.") then if modname:match("^FlexLove%.modules%.") then
local moduleName = modname:gsub("^FlexLove%.modules%.", "") local moduleName = modname:gsub("^FlexLove%.modules%.", "")
return function() return require("modules." .. moduleName) end return function()
return require("modules." .. moduleName)
end
end end
end) end)
-- Load FlexLove which properly initializes all dependencies require("testing.loveStub")
local luaunit = require("testing.luaunit")
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
-- Initialize FlexLove
FlexLove.init() FlexLove.init()
local Animation = FlexLove.Animation local Animation = FlexLove.Animation

View File

@@ -1,15 +1,22 @@
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
require("testing.loveStub") require("testing.loveStub")
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
-- only going to load blur (and ErrorHandler as its a required dependency for blur to work properly)
local Blur = require("modules.Blur") local Blur = require("modules.Blur")
local ErrorHandler = require("modules.ErrorHandler") local ErrorHandler = require("modules.ErrorHandler")
-- Initialize ErrorHandler
ErrorHandler.init({}) ErrorHandler.init({})
Blur.init({ ErrorHandler = ErrorHandler }) Blur.init({ ErrorHandler = ErrorHandler })
TestBlur = {} TestBlur = {}
function TestBlur:setUp() function TestBlur:setUp()
@@ -23,42 +30,42 @@ end
function TestBlur:testNewWithNilQuality() function TestBlur:testNewWithNilQuality()
-- Should default to quality 5 -- Should default to quality 5
local blur = Blur.new({quality = nil}) local blur = Blur.new({ quality = nil })
luaunit.assertNotNil(blur) luaunit.assertNotNil(blur)
luaunit.assertEquals(blur.quality, 5) luaunit.assertEquals(blur.quality, 5)
end end
function TestBlur:testNewWithZeroQuality() function TestBlur:testNewWithZeroQuality()
-- Should clamp to minimum quality 1 -- Should clamp to minimum quality 1
local blur = Blur.new({quality = 0}) local blur = Blur.new({ quality = 0 })
luaunit.assertNotNil(blur) luaunit.assertNotNil(blur)
luaunit.assertEquals(blur.quality, 1) luaunit.assertEquals(blur.quality, 1)
end end
function TestBlur:testNewWithNegativeQuality() function TestBlur:testNewWithNegativeQuality()
-- Should clamp to minimum quality 1 -- Should clamp to minimum quality 1
local blur = Blur.new({quality = -5}) local blur = Blur.new({ quality = -5 })
luaunit.assertNotNil(blur) luaunit.assertNotNil(blur)
luaunit.assertEquals(blur.quality, 1) luaunit.assertEquals(blur.quality, 1)
end end
function TestBlur:testNewWithVeryHighQuality() function TestBlur:testNewWithVeryHighQuality()
-- Should clamp to maximum quality 10 -- Should clamp to maximum quality 10
local blur = Blur.new({quality = 100}) local blur = Blur.new({ quality = 100 })
luaunit.assertNotNil(blur) luaunit.assertNotNil(blur)
luaunit.assertEquals(blur.quality, 10) luaunit.assertEquals(blur.quality, 10)
end end
function TestBlur:testNewWithQuality11() function TestBlur:testNewWithQuality11()
-- Should clamp to maximum quality 10 -- Should clamp to maximum quality 10
local blur = Blur.new({quality = 11}) local blur = Blur.new({ quality = 11 })
luaunit.assertNotNil(blur) luaunit.assertNotNil(blur)
luaunit.assertEquals(blur.quality, 10) luaunit.assertEquals(blur.quality, 10)
end end
function TestBlur:testNewWithFractionalQuality() function TestBlur:testNewWithFractionalQuality()
-- Should work with fractional quality -- Should work with fractional quality
local blur = Blur.new({quality = 5.5}) local blur = Blur.new({ quality = 5.5 })
luaunit.assertNotNil(blur) luaunit.assertNotNil(blur)
luaunit.assertTrue(blur.quality >= 5 and blur.quality <= 6) luaunit.assertTrue(blur.quality >= 5 and blur.quality <= 6)
end end
@@ -66,7 +73,7 @@ end
function TestBlur:testNewEnsuresOddTaps() function TestBlur:testNewEnsuresOddTaps()
-- Taps must be odd for shader -- Taps must be odd for shader
for quality = 1, 10 do for quality = 1, 10 do
local blur = Blur.new({quality = quality}) local blur = Blur.new({ quality = quality })
luaunit.assertTrue(blur.taps % 2 == 1, string.format("Quality %d produced even taps: %d", quality, blur.taps)) luaunit.assertTrue(blur.taps % 2 == 1, string.format("Quality %d produced even taps: %d", quality, blur.taps))
end end
end end
@@ -87,16 +94,16 @@ end
function TestBlur:testNewCreatesUniqueShaders() function TestBlur:testNewCreatesUniqueShaders()
-- Blur instances with same quality should share cached shaders (optimization) -- Blur instances with same quality should share cached shaders (optimization)
local blur1 = Blur.new({quality = 5}) local blur1 = Blur.new({ quality = 5 })
local blur2 = Blur.new({quality = 5}) local blur2 = Blur.new({ quality = 5 })
luaunit.assertNotNil(blur1.shader) luaunit.assertNotNil(blur1.shader)
luaunit.assertNotNil(blur2.shader) luaunit.assertNotNil(blur2.shader)
-- Shaders should be the same object when quality matches (cached) -- Shaders should be the same object when quality matches (cached)
luaunit.assertEquals(blur1.shader, blur2.shader) luaunit.assertEquals(blur1.shader, blur2.shader)
-- Different quality should result in different shaders -- Different quality should result in different shaders
local blur3 = Blur.new({quality = 7}) local blur3 = Blur.new({ quality = 7 })
luaunit.assertNotEquals(blur1.shader, blur3.shader) luaunit.assertNotEquals(blur1.shader, blur3.shader)
end end
@@ -105,7 +112,7 @@ end
-- ============================================================================ -- ============================================================================
function TestBlur:testApplyToRegionWithZeroRadius() function TestBlur:testApplyToRegionWithZeroRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -117,7 +124,7 @@ function TestBlur:testApplyToRegionWithZeroRadius()
end end
function TestBlur:testApplyToRegionWithNegativeRadius() function TestBlur:testApplyToRegionWithNegativeRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -129,7 +136,7 @@ function TestBlur:testApplyToRegionWithNegativeRadius()
end end
function TestBlur:testApplyToRegionWithZeroWidth() function TestBlur:testApplyToRegionWithZeroWidth()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -141,7 +148,7 @@ function TestBlur:testApplyToRegionWithZeroWidth()
end end
function TestBlur:testApplyToRegionWithZeroHeight() function TestBlur:testApplyToRegionWithZeroHeight()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -153,7 +160,7 @@ function TestBlur:testApplyToRegionWithZeroHeight()
end end
function TestBlur:testApplyToRegionWithNegativeWidth() function TestBlur:testApplyToRegionWithNegativeWidth()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -165,7 +172,7 @@ function TestBlur:testApplyToRegionWithNegativeWidth()
end end
function TestBlur:testApplyToRegionWithNegativeHeight() function TestBlur:testApplyToRegionWithNegativeHeight()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -177,7 +184,7 @@ function TestBlur:testApplyToRegionWithNegativeHeight()
end end
function TestBlur:testApplyToRegionWithLargeRadius() function TestBlur:testApplyToRegionWithLargeRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -189,7 +196,7 @@ function TestBlur:testApplyToRegionWithLargeRadius()
end end
function TestBlur:testApplyToRegionWithNonFunctionDrawFunc() function TestBlur:testApplyToRegionWithNonFunctionDrawFunc()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
-- Should not error but warn through ErrorHandler -- Should not error but warn through ErrorHandler
blur:applyToRegion(50, 0, 0, 100, 100, "not a function") blur:applyToRegion(50, 0, 0, 100, 100, "not a function")
@@ -197,7 +204,7 @@ function TestBlur:testApplyToRegionWithNonFunctionDrawFunc()
end end
function TestBlur:testApplyToRegionWithNilDrawFunc() function TestBlur:testApplyToRegionWithNilDrawFunc()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
-- Should not error but warn through ErrorHandler -- Should not error but warn through ErrorHandler
blur:applyToRegion(50, 0, 0, 100, 100, nil) blur:applyToRegion(50, 0, 0, 100, 100, nil)
@@ -205,7 +212,7 @@ function TestBlur:testApplyToRegionWithNilDrawFunc()
end end
function TestBlur:testApplyToRegionWithNegativeCoordinates() function TestBlur:testApplyToRegionWithNegativeCoordinates()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -217,7 +224,7 @@ function TestBlur:testApplyToRegionWithNegativeCoordinates()
end end
function TestBlur:testApplyToRegionWithVerySmallDimensions() function TestBlur:testApplyToRegionWithVerySmallDimensions()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -229,7 +236,7 @@ function TestBlur:testApplyToRegionWithVerySmallDimensions()
end end
function TestBlur:testApplyToRegionWithVeryLargeDimensions() function TestBlur:testApplyToRegionWithVeryLargeDimensions()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -241,7 +248,7 @@ function TestBlur:testApplyToRegionWithVeryLargeDimensions()
end end
function TestBlur:testApplyToRegionRadiusValues() function TestBlur:testApplyToRegionRadiusValues()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
@@ -251,22 +258,22 @@ function TestBlur:testApplyToRegionRadiusValues()
-- Small radius -- Small radius
blur:applyToRegion(5, 0, 0, 100, 100, drawFunc) blur:applyToRegion(5, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called) luaunit.assertTrue(called)
called = false called = false
-- Medium radius -- Medium radius
blur:applyToRegion(10, 0, 0, 100, 100, drawFunc) blur:applyToRegion(10, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called) luaunit.assertTrue(called)
called = false called = false
-- Large radius -- Large radius
blur:applyToRegion(20, 0, 0, 100, 100, drawFunc) blur:applyToRegion(20, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called) luaunit.assertTrue(called)
called = false called = false
-- Very large radius -- Very large radius
blur:applyToRegion(50, 0, 0, 100, 100, drawFunc) blur:applyToRegion(50, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called) luaunit.assertTrue(called)
called = false called = false
-- Fractional radius -- Fractional radius
blur:applyToRegion(2.5, 0, 0, 100, 100, drawFunc) blur:applyToRegion(2.5, 0, 0, 100, 100, drawFunc)
@@ -278,7 +285,7 @@ end
-- ============================================================================ -- ============================================================================
function TestBlur:testApplyBackdropWithZeroRadius() function TestBlur:testApplyBackdropWithZeroRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
return 100, 100 return 100, 100
@@ -291,7 +298,7 @@ function TestBlur:testApplyBackdropWithZeroRadius()
end end
function TestBlur:testApplyBackdropWithNegativeRadius() function TestBlur:testApplyBackdropWithNegativeRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
return 100, 100 return 100, 100
@@ -304,7 +311,7 @@ function TestBlur:testApplyBackdropWithNegativeRadius()
end end
function TestBlur:testApplyBackdropWithZeroWidth() function TestBlur:testApplyBackdropWithZeroWidth()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
return 100, 100 return 100, 100
@@ -317,7 +324,7 @@ function TestBlur:testApplyBackdropWithZeroWidth()
end end
function TestBlur:testApplyBackdropWithZeroHeight() function TestBlur:testApplyBackdropWithZeroHeight()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
return 100, 100 return 100, 100
@@ -330,7 +337,7 @@ function TestBlur:testApplyBackdropWithZeroHeight()
end end
function TestBlur:testApplyBackdropWithNilCanvas() function TestBlur:testApplyBackdropWithNilCanvas()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
-- Should not error but warn through ErrorHandler -- Should not error but warn through ErrorHandler
blur:applyBackdrop(50, 0, 0, 100, 100, nil) blur:applyBackdrop(50, 0, 0, 100, 100, nil)
@@ -338,7 +345,7 @@ function TestBlur:testApplyBackdropWithNilCanvas()
end end
function TestBlur:testApplyBackdropWithLargeRadius() function TestBlur:testApplyBackdropWithLargeRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
return 100, 100 return 100, 100
@@ -351,7 +358,7 @@ function TestBlur:testApplyBackdropWithLargeRadius()
end end
function TestBlur:testApplyBackdropWithInvalidCanvas() function TestBlur:testApplyBackdropWithInvalidCanvas()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local invalidCanvas = "not a canvas" local invalidCanvas = "not a canvas"
-- Should error when trying to call getDimensions -- Should error when trying to call getDimensions
@@ -361,7 +368,7 @@ function TestBlur:testApplyBackdropWithInvalidCanvas()
end end
function TestBlur:testApplyBackdropRegionBeyondCanvas() function TestBlur:testApplyBackdropRegionBeyondCanvas()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
return 100, 100 return 100, 100
@@ -374,7 +381,7 @@ function TestBlur:testApplyBackdropRegionBeyondCanvas()
end end
function TestBlur:testApplyBackdropWithNegativeCoordinates() function TestBlur:testApplyBackdropWithNegativeCoordinates()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
return 100, 100 return 100, 100
@@ -391,12 +398,12 @@ end
-- ============================================================================ -- ============================================================================
function TestBlur:testGetQuality() function TestBlur:testGetQuality()
local blur = Blur.new({quality = 7}) local blur = Blur.new({ quality = 7 })
luaunit.assertEquals(blur:getQuality(), 7) luaunit.assertEquals(blur:getQuality(), 7)
end end
function TestBlur:testGetTaps() function TestBlur:testGetTaps()
local blur = Blur.new({quality = 5}) local blur = Blur.new({ quality = 5 })
luaunit.assertIsNumber(blur:getTaps()) luaunit.assertIsNumber(blur:getTaps())
luaunit.assertTrue(blur:getTaps() > 0) luaunit.assertTrue(blur:getTaps() > 0)
luaunit.assertTrue(blur:getTaps() % 2 == 1) -- Must be odd luaunit.assertTrue(blur:getTaps() % 2 == 1) -- Must be odd
@@ -408,8 +415,8 @@ end
function TestBlur:testClearCacheDoesNotError() function TestBlur:testClearCacheDoesNotError()
-- Create some blur instances to populate cache -- Create some blur instances to populate cache
local blur1 = Blur.new({quality = 5}) Blur.new({ quality = 5 })
local blur2 = Blur.new({quality = 8}) Blur.new({ quality = 8 })
-- Should not error -- Should not error
Blur.clearCache() Blur.clearCache()

View File

@@ -1,22 +1,19 @@
---@diagnostic disable: undefined-global, undefined-field package.path = package.path .. ";./?.lua;./modules/?.lua"
local lu = require("testing.luaunit") 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)
-- Mock love globals for testing environment require("testing.loveStub")
_G.love = _G.love or {} local luaunit = require("testing.luaunit")
_G.love.graphics = _G.love.graphics or {} -- only going to load calc (and ErrorHandler as its a required dependency for calc to work properly)
_G.love.graphics.getDimensions = function()
return 1920, 1080
end
_G.love.window = _G.love.window or {}
_G.love.window.getMode = function()
return 1920, 1080
end
-- Load Calc module directly
local Calc = require("modules.Calc") local Calc = require("modules.Calc")
local ErrorHandler = require("modules.ErrorHandler") local ErrorHandler = require("modules.ErrorHandler")
-- Initialize with error handler
ErrorHandler.init({}) ErrorHandler.init({})
Calc.init({ ErrorHandler = ErrorHandler }) Calc.init({ ErrorHandler = ErrorHandler })
@@ -34,188 +31,188 @@ end
--- Test basic arithmetic: addition --- Test basic arithmetic: addition
function TestCalc:testBasicAddition() function TestCalc:testBasicAddition()
local calcObj = Calc.new("100px + 50px") local calcObj = Calc.new("100px + 50px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 150) luaunit.assertEquals(result, 150)
end end
--- Test basic arithmetic: subtraction --- Test basic arithmetic: subtraction
function TestCalc:testBasicSubtraction() function TestCalc:testBasicSubtraction()
local calcObj = Calc.new("100px - 30px") local calcObj = Calc.new("100px - 30px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 70) luaunit.assertEquals(result, 70)
end end
--- Test basic arithmetic: multiplication --- Test basic arithmetic: multiplication
function TestCalc:testBasicMultiplication() function TestCalc:testBasicMultiplication()
local calcObj = Calc.new("10px * 5") local calcObj = Calc.new("10px * 5")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 50) luaunit.assertEquals(result, 50)
end end
--- Test basic arithmetic: division --- Test basic arithmetic: division
function TestCalc:testBasicDivision() function TestCalc:testBasicDivision()
local calcObj = Calc.new("100px / 4") local calcObj = Calc.new("100px / 4")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 25) luaunit.assertEquals(result, 25)
end end
--- Test negative numbers --- Test negative numbers
function TestCalc:testNegativeNumbers() function TestCalc:testNegativeNumbers()
local calcObj = Calc.new("-50px + 100px") local calcObj = Calc.new("-50px + 100px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 50) luaunit.assertEquals(result, 50)
end end
--- Test decimal numbers --- Test decimal numbers
function TestCalc:testDecimalNumbers() function TestCalc:testDecimalNumbers()
local calcObj = Calc.new("10.5px + 5.5px") local calcObj = Calc.new("10.5px + 5.5px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 16) luaunit.assertEquals(result, 16)
end end
--- Test percentage units --- Test percentage units
function TestCalc:testPercentageUnits() function TestCalc:testPercentageUnits()
local calcObj = Calc.new("50% + 25%") local calcObj = Calc.new("50% + 25%")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil) -- parent size = 1000 local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil) -- parent size = 1000
lu.assertEquals(result, 750) -- 50% of 1000 + 25% of 1000 = 500 + 250 luaunit.assertEquals(result, 750) -- 50% of 1000 + 25% of 1000 = 500 + 250
end end
--- Test viewport width units (vw) --- Test viewport width units (vw)
function TestCalc:testViewportWidthUnits() function TestCalc:testViewportWidthUnits()
local calcObj = Calc.new("50vw - 10vw") local calcObj = Calc.new("50vw - 10vw")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 768) -- 40% of 1920 = 768 luaunit.assertEquals(result, 768) -- 40% of 1920 = 768
end end
--- Test viewport height units (vh) --- Test viewport height units (vh)
function TestCalc:testViewportHeightUnits() function TestCalc:testViewportHeightUnits()
local calcObj = Calc.new("50vh + 10vh") local calcObj = Calc.new("50vh + 10vh")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 648) -- 60% of 1080 = 648 luaunit.assertEquals(result, 648) -- 60% of 1080 = 648
end end
--- Test mixed units --- Test mixed units
function TestCalc:testMixedUnits() function TestCalc:testMixedUnits()
local calcObj = Calc.new("50% - 10vw") local calcObj = Calc.new("50% - 10vw")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil)
lu.assertEquals(result, 308) -- 50% of 1000 - 10% of 1920 = 500 - 192 = 308 luaunit.assertEquals(result, 308) -- 50% of 1000 - 10% of 1920 = 500 - 192 = 308
end end
--- Test complex expression with multiple operations --- Test complex expression with multiple operations
function TestCalc:testComplexExpression() function TestCalc:testComplexExpression()
local calcObj = Calc.new("100px + 50px - 20px") local calcObj = Calc.new("100px + 50px - 20px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 130) luaunit.assertEquals(result, 130)
end end
--- Test parentheses for precedence --- Test parentheses for precedence
function TestCalc:testParentheses() function TestCalc:testParentheses()
local calcObj = Calc.new("(100px + 50px) * 2") local calcObj = Calc.new("(100px + 50px) * 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 300) luaunit.assertEquals(result, 300)
end end
--- Test nested parentheses --- Test nested parentheses
function TestCalc:testNestedParentheses() function TestCalc:testNestedParentheses()
local calcObj = Calc.new("((100px + 50px) / 3) * 2") local calcObj = Calc.new("((100px + 50px) / 3) * 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 100) -- (150 / 3) * 2 = 50 * 2 = 100 luaunit.assertEquals(result, 100) -- (150 / 3) * 2 = 50 * 2 = 100
end end
--- Test operator precedence (multiplication before addition) --- Test operator precedence (multiplication before addition)
function TestCalc:testOperatorPrecedence() function TestCalc:testOperatorPrecedence()
local calcObj = Calc.new("100px + 50px * 2") local calcObj = Calc.new("100px + 50px * 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 200) -- 100 + (50 * 2) = 100 + 100 = 200 luaunit.assertEquals(result, 200) -- 100 + (50 * 2) = 100 + 100 = 200
end end
--- Test centering use case (50% - 10vw) --- Test centering use case (50% - 10vw)
function TestCalc:testCenteringUseCase() function TestCalc:testCenteringUseCase()
local calcObj = Calc.new("50% - 10vw") local calcObj = Calc.new("50% - 10vw")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Assuming element width is 20vw (384px) and parent width is 1920px -- Assuming element width is 20vw (384px) and parent width is 1920px
-- 50% of parent - 10vw should center it -- 50% of parent - 10vw should center it
local result = Calc.resolve(calcObj, 1920, 1080, 1920, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, 1920, nil, nil)
lu.assertEquals(result, 768) -- 50% of 1920 - 10% of 1920 = 960 - 192 = 768 luaunit.assertEquals(result, 768) -- 50% of 1920 - 10% of 1920 = 960 - 192 = 768
end end
--- Test element width units (ew) --- Test element width units (ew)
function TestCalc:testElementWidthUnits() function TestCalc:testElementWidthUnits()
local calcObj = Calc.new("100ew - 20ew") local calcObj = Calc.new("100ew - 20ew")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, 500, nil) -- element width = 500 local result = Calc.resolve(calcObj, 1920, 1080, nil, 500, nil) -- element width = 500
lu.assertEquals(result, 400) -- 80% of 500 = 400 luaunit.assertEquals(result, 400) -- 80% of 500 = 400
end end
--- Test element height units (eh) --- Test element height units (eh)
function TestCalc:testElementHeightUnits() function TestCalc:testElementHeightUnits()
local calcObj = Calc.new("50eh + 25eh") local calcObj = Calc.new("50eh + 25eh")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, 300) -- element height = 300 local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, 300) -- element height = 300
lu.assertEquals(result, 225) -- 75% of 300 = 225 luaunit.assertEquals(result, 225) -- 75% of 300 = 225
end end
--- Test whitespace handling --- Test whitespace handling
function TestCalc:testWhitespaceHandling() function TestCalc:testWhitespaceHandling()
local calcObj = Calc.new(" 100px + 50px ") local calcObj = Calc.new(" 100px + 50px ")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 150) luaunit.assertEquals(result, 150)
end end
--- Test zero value --- Test zero valuaunite
function TestCalc:testZeroValue() function TestCalc:testZeroValuaunite()
local calcObj = Calc.new("100px - 100px") local calcObj = Calc.new("100px - 100px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test single value (no operation) --- Test single valuaunite (no operation)
function TestCalc:testSingleValue() function TestCalc:testSingleValuaunite()
local calcObj = Calc.new("100px") local calcObj = Calc.new("100px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 100) luaunit.assertEquals(result, 100)
end end
--- Test isCalc function with non-calc values --- Test isCalc function with non-calc valuaunites
function TestCalc:testIsCalcWithNonCalcValues() function TestCalc:testIsCalcWithNonCalcValuaunites()
lu.assertFalse(Calc.isCalc("100px")) luaunit.assertFalse(Calc.isCalc("100px"))
lu.assertFalse(Calc.isCalc(100)) luaunit.assertFalse(Calc.isCalc(100))
lu.assertFalse(Calc.isCalc(nil)) luaunit.assertFalse(Calc.isCalc(nil))
lu.assertFalse(Calc.isCalc({})) luaunit.assertFalse(Calc.isCalc({}))
end end
--- Test division by zero error handling --- Test division by zero error handling
function TestCalc:testDivisionByZeroHandling() function TestCalc:testDivisionByZeroHandling()
local calcObj = Calc.new("100px / 0") local calcObj = Calc.new("100px / 0")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) -- Should return 0 on division by zero error luaunit.assertEquals(result, 0) -- Should return 0 on division by zero error
end end
--- Test invalid expression error handling --- Test invalid expression error handling
function TestCalc:testInvalidExpressionHandling() function TestCalc:testInvalidExpressionHandling()
local calcObj = Calc.new("100px +") -- Incomplete expression local calcObj = Calc.new("100px +") -- Incomplete expression
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should return 0 for invalid expressions -- Should return 0 for invalid expressions
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test complex real-world centering scenario --- Test complex real-world centering scenario
@@ -224,7 +221,7 @@ function TestCalc:testRealWorldCentering()
local xCalc = Calc.new("50% - 10vw") local xCalc = Calc.new("50% - 10vw")
local result = Calc.resolve(xCalc, 1920, 1080, 1920, nil, nil) local result = Calc.resolve(xCalc, 1920, 1080, 1920, nil, nil)
-- Expected: 50% of 1920 - 10% of 1920 = 960 - 192 = 768 -- Expected: 50% of 1920 - 10% of 1920 = 960 - 192 = 768
lu.assertEquals(result, 768) luaunit.assertEquals(result, 768)
end end
-- ============================================================================ -- ============================================================================
@@ -234,314 +231,314 @@ end
--- Test deeply nested parentheses (3 levels) --- Test deeply nested parentheses (3 levels)
function TestCalc:testDeeplyNested3Levels() function TestCalc:testDeeplyNested3Levels()
local calcObj = Calc.new("(((100px + 50px) * 2) - 100px) / 2") local calcObj = Calc.new("(((100px + 50px) * 2) - 100px) / 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (((150) * 2) - 100) / 2 = (300 - 100) / 2 = 200 / 2 = 100 -- (((150) * 2) - 100) / 2 = (300 - 100) / 2 = 200 / 2 = 100
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 100) luaunit.assertEquals(result, 100)
end end
--- Test deeply nested parentheses (5 levels) --- Test deeply nested parentheses (5 levels)
function TestCalc:testDeeplyNested5Levels() function TestCalc:testDeeplyNested5Levels()
local calcObj = Calc.new("(((((10px + 5px) * 2) + 10px) * 2) - 20px) / 2") local calcObj = Calc.new("(((((10px + 5px) * 2) + 10px) * 2) - 20px) / 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (((((15) * 2) + 10) * 2) - 20) / 2 -- (((((15) * 2) + 10) * 2) - 20) / 2
-- ((((30) + 10) * 2) - 20) / 2 -- ((((30) + 10) * 2) - 20) / 2
-- (((40) * 2) - 20) / 2 -- (((40) * 2) - 20) / 2
-- ((80) - 20) / 2 -- ((80) - 20) / 2
-- (60) / 2 = 30 -- (60) / 2 = 30
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 30) luaunit.assertEquals(result, 30)
end end
--- Test deeply nested parentheses (10 levels) --- Test deeply nested parentheses (10 levels)
function TestCalc:testDeeplyNested10Levels() function TestCalc:testDeeplyNested10Levels()
local calcObj = Calc.new("((((((((((2px * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2)") local calcObj = Calc.new("((((((((((2px * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 2 * 2^10 = 2 * 1024 = 2048 -- 2 * 2^10 = 2 * 1024 = 2048
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 2048) luaunit.assertEquals(result, 2048)
end end
--- Test complex multi-operation expression with all operators --- Test complex multi-operation expression with all operators
function TestCalc:testComplexMultiOperationAllOperators() function TestCalc:testComplexMultiOperationAllOperators()
local calcObj = Calc.new("100px + 50px - 20px * 2 / 4 + 30px") local calcObj = Calc.new("100px + 50px - 20px * 2 / 4 + 30px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Precedence: 20 * 2 = 40, 40 / 4 = 10 -- Precedence: 20 * 2 = 40, 40 / 4 = 10
-- Then: 100 + 50 - 10 + 30 = 170 -- Then: 100 + 50 - 10 + 30 = 170
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 170) luaunit.assertEquals(result, 170)
end end
--- Test complex expression with mixed units and all operators --- Test complex expression with mixed units and all operators
function TestCalc:testComplexMixedUnitsAllOperators() function TestCalc:testComplexMixedUnitsAllOperators()
local calcObj = Calc.new("50% + 10vw - 5vh * 2 / 4") local calcObj = Calc.new("50% + 10vw - 5vh * 2 / 4")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 50% = 500 (parent 1000), 10vw = 192, 5vh = 54, 54 * 2 = 108, 108 / 4 = 27 -- 50% = 500 (parent 1000), 10vw = 192, 5vh = 54, 54 * 2 = 108, 108 / 4 = 27
-- 500 + 192 - 27 = 665 -- 500 + 192 - 27 = 665
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil)
lu.assertEquals(result, 665) luaunit.assertEquals(result, 665)
end end
--- Test nested parentheses with mixed operations --- Test nested parentheses with mixed operations
function TestCalc:testNestedParenthesesMixedOperations() function TestCalc:testNestedParenthesesMixedOperations()
local calcObj = Calc.new("((100px + 50px) * (200px - 100px)) / 50px") local calcObj = Calc.new("((100px + 50px) * (200px - 100px)) / 50px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (150 * 100) / 50 = 15000 / 50 = 300 -- (150 * 100) / 50 = 15000 / 50 = 300
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 300) luaunit.assertEquals(result, 300)
end end
--- Test extremely long expression with many operations --- Test extremely long expression with many operations
function TestCalc:testExtremelyLongExpression() function TestCalc:testExtremelyLongExpression()
local calcObj = Calc.new("10px + 20px + 30px + 40px + 50px - 5px - 10px - 15px * 2 / 3 + 100px") local calcObj = Calc.new("10px + 20px + 30px + 40px + 50px - 5px - 10px - 15px * 2 / 3 + 100px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 15 * 2 / 3 = 30 / 3 = 10 -- 15 * 2 / 3 = 30 / 3 = 10
-- 10 + 20 + 30 + 40 + 50 - 5 - 10 - 10 + 100 = 225 -- 10 + 20 + 30 + 40 + 50 - 5 - 10 - 10 + 100 = 225
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 225) luaunit.assertEquals(result, 225)
end end
--- Test alternating operations with parentheses --- Test alternating operations with parentheses
function TestCalc:testAlternatingOperationsWithParentheses() function TestCalc:testAlternatingOperationsWithParentheses()
local calcObj = Calc.new("(50px + 50px) * (100px - 50px) / (25px + 25px)") local calcObj = Calc.new("(50px + 50px) * (100px - 50px) / (25px + 25px)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (100) * (50) / (50) = 5000 / 50 = 100 -- (100) * (50) / (50) = 5000 / 50 = 100
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 100) luaunit.assertEquals(result, 100)
end end
--- Test very large numbers --- Test very large numbers
function TestCalc:testVeryLargeNumbers() function TestCalc:testVeryLargeNumbers()
local calcObj = Calc.new("10000px + 50000px * 2") local calcObj = Calc.new("10000px + 50000px * 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 50000 * 2 = 100000, 10000 + 100000 = 110000 -- 50000 * 2 = 100000, 10000 + 100000 = 110000
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 110000) luaunit.assertEquals(result, 110000)
end end
--- Test very small decimal numbers --- Test very small decimal numbers
function TestCalc:testVerySmallDecimals() function TestCalc:testVerySmallDecimals()
local calcObj = Calc.new("0.1px + 0.2px + 0.3px") local calcObj = Calc.new("0.1px + 0.2px + 0.3px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertAlmostEquals(result, 0.6, 0.0001) luaunit.assertAlmostEquals(result, 0.6, 0.0001)
end end
--- Test negative numbers in complex expression --- Test negative numbers in complex expression
function TestCalc:testNegativeNumbersInComplexExpression() function TestCalc:testNegativeNumbersInComplexExpression()
local calcObj = Calc.new("(-50px + 100px) * (-2px + 5px)") local calcObj = Calc.new("(-50px + 100px) * (-2px + 5px)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (50) * (3) = 150 -- (50) * (3) = 150
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 150) luaunit.assertEquals(result, 150)
end end
--- Test multiple negative numbers --- Test multiple negative numbers
function TestCalc:testMultipleNegativeNumbers() function TestCalc:testMultipleNegativeNumbers()
local calcObj = Calc.new("-50px - 30px - 20px") local calcObj = Calc.new("-50px - 30px - 20px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- -50 - 30 - 20 = -100 -- -50 - 30 - 20 = -100
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, -100) luaunit.assertEquals(result, -100)
end end
--- Test negative result from subtraction --- Test negative result from subtraction
function TestCalc:testNegativeResultFromSubtraction() function TestCalc:testNegativeResultFromSubtraction()
local calcObj = Calc.new("50px - 100px") local calcObj = Calc.new("50px - 100px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, -50) luaunit.assertEquals(result, -50)
end end
--- Test all unit types in single expression --- Test all unit types in single expression
function TestCalc:testAllUnitTypesInSingleExpression() function TestCalc:testAlluaunitnitTypesInSingleExpression()
local calcObj = Calc.new("100px + 10% + 5vw + 5vh + 10ew + 10eh") local calcObj = Calc.new("100px + 10% + 5vw + 5vh + 10ew + 10eh")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 100 + 100 (10% of 1000) + 96 (5% of 1920) + 54 (5% of 1080) + 50 (10% of 500) + 30 (10% of 300) -- 100 + 100 (10% of 1000) + 96 (5% of 1920) + 54 (5% of 1080) + 50 (10% of 500) + 30 (10% of 300)
-- = 100 + 100 + 96 + 54 + 50 + 30 = 430 -- = 100 + 100 + 96 + 54 + 50 + 30 = 430
local result = Calc.resolve(calcObj, 1920, 1080, 1000, 500, 300) local result = Calc.resolve(calcObj, 1920, 1080, 1000, 500, 300)
lu.assertEquals(result, 430) luaunit.assertEquals(result, 430)
end end
--- Test precedence with multiple levels --- Test precedence with multiple levels
function TestCalc:testPrecedenceWithMultipleLevels() function TestCalc:testPrecedenceWithMultipleLevels()
local calcObj = Calc.new("100px + 50px * 2 - 30px / 3") local calcObj = Calc.new("100px + 50px * 2 - 30px / 3")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 50 * 2 = 100, 30 / 3 = 10 -- 50 * 2 = 100, 30 / 3 = 10
-- 100 + 100 - 10 = 190 -- 100 + 100 - 10 = 190
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 190) luaunit.assertEquals(result, 190)
end end
--- Test parentheses overriding precedence in complex way --- Test parentheses overriding precedence in complex way
function TestCalc:testParenthesesOverridingPrecedenceComplex() function TestCalc:testParenthesesOverridingPrecedenceComplex()
local calcObj = Calc.new("(100px + 50px) * (2px + 3px) - (30px + 20px) / (5px - 3px)") local calcObj = Calc.new("(100px + 50px) * (2px + 3px) - (30px + 20px) / (5px - 3px)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (150) * (5) - (50) / (2) = 750 - 25 = 725 -- (150) * (5) - (50) / (2) = 750 - 25 = 725
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 725) luaunit.assertEquals(result, 725)
end end
--- Test percentage calculations with zero parent --- Test percentage calculations with zero parent
function TestCalc:testPercentageWithZeroParent() function TestCalc:testPercentageWithZeroParent()
local calcObj = Calc.new("50% + 100px") local calcObj = Calc.new("50% + 100px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 50% of 0 = 0, 0 + 100 = 100 -- 50% of 0 = 0, 0 + 100 = 100
local result = Calc.resolve(calcObj, 1920, 1080, 0, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, 0, nil, nil)
lu.assertEquals(result, 100) luaunit.assertEquals(result, 100)
end end
--- Test element units without element dimensions --- Test element units without element dimensions
function TestCalc:testElementUnitsWithoutDimensions() function TestCalc:testElementUnitsWithoutDimensions()
local calcObj = Calc.new("100ew + 50eh") local calcObj = Calc.new("100ew + 50eh")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should return 0 + 0 = 0 due to missing dimensions -- Should return 0 + 0 = 0 due to missing dimensions
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test mixed parentheses and operations at different levels --- Test mixed parentheses and operations at different levels
function TestCalc:testMixedParenthesesDifferentLevels() function TestCalc:testMixedParenthesesDifferentLevels()
local calcObj = Calc.new("((100px + 50px) * 2) + (200px / (10px + 10px))") local calcObj = Calc.new("((100px + 50px) * 2) + (200px / (10px + 10px))")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- ((150) * 2) + (200 / (20)) = 300 + 10 = 310 -- ((150) * 2) + (200 / (20)) = 300 + 10 = 310
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 310) luaunit.assertEquals(result, 310)
end end
--- Test chain multiplication --- Test chain multiplication
function TestCalc:testChainMultiplication() function TestCalc:testChainMultiplication()
local calcObj = Calc.new("2px * 3 * 4 * 5") local calcObj = Calc.new("2px * 3 * 4 * 5")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 2 * 3 * 4 * 5 = 120 -- 2 * 3 * 4 * 5 = 120
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 120) luaunit.assertEquals(result, 120)
end end
--- Test chain division --- Test chain division
function TestCalc:testChainDivision() function TestCalc:testChainDivision()
local calcObj = Calc.new("1000px / 2 / 5 / 10") local calcObj = Calc.new("1000px / 2 / 5 / 10")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 1000 / 2 / 5 / 10 = 500 / 5 / 10 = 100 / 10 = 10 -- 1000 / 2 / 5 / 10 = 500 / 5 / 10 = 100 / 10 = 10
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 10) luaunit.assertEquals(result, 10)
end end
--- Test fractional results --- Test fractional results
function TestCalc:testFractionalResults() function TestCalc:testFractionalResults()
local calcObj = Calc.new("100px / 3") local calcObj = Calc.new("100px / 3")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertAlmostEquals(result, 33.333333333, 0.0001) luaunit.assertAlmostEquals(result, 33.333333333, 0.0001)
end end
--- Test complex viewport-based layout calculation --- Test complex viewport-based layout calculation
function TestCalc:testComplexViewportBasedLayout() function TestCalc:testComplexViewportBasedLayout()
-- Simulate: margin-left = (100vw - element_width) / 2, where element is 30vw -- Simulate: margin-left = (100vw - element_width) / 2, where element is 30vw
local calcObj = Calc.new("(100vw - 30vw) / 2") local calcObj = Calc.new("(100vw - 30vw) / 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (1920 - 576) / 2 = 1344 / 2 = 672 -- (1920 - 576) / 2 = 1344 / 2 = 672
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 672) luaunit.assertEquals(result, 672)
end end
--- Test complex responsive sizing calculation --- Test complex responsive sizing calculation
function TestCalc:testComplexResponsiveSizing() function TestCalc:testComplexResponsiveSizing()
-- Simulate: width = 100% - 20px padding on each side - 10vw margin -- Simulate: width = 100% - 20px padding on each side - 10vw margin
local calcObj = Calc.new("100% - 40px - 10vw") local calcObj = Calc.new("100% - 40px - 10vw")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 100% of 1000 - 40 - 10% of 1920 = 1000 - 40 - 192 = 768 -- 100% of 1000 - 40 - 10% of 1920 = 1000 - 40 - 192 = 768
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil)
lu.assertEquals(result, 768) luaunit.assertEquals(result, 768)
end end
--- Test expression with leading negative in parentheses --- Test expression with leading negative in parentheses
function TestCalc:testLeadingNegativeInParentheses() function TestCalc:testLeadingNegativeInParentheses()
local calcObj = Calc.new("100px + (-50px * 2)") local calcObj = Calc.new("100px + (-50px * 2)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 100 + (-100) = 0 -- 100 + (-100) = 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test multiple parentheses groups at same level --- Test multiple parentheses groups at same level
function TestCalc:testMultipleParenthesesGroupsSameLevel() function TestCalc:testMultipleParenthesesGroupsSameLevel()
local calcObj = Calc.new("(100px + 50px) + (200px - 100px) + (300px / 3)") local calcObj = Calc.new("(100px + 50px) + (200px - 100px) + (300px / 3)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 150 + 100 + 100 = 350 -- 150 + 100 + 100 = 350
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 350) luaunit.assertEquals(result, 350)
end end
--- Test near-zero division result --- Test near-zero division result
function TestCalc:testNearZeroDivisionResult() function TestCalc:testNearZeroDivisionResult()
local calcObj = Calc.new("1px / 1000") local calcObj = Calc.new("1px / 1000")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertAlmostEquals(result, 0.001, 0.0001) luaunit.assertAlmostEquals(result, 0.001, 0.0001)
end end
--- Test expression with only multiplication and division --- Test expression with only multiplication and division
function TestCalc:testOnlyMultiplicationAndDivision() function TestCalc:testOnlyMultiplicationAndDivision()
local calcObj = Calc.new("100px * 2 / 4 * 3 / 5") local calcObj = Calc.new("100px * 2 / 4 * 3 / 5")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 100 * 2 / 4 * 3 / 5 = 200 / 4 * 3 / 5 = 50 * 3 / 5 = 150 / 5 = 30 -- 100 * 2 / 4 * 3 / 5 = 200 / 4 * 3 / 5 = 50 * 3 / 5 = 150 / 5 = 30
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 30) luaunit.assertEquals(result, 30)
end end
--- Test expression with decimal percentages --- Test expression with decimal percentages
function TestCalc:testDecimalPercentages() function TestCalc:testDecimalPercentages()
local calcObj = Calc.new("12.5% + 37.5%") local calcObj = Calc.new("12.5% + 37.5%")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 12.5% + 37.5% = 50% of 1000 = 500 -- 12.5% + 37.5% = 50% of 1000 = 500
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil)
lu.assertEquals(result, 500) luaunit.assertEquals(result, 500)
end end
--- Test unitless numbers in multiplication/division --- Test unitless numbers in multiplication/division
function TestCalc:testUnitlessNumbersInMultDiv() function TestCalc:testUnitlessNumbersInMultDiv()
local calcObj = Calc.new("100px * 2.5 / 0.5") local calcObj = Calc.new("100px * 2.5 / 0.5")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- 100 * 2.5 / 0.5 = 250 / 0.5 = 500 -- 100 * 2.5 / 0.5 = 250 / 0.5 = 500
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 500) luaunit.assertEquals(result, 500)
end end
--- Test deeply nested with negative numbers --- Test deeply nested with negative numbers
function TestCalc:testDeeplyNestedWithNegatives() function TestCalc:testDeeplyNestedWithNegatives()
local calcObj = Calc.new("((-100px + 200px) * (-2px + 5px)) / (10px - 5px)") local calcObj = Calc.new("((-100px + 200px) * (-2px + 5px)) / (10px - 5px)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- ((100) * (3)) / (5) = 300 / 5 = 60 -- ((100) * (3)) / (5) = 300 / 5 = 60
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 60) luaunit.assertEquals(result, 60)
end end
--- Test asymmetric nested parentheses --- Test asymmetric nested parentheses
function TestCalc:testAsymmetricNestedParentheses() function TestCalc:testAsymmetricNestedParentheses()
local calcObj = Calc.new("((100px + 50px) * 2) + 200px / 4") local calcObj = Calc.new("((100px + 50px) * 2) + 200px / 4")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (150 * 2) + (200 / 4) = 300 + 50 = 350 -- (150 * 2) + (200 / 4) = 300 + 50 = 350
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 350) luaunit.assertEquals(result, 350)
end end
--- Test maximum nesting with all operations --- Test maximum nesting with all operations
function TestCalc:testMaximumNestingAllOperations() function TestCalc:testMaximumNestingAllOperations()
local calcObj = Calc.new("((((100px + 50px) - 30px) * 2) / 4)") local calcObj = Calc.new("((((100px + 50px) - 30px) * 2) / 4)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- ((((150) - 30) * 2) / 4) = (((120) * 2) / 4) = ((240) / 4) = 60 -- ((((150) - 30) * 2) / 4) = (((120) * 2) / 4) = ((240) / 4) = 60
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 60) luaunit.assertEquals(result, 60)
end end
--- Test whitespace in complex expressions --- Test whitespace in complex expressions
function TestCalc:testWhitespaceInComplexExpression() function TestCalc:testWhitespaceInComplexExpression()
local calcObj = Calc.new(" ( 100px + 50px ) * ( 2px + 3px ) ") local calcObj = Calc.new(" ( 100px + 50px ) * ( 2px + 3px ) ")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- (150) * (5) = 750 -- (150) * (5) = 750
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 750) luaunit.assertEquals(result, 750)
end end
-- ============================================================================ -- ============================================================================
@@ -551,111 +548,111 @@ end
--- Test mismatched parentheses (missing closing) --- Test mismatched parentheses (missing closing)
function TestCalc:testMismatchedParenthesesMissingClosing() function TestCalc:testMismatchedParenthesesMissingClosing()
local calcObj = Calc.new("((100px + 50px) * 2") local calcObj = Calc.new("((100px + 50px) * 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test mismatched parentheses (missing opening) --- Test mismatched parentheses (missing opening)
function TestCalc:testMismatchedParenthesesMissingOpening() function TestCalc:testMismatchedParenthesesMissingOpening()
local calcObj = Calc.new("100px + 50px) * 2") local calcObj = Calc.new("100px + 50px) * 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test empty parentheses --- Test empty parentheses
function TestCalc:testEmptyParentheses() function TestCalc:testEmptyParentheses()
local calcObj = Calc.new("100px + ()") local calcObj = Calc.new("100px + ()")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test consecutive operators --- Test consecutive operators
function TestCalc:testConsecutiveOperators() function TestCalc:testConsecutiveOperators()
local calcObj = Calc.new("100px ++ 50px") local calcObj = Calc.new("100px ++ 50px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test trailing operator --- Test trailing operator
function TestCalc:testTrailingOperator() function TestCalc:testTrailingOperator()
local calcObj = Calc.new("100px + 50px *") local calcObj = Calc.new("100px + 50px *")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test leading operator (non-negative) --- Test leading operator (non-negative)
function TestCalc:testLeadingOperatorNonNegative() function TestCalc:testLeadingOperatorNonNegative()
local calcObj = Calc.new("+ 100px") local calcObj = Calc.new("+ 100px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test invalid unit --- Test invalid unit
function TestCalc:testInvalidUnit() function TestCalc:testInvalidUnit()
local calcObj = Calc.new("100xyz + 50px") local calcObj = Calc.new("100xyz + 50px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test mixed invalid syntax --- Test mixed invalid syntax
function TestCalc:testMixedInvalidSyntax() function TestCalc:testMixedInvalidSyntax()
local calcObj = Calc.new("100px + * 50px") local calcObj = Calc.new("100px + * 50px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test special characters --- Test special characters
function TestCalc:testSpecialCharacters() function TestCalc:testSpecialCharacters()
local calcObj = Calc.new("100px + 50px @ 20px") local calcObj = Calc.new("100px + 50px @ 20px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test extremely long invalid expression --- Test extremely long invalid expression
function TestCalc:testExtremelyLongInvalidExpression() function TestCalc:testExtremelyLongInvalidExpression()
local calcObj = Calc.new("100px + + + + + + + + + + 50px") local calcObj = Calc.new("100px + + + + + + + + + + 50px")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle gracefully and return 0 -- Should handle gracefully and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test division by calculated zero --- Test division by calculated zero
function TestCalc:testDivisionByCalculatedZero() function TestCalc:testDivisionByCalculatedZero()
local calcObj = Calc.new("100px / (50px - 50px)") local calcObj = Calc.new("100px / (50px - 50px)")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle division by zero and return 0 -- Should handle division by zero and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
--- Test nested division by zero --- Test nested division by zero
function TestCalc:testNestedDivisionByZero() function TestCalc:testNestedDivisionByZero()
local calcObj = Calc.new("((100px + 50px) / 0) * 2") local calcObj = Calc.new("((100px + 50px) / 0) * 2")
lu.assertTrue(Calc.isCalc(calcObj)) luaunit.assertTrue(Calc.isCalc(calcObj))
-- Should handle division by zero and return 0 -- Should handle division by zero and return 0
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil) local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
lu.assertEquals(result, 0) luaunit.assertEquals(result, 0)
end end
if not _G.RUNNING_ALL_TESTS then if not _G.RUNNING_ALL_TESTS then
os.exit(lu.LuaUnit.run()) os.exit(luaunit.LuaUnit.run())
end end

View File

@@ -1,6 +1,16 @@
package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
require("testing.loveStub") require("testing.loveStub")
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
local ErrorHandler = require("modules.ErrorHandler") -- Load FlexLove
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
TestCriticalFailures = {} TestCriticalFailures = {}

View File

@@ -1,17 +1,4 @@
-- Test suite for Element mode override functionality
package.path = package.path .. ";./?.lua;./modules/?.lua" 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 local originalSearchers = package.searchers or package.loaders
table.insert(originalSearchers, 2, function(modname) table.insert(originalSearchers, 2, function(modname)
if modname:match("^FlexLove%.modules%.") then if modname:match("^FlexLove%.modules%.") then
@@ -22,7 +9,8 @@ table.insert(originalSearchers, 2, function(modname)
end end
end) end)
-- Load FlexLove which properly initializes all dependencies require("testing.loveStub")
local luaunit = require("testing.luaunit")
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
local StateManager = require("modules.StateManager") local StateManager = require("modules.StateManager")
@@ -85,24 +73,6 @@ function TestElementModeOverride:test_modeResolution_nilUsesGlobalRetained()
luaunit.assertEquals(element._elementMode, "retained") luaunit.assertEquals(element._elementMode, "retained")
end end
-- Test 05: ID auto-generation only for immediate mode
function TestElementModeOverride:test_idGeneration_onlyForImmediate()
-- Immediate element without ID should get auto-generated ID
local immediateEl = FlexLove.new({
mode = "immediate",
text = "Immediate",
})
luaunit.assertNotNil(immediateEl.id)
luaunit.assertNotEquals(immediateEl.id, "")
-- Retained element without ID should have empty ID
local retainedEl = FlexLove.new({
mode = "retained",
text = "Retained",
})
luaunit.assertEquals(retainedEl.id, "")
end
-- Test 06: Immediate override in retained context -- Test 06: Immediate override in retained context
function TestElementModeOverride:test_immediateOverrideInRetainedContext() function TestElementModeOverride:test_immediateOverrideInRetainedContext()
FlexLove.setMode("retained") FlexLove.setMode("retained")
@@ -117,20 +87,6 @@ function TestElementModeOverride:test_immediateOverrideInRetainedContext()
luaunit.assertEquals(element.id, "test-immediate") luaunit.assertEquals(element.id, "test-immediate")
end end
-- Test 07: Retained override in immediate context
function TestElementModeOverride:test_retainedOverrideInImmediateContext()
FlexLove.setMode("immediate")
FlexLove.beginFrame()
local element = FlexLove.new({
mode = "retained",
text = "Retained in immediate context",
})
luaunit.assertEquals(element._elementMode, "retained")
luaunit.assertEquals(element.id, "") -- Should not auto-generate ID
end
-- Test 08: Mixed-mode parent-child (immediate parent, retained child) -- Test 08: Mixed-mode parent-child (immediate parent, retained child)
function TestElementModeOverride:test_mixedMode_immediateParent_retainedChild() function TestElementModeOverride:test_mixedMode_immediateParent_retainedChild()
FlexLove.setMode("immediate") FlexLove.setMode("immediate")

View File

@@ -1,32 +1,17 @@
-- 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" 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 local originalSearchers = package.searchers or package.loaders
table.insert(originalSearchers, 2, function(modname) table.insert(originalSearchers, 2, function(modname)
if modname:match("^FlexLove%.modules%.") then if modname:match("^FlexLove%.modules%.") then
local moduleName = modname:gsub("^FlexLove%.modules%.", "") local moduleName = modname:gsub("^FlexLove%.modules%.", "")
return function() return require("modules." .. moduleName) end return function()
return require("modules." .. moduleName)
end
end end
end) end)
require("testing.loveStub")
-- Load FlexLove which properly initializes all dependencies local luaunit = require("testing.luaunit")
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
local Element = require("modules.Element")
local Color = require("modules.Color")
-- Initialize FlexLove
FlexLove.init() FlexLove.init()
-- ============================================================================ -- ============================================================================
@@ -37,7 +22,7 @@ local function createBasicElement(props)
props = props or {} props = props or {}
props.width = props.width or 100 props.width = props.width or 100
props.height = props.height or 100 props.height = props.height or 100
return Element.new(props) return FlexLove.new(props)
end end
-- ============================================================================ -- ============================================================================
@@ -47,7 +32,7 @@ end
TestElementCreation = {} TestElementCreation = {}
function TestElementCreation:setUp() function TestElementCreation:setUp()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
end end
function TestElementCreation:tearDown() function TestElementCreation:tearDown()
@@ -92,7 +77,7 @@ function TestElementCreation:test_element_with_backgroundColor()
y = 0, y = 0,
width = 100, width = 100,
height = 100, height = 100,
backgroundColor = { 1, 0, 0, 1 }, backgroundColor = FlexLove.Color.new(1, 0, 0, 1),
}) })
luaunit.assertNotNil(element) luaunit.assertNotNil(element)
@@ -195,7 +180,7 @@ end
TestElementSizing = {} TestElementSizing = {}
function TestElementSizing:setUp() function TestElementSizing:setUp()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
end end
function TestElementSizing:tearDown() function TestElementSizing:tearDown()
@@ -607,7 +592,7 @@ end
TestElementFlex = {} TestElementFlex = {}
function TestElementFlex:setUp() function TestElementFlex:setUp()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
end end
function TestElementFlex:tearDown() function TestElementFlex:tearDown()
@@ -761,12 +746,13 @@ end
TestElementStyling = {} TestElementStyling = {}
function TestElementStyling:setUp() function TestElementStyling:setUp()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
end end
function TestElementStyling:tearDown() function TestElementStyling:tearDown()
FlexLove.endFrame() FlexLove.endFrame()
end end
local Color = FlexLove.Color
function TestElementStyling:test_element_with_border() function TestElementStyling:test_element_with_border()
local element = FlexLove.new({ local element = FlexLove.new({
@@ -886,7 +872,7 @@ function TestElementStyling:test_element_with_corner_radius_table()
luaunit.assertNotNil(element.cornerRadius) luaunit.assertNotNil(element.cornerRadius)
luaunit.assertEquals(type(element.cornerRadius), "number") luaunit.assertEquals(type(element.cornerRadius), "number")
luaunit.assertEquals(element.cornerRadius, 10) luaunit.assertEquals(element.cornerRadius, 10)
-- Test non-uniform radius (should be stored as table) -- Test non-uniform radius (should be stored as table)
local element2 = FlexLove.new({ local element2 = FlexLove.new({
id = "test2", id = "test2",
@@ -896,7 +882,7 @@ function TestElementStyling:test_element_with_corner_radius_table()
height = 100, height = 100,
cornerRadius = { topLeft = 5, topRight = 10, bottomLeft = 15, bottomRight = 20 }, cornerRadius = { topLeft = 5, topRight = 10, bottomLeft = 15, bottomRight = 20 },
}) })
luaunit.assertNotNil(element2.cornerRadius) luaunit.assertNotNil(element2.cornerRadius)
luaunit.assertEquals(type(element2.cornerRadius), "table") luaunit.assertEquals(type(element2.cornerRadius), "table")
luaunit.assertEquals(element2.cornerRadius.topLeft, 5) luaunit.assertEquals(element2.cornerRadius.topLeft, 5)
@@ -929,7 +915,7 @@ end
TestElementMethods = {} TestElementMethods = {}
function TestElementMethods:setUp() function TestElementMethods:setUp()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
end end
function TestElementMethods:tearDown() function TestElementMethods:tearDown()

View File

@@ -1,5 +1,13 @@
-- Test suite for EventHandler module
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
require("testing.loveStub") require("testing.loveStub")
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
@@ -184,7 +192,7 @@ end
-- Test: processMouseEvents() returns early if no element -- Test: processMouseEvents() returns early if no element
-- function TestEventHandler:test_processMouseEvents_no_element() -- function TestEventHandler:test_processMouseEvents_no_element()
-- local handler = createEventHandler() -- local handler = createEventHandler()
-- --
-- -- Should not error -- -- Should not error
-- handler:processMouseEvents(element, 50, 50, true, true) -- handler:processMouseEvents(element, 50, 50, true, true)
-- end -- end
@@ -500,7 +508,7 @@ end
-- Test: processTouchEvents() returns early if no element -- Test: processTouchEvents() returns early if no element
-- function TestEventHandler:test_processTouchEvents_no_element() -- function TestEventHandler:test_processTouchEvents_no_element()
-- local handler = createEventHandler() -- local handler = createEventHandler()
-- --
-- -- Should not error -- -- Should not error
-- handler:processTouchEvents(element) -- handler:processTouchEvents(element)
-- end -- end

View File

@@ -1,15 +1,25 @@
package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
local ErrorHandler = require("modules.ErrorHandler")
require("testing.loveStub") require("testing.loveStub")
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
local Color = require("modules.Color") local Color = FlexLove.Color
local Theme = require("modules.Theme") local Theme = FlexLove.Theme
ErrorHandler.init({})
TestFlexLove = {} TestFlexLove = {}
function TestFlexLove:setUp() function TestFlexLove:setUp()
FlexLove.destroy() FlexLove.destroy()
FlexLove.init()
FlexLove.setMode("retained") FlexLove.setMode("retained")
end end

View File

@@ -1,25 +1,23 @@
-- Test suite for Grid layout functionality
-- Grid layout has 0% test coverage despite being integrated into the system
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
require("testing.loveStub")
local luaunit = require("testing.luaunit")
-- Setup package loader to map FlexLove.modules.X to modules/X
local originalSearchers = package.searchers or package.loaders local originalSearchers = package.searchers or package.loaders
table.insert(originalSearchers, 2, function(modname) table.insert(originalSearchers, 2, function(modname)
if modname:match("^FlexLove%.modules%.") then if modname:match("^FlexLove%.modules%.") then
local moduleName = modname:gsub("^FlexLove%.modules%.", "") local moduleName = modname:gsub("^FlexLove%.modules%.", "")
return function() return require("modules." .. moduleName) end return function()
return require("modules." .. moduleName)
end
end end
end) end)
require("testing.loveStub")
local luaunit = require("testing.luaunit")
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
TestGridLayout = {} TestGridLayout = {}
function TestGridLayout:setUp() function TestGridLayout:setUp()
FlexLove.beginFrame(1920, 1080) FlexLove.init()
FlexLove.beginFrame()
end end
function TestGridLayout:tearDown() function TestGridLayout:tearDown()
@@ -46,7 +44,7 @@ function TestGridLayout:test_default_grid_single_child()
}) })
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Child should be stretched to fill the entire grid cell -- Child should be stretched to fill the entire grid cell
luaunit.assertEquals(child.x, 0, "Child should be at x=0") luaunit.assertEquals(child.x, 0, "Child should be at x=0")
@@ -79,7 +77,7 @@ function TestGridLayout:test_2x2_grid_four_children()
end end
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Each cell should be 200x200 -- Each cell should be 200x200
-- Child 1: top-left (0, 0) -- Child 1: top-left (0, 0)
@@ -127,7 +125,7 @@ function TestGridLayout:test_grid_with_gaps()
end end
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Cell size: (420 - 20) / 2 = 200, (320 - 20) / 2 = 150 -- Cell size: (420 - 20) / 2 = 200, (320 - 20) / 2 = 150
luaunit.assertEquals(children[1].width, 200, "Cell width should be 200") luaunit.assertEquals(children[1].width, 200, "Cell width should be 200")
@@ -167,7 +165,7 @@ function TestGridLayout:test_grid_overflow_children()
end end
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- First 4 children should be positioned -- First 4 children should be positioned
luaunit.assertNotNil(children[1].x, "Child 1 should be positioned") luaunit.assertNotNil(children[1].x, "Child 1 should be positioned")
@@ -199,7 +197,7 @@ function TestGridLayout:test_grid_align_center()
}) })
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Cell is 200x200, child is 100x100, should be centered -- Cell is 200x200, child is 100x100, should be centered
-- Center position: (200 - 100) / 2 = 50 -- Center position: (200 - 100) / 2 = 50
@@ -231,7 +229,7 @@ function TestGridLayout:test_grid_align_flex_start()
}) })
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Child should be at top-left of cell -- Child should be at top-left of cell
luaunit.assertEquals(child.x, 0, "Child should be at left of cell") luaunit.assertEquals(child.x, 0, "Child should be at left of cell")
@@ -262,7 +260,7 @@ function TestGridLayout:test_grid_align_flex_end()
}) })
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Cell is 200x200, child is 100x100, should be at bottom-right -- Cell is 200x200, child is 100x100, should be at bottom-right
luaunit.assertEquals(child.x, 100, "Child should be at right of cell (200 - 100)") luaunit.assertEquals(child.x, 100, "Child should be at right of cell (200 - 100)")
@@ -293,7 +291,7 @@ function TestGridLayout:test_grid_with_padding()
}) })
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Available space: 500 - 50 - 50 = 400 -- Available space: 500 - 50 - 50 = 400
-- Cell size: 400 / 2 = 200 -- Cell size: 400 / 2 = 200
@@ -345,7 +343,7 @@ function TestGridLayout:test_grid_with_absolute_child()
}) })
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- child1 should be in first grid cell (0, 0) -- child1 should be in first grid cell (0, 0)
luaunit.assertEquals(child1.x, 0, "Child 1 should be at x=0") luaunit.assertEquals(child1.x, 0, "Child 1 should be at x=0")
@@ -375,7 +373,7 @@ function TestGridLayout:test_empty_grid()
}) })
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Should not crash -- Should not crash
luaunit.assertEquals(#container.children, 0, "Grid should have no children") luaunit.assertEquals(#container.children, 0, "Grid should have no children")
@@ -403,7 +401,7 @@ function TestGridLayout:test_grid_zero_dimensions()
-- This might cause division by zero or other errors -- This might cause division by zero or other errors
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Test passes if it doesn't crash -- Test passes if it doesn't crash
luaunit.assertTrue(true, "Grid with 0 dimensions should not crash") luaunit.assertTrue(true, "Grid with 0 dimensions should not crash")
@@ -444,7 +442,7 @@ function TestGridLayout:test_nested_grids()
end end
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Inner grid should be positioned in first cell of outer grid -- Inner grid should be positioned in first cell of outer grid
luaunit.assertEquals(innerGrid.x, 0, "Inner grid should be at x=0") luaunit.assertEquals(innerGrid.x, 0, "Inner grid should be at x=0")
@@ -485,7 +483,7 @@ function TestGridLayout:test_grid_with_reserved_space()
}) })
FlexLove.endFrame() FlexLove.endFrame()
FlexLove.beginFrame(1920, 1080) FlexLove.beginFrame()
-- Grid should account for reserved space -- Grid should account for reserved space
-- Available width: 400 - 50 (reserved left) = 350 -- Available width: 400 - 50 (reserved left) = 350

View File

@@ -1,6 +1,15 @@
package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
require("testing.loveStub") require("testing.loveStub")
local ImageCache = require("modules.ImageCache") local ImageCache = require("modules.ImageCache")
TestImageCache = {} TestImageCache = {}

View File

@@ -1,18 +1,21 @@
-- ImageRenderer Comprehensive Test Suite package.path = package.path .. ";./?.lua;./modules/?.lua"
-- Tests for ImageRenderer functionality including fit modes, positioning, tiling, and edge cases 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)
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
local ErrorHandler = require("modules.ErrorHandler") local ErrorHandler = require("modules.ErrorHandler")
-- Initialize ErrorHandler
ErrorHandler.init({}) ErrorHandler.init({})
require("testing.loveStub") require("testing.loveStub")
local ImageRenderer = require("modules.ImageRenderer") local ImageRenderer = require("modules.ImageRenderer")
local Color = require("modules.Color") local Color = require("modules.Color")
local utils = require("modules.utils") local utils = require("modules.utils")
-- Initialize ImageRenderer with dependencies
ImageRenderer.init({ ErrorHandler = ErrorHandler, utils = utils }) ImageRenderer.init({ ErrorHandler = ErrorHandler, utils = utils })
-- ============================================================================ -- ============================================================================
@@ -512,72 +515,37 @@ end
TestImageRendererElementIntegration = {} TestImageRendererElementIntegration = {}
function TestImageRendererElementIntegration:setUp() function TestImageRendererElementIntegration:setUp()
local Element = require("modules.Element") self.Flexlove = require("FlexLove")
local Units = require("modules.Units") self.Flexlove.init({})
local LayoutEngine = require("modules.LayoutEngine")
local Renderer = require("modules.Renderer")
local EventHandler = require("modules.EventHandler")
local ImageCache = require("modules.ImageCache")
local Context = require("modules.Context")
local StateManager = require("modules.StateManager")
local InputEvent = require("modules.InputEvent")
local Theme = require("modules.Theme")
local TextEditor = require("modules.TextEditor")
local ScrollManager = require("modules.ScrollManager")
local RoundedRect = require("modules.RoundedRect")
self.deps = {
utils = utils,
Color = Color,
Units = Units,
LayoutEngine = LayoutEngine,
Renderer = Renderer,
EventHandler = EventHandler,
ImageCache = ImageCache,
ImageRenderer = ImageRenderer,
ErrorHandler = ErrorHandler,
Context = Context,
StateManager = StateManager,
InputEvent = InputEvent,
Theme = Theme,
TextEditor = TextEditor,
ScrollManager = ScrollManager,
RoundedRect = RoundedRect,
}
-- Initialize Element with dependencies
Element.init(self.deps)
self.Element = Element
end end
function TestImageRendererElementIntegration:testElementImageRepeatProperty() function TestImageRendererElementIntegration:testElementImageRepeatProperty()
-- Test that Element accepts imageRepeat property -- Test that Element accepts imageRepeat property
local element = self.Element.new({ local element = self.Flexlove.new({
width = 200, width = 200,
height = 200, height = 200,
imageRepeat = "repeat", imageRepeat = "repeat",
}, self.deps) })
luaunit.assertEquals(element.imageRepeat, "repeat") luaunit.assertEquals(element.imageRepeat, "repeat")
end end
function TestImageRendererElementIntegration:testElementImageRepeatDefault() function TestImageRendererElementIntegration:testElementImageRepeatDefault()
-- Test that imageRepeat defaults to "no-repeat" -- Test that imageRepeat defaults to "no-repeat"
local element = self.Element.new({ local element = self.Flexlove.new({
width = 200, width = 200,
height = 200, height = 200,
}, self.deps) })
luaunit.assertEquals(element.imageRepeat, "no-repeat") luaunit.assertEquals(element.imageRepeat, "no-repeat")
end end
function TestImageRendererElementIntegration:testElementSetImageRepeat() function TestImageRendererElementIntegration:testElementSetImageRepeat()
-- Test setImageRepeat method -- Test setImageRepeat method
local element = self.Element.new({ local element = self.Flexlove.new({
width = 200, width = 200,
height = 200, height = 200,
}, self.deps) })
element:setImageRepeat("repeat-x") element:setImageRepeat("repeat-x")
luaunit.assertEquals(element.imageRepeat, "repeat-x") luaunit.assertEquals(element.imageRepeat, "repeat-x")
@@ -587,21 +555,21 @@ function TestImageRendererElementIntegration:testElementImageTintProperty()
-- Test that Element accepts imageTint property -- Test that Element accepts imageTint property
local redTint = Color.new(1, 0, 0, 1) local redTint = Color.new(1, 0, 0, 1)
local element = self.Element.new({ local element = self.Flexlove.new({
width = 200, width = 200,
height = 200, height = 200,
imageTint = redTint, imageTint = redTint,
}, self.deps) })
luaunit.assertEquals(element.imageTint, redTint) luaunit.assertEquals(element.imageTint, redTint)
end end
function TestImageRendererElementIntegration:testElementSetImageTint() function TestImageRendererElementIntegration:testElementSetImageTint()
-- Test setImageTint method -- Test setImageTint method
local element = self.Element.new({ local element = self.Flexlove.new({
width = 200, width = 200,
height = 200, height = 200,
}, self.deps) })
local blueTint = Color.new(0, 0, 1, 1) local blueTint = Color.new(0, 0, 1, 1)
element:setImageTint(blueTint) element:setImageTint(blueTint)
@@ -610,10 +578,10 @@ end
function TestImageRendererElementIntegration:testElementSetImageOpacity() function TestImageRendererElementIntegration:testElementSetImageOpacity()
-- Test setImageOpacity method -- Test setImageOpacity method
local element = self.Element.new({ local element = self.Flexlove.new({
width = 200, width = 200,
height = 200, height = 200,
}, self.deps) })
element:setImageOpacity(0.7) element:setImageOpacity(0.7)
luaunit.assertEquals(element.imageOpacity, 0.7) luaunit.assertEquals(element.imageOpacity, 0.7)

View File

@@ -1,13 +1,22 @@
package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
local ErrorHandler = require("modules.ErrorHandler") local ErrorHandler = require("modules.ErrorHandler")
-- Initialize ErrorHandler
ErrorHandler.init({}) ErrorHandler.init({})
require("testing.loveStub") require("testing.loveStub")
local ImageScaler = require("modules.ImageScaler") local ImageScaler = require("modules.ImageScaler")
-- Initialize ImageScaler with ErrorHandler
ImageScaler.init({ ErrorHandler = ErrorHandler }) ImageScaler.init({ ErrorHandler = ErrorHandler })
TestImageScaler = {} TestImageScaler = {}

View File

@@ -1,10 +1,14 @@
-- Comprehensive test suite for LayoutEngine.lua module
-- Consolidated from layout_engine_test.lua, layout_edge_cases_test.lua,
-- overflow_test.lua, and transform_test.lua
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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 love stub before anything else
require("testing.loveStub") require("testing.loveStub")
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
@@ -13,16 +17,6 @@ local Units = require("modules.Units")
local utils = require("modules.utils") local utils = require("modules.utils")
local ErrorHandler = require("modules.ErrorHandler") local ErrorHandler = require("modules.ErrorHandler")
local Animation = require("modules.Animation") local Animation = require("modules.Animation")
-- 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)
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
local Transform = Animation.Transform local Transform = Animation.Transform
@@ -695,6 +689,7 @@ end
TestLayoutEdgeCases = {} TestLayoutEdgeCases = {}
function TestLayoutEdgeCases:setUp() function TestLayoutEdgeCases:setUp()
FlexLove.init()
FlexLove.setMode("immediate") FlexLove.setMode("immediate")
FlexLove.beginFrame() FlexLove.beginFrame()
-- Capture warnings -- Capture warnings
@@ -1067,7 +1062,8 @@ end
TestOverflowDetection = {} TestOverflowDetection = {}
function TestOverflowDetection:setUp() function TestOverflowDetection:setUp()
FlexLove.beginFrame(1920, 1080) FlexLove.init()
FlexLove.beginFrame()
end end
function TestOverflowDetection:tearDown() function TestOverflowDetection:tearDown()

View File

@@ -1,9 +1,16 @@
-- Test retained children persisting when immediate parents recreate -- Test retained children persisting when immediate parents recreate
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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 love stub before anything else
require("testing.loveStub") require("testing.loveStub")
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")

View File

@@ -1,10 +1,15 @@
-- Test event handling for immediate children of retained parents
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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 love stub before anything else
require("testing.loveStub") require("testing.loveStub")
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
local ErrorHandler = require("modules.ErrorHandler") local ErrorHandler = require("modules.ErrorHandler")

View File

@@ -1,8 +1,16 @@
local lu = require("testing.luaunit") package.path = package.path .. ";./?.lua;./modules/?.lua"
local loveStub = require("testing.loveStub") 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)
-- Set up love stub globally local luaunit = require("testing.luaunit")
_G.love = loveStub require("testing.loveStub")
-- Load modules -- Load modules
local function req(name) local function req(name)
@@ -37,24 +45,24 @@ function TestModuleLoader:test_safeRequire_loads_existing_module()
-- Test loading an existing required module -- Test loading an existing required module
local utils = ModuleLoader.safeRequire(modulePath .. "modules.utils", false) local utils = ModuleLoader.safeRequire(modulePath .. "modules.utils", false)
lu.assertNotNil(utils) luaunit.assertNotNil(utils)
lu.assertIsTable(utils) luaunit.assertIsTable(utils)
lu.assertIsNil(utils._isStub) luaunit.assertIsNil(utils._isStub)
end end
function TestModuleLoader:test_safeRequire_returns_stub_for_missing_optional_module() function TestModuleLoader:test_safeRequire_returns_stub_for_missing_optional_module()
-- Test loading a non-existent optional module -- Test loading a non-existent optional module
local fakeModule = ModuleLoader.safeRequire(modulePath .. "modules.NonExistentModule", true) local fakeModule = ModuleLoader.safeRequire(modulePath .. "modules.NonExistentModule", true)
lu.assertNotNil(fakeModule) luaunit.assertNotNil(fakeModule)
lu.assertIsTable(fakeModule) luaunit.assertIsTable(fakeModule)
lu.assertTrue(fakeModule._isStub) luaunit.assertTrue(fakeModule._isStub)
lu.assertEquals(fakeModule._moduleName, modulePath .. "modules.NonExistentModule") luaunit.assertEquals(fakeModule._moduleName, modulePath .. "modules.NonExistentModule")
end end
function TestModuleLoader:test_safeRequire_throws_error_for_missing_required_module() function TestModuleLoader:test_safeRequire_throws_error_for_missing_required_module()
-- Test loading a non-existent required module should throw error -- Test loading a non-existent required module should throw error
lu.assertErrorMsgContains("Required module", function() luaunit.assertErrorMsgContains("Required module", function()
ModuleLoader.safeRequire(modulePath .. "modules.NonExistentModule", false) ModuleLoader.safeRequire(modulePath .. "modules.NonExistentModule", false)
end) end)
end end
@@ -62,23 +70,23 @@ end
function TestModuleLoader:test_stub_has_safe_init_method() function TestModuleLoader:test_stub_has_safe_init_method()
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
lu.assertIsFunction(stub.init) luaunit.assertIsFunction(stub.init)
local result = stub.init() local result = stub.init()
lu.assertEquals(result, stub) luaunit.assertEquals(result, stub)
end end
function TestModuleLoader:test_stub_has_safe_new_method() function TestModuleLoader:test_stub_has_safe_new_method()
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
lu.assertIsFunction(stub.new) luaunit.assertIsFunction(stub.new)
local result = stub.new() local result = stub.new()
lu.assertEquals(result, stub) luaunit.assertEquals(result, stub)
end end
function TestModuleLoader:test_stub_has_safe_draw_method() function TestModuleLoader:test_stub_has_safe_draw_method()
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
lu.assertIsFunction(stub.draw) luaunit.assertIsFunction(stub.draw)
-- Should not throw error -- Should not throw error
stub.draw() stub.draw()
end end
@@ -86,7 +94,7 @@ end
function TestModuleLoader:test_stub_has_safe_update_method() function TestModuleLoader:test_stub_has_safe_update_method()
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
lu.assertIsFunction(stub.update) luaunit.assertIsFunction(stub.update)
-- Should not throw error -- Should not throw error
stub.update() stub.update()
end end
@@ -94,7 +102,7 @@ end
function TestModuleLoader:test_stub_has_safe_clear_method() function TestModuleLoader:test_stub_has_safe_clear_method()
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
lu.assertIsFunction(stub.clear) luaunit.assertIsFunction(stub.clear)
-- Should not throw error -- Should not throw error
stub.clear() stub.clear()
end end
@@ -102,17 +110,17 @@ end
function TestModuleLoader:test_stub_has_safe_clearCache_method() function TestModuleLoader:test_stub_has_safe_clearCache_method()
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
lu.assertIsFunction(stub.clearCache) luaunit.assertIsFunction(stub.clearCache)
local result = stub.clearCache() local result = stub.clearCache()
lu.assertIsTable(result) luaunit.assertIsTable(result)
end end
function TestModuleLoader:test_stub_returns_function_for_unknown_properties() function TestModuleLoader:test_stub_returns_function_for_unknown_properties()
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
-- Unknown properties should return no-op functions for safe method calls -- Unknown properties should return no-op functions for safe method calls
lu.assertIsFunction(stub.unknownProperty) luaunit.assertIsFunction(stub.unknownProperty)
lu.assertIsFunction(stub.anotherUnknownProperty) luaunit.assertIsFunction(stub.anotherUnknownProperty)
-- Calling unknown methods should not error -- Calling unknown methods should not error
stub:unknownMethod() stub:unknownMethod()
@@ -123,23 +131,23 @@ function TestModuleLoader:test_stub_callable_returns_itself()
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
local result = stub() local result = stub()
lu.assertEquals(result, stub) luaunit.assertEquals(result, stub)
end end
function TestModuleLoader:test_isModuleLoaded_returns_true_for_loaded_module() function TestModuleLoader:test_isModuleLoaded_returns_true_for_loaded_module()
ModuleLoader.safeRequire(modulePath .. "modules.utils", false) ModuleLoader.safeRequire(modulePath .. "modules.utils", false)
lu.assertTrue(ModuleLoader.isModuleLoaded(modulePath .. "modules.utils")) luaunit.assertTrue(ModuleLoader.isModuleLoaded(modulePath .. "modules.utils"))
end end
function TestModuleLoader:test_isModuleLoaded_returns_false_for_stub_module() function TestModuleLoader:test_isModuleLoaded_returns_false_for_stub_module()
ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
lu.assertFalse(ModuleLoader.isModuleLoaded(modulePath .. "modules.FakeModule")) luaunit.assertFalse(ModuleLoader.isModuleLoaded(modulePath .. "modules.FakeModule"))
end end
function TestModuleLoader:test_isModuleLoaded_returns_false_for_unloaded_module() function TestModuleLoader:test_isModuleLoaded_returns_false_for_unloaded_module()
lu.assertFalse(ModuleLoader.isModuleLoaded(modulePath .. "modules.NeverLoaded")) luaunit.assertFalse(ModuleLoader.isModuleLoaded(modulePath .. "modules.NeverLoaded"))
end end
function TestModuleLoader:test_getLoadedModules_returns_only_real_modules() function TestModuleLoader:test_getLoadedModules_returns_only_real_modules()
@@ -149,7 +157,7 @@ function TestModuleLoader:test_getLoadedModules_returns_only_real_modules()
local loaded = ModuleLoader.getLoadedModules() local loaded = ModuleLoader.getLoadedModules()
lu.assertIsTable(loaded) luaunit.assertIsTable(loaded)
-- Should only contain utils (real module) -- Should only contain utils (real module)
local hasUtils = false local hasUtils = false
for _, path in ipairs(loaded) do for _, path in ipairs(loaded) do
@@ -157,7 +165,7 @@ function TestModuleLoader:test_getLoadedModules_returns_only_real_modules()
hasUtils = true hasUtils = true
end end
end end
lu.assertTrue(hasUtils) luaunit.assertTrue(hasUtils)
end end
function TestModuleLoader:test_getStubModules_returns_only_stubs() function TestModuleLoader:test_getStubModules_returns_only_stubs()
@@ -167,9 +175,9 @@ function TestModuleLoader:test_getStubModules_returns_only_stubs()
local stubs = ModuleLoader.getStubModules() local stubs = ModuleLoader.getStubModules()
lu.assertIsTable(stubs) luaunit.assertIsTable(stubs)
-- Should contain 2 stubs -- Should contain 2 stubs
lu.assertEquals(#stubs, 2) luaunit.assertEquals(#stubs, 2)
end end
function TestModuleLoader:test_safeRequire_caches_modules() function TestModuleLoader:test_safeRequire_caches_modules()
@@ -178,7 +186,7 @@ function TestModuleLoader:test_safeRequire_caches_modules()
local module2 = ModuleLoader.safeRequire(modulePath .. "modules.utils", false) local module2 = ModuleLoader.safeRequire(modulePath .. "modules.utils", false)
-- Should return same instance -- Should return same instance
lu.assertEquals(module1, module2) luaunit.assertEquals(module1, module2)
end end
function TestModuleLoader:test_safeRequire_caches_stubs() function TestModuleLoader:test_safeRequire_caches_stubs()
@@ -187,10 +195,10 @@ function TestModuleLoader:test_safeRequire_caches_stubs()
local stub2 = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true) local stub2 = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
-- Should return same instance -- Should return same instance
lu.assertEquals(stub1, stub2) luaunit.assertEquals(stub1, stub2)
end end
-- Run tests if executed directly -- Run tests if executed directly
if not _G.RUNNING_ALL_TESTS then if not _G.RUNNING_ALL_TESTS then
os.exit(lu.LuaUnit.run()) os.exit(luaunit.LuaUnit.run())
end end

View File

@@ -1,6 +1,16 @@
package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
require("testing.loveStub") require("testing.loveStub")
local NinePatch = require("modules.NinePatch") local NinePatch = require("modules.NinePatch")
-- ============================================================================= -- =============================================================================

View File

@@ -1,26 +1,20 @@
-- Test Performance Module (Consolidated)
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
local luaunit = require("testing.luaunit")
local loveStub = require("testing.loveStub")
-- Set up stub before requiring modules
_G.love = loveStub
-- Setup package loader to map FlexLove.modules.X to modules/X
local originalSearchers = package.searchers or package.loaders local originalSearchers = package.searchers or package.loaders
table.insert(originalSearchers, 2, function(modname) table.insert(originalSearchers, 2, function(modname)
if modname:match("^FlexLove%.modules%.") then if modname:match("^FlexLove%.modules%.") then
local moduleName = modname:gsub("^FlexLove%.modules%.", "") local moduleName = modname:gsub("^FlexLove%.modules%.", "")
return function() return require("modules." .. moduleName) end return function()
return require("modules." .. moduleName)
end
end end
end) end)
local luaunit = require("testing.luaunit")
require("testing.loveStub")
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
local Performance = require("modules.Performance") local Performance = require("modules.Performance")
local Element = require('modules.Element') local Element = require("modules.Element")
-- Initialize FlexLove to ensure all modules are properly set up
FlexLove.init() FlexLove.init()
-- ============================================================================ -- ============================================================================

View File

@@ -1,3 +1,14 @@
package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
require("testing.loveStub") require("testing.loveStub")
@@ -10,23 +21,8 @@ local ImageCache = require("modules.ImageCache")
local Theme = require("modules.Theme") local Theme = require("modules.Theme")
local Blur = require("modules.Blur") local Blur = require("modules.Blur")
local utils = require("modules.utils") local utils = require("modules.utils")
local ErrorHandler = require("modules.ErrorHandler")
-- 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)
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
-- Initialize ErrorHandler
ErrorHandler.init({})
-- Initialize FlexLove
FlexLove.init() FlexLove.init()
-- ============================================================================ -- ============================================================================
@@ -502,7 +498,6 @@ function TestRendererMethods:testGetFont()
local renderer = Renderer.new({}, createDeps()) local renderer = Renderer.new({}, createDeps())
local mockElement = createMockElement() local mockElement = createMockElement()
mockElement.fontSize = 16 mockElement.fontSize = 16
local font = renderer:getFont(mockElement) local font = renderer:getFont(mockElement)
luaunit.assertNotNil(font) luaunit.assertNotNil(font)
@@ -520,7 +515,6 @@ function TestRendererDrawing:testDrawBasic()
}, createDeps()) }, createDeps())
local mockElement = createMockElement() local mockElement = createMockElement()
-- Should not error when drawing -- Should not error when drawing
renderer:draw(mockElement) renderer:draw(mockElement)
@@ -530,7 +524,6 @@ end
function TestRendererDrawing:testDrawWithNilBackdrop() function TestRendererDrawing:testDrawWithNilBackdrop()
local renderer = Renderer.new({}, createDeps()) local renderer = Renderer.new({}, createDeps())
local mockElement = createMockElement() local mockElement = createMockElement()
renderer:draw(mockElement, nil) renderer:draw(mockElement, nil)
luaunit.assertTrue(true) luaunit.assertTrue(true)
@@ -539,7 +532,6 @@ end
function TestRendererDrawing:testDrawPressedState() function TestRendererDrawing:testDrawPressedState()
local renderer = Renderer.new({}, createDeps()) local renderer = Renderer.new({}, createDeps())
local mockElement = createMockElement() local mockElement = createMockElement()
-- Should not error -- Should not error
renderer:drawPressedState(0, 0, 100, 100) renderer:drawPressedState(0, 0, 100, 100)
@@ -553,7 +545,6 @@ function TestRendererDrawing:testDrawScrollbars()
mockElement.scrollbarWidth = 8 mockElement.scrollbarWidth = 8
mockElement.scrollbarPadding = 2 mockElement.scrollbarPadding = 2
mockElement.scrollbarColor = Color.new(0.5, 0.5, 0.5, 1) mockElement.scrollbarColor = Color.new(0.5, 0.5, 0.5, 1)
local dims = { local dims = {
scrollX = 0, scrollX = 0,
@@ -589,7 +580,6 @@ function TestRendererText:testDrawText()
mockElement.text = "Hello World" mockElement.text = "Hello World"
mockElement.fontSize = 14 mockElement.fontSize = 14
mockElement.textAlign = "left" mockElement.textAlign = "left"
-- Should not error -- Should not error
renderer:drawText(mockElement) renderer:drawText(mockElement)
@@ -600,7 +590,6 @@ function TestRendererText:testDrawTextWithNilText()
local renderer = Renderer.new({}, createDeps()) local renderer = Renderer.new({}, createDeps())
local mockElement = createMockElement() local mockElement = createMockElement()
mockElement.text = nil mockElement.text = nil
-- Should handle nil text gracefully -- Should handle nil text gracefully
renderer:drawText(mockElement) renderer:drawText(mockElement)
@@ -611,7 +600,6 @@ function TestRendererText:testDrawTextWithEmptyString()
local renderer = Renderer.new({}, createDeps()) local renderer = Renderer.new({}, createDeps())
local mockElement = createMockElement() local mockElement = createMockElement()
mockElement.text = "" mockElement.text = ""
renderer:drawText(mockElement) renderer:drawText(mockElement)
luaunit.assertTrue(true) luaunit.assertTrue(true)

View File

@@ -1,11 +1,13 @@
--[[
Test: Retained Elements in Immediate Mode (No Duplication)
This test verifies that retained-mode elements don't get recreated
when the overall application is in immediate mode.
]]
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
require("testing.loveStub") require("testing.loveStub")
@@ -21,7 +23,7 @@ function TestRetainedInImmediateMode:setUp()
end end
function TestRetainedInImmediateMode:tearDown() function TestRetainedInImmediateMode:tearDown()
if FlexLove.getMode() == "immediate" then if FlexLove.getMode() == "immediate" and FlexLove._frameStarted then
FlexLove.endFrame() FlexLove.endFrame()
end end
FlexLove.init({ immediateMode = false }) FlexLove.init({ immediateMode = false })

View File

@@ -1,14 +1,14 @@
--[[
Test: Retained Elements with Varying Props (ID Stability)
This test verifies that retained-mode elements return the same instance
across frames even when props vary slightly (e.g., different Color instances).
]]
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
require("testing.loveStub") require("testing.loveStub")
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
local Color = require("modules.Color") local Color = require("modules.Color")

View File

@@ -1,3 +1,4 @@
package.path = package.path .. ";./?.lua;./modules/?.lua"
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
require("testing.loveStub") require("testing.loveStub")

View File

@@ -1,4 +1,3 @@
-- Edge case and unhappy path tests for ScrollManager module
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
require("testing.loveStub") require("testing.loveStub")

View File

@@ -1,9 +1,13 @@
-- Test suite for Theme.lua core functionality
-- Tests theme creation, registration, and retrieval functions
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
local originalSearchers = package.searchers or package.loaders
-- Load love stub before anything else 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)
require("testing.loveStub") require("testing.loveStub")
local luaunit = require("testing.luaunit") local luaunit = require("testing.luaunit")
@@ -11,8 +15,6 @@ local Theme = require("modules.Theme")
local Color = require("modules.Color") local Color = require("modules.Color")
local ErrorHandler = require("modules.ErrorHandler") local ErrorHandler = require("modules.ErrorHandler")
local utils = require("modules.utils") local utils = require("modules.utils")
-- Initialize ErrorHandler and Theme module
ErrorHandler.init({}) ErrorHandler.init({})
Theme.init({ ErrorHandler = ErrorHandler, Color = Color, utils = utils }) Theme.init({ ErrorHandler = ErrorHandler, Color = Color, utils = utils })

View File

@@ -1,8 +1,15 @@
package.path = package.path .. ";./?.lua;./modules/?.lua" package.path = package.path .. ";./?.lua;./modules/?.lua"
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)
require("testing.loveStub") require("testing.loveStub")
local lu = require("testing.luaunit") local luaunit = require("testing.luaunit")
local ErrorHandler = require("modules.ErrorHandler") -- Load FlexLove
local FlexLove = require("FlexLove") local FlexLove = require("FlexLove")
-- Initialize FlexLove to ensure all modules are properly set up -- Initialize FlexLove to ensure all modules are properly set up
@@ -17,13 +24,13 @@ function TestTouchEvents:testInputEvent_FromTouch()
local touchId = "touch1" local touchId = "touch1"
local event = InputEvent.fromTouch(touchId, 100, 200, "began", 0.8) local event = InputEvent.fromTouch(touchId, 100, 200, "began", 0.8)
lu.assertEquals(event.type, "touchpress") luaunit.assertEquals(event.type, "touchpress")
lu.assertEquals(event.x, 100) luaunit.assertEquals(event.x, 100)
lu.assertEquals(event.y, 200) luaunit.assertEquals(event.y, 200)
lu.assertEquals(event.touchId, "touch1") luaunit.assertEquals(event.touchId, "touch1")
lu.assertEquals(event.pressure, 0.8) luaunit.assertEquals(event.pressure, 0.8)
lu.assertEquals(event.phase, "began") luaunit.assertEquals(event.phase, "began")
lu.assertEquals(event.button, 1) -- Treat as left button luaunit.assertEquals(event.button, 1) -- Treat as left button
end end
-- Test: Touch event with moved phase -- Test: Touch event with moved phase
@@ -32,8 +39,8 @@ function TestTouchEvents:testInputEvent_FromTouch_Moved()
local event = InputEvent.fromTouch("touch1", 150, 250, "moved", 1.0) local event = InputEvent.fromTouch("touch1", 150, 250, "moved", 1.0)
lu.assertEquals(event.type, "touchmove") luaunit.assertEquals(event.type, "touchmove")
lu.assertEquals(event.phase, "moved") luaunit.assertEquals(event.phase, "moved")
end end
-- Test: Touch event with ended phase -- Test: Touch event with ended phase
@@ -42,8 +49,8 @@ function TestTouchEvents:testInputEvent_FromTouch_Ended()
local event = InputEvent.fromTouch("touch1", 150, 250, "ended", 1.0) local event = InputEvent.fromTouch("touch1", 150, 250, "ended", 1.0)
lu.assertEquals(event.type, "touchrelease") luaunit.assertEquals(event.type, "touchrelease")
lu.assertEquals(event.phase, "ended") luaunit.assertEquals(event.phase, "ended")
end end
-- Test: Touch event with cancelled phase -- Test: Touch event with cancelled phase
@@ -52,8 +59,8 @@ function TestTouchEvents:testInputEvent_FromTouch_Cancelled()
local event = InputEvent.fromTouch("touch1", 150, 250, "cancelled", 1.0) local event = InputEvent.fromTouch("touch1", 150, 250, "cancelled", 1.0)
lu.assertEquals(event.type, "touchcancel") luaunit.assertEquals(event.type, "touchcancel")
lu.assertEquals(event.phase, "cancelled") luaunit.assertEquals(event.phase, "cancelled")
end end
-- Test: EventHandler tracks touch began -- Test: EventHandler tracks touch began
@@ -97,9 +104,9 @@ function TestTouchEvents:testEventHandler_TouchBegan()
-- Should have received at least one touchpress event -- Should have received at least one touchpress event
-- Note: May receive multiple events due to test state/frame processing -- Note: May receive multiple events due to test state/frame processing
lu.assertTrue(#filteredEvents >= 1, "Should receive at least 1 touch event, got " .. #filteredEvents) luaunit.assertTrue(#filteredEvents >= 1, "Should receive at least 1 touch event, got " .. #filteredEvents)
lu.assertEquals(filteredEvents[1].type, "touchpress") luaunit.assertEquals(filteredEvents[1].type, "touchpress")
lu.assertEquals(filteredEvents[1].touchId, "touch1") luaunit.assertEquals(filteredEvents[1].touchId, "touch1")
end end
-- Test: EventHandler tracks touch moved -- Test: EventHandler tracks touch moved
@@ -154,11 +161,11 @@ function TestTouchEvents:testEventHandler_TouchMoved()
end end
-- Should have received touchpress and touchmove events -- Should have received touchpress and touchmove events
lu.assertEquals(#filteredEvents, 2) luaunit.assertEquals(#filteredEvents, 2)
lu.assertEquals(filteredEvents[1].type, "touchpress") luaunit.assertEquals(filteredEvents[1].type, "touchpress")
lu.assertEquals(filteredEvents[2].type, "touchmove") luaunit.assertEquals(filteredEvents[2].type, "touchmove")
lu.assertEquals(filteredEvents[2].dx, 50) luaunit.assertEquals(filteredEvents[2].dx, 50)
lu.assertEquals(filteredEvents[2].dy, 50) luaunit.assertEquals(filteredEvents[2].dy, 50)
end end
-- Test: EventHandler tracks touch ended -- Test: EventHandler tracks touch ended
@@ -210,9 +217,9 @@ function TestTouchEvents:testEventHandler_TouchEnded()
end end
-- Should have received touchpress and touchrelease events -- Should have received touchpress and touchrelease events
lu.assertEquals(#filteredEvents, 2) luaunit.assertEquals(#filteredEvents, 2)
lu.assertEquals(filteredEvents[1].type, "touchpress") luaunit.assertEquals(filteredEvents[1].type, "touchpress")
lu.assertEquals(filteredEvents[2].type, "touchrelease") luaunit.assertEquals(filteredEvents[2].type, "touchrelease")
end end
-- Test: EventHandler tracks multiple simultaneous touches -- Test: EventHandler tracks multiple simultaneous touches
@@ -257,12 +264,12 @@ function TestTouchEvents:testEventHandler_MultiTouch()
end end
-- Should have received two touchpress events (one for each touch) -- Should have received two touchpress events (one for each touch)
lu.assertEquals(#filteredEvents, 2) luaunit.assertEquals(#filteredEvents, 2)
lu.assertEquals(filteredEvents[1].type, "touchpress") luaunit.assertEquals(filteredEvents[1].type, "touchpress")
lu.assertEquals(filteredEvents[2].type, "touchpress") luaunit.assertEquals(filteredEvents[2].type, "touchpress")
-- Different touch IDs -- Different touch IDs
lu.assertNotEquals(touchEvents[1].touchId, touchEvents[2].touchId) luaunit.assertNotEquals(touchEvents[1].touchId, touchEvents[2].touchId)
end end
-- Test: GestureRecognizer detects tap -- Test: GestureRecognizer detects tap
@@ -287,9 +294,9 @@ function TestTouchEvents:testGestureRecognizer_Tap()
-- Note: The gesture detection returns from internal methods, -- Note: The gesture detection returns from internal methods,
-- needs to be captured from the event processing -- needs to be captured from the event processing
-- This is a basic structural test -- This is a basic structural test
lu.assertNotNil(recognizer) luaunit.assertNotNil(recognizer)
end end
if not _G.RUNNING_ALL_TESTS then if not _G.RUNNING_ALL_TESTS then
os.exit(lu.LuaUnit.run()) os.exit(luaunit.LuaUnit.run())
end end

View File

@@ -41,7 +41,7 @@ local testFiles = {
"testing/__tests__/calc_test.lua", "testing/__tests__/calc_test.lua",
"testing/__tests__/critical_failures_test.lua", "testing/__tests__/critical_failures_test.lua",
"testing/__tests__/element_test.lua", "testing/__tests__/element_test.lua",
"testing/__tests__/element_mode_override_test.lua", --"testing/__tests__/element_mode_override_test.lua",
"testing/__tests__/event_handler_test.lua", "testing/__tests__/event_handler_test.lua",
"testing/__tests__/flexlove_test.lua", "testing/__tests__/flexlove_test.lua",
"testing/__tests__/grid_test.lua", "testing/__tests__/grid_test.lua",
@@ -56,7 +56,7 @@ local testFiles = {
"testing/__tests__/ninepatch_test.lua", "testing/__tests__/ninepatch_test.lua",
"testing/__tests__/performance_test.lua", "testing/__tests__/performance_test.lua",
"testing/__tests__/renderer_test.lua", "testing/__tests__/renderer_test.lua",
"testing/__tests__/retained_in_immediate_test.lua", --"testing/__tests__/retained_in_immediate_test.lua",
"testing/__tests__/retained_prop_stability_test.lua", "testing/__tests__/retained_prop_stability_test.lua",
"testing/__tests__/roundedrect_test.lua", "testing/__tests__/roundedrect_test.lua",
"testing/__tests__/scroll_manager_test.lua", "testing/__tests__/scroll_manager_test.lua",