done for the day
This commit is contained in:
318
testing/__tests__/blur_test.lua
Normal file
318
testing/__tests__/blur_test.lua
Normal file
@@ -0,0 +1,318 @@
|
||||
local luaunit = require("testing.luaunit")
|
||||
require("testing.loveStub")
|
||||
|
||||
local Blur = require("modules.Blur")
|
||||
|
||||
TestBlur = {}
|
||||
|
||||
function TestBlur:setUp()
|
||||
-- Reset any cached state
|
||||
Blur.clearCache()
|
||||
end
|
||||
|
||||
-- Unhappy path tests for Blur.new()
|
||||
|
||||
function TestBlur:testNewWithNilQuality()
|
||||
-- Should default to quality 5
|
||||
local blur = Blur.new(nil)
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertEquals(blur.quality, 5)
|
||||
end
|
||||
|
||||
function TestBlur:testNewWithZeroQuality()
|
||||
-- Should clamp to minimum quality 1
|
||||
local blur = Blur.new(0)
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertEquals(blur.quality, 1)
|
||||
end
|
||||
|
||||
function TestBlur:testNewWithNegativeQuality()
|
||||
-- Should clamp to minimum quality 1
|
||||
local blur = Blur.new(-5)
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertEquals(blur.quality, 1)
|
||||
end
|
||||
|
||||
function TestBlur:testNewWithVeryHighQuality()
|
||||
-- Should clamp to maximum quality 10
|
||||
local blur = Blur.new(100)
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertEquals(blur.quality, 10)
|
||||
end
|
||||
|
||||
function TestBlur:testNewWithQuality11()
|
||||
-- Should clamp to maximum quality 10
|
||||
local blur = Blur.new(11)
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertEquals(blur.quality, 10)
|
||||
end
|
||||
|
||||
function TestBlur:testNewWithFractionalQuality()
|
||||
-- Should work with fractional quality
|
||||
local blur = Blur.new(5.5)
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertTrue(blur.quality >= 5 and blur.quality <= 6)
|
||||
end
|
||||
|
||||
function TestBlur:testNewEnsuresOddTaps()
|
||||
-- Taps must be odd for shader
|
||||
for quality = 1, 10 do
|
||||
local blur = Blur.new(quality)
|
||||
luaunit.assertTrue(blur.taps % 2 == 1, string.format("Quality %d produced even taps: %d", quality, blur.taps))
|
||||
end
|
||||
end
|
||||
|
||||
-- Unhappy path tests for Blur.applyToRegion()
|
||||
|
||||
function TestBlur:testApplyToRegionWithNilBlurInstance()
|
||||
local called = false
|
||||
local drawFunc = function()
|
||||
called = true
|
||||
end
|
||||
|
||||
luaunit.assertError(function()
|
||||
Blur.applyToRegion(nil, 50, 0, 0, 100, 100, drawFunc)
|
||||
end)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithZeroIntensity()
|
||||
local blur = Blur.new(5)
|
||||
local called = false
|
||||
local drawFunc = function()
|
||||
called = true
|
||||
end
|
||||
|
||||
-- Should just call drawFunc and return early
|
||||
Blur.applyToRegion(blur, 0, 0, 0, 100, 100, drawFunc)
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithNegativeIntensity()
|
||||
local blur = Blur.new(5)
|
||||
local called = false
|
||||
local drawFunc = function()
|
||||
called = true
|
||||
end
|
||||
|
||||
-- Should just call drawFunc and return early
|
||||
Blur.applyToRegion(blur, -10, 0, 0, 100, 100, drawFunc)
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithZeroWidth()
|
||||
local blur = Blur.new(5)
|
||||
local called = false
|
||||
local drawFunc = function()
|
||||
called = true
|
||||
end
|
||||
|
||||
-- Should just call drawFunc and return early
|
||||
Blur.applyToRegion(blur, 50, 0, 0, 0, 100, drawFunc)
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithZeroHeight()
|
||||
local blur = Blur.new(5)
|
||||
local called = false
|
||||
local drawFunc = function()
|
||||
called = true
|
||||
end
|
||||
|
||||
-- Should just call drawFunc and return early
|
||||
Blur.applyToRegion(blur, 50, 0, 0, 100, 0, drawFunc)
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithNegativeWidth()
|
||||
local blur = Blur.new(5)
|
||||
local called = false
|
||||
local drawFunc = function()
|
||||
called = true
|
||||
end
|
||||
|
||||
-- Should just call drawFunc and return early
|
||||
Blur.applyToRegion(blur, 50, 0, 0, -100, 100, drawFunc)
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithNegativeHeight()
|
||||
local blur = Blur.new(5)
|
||||
local called = false
|
||||
local drawFunc = function()
|
||||
called = true
|
||||
end
|
||||
|
||||
-- Should just call drawFunc and return early
|
||||
Blur.applyToRegion(blur, 50, 0, 0, 100, -100, drawFunc)
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithIntensityOver100()
|
||||
local blur = Blur.new(5)
|
||||
|
||||
-- We can't fully test rendering without complete LÖVE graphics
|
||||
-- But we can verify the blur instance was created
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithSmallDimensions()
|
||||
local blur = Blur.new(5)
|
||||
local called = false
|
||||
local drawFunc = function()
|
||||
called = true
|
||||
end
|
||||
|
||||
-- For small dimensions, we test that it doesn't error
|
||||
-- We can't fully test the rendering without full LÖVE graphics
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyToRegionWithNilDrawFunc()
|
||||
local blur = Blur.new(5)
|
||||
|
||||
luaunit.assertError(function()
|
||||
Blur.applyToRegion(blur, 50, 0, 0, 100, 100, nil)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Unhappy path tests for Blur.applyBackdrop()
|
||||
|
||||
function TestBlur:testApplyBackdropWithNilBlurInstance()
|
||||
local mockCanvas = {
|
||||
getDimensions = function()
|
||||
return 100, 100
|
||||
end,
|
||||
}
|
||||
|
||||
luaunit.assertError(function()
|
||||
Blur.applyBackdrop(nil, 50, 0, 0, 100, 100, mockCanvas)
|
||||
end)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyBackdropWithZeroIntensity()
|
||||
local blur = Blur.new(5)
|
||||
local mockCanvas = {
|
||||
getDimensions = function()
|
||||
return 100, 100
|
||||
end,
|
||||
}
|
||||
|
||||
-- Should return early without error
|
||||
Blur.applyBackdrop(blur, 0, 0, 0, 100, 100, mockCanvas)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyBackdropWithNegativeIntensity()
|
||||
local blur = Blur.new(5)
|
||||
local mockCanvas = {
|
||||
getDimensions = function()
|
||||
return 100, 100
|
||||
end,
|
||||
}
|
||||
|
||||
-- Should return early without error
|
||||
Blur.applyBackdrop(blur, -10, 0, 0, 100, 100, mockCanvas)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyBackdropWithZeroWidth()
|
||||
local blur = Blur.new(5)
|
||||
local mockCanvas = {
|
||||
getDimensions = function()
|
||||
return 100, 100
|
||||
end,
|
||||
}
|
||||
|
||||
-- Should return early without error
|
||||
Blur.applyBackdrop(blur, 50, 0, 0, 0, 100, mockCanvas)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyBackdropWithZeroHeight()
|
||||
local blur = Blur.new(5)
|
||||
local mockCanvas = {
|
||||
getDimensions = function()
|
||||
return 100, 100
|
||||
end,
|
||||
}
|
||||
|
||||
-- Should return early without error
|
||||
Blur.applyBackdrop(blur, 50, 0, 0, 100, 0, mockCanvas)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyBackdropWithNilCanvas()
|
||||
local blur = Blur.new(5)
|
||||
|
||||
luaunit.assertError(function()
|
||||
Blur.applyBackdrop(blur, 50, 0, 0, 100, 100, nil)
|
||||
end)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyBackdropWithIntensityOver100()
|
||||
local blur = Blur.new(5)
|
||||
local mockCanvas = {
|
||||
getDimensions = function()
|
||||
return 100, 100
|
||||
end,
|
||||
}
|
||||
|
||||
-- We can't fully test rendering without complete LÖVE graphics
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertNotNil(mockCanvas)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestBlur:testApplyBackdropWithSmallDimensions()
|
||||
local blur = Blur.new(5)
|
||||
local mockCanvas = {
|
||||
getDimensions = function()
|
||||
return 100, 100
|
||||
end,
|
||||
}
|
||||
|
||||
-- We can't fully test rendering without complete LÖVE graphics
|
||||
luaunit.assertNotNil(blur)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Tests for Blur.clearCache()
|
||||
|
||||
function TestBlur:testClearCacheDoesNotError()
|
||||
-- Create some blur instances to populate cache
|
||||
local blur1 = Blur.new(5)
|
||||
local blur2 = Blur.new(8)
|
||||
|
||||
-- Should not error
|
||||
Blur.clearCache()
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestBlur:testClearCacheMultipleTimes()
|
||||
Blur.clearCache()
|
||||
Blur.clearCache()
|
||||
Blur.clearCache()
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Edge case: intensity boundaries
|
||||
|
||||
function TestBlur:testIntensityBoundaries()
|
||||
local blur = Blur.new(5)
|
||||
|
||||
-- Test that various quality levels create valid blur instances
|
||||
for quality = 1, 10 do
|
||||
local b = Blur.new(quality)
|
||||
luaunit.assertNotNil(b)
|
||||
luaunit.assertNotNil(b.shader)
|
||||
luaunit.assertTrue(b.taps % 2 == 1) -- Taps must be odd
|
||||
end
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
656
testing/__tests__/flexlove_test.lua
Normal file
656
testing/__tests__/flexlove_test.lua
Normal file
@@ -0,0 +1,656 @@
|
||||
local luaunit = require("testing.luaunit")
|
||||
require("testing.loveStub")
|
||||
|
||||
local FlexLove = require("FlexLove")
|
||||
local Color = require("modules.Color")
|
||||
local Theme = require("modules.Theme")
|
||||
|
||||
TestFlexLove = {}
|
||||
|
||||
function TestFlexLove:setUp()
|
||||
-- Reset FlexLove state before each test
|
||||
FlexLove.destroy()
|
||||
FlexLove.setMode("retained")
|
||||
end
|
||||
|
||||
function TestFlexLove:tearDown()
|
||||
FlexLove.destroy()
|
||||
end
|
||||
|
||||
-- Test: Module loads and has expected properties
|
||||
function TestFlexLove:testModuleLoads()
|
||||
luaunit.assertNotNil(FlexLove)
|
||||
luaunit.assertNotNil(FlexLove._VERSION)
|
||||
luaunit.assertEquals(FlexLove._VERSION, "0.2.0")
|
||||
luaunit.assertNotNil(FlexLove._DESCRIPTION)
|
||||
luaunit.assertNotNil(FlexLove._URL)
|
||||
luaunit.assertNotNil(FlexLove._LICENSE)
|
||||
end
|
||||
|
||||
-- Test: init() with no config
|
||||
function TestFlexLove:testInitNoConfig()
|
||||
FlexLove.init()
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: init() with empty config
|
||||
function TestFlexLove:testInitEmptyConfig()
|
||||
FlexLove.init({})
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: init() with baseScale
|
||||
function TestFlexLove:testInitWithBaseScale()
|
||||
FlexLove.init({
|
||||
baseScale = {
|
||||
width = 1920,
|
||||
height = 1080
|
||||
}
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(FlexLove.baseScale)
|
||||
luaunit.assertEquals(FlexLove.baseScale.width, 1920)
|
||||
luaunit.assertEquals(FlexLove.baseScale.height, 1080)
|
||||
end
|
||||
|
||||
-- Test: init() with partial baseScale (uses defaults)
|
||||
function TestFlexLove:testInitWithPartialBaseScale()
|
||||
FlexLove.init({
|
||||
baseScale = {}
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(FlexLove.baseScale)
|
||||
luaunit.assertEquals(FlexLove.baseScale.width, 1920)
|
||||
luaunit.assertEquals(FlexLove.baseScale.height, 1080)
|
||||
end
|
||||
|
||||
-- Test: init() with string theme
|
||||
function TestFlexLove:testInitWithStringTheme()
|
||||
-- Pre-register a theme
|
||||
local theme = Theme.new({
|
||||
name = "test",
|
||||
components = {}
|
||||
})
|
||||
|
||||
-- init() tries to load and then set active, which may fail if theme path doesn't exist
|
||||
-- Just check that it doesn't crash
|
||||
FlexLove.init({
|
||||
theme = "test"
|
||||
})
|
||||
|
||||
-- The theme setting may fail silently, so just check it doesn't crash
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: init() with table theme
|
||||
function TestFlexLove:testInitWithTableTheme()
|
||||
FlexLove.init({
|
||||
theme = {
|
||||
name = "custom",
|
||||
components = {}
|
||||
}
|
||||
})
|
||||
|
||||
luaunit.assertEquals(FlexLove.defaultTheme, "custom")
|
||||
end
|
||||
|
||||
-- Test: init() with invalid theme (should not crash)
|
||||
function TestFlexLove:testInitWithInvalidTheme()
|
||||
FlexLove.init({
|
||||
theme = "nonexistent-theme"
|
||||
})
|
||||
|
||||
-- Should not crash, just print warning
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: init() with immediateMode = true
|
||||
function TestFlexLove:testInitWithImmediateMode()
|
||||
FlexLove.init({
|
||||
immediateMode = true
|
||||
})
|
||||
|
||||
luaunit.assertEquals(FlexLove.getMode(), "immediate")
|
||||
end
|
||||
|
||||
-- Test: init() with immediateMode = false
|
||||
function TestFlexLove:testInitWithRetainedMode()
|
||||
FlexLove.init({
|
||||
immediateMode = false
|
||||
})
|
||||
|
||||
luaunit.assertEquals(FlexLove.getMode(), "retained")
|
||||
end
|
||||
|
||||
-- Test: init() with autoFrameManagement
|
||||
function TestFlexLove:testInitWithAutoFrameManagement()
|
||||
FlexLove.init({
|
||||
autoFrameManagement = true
|
||||
})
|
||||
|
||||
luaunit.assertEquals(FlexLove._autoFrameManagement, true)
|
||||
end
|
||||
|
||||
-- Test: init() with state configuration
|
||||
function TestFlexLove:testInitWithStateConfig()
|
||||
FlexLove.init({
|
||||
stateRetentionFrames = 5,
|
||||
maxStateEntries = 100
|
||||
})
|
||||
|
||||
luaunit.assertTrue(true) -- Should configure StateManager
|
||||
end
|
||||
|
||||
-- Test: setMode() to immediate
|
||||
function TestFlexLove:testSetModeImmediate()
|
||||
FlexLove.setMode("immediate")
|
||||
luaunit.assertTrue(FlexLove._immediateMode)
|
||||
luaunit.assertFalse(FlexLove._frameStarted)
|
||||
end
|
||||
|
||||
-- Test: setMode() to retained
|
||||
function TestFlexLove:testSetModeRetained()
|
||||
FlexLove.setMode("immediate") -- First set to immediate
|
||||
FlexLove.setMode("retained") -- Then to retained
|
||||
|
||||
luaunit.assertFalse(FlexLove._immediateMode)
|
||||
luaunit.assertEquals(FlexLove._frameNumber, 0)
|
||||
end
|
||||
|
||||
-- Test: setMode() with invalid mode
|
||||
function TestFlexLove:testSetModeInvalid()
|
||||
local success = pcall(function()
|
||||
FlexLove.setMode("invalid")
|
||||
end)
|
||||
|
||||
luaunit.assertFalse(success)
|
||||
end
|
||||
|
||||
-- Test: getMode() returns correct mode
|
||||
function TestFlexLove:testGetMode()
|
||||
FlexLove.setMode("immediate")
|
||||
luaunit.assertEquals(FlexLove.getMode(), "immediate")
|
||||
|
||||
FlexLove.setMode("retained")
|
||||
luaunit.assertEquals(FlexLove.getMode(), "retained")
|
||||
end
|
||||
|
||||
-- Test: beginFrame() in immediate mode
|
||||
function TestFlexLove:testBeginFrameImmediate()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
luaunit.assertTrue(FlexLove._frameStarted)
|
||||
luaunit.assertEquals(#FlexLove._currentFrameElements, 0)
|
||||
end
|
||||
|
||||
-- Test: beginFrame() in retained mode (should do nothing)
|
||||
function TestFlexLove:testBeginFrameRetained()
|
||||
FlexLove.setMode("retained")
|
||||
local frameNumber = FlexLove._frameNumber or 0
|
||||
FlexLove.beginFrame()
|
||||
|
||||
-- Frame number should not change in retained mode
|
||||
luaunit.assertEquals(FlexLove._frameNumber or 0, frameNumber)
|
||||
end
|
||||
|
||||
-- Test: endFrame() in immediate mode
|
||||
function TestFlexLove:testEndFrameImmediate()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
FlexLove.endFrame()
|
||||
|
||||
luaunit.assertFalse(FlexLove._frameStarted)
|
||||
end
|
||||
|
||||
-- Test: endFrame() in retained mode (should do nothing)
|
||||
function TestFlexLove:testEndFrameRetained()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.endFrame()
|
||||
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: new() creates element in retained mode
|
||||
function TestFlexLove:testNewRetainedMode()
|
||||
FlexLove.setMode("retained")
|
||||
local element = FlexLove.new({ width = 100, height = 100 })
|
||||
|
||||
luaunit.assertNotNil(element)
|
||||
luaunit.assertEquals(element.width, 100)
|
||||
luaunit.assertEquals(element.height, 100)
|
||||
end
|
||||
|
||||
-- Test: new() creates element in immediate mode
|
||||
function TestFlexLove:testNewImmediateMode()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local element = FlexLove.new({
|
||||
id = "test-element",
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(element)
|
||||
luaunit.assertEquals(element.width, 100)
|
||||
luaunit.assertEquals(element.height, 100)
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test: new() auto-begins frame if not started
|
||||
function TestFlexLove:testNewAutoBeginFrame()
|
||||
FlexLove.setMode("immediate")
|
||||
|
||||
local element = FlexLove.new({
|
||||
id = "auto-begin-test",
|
||||
width = 50,
|
||||
height = 50
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(element)
|
||||
luaunit.assertTrue(FlexLove._autoBeganFrame)
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test: new() generates ID if not provided (immediate mode)
|
||||
function TestFlexLove:testNewGeneratesID()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local element = FlexLove.new({ width = 100, height = 100 })
|
||||
|
||||
luaunit.assertNotNil(element.id)
|
||||
luaunit.assertTrue(element.id ~= "")
|
||||
|
||||
FlexLove.endFrame()
|
||||
end
|
||||
|
||||
-- Test: draw() with no arguments
|
||||
function TestFlexLove:testDrawNoArgs()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.draw()
|
||||
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: draw() with gameDrawFunc
|
||||
function TestFlexLove:testDrawWithGameFunc()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local called = false
|
||||
FlexLove.draw(function()
|
||||
called = true
|
||||
end)
|
||||
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
-- Test: draw() with postDrawFunc
|
||||
function TestFlexLove:testDrawWithPostFunc()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local called = false
|
||||
FlexLove.draw(nil, function()
|
||||
called = true
|
||||
end)
|
||||
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
-- Test: draw() with both functions
|
||||
function TestFlexLove:testDrawWithBothFuncs()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local gameCalled = false
|
||||
local postCalled = false
|
||||
|
||||
FlexLove.draw(
|
||||
function() gameCalled = true end,
|
||||
function() postCalled = true end
|
||||
)
|
||||
|
||||
luaunit.assertTrue(gameCalled)
|
||||
luaunit.assertTrue(postCalled)
|
||||
end
|
||||
|
||||
-- Test: draw() with elements (no backdrop blur)
|
||||
function TestFlexLove:testDrawWithElements()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local element = FlexLove.new({
|
||||
width = 100,
|
||||
height = 100,
|
||||
backgroundColor = Color.new(1, 1, 1, 1)
|
||||
})
|
||||
|
||||
FlexLove.draw()
|
||||
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: draw() auto-ends frame in immediate mode
|
||||
function TestFlexLove:testDrawAutoEndFrame()
|
||||
FlexLove.setMode("immediate")
|
||||
|
||||
local element = FlexLove.new({
|
||||
id = "auto-end-test",
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
-- draw() should call endFrame() if _autoBeganFrame is true
|
||||
FlexLove.draw()
|
||||
|
||||
luaunit.assertFalse(FlexLove._autoBeganFrame)
|
||||
end
|
||||
|
||||
-- Test: update() with no elements
|
||||
function TestFlexLove:testUpdateNoElements()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.update(0.016)
|
||||
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: update() in retained mode with elements
|
||||
function TestFlexLove:testUpdateRetainedMode()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local element = FlexLove.new({
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
FlexLove.update(0.016)
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: update() in immediate mode (should skip element updates)
|
||||
function TestFlexLove:testUpdateImmediateMode()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local element = FlexLove.new({
|
||||
id = "update-test",
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
FlexLove.endFrame()
|
||||
FlexLove.update(0.016)
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: resize() with no baseScale
|
||||
function TestFlexLove:testResizeNoBaseScale()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.resize()
|
||||
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: resize() with baseScale
|
||||
function TestFlexLove:testResizeWithBaseScale()
|
||||
FlexLove.init({
|
||||
baseScale = {
|
||||
width = 1920,
|
||||
height = 1080
|
||||
}
|
||||
})
|
||||
|
||||
FlexLove.resize()
|
||||
|
||||
luaunit.assertNotNil(FlexLove.scaleFactors)
|
||||
end
|
||||
|
||||
-- Test: resize() with elements
|
||||
function TestFlexLove:testResizeWithElements()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local element = FlexLove.new({
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
FlexLove.resize()
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: destroy() clears all elements
|
||||
function TestFlexLove:testDestroy()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local element = FlexLove.new({
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
FlexLove.destroy()
|
||||
|
||||
luaunit.assertEquals(#FlexLove.topElements, 0)
|
||||
luaunit.assertNil(FlexLove.baseScale)
|
||||
luaunit.assertNil(FlexLove._focusedElement)
|
||||
end
|
||||
|
||||
-- Test: textinput() with no focused element
|
||||
function TestFlexLove:testTextInputNoFocus()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.textinput("a")
|
||||
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: textinput() with focused element
|
||||
function TestFlexLove:testTextInputWithFocus()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local element = FlexLove.new({
|
||||
width = 100,
|
||||
height = 100,
|
||||
editable = true
|
||||
})
|
||||
|
||||
FlexLove._focusedElement = element
|
||||
FlexLove.textinput("a")
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: keypressed() with no focused element
|
||||
function TestFlexLove:testKeyPressedNoFocus()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.keypressed("return", "return", false)
|
||||
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: keypressed() with focused element
|
||||
function TestFlexLove:testKeyPressedWithFocus()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local element = FlexLove.new({
|
||||
width = 100,
|
||||
height = 100,
|
||||
editable = true
|
||||
})
|
||||
|
||||
FlexLove._focusedElement = element
|
||||
FlexLove.keypressed("return", "return", false)
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: wheelmoved() in retained mode with no elements
|
||||
function TestFlexLove:testWheelMovedRetainedNoElements()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.wheelmoved(0, 1)
|
||||
|
||||
luaunit.assertTrue(true) -- Should not error
|
||||
end
|
||||
|
||||
-- Test: wheelmoved() in immediate mode
|
||||
function TestFlexLove:testWheelMovedImmediate()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local element = FlexLove.new({
|
||||
id = "wheel-test",
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
FlexLove.endFrame()
|
||||
FlexLove.wheelmoved(0, 1)
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: getStateCount() in retained mode
|
||||
function TestFlexLove:testGetStateCountRetained()
|
||||
FlexLove.setMode("retained")
|
||||
local count = FlexLove.getStateCount()
|
||||
|
||||
luaunit.assertEquals(count, 0)
|
||||
end
|
||||
|
||||
-- Test: getStateCount() in immediate mode
|
||||
function TestFlexLove:testGetStateCountImmediate()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local element = FlexLove.new({
|
||||
id = "state-test",
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
local count = FlexLove.getStateCount()
|
||||
luaunit.assertTrue(count >= 0)
|
||||
end
|
||||
|
||||
-- Test: clearState() in retained mode (should do nothing)
|
||||
function TestFlexLove:testClearStateRetained()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.clearState("test-id")
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: clearState() in immediate mode
|
||||
function TestFlexLove:testClearStateImmediate()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local element = FlexLove.new({
|
||||
id = "clear-test",
|
||||
width = 100,
|
||||
height = 100
|
||||
})
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
FlexLove.clearState("clear-test")
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: clearAllStates() in retained mode
|
||||
function TestFlexLove:testClearAllStatesRetained()
|
||||
FlexLove.setMode("retained")
|
||||
FlexLove.clearAllStates()
|
||||
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: clearAllStates() in immediate mode
|
||||
function TestFlexLove:testClearAllStatesImmediate()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
FlexLove.endFrame()
|
||||
|
||||
FlexLove.clearAllStates()
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: getStateStats() in retained mode
|
||||
function TestFlexLove:testGetStateStatsRetained()
|
||||
FlexLove.setMode("retained")
|
||||
local stats = FlexLove.getStateStats()
|
||||
|
||||
luaunit.assertEquals(stats.stateCount, 0)
|
||||
luaunit.assertEquals(stats.frameNumber, 0)
|
||||
end
|
||||
|
||||
-- Test: getStateStats() in immediate mode
|
||||
function TestFlexLove:testGetStateStatsImmediate()
|
||||
FlexLove.setMode("immediate")
|
||||
FlexLove.beginFrame()
|
||||
FlexLove.endFrame()
|
||||
|
||||
local stats = FlexLove.getStateStats()
|
||||
luaunit.assertNotNil(stats)
|
||||
end
|
||||
|
||||
-- Test: getElementAtPosition() with no elements
|
||||
function TestFlexLove:testGetElementAtPositionNoElements()
|
||||
FlexLove.setMode("retained")
|
||||
local element = FlexLove.getElementAtPosition(50, 50)
|
||||
|
||||
luaunit.assertNil(element)
|
||||
end
|
||||
|
||||
-- Test: getElementAtPosition() with element at position
|
||||
function TestFlexLove:testGetElementAtPosition()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local element = FlexLove.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 100,
|
||||
height = 100,
|
||||
onEvent = function() end
|
||||
})
|
||||
|
||||
local found = FlexLove.getElementAtPosition(50, 50)
|
||||
luaunit.assertEquals(found, element)
|
||||
end
|
||||
|
||||
-- Test: getElementAtPosition() outside element bounds
|
||||
function TestFlexLove:testGetElementAtPositionOutside()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local element = FlexLove.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 100,
|
||||
height = 100,
|
||||
onEvent = function() end
|
||||
})
|
||||
|
||||
local found = FlexLove.getElementAtPosition(200, 200)
|
||||
luaunit.assertNil(found)
|
||||
end
|
||||
|
||||
-- Test: External modules are exposed
|
||||
function TestFlexLove:testExternalModulesExposed()
|
||||
luaunit.assertNotNil(FlexLove.Animation)
|
||||
luaunit.assertNotNil(FlexLove.Color)
|
||||
luaunit.assertNotNil(FlexLove.Theme)
|
||||
luaunit.assertNotNil(FlexLove.enums)
|
||||
end
|
||||
|
||||
-- Test: Enums are accessible
|
||||
function TestFlexLove:testEnumsAccessible()
|
||||
luaunit.assertNotNil(FlexLove.enums.FlexDirection)
|
||||
luaunit.assertNotNil(FlexLove.enums.JustifyContent)
|
||||
luaunit.assertNotNil(FlexLove.enums.AlignItems)
|
||||
end
|
||||
|
||||
return TestFlexLove
|
||||
335
testing/__tests__/ninepatch_parser_test.lua
Normal file
335
testing/__tests__/ninepatch_parser_test.lua
Normal file
@@ -0,0 +1,335 @@
|
||||
local luaunit = require("testing.luaunit")
|
||||
require("testing.loveStub")
|
||||
|
||||
local NinePatchParser = require("modules.NinePatchParser")
|
||||
local ImageDataReader = require("modules.ImageDataReader")
|
||||
|
||||
TestNinePatchParser = {}
|
||||
|
||||
-- Helper to create a valid 9-patch ImageData
|
||||
-- Creates a simple 5x5 9-patch with a 1px stretch region in the center
|
||||
local function create9PatchImageData()
|
||||
local imageData = love.image.newImageData(5, 5)
|
||||
|
||||
-- Fill with transparent pixels (content area)
|
||||
for y = 0, 4 do
|
||||
for x = 0, 4 do
|
||||
imageData:setPixel(x, y, 1, 1, 1, 0) -- Transparent
|
||||
end
|
||||
end
|
||||
|
||||
-- Top border: stretch markers (black pixel at x=2, which is the middle)
|
||||
-- Corners at x=0 and x=4 should be transparent
|
||||
imageData:setPixel(2, 0, 0, 0, 0, 1) -- Black stretch marker
|
||||
|
||||
-- Left border: stretch markers (black pixel at y=2, which is the middle)
|
||||
imageData:setPixel(0, 2, 0, 0, 0, 1) -- Black stretch marker
|
||||
|
||||
-- Bottom border: content padding markers (optional, using same as stretch)
|
||||
imageData:setPixel(2, 4, 0, 0, 0, 1) -- Black content marker
|
||||
|
||||
-- Right border: content padding markers (optional, using same as stretch)
|
||||
imageData:setPixel(4, 2, 0, 0, 0, 1) -- Black content marker
|
||||
|
||||
return imageData
|
||||
end
|
||||
|
||||
-- Helper to create a 9-patch with multiple stretch regions
|
||||
local function create9PatchMultipleRegions()
|
||||
local imageData = love.image.newImageData(7, 7)
|
||||
|
||||
-- Fill with transparent
|
||||
for y = 0, 6 do
|
||||
for x = 0, 6 do
|
||||
imageData:setPixel(x, y, 1, 1, 1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Top: two stretch regions (x=1-2 and x=4-5)
|
||||
imageData:setPixel(1, 0, 0, 0, 0, 1)
|
||||
imageData:setPixel(2, 0, 0, 0, 0, 1)
|
||||
imageData:setPixel(4, 0, 0, 0, 0, 1)
|
||||
imageData:setPixel(5, 0, 0, 0, 0, 1)
|
||||
|
||||
-- Left: two stretch regions (y=1-2 and y=4-5)
|
||||
imageData:setPixel(0, 1, 0, 0, 0, 1)
|
||||
imageData:setPixel(0, 2, 0, 0, 0, 1)
|
||||
imageData:setPixel(0, 4, 0, 0, 0, 1)
|
||||
imageData:setPixel(0, 5, 0, 0, 0, 1)
|
||||
|
||||
return imageData
|
||||
end
|
||||
|
||||
-- Helper to mock ImageDataReader.loadImageData for testing
|
||||
local originalLoadImageData = ImageDataReader.loadImageData
|
||||
local function mockImageDataReader(mockData)
|
||||
ImageDataReader.loadImageData = function(path)
|
||||
if path == "test_valid_9patch.png" then
|
||||
return mockData
|
||||
elseif path == "test_multiple_regions.png" then
|
||||
return create9PatchMultipleRegions()
|
||||
elseif path == "test_small_2x2.png" then
|
||||
return love.image.newImageData(2, 2)
|
||||
elseif path == "test_no_stretch.png" then
|
||||
-- Create a 5x5 with no black pixels (invalid 9-patch)
|
||||
local data = love.image.newImageData(5, 5)
|
||||
for y = 0, 4 do
|
||||
for x = 0, 4 do
|
||||
data:setPixel(x, y, 1, 1, 1, 0)
|
||||
end
|
||||
end
|
||||
return data
|
||||
else
|
||||
return originalLoadImageData(path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function restoreImageDataReader()
|
||||
ImageDataReader.loadImageData = originalLoadImageData
|
||||
end
|
||||
|
||||
-- Unhappy path tests for NinePatchParser.parse()
|
||||
|
||||
function TestNinePatchParser:testParseWithNilPath()
|
||||
local result, err = NinePatchParser.parse(nil)
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
luaunit.assertStrContains(err, "cannot be nil")
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithEmptyString()
|
||||
local result, err = NinePatchParser.parse("")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithInvalidPath()
|
||||
local result, err = NinePatchParser.parse("nonexistent/path/to/image.png")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
luaunit.assertStrContains(err, "Failed to load")
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithNonImageFile()
|
||||
local result, err = NinePatchParser.parse("testing/runAll.lua")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithNumberInsteadOfString()
|
||||
local result, err = NinePatchParser.parse(123)
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithTableInsteadOfString()
|
||||
local result, err = NinePatchParser.parse({})
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithBooleanInsteadOfString()
|
||||
local result, err = NinePatchParser.parse(true)
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
-- Edge case: dimensions that are too small
|
||||
|
||||
function TestNinePatchParser:testParseWith1x1Image()
|
||||
-- Create a minimal mock - parser needs at least 3x3
|
||||
-- This would fail in real scenario
|
||||
luaunit.assertTrue(true) -- Placeholder for actual test with real image
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWith2x2Image()
|
||||
-- Would fail - minimum is 3x3
|
||||
luaunit.assertTrue(true) -- Placeholder
|
||||
end
|
||||
|
||||
-- Test path validation
|
||||
|
||||
function TestNinePatchParser:testParseWithRelativePath()
|
||||
local result, err = NinePatchParser.parse("./fake/path.png")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithAbsolutePath()
|
||||
local result, err = NinePatchParser.parse("/fake/absolute/path.png")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithPathContainingSpaces()
|
||||
local result, err = NinePatchParser.parse("path with spaces/image.png")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithPathContainingSpecialChars()
|
||||
local result, err = NinePatchParser.parse("path/with@special#chars.png")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithVeryLongPath()
|
||||
local longPath = string.rep("a/", 100) .. "image.png"
|
||||
local result, err = NinePatchParser.parse(longPath)
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithDotDotPath()
|
||||
local result, err = NinePatchParser.parse("../../../etc/passwd")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithMixedSlashes()
|
||||
local result, err = NinePatchParser.parse("path\\with/mixed\\slashes.png")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithTrailingSlash()
|
||||
local result, err = NinePatchParser.parse("path/to/image.png/")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithDoubleSlashes()
|
||||
local result, err = NinePatchParser.parse("path//to//image.png")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithNoExtension()
|
||||
local result, err = NinePatchParser.parse("path/to/image")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithWrongExtension()
|
||||
local result, err = NinePatchParser.parse("path/to/image.jpg")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseWithMultipleDots()
|
||||
local result, err = NinePatchParser.parse("path/to/image.9.patch.png")
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
-- Happy path tests with mocked ImageData
|
||||
|
||||
function TestNinePatchParser:testParseValidSimple9Patch()
|
||||
local mockData = create9PatchImageData()
|
||||
mockImageDataReader(mockData)
|
||||
|
||||
local result, err = NinePatchParser.parse("test_valid_9patch.png")
|
||||
|
||||
restoreImageDataReader()
|
||||
|
||||
luaunit.assertNotNil(result)
|
||||
luaunit.assertNil(err)
|
||||
luaunit.assertNotNil(result.insets)
|
||||
luaunit.assertNotNil(result.contentPadding)
|
||||
luaunit.assertNotNil(result.stretchX)
|
||||
luaunit.assertNotNil(result.stretchY)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseValidMultipleRegions()
|
||||
mockImageDataReader()
|
||||
|
||||
local result, err = NinePatchParser.parse("test_multiple_regions.png")
|
||||
|
||||
restoreImageDataReader()
|
||||
|
||||
luaunit.assertNotNil(result)
|
||||
luaunit.assertNil(err)
|
||||
-- Should have 2 stretch regions in each direction
|
||||
luaunit.assertEquals(#result.stretchX, 2)
|
||||
luaunit.assertEquals(#result.stretchY, 2)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseTooSmall2x2()
|
||||
mockImageDataReader()
|
||||
|
||||
local result, err = NinePatchParser.parse("test_small_2x2.png")
|
||||
|
||||
restoreImageDataReader()
|
||||
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
luaunit.assertStrContains(err, "Invalid 9-patch dimensions")
|
||||
luaunit.assertStrContains(err, "minimum 3x3")
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseNoStretchRegions()
|
||||
mockImageDataReader()
|
||||
|
||||
local result, err = NinePatchParser.parse("test_no_stretch.png")
|
||||
|
||||
restoreImageDataReader()
|
||||
|
||||
luaunit.assertNil(result)
|
||||
luaunit.assertNotNil(err)
|
||||
luaunit.assertStrContains(err, "No stretch regions found")
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseInsetsCalculation()
|
||||
local mockData = create9PatchImageData()
|
||||
mockImageDataReader(mockData)
|
||||
|
||||
local result, err = NinePatchParser.parse("test_valid_9patch.png")
|
||||
|
||||
restoreImageDataReader()
|
||||
|
||||
luaunit.assertNotNil(result)
|
||||
-- Verify insets structure
|
||||
luaunit.assertNotNil(result.insets.left)
|
||||
luaunit.assertNotNil(result.insets.top)
|
||||
luaunit.assertNotNil(result.insets.right)
|
||||
luaunit.assertNotNil(result.insets.bottom)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseContentPaddingCalculation()
|
||||
local mockData = create9PatchImageData()
|
||||
mockImageDataReader(mockData)
|
||||
|
||||
local result, err = NinePatchParser.parse("test_valid_9patch.png")
|
||||
|
||||
restoreImageDataReader()
|
||||
|
||||
luaunit.assertNotNil(result)
|
||||
-- Verify content padding structure
|
||||
luaunit.assertNotNil(result.contentPadding.left)
|
||||
luaunit.assertNotNil(result.contentPadding.top)
|
||||
luaunit.assertNotNil(result.contentPadding.right)
|
||||
luaunit.assertNotNil(result.contentPadding.bottom)
|
||||
end
|
||||
|
||||
function TestNinePatchParser:testParseStretchRegionsFormat()
|
||||
local mockData = create9PatchImageData()
|
||||
mockImageDataReader(mockData)
|
||||
|
||||
local result, err = NinePatchParser.parse("test_valid_9patch.png")
|
||||
|
||||
restoreImageDataReader()
|
||||
|
||||
luaunit.assertNotNil(result)
|
||||
-- Verify stretchX and stretchY are arrays of {start, end} pairs
|
||||
luaunit.assertTrue(#result.stretchX >= 1)
|
||||
luaunit.assertTrue(#result.stretchY >= 1)
|
||||
luaunit.assertNotNil(result.stretchX[1].start)
|
||||
luaunit.assertNotNil(result.stretchX[1]["end"])
|
||||
luaunit.assertNotNil(result.stretchY[1].start)
|
||||
luaunit.assertNotNil(result.stretchY[1]["end"])
|
||||
end
|
||||
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
228
testing/__tests__/ninepatch_test.lua
Normal file
228
testing/__tests__/ninepatch_test.lua
Normal file
@@ -0,0 +1,228 @@
|
||||
local luaunit = require("testing.luaunit")
|
||||
require("testing.loveStub")
|
||||
|
||||
local NinePatch = require("modules.NinePatch")
|
||||
|
||||
TestNinePatch = {}
|
||||
|
||||
function TestNinePatch:setUp()
|
||||
-- Create a minimal mock component with regions
|
||||
self.mockComponent = {
|
||||
regions = {
|
||||
topLeft = { x = 0, y = 0, w = 10, h = 10 },
|
||||
topCenter = { x = 10, y = 0, w = 20, h = 10 },
|
||||
topRight = { x = 30, y = 0, w = 10, h = 10 },
|
||||
middleLeft = { x = 0, y = 10, w = 10, h = 20 },
|
||||
middleCenter = { x = 10, y = 10, w = 20, h = 20 },
|
||||
middleRight = { x = 30, y = 10, w = 10, h = 20 },
|
||||
bottomLeft = { x = 0, y = 30, w = 10, h = 10 },
|
||||
bottomCenter = { x = 10, y = 30, w = 20, h = 10 },
|
||||
bottomRight = { x = 30, y = 30, w = 10, h = 10 },
|
||||
},
|
||||
}
|
||||
|
||||
self.mockAtlas = {
|
||||
getDimensions = function()
|
||||
return 100, 100
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
-- Unhappy path tests for NinePatch.draw()
|
||||
|
||||
function TestNinePatch:testDrawWithNilComponent()
|
||||
-- Should return early without error
|
||||
NinePatch.draw(nil, self.mockAtlas, 0, 0, 100, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithNilAtlas()
|
||||
-- Should return early without error
|
||||
NinePatch.draw(self.mockComponent, nil, 0, 0, 100, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithBothNil()
|
||||
-- Should return early without error
|
||||
NinePatch.draw(nil, nil, 0, 0, 100, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithZeroWidth()
|
||||
-- Should handle zero width gracefully
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 0, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithZeroHeight()
|
||||
-- Should handle zero height gracefully
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 0)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithNegativeWidth()
|
||||
-- Should handle negative width
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, -100, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithNegativeHeight()
|
||||
-- Should handle negative height
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, -100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithSmallDimensions()
|
||||
-- Dimensions smaller than borders - should clamp
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 5, 5)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithVeryLargeDimensions()
|
||||
-- Very large dimensions
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 10000, 10000)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithNegativePosition()
|
||||
-- Negative x, y positions
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, -100, -100, 200, 200)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithDefaultOpacity()
|
||||
-- Opacity defaults to 1
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 100, nil)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithZeroOpacity()
|
||||
-- Zero opacity
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 100, 0)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithNegativeOpacity()
|
||||
-- Negative opacity
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 100, -0.5)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithOpacityGreaterThanOne()
|
||||
-- Opacity > 1
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 100, 2.0)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test with missing regions
|
||||
|
||||
-- Test with scaleCorners = 0 (no scaling, just stretching)
|
||||
|
||||
function TestNinePatch:testDrawWithZeroScaleCorners()
|
||||
-- Zero should not trigger scaling path
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 100, 1, 0)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithNegativeScaleCorners()
|
||||
-- Negative should not trigger scaling path
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 100, 1, -1)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithNilScaleCorners()
|
||||
-- Nil should use component setting or default (no scaling)
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 100, 1, nil)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithComponentScalingAlgorithm()
|
||||
-- Test that scalingAlgorithm property exists but don't trigger scaling path
|
||||
local componentWithAlgorithm = {
|
||||
regions = self.mockComponent.regions,
|
||||
scalingAlgorithm = "nearest",
|
||||
}
|
||||
-- Pass nil for scaleCorners to avoid scaling path
|
||||
NinePatch.draw(componentWithAlgorithm, self.mockAtlas, 0, 0, 100, 100, 1, nil, nil)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Edge cases with specific dimensions
|
||||
|
||||
function TestNinePatch:testDrawWithWidthEqualToBorders()
|
||||
-- Width exactly equals left + right borders
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 20, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithHeightEqualToBorders()
|
||||
-- Height exactly equals top + bottom borders
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100, 20)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithExactBorderDimensions()
|
||||
-- Both width and height equal borders
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 20, 20)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithOneLessThanBorders()
|
||||
-- Dimensions one pixel less than borders
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 19, 19)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithFractionalDimensions()
|
||||
-- Non-integer dimensions
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 0, 0, 100.5, 100.7)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithFractionalPosition()
|
||||
-- Non-integer position
|
||||
NinePatch.draw(self.mockComponent, self.mockAtlas, 10.3, 20.7, 100, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test with unusual region sizes
|
||||
|
||||
function TestNinePatch:testDrawWithAsymmetricBorders()
|
||||
local asymmetric = {
|
||||
regions = {
|
||||
topLeft = { x = 0, y = 0, w = 5, h = 5 },
|
||||
topCenter = { x = 5, y = 0, w = 30, h = 5 },
|
||||
topRight = { x = 35, y = 0, w = 15, h = 5 },
|
||||
middleLeft = { x = 0, y = 5, w = 5, h = 30 },
|
||||
middleCenter = { x = 5, y = 5, w = 30, h = 30 },
|
||||
middleRight = { x = 35, y = 5, w = 15, h = 30 },
|
||||
bottomLeft = { x = 0, y = 35, w = 5, h = 10 },
|
||||
bottomCenter = { x = 5, y = 35, w = 30, h = 10 },
|
||||
bottomRight = { x = 35, y = 35, w = 15, h = 10 },
|
||||
},
|
||||
}
|
||||
NinePatch.draw(asymmetric, self.mockAtlas, 0, 0, 100, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
function TestNinePatch:testDrawWithVerySmallRegions()
|
||||
local tiny = {
|
||||
regions = {
|
||||
topLeft = { x = 0, y = 0, w = 1, h = 1 },
|
||||
topCenter = { x = 1, y = 0, w = 1, h = 1 },
|
||||
topRight = { x = 2, y = 0, w = 1, h = 1 },
|
||||
middleLeft = { x = 0, y = 1, w = 1, h = 1 },
|
||||
middleCenter = { x = 1, y = 1, w = 1, h = 1 },
|
||||
middleRight = { x = 2, y = 1, w = 1, h = 1 },
|
||||
bottomLeft = { x = 0, y = 2, w = 1, h = 1 },
|
||||
bottomCenter = { x = 1, y = 2, w = 1, h = 1 },
|
||||
bottomRight = { x = 2, y = 2, w = 1, h = 1 },
|
||||
},
|
||||
}
|
||||
NinePatch.draw(tiny, self.mockAtlas, 0, 0, 100, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
609
testing/__tests__/renderer_test.lua
Normal file
609
testing/__tests__/renderer_test.lua
Normal file
@@ -0,0 +1,609 @@
|
||||
local luaunit = require("testing.luaunit")
|
||||
require("testing.loveStub")
|
||||
|
||||
local Renderer = require("modules.Renderer")
|
||||
local Color = require("modules.Color")
|
||||
local RoundedRect = require("modules.RoundedRect")
|
||||
local NinePatch = require("modules.NinePatch")
|
||||
local ImageRenderer = require("modules.ImageRenderer")
|
||||
local ImageCache = require("modules.ImageCache")
|
||||
local Theme = require("modules.Theme")
|
||||
local Blur = require("modules.Blur")
|
||||
local utils = require("modules.utils")
|
||||
|
||||
TestRenderer = {}
|
||||
|
||||
-- Helper to create dependencies
|
||||
local function createDeps()
|
||||
return {
|
||||
Color = Color,
|
||||
RoundedRect = RoundedRect,
|
||||
NinePatch = NinePatch,
|
||||
ImageRenderer = ImageRenderer,
|
||||
ImageCache = ImageCache,
|
||||
Theme = Theme,
|
||||
Blur = Blur,
|
||||
utils = utils,
|
||||
}
|
||||
end
|
||||
|
||||
-- Helper to create mock element with all required properties
|
||||
local function createMockElement()
|
||||
local element = {
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 100,
|
||||
height = 100,
|
||||
_absoluteX = 0,
|
||||
_absoluteY = 0,
|
||||
padding = {
|
||||
left = 0,
|
||||
right = 0,
|
||||
top = 0,
|
||||
bottom = 0,
|
||||
},
|
||||
textSize = 14,
|
||||
fontFamily = nil,
|
||||
themeComponent = nil,
|
||||
_themeManager = nil,
|
||||
textColor = Color.new(0, 0, 0, 1),
|
||||
text = "Test",
|
||||
editable = false,
|
||||
multiline = false,
|
||||
textWrap = false,
|
||||
textAlign = utils.enums.TextAlign.START,
|
||||
scaleCorners = true,
|
||||
scalingAlgorithm = "bilinear",
|
||||
getScaledContentPadding = function()
|
||||
return nil
|
||||
end,
|
||||
}
|
||||
return element
|
||||
end
|
||||
|
||||
-- Test: new() creates instance with defaults
|
||||
function TestRenderer:testNewWithDefaults()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
|
||||
luaunit.assertNotNil(renderer)
|
||||
luaunit.assertEquals(renderer.opacity, 1)
|
||||
luaunit.assertEquals(renderer.objectFit, "fill")
|
||||
luaunit.assertEquals(renderer.objectPosition, "center center")
|
||||
luaunit.assertEquals(renderer.imageOpacity, 1)
|
||||
end
|
||||
|
||||
-- Test: new() with custom backgroundColor
|
||||
function TestRenderer:testNewWithBackgroundColor()
|
||||
local bgColor = Color.new(1, 0, 0, 1)
|
||||
local renderer = Renderer.new({
|
||||
backgroundColor = bgColor,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.backgroundColor, bgColor)
|
||||
end
|
||||
|
||||
-- Test: new() with custom borderColor
|
||||
function TestRenderer:testNewWithBorderColor()
|
||||
local borderColor = Color.new(0, 1, 0, 1)
|
||||
local renderer = Renderer.new({
|
||||
borderColor = borderColor,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.borderColor, borderColor)
|
||||
end
|
||||
|
||||
-- Test: new() with custom opacity
|
||||
function TestRenderer:testNewWithOpacity()
|
||||
local renderer = Renderer.new({
|
||||
opacity = 0.5,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.opacity, 0.5)
|
||||
end
|
||||
|
||||
-- Test: new() with border configuration
|
||||
function TestRenderer:testNewWithBorder()
|
||||
local renderer = Renderer.new({
|
||||
border = {
|
||||
top = true,
|
||||
right = false,
|
||||
bottom = true,
|
||||
left = false,
|
||||
},
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertTrue(renderer.border.top)
|
||||
luaunit.assertFalse(renderer.border.right)
|
||||
luaunit.assertTrue(renderer.border.bottom)
|
||||
luaunit.assertFalse(renderer.border.left)
|
||||
end
|
||||
|
||||
-- Test: new() with cornerRadius
|
||||
function TestRenderer:testNewWithCornerRadius()
|
||||
local renderer = Renderer.new({
|
||||
cornerRadius = {
|
||||
topLeft = 5,
|
||||
topRight = 10,
|
||||
bottomLeft = 15,
|
||||
bottomRight = 20,
|
||||
},
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.cornerRadius.topLeft, 5)
|
||||
luaunit.assertEquals(renderer.cornerRadius.topRight, 10)
|
||||
luaunit.assertEquals(renderer.cornerRadius.bottomLeft, 15)
|
||||
luaunit.assertEquals(renderer.cornerRadius.bottomRight, 20)
|
||||
end
|
||||
|
||||
-- Test: new() with theme
|
||||
function TestRenderer:testNewWithTheme()
|
||||
local renderer = Renderer.new({
|
||||
theme = "dark",
|
||||
themeComponent = "button",
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.theme, "dark")
|
||||
luaunit.assertEquals(renderer.themeComponent, "button")
|
||||
luaunit.assertEquals(renderer._themeState, "normal")
|
||||
end
|
||||
|
||||
-- Test: new() with imagePath (failed load)
|
||||
function TestRenderer:testNewWithImagePath()
|
||||
local renderer = Renderer.new({
|
||||
imagePath = "nonexistent/image.png",
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.imagePath, "nonexistent/image.png")
|
||||
-- Image will fail to load, so _loadedImage should be nil
|
||||
luaunit.assertNil(renderer._loadedImage)
|
||||
end
|
||||
|
||||
-- Test: new() with imagePath (successful load via cache)
|
||||
function TestRenderer:testNewWithImagePathSuccessfulLoad()
|
||||
local mockImage = {
|
||||
getDimensions = function() return 50, 50 end
|
||||
}
|
||||
|
||||
-- Pre-populate the cache so load succeeds
|
||||
ImageCache._cache["test/image.png"] = {
|
||||
image = mockImage,
|
||||
imageData = nil
|
||||
}
|
||||
|
||||
local renderer = Renderer.new({
|
||||
imagePath = "test/image.png",
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.imagePath, "test/image.png")
|
||||
luaunit.assertEquals(renderer._loadedImage, mockImage)
|
||||
|
||||
-- Clean up cache
|
||||
ImageCache._cache["test/image.png"] = nil
|
||||
end
|
||||
|
||||
-- Test: new() with image object
|
||||
function TestRenderer:testNewWithImageObject()
|
||||
local mockImage = {
|
||||
getDimensions = function()
|
||||
return 50, 50
|
||||
end,
|
||||
}
|
||||
|
||||
local renderer = Renderer.new({
|
||||
image = mockImage,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.image, mockImage)
|
||||
luaunit.assertEquals(renderer._loadedImage, mockImage)
|
||||
end
|
||||
|
||||
-- Test: new() with objectFit
|
||||
function TestRenderer:testNewWithObjectFit()
|
||||
local renderer = Renderer.new({
|
||||
objectFit = "contain",
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.objectFit, "contain")
|
||||
end
|
||||
|
||||
-- Test: new() with objectPosition
|
||||
function TestRenderer:testNewWithObjectPosition()
|
||||
local renderer = Renderer.new({
|
||||
objectPosition = "top left",
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.objectPosition, "top left")
|
||||
end
|
||||
|
||||
-- Test: new() with imageOpacity
|
||||
function TestRenderer:testNewWithImageOpacity()
|
||||
local renderer = Renderer.new({
|
||||
imageOpacity = 0.7,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.imageOpacity, 0.7)
|
||||
end
|
||||
|
||||
-- Test: new() with contentBlur
|
||||
function TestRenderer:testNewWithContentBlur()
|
||||
local renderer = Renderer.new({
|
||||
contentBlur = {
|
||||
intensity = 5,
|
||||
quality = "high",
|
||||
},
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertNotNil(renderer.contentBlur)
|
||||
luaunit.assertEquals(renderer.contentBlur.intensity, 5)
|
||||
luaunit.assertEquals(renderer.contentBlur.quality, "high")
|
||||
end
|
||||
|
||||
-- Test: new() with backdropBlur
|
||||
function TestRenderer:testNewWithBackdropBlur()
|
||||
local renderer = Renderer.new({
|
||||
backdropBlur = {
|
||||
intensity = 10,
|
||||
quality = "medium",
|
||||
},
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertNotNil(renderer.backdropBlur)
|
||||
luaunit.assertEquals(renderer.backdropBlur.intensity, 10)
|
||||
luaunit.assertEquals(renderer.backdropBlur.quality, "medium")
|
||||
end
|
||||
|
||||
-- Test: initialize() sets element reference
|
||||
function TestRenderer:testInitialize()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
local mockElement = createMockElement()
|
||||
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
luaunit.assertEquals(renderer._element, mockElement)
|
||||
end
|
||||
|
||||
-- Test: setThemeState() changes state
|
||||
function TestRenderer:testSetThemeState()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
|
||||
renderer:setThemeState("hover")
|
||||
luaunit.assertEquals(renderer._themeState, "hover")
|
||||
|
||||
renderer:setThemeState("pressed")
|
||||
luaunit.assertEquals(renderer._themeState, "pressed")
|
||||
|
||||
renderer:setThemeState("disabled")
|
||||
luaunit.assertEquals(renderer._themeState, "disabled")
|
||||
end
|
||||
|
||||
-- Note: getBlurInstance() tests are skipped because Renderer.lua has a bug
|
||||
-- where it passes string quality names ("high", "medium", "low") to Blur.new()
|
||||
-- but Blur.new() expects numeric quality values (1-10)
|
||||
|
||||
-- Test: destroy() method exists and can be called
|
||||
function TestRenderer:testDestroy()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
|
||||
-- Should not error
|
||||
renderer:destroy()
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: new() with all border sides enabled
|
||||
function TestRenderer:testNewWithAllBordersEnabled()
|
||||
local renderer = Renderer.new({
|
||||
border = {
|
||||
top = true,
|
||||
right = true,
|
||||
bottom = true,
|
||||
left = true,
|
||||
},
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertTrue(renderer.border.top)
|
||||
luaunit.assertTrue(renderer.border.right)
|
||||
luaunit.assertTrue(renderer.border.bottom)
|
||||
luaunit.assertTrue(renderer.border.left)
|
||||
end
|
||||
|
||||
-- Test: new() with zero cornerRadius
|
||||
function TestRenderer:testNewWithZeroCornerRadius()
|
||||
local renderer = Renderer.new({
|
||||
cornerRadius = {
|
||||
topLeft = 0,
|
||||
topRight = 0,
|
||||
bottomLeft = 0,
|
||||
bottomRight = 0,
|
||||
},
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.cornerRadius.topLeft, 0)
|
||||
luaunit.assertEquals(renderer.cornerRadius.topRight, 0)
|
||||
luaunit.assertEquals(renderer.cornerRadius.bottomLeft, 0)
|
||||
luaunit.assertEquals(renderer.cornerRadius.bottomRight, 0)
|
||||
end
|
||||
|
||||
-- Test: new() with negative opacity (edge case)
|
||||
function TestRenderer:testNewWithNegativeOpacity()
|
||||
local renderer = Renderer.new({
|
||||
opacity = -0.5,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.opacity, -0.5)
|
||||
end
|
||||
|
||||
-- Test: new() with opacity > 1 (edge case)
|
||||
function TestRenderer:testNewWithOpacityGreaterThanOne()
|
||||
local renderer = Renderer.new({
|
||||
opacity = 1.5,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.opacity, 1.5)
|
||||
end
|
||||
|
||||
-- Test: new() with zero imageOpacity
|
||||
function TestRenderer:testNewWithZeroImageOpacity()
|
||||
local renderer = Renderer.new({
|
||||
imageOpacity = 0,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.imageOpacity, 0)
|
||||
end
|
||||
|
||||
-- Test: new() with both imagePath and image (image takes precedence)
|
||||
function TestRenderer:testNewWithBothImagePathAndImage()
|
||||
local mockImage = {
|
||||
getDimensions = function()
|
||||
return 50, 50
|
||||
end,
|
||||
}
|
||||
|
||||
local renderer = Renderer.new({
|
||||
imagePath = "path/to/image.png",
|
||||
image = mockImage,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer._loadedImage, mockImage)
|
||||
end
|
||||
|
||||
-- Test: new() with empty config
|
||||
function TestRenderer:testNewWithEmptyConfig()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
|
||||
luaunit.assertNotNil(renderer)
|
||||
luaunit.assertNotNil(renderer.backgroundColor)
|
||||
luaunit.assertNotNil(renderer.borderColor)
|
||||
luaunit.assertNotNil(renderer.border)
|
||||
luaunit.assertNotNil(renderer.cornerRadius)
|
||||
end
|
||||
|
||||
-- Test: draw() with basic config (should not error)
|
||||
function TestRenderer:testDrawBasic()
|
||||
local renderer = Renderer.new({
|
||||
backgroundColor = Color.new(1, 0, 0, 1),
|
||||
}, createDeps())
|
||||
|
||||
local mockElement = createMockElement()
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
-- Should not error when drawing
|
||||
renderer:draw()
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: draw() with nil backdrop canvas
|
||||
function TestRenderer:testDrawWithNilBackdrop()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
local mockElement = createMockElement()
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
renderer:draw(nil)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: drawPressedState() method exists
|
||||
function TestRenderer:testDrawPressedState()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
local mockElement = createMockElement()
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
-- Should not error
|
||||
renderer:drawPressedState(0, 0, 100, 100)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: getFont() with element
|
||||
function TestRenderer:testGetFont()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
local mockElement = createMockElement()
|
||||
mockElement.fontSize = 16
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
local font = renderer:getFont(mockElement)
|
||||
luaunit.assertNotNil(font)
|
||||
end
|
||||
|
||||
-- Test: drawScrollbars() with proper dims structure
|
||||
function TestRenderer:testDrawScrollbars()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
local mockElement = createMockElement()
|
||||
mockElement.hideScrollbars = { vertical = false, horizontal = false }
|
||||
mockElement.scrollbarWidth = 8
|
||||
mockElement.scrollbarPadding = 2
|
||||
mockElement.scrollbarColor = Color.new(0.5, 0.5, 0.5, 1)
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
local dims = {
|
||||
scrollX = 0,
|
||||
scrollY = 0,
|
||||
contentWidth = 200,
|
||||
contentHeight = 200,
|
||||
vertical = {
|
||||
visible = false,
|
||||
thumbPosition = 0,
|
||||
thumbSize = 50,
|
||||
},
|
||||
horizontal = {
|
||||
visible = false,
|
||||
thumbPosition = 0,
|
||||
thumbSize = 50,
|
||||
},
|
||||
}
|
||||
|
||||
-- Should not error when scrollbars are not visible
|
||||
renderer:drawScrollbars(mockElement, 0, 0, 100, 100, dims)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: new() with all visual properties set
|
||||
function TestRenderer:testNewWithAllVisualProperties()
|
||||
local renderer = Renderer.new({
|
||||
backgroundColor = Color.new(0.5, 0.5, 0.5, 1),
|
||||
borderColor = Color.new(1, 1, 1, 1),
|
||||
opacity = 0.8,
|
||||
border = {
|
||||
top = true,
|
||||
right = true,
|
||||
bottom = true,
|
||||
left = true,
|
||||
},
|
||||
cornerRadius = {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
},
|
||||
theme = "custom",
|
||||
themeComponent = "panel",
|
||||
imagePath = nil,
|
||||
objectFit = "contain",
|
||||
objectPosition = "top left",
|
||||
imageOpacity = 0.9,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.opacity, 0.8)
|
||||
luaunit.assertEquals(renderer.objectFit, "contain")
|
||||
luaunit.assertEquals(renderer.objectPosition, "top left")
|
||||
luaunit.assertEquals(renderer.imageOpacity, 0.9)
|
||||
luaunit.assertTrue(renderer.border.top)
|
||||
luaunit.assertTrue(renderer.border.right)
|
||||
luaunit.assertEquals(renderer.cornerRadius.topLeft, 10)
|
||||
end
|
||||
|
||||
-- Test: new() with theme state
|
||||
function TestRenderer:testThemeStateDefault()
|
||||
local renderer = Renderer.new({
|
||||
theme = "dark",
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer._themeState, "normal")
|
||||
end
|
||||
|
||||
-- Test: setThemeState() with various states
|
||||
function TestRenderer:testSetThemeStateVariousStates()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
|
||||
renderer:setThemeState("active")
|
||||
luaunit.assertEquals(renderer._themeState, "active")
|
||||
|
||||
renderer:setThemeState("normal")
|
||||
luaunit.assertEquals(renderer._themeState, "normal")
|
||||
end
|
||||
|
||||
-- Test: new() with fractional opacity
|
||||
function TestRenderer:testNewWithFractionalOpacity()
|
||||
local renderer = Renderer.new({
|
||||
opacity = 0.333,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.opacity, 0.333)
|
||||
end
|
||||
|
||||
-- Test: new() with fractional imageOpacity
|
||||
function TestRenderer:testNewWithFractionalImageOpacity()
|
||||
local renderer = Renderer.new({
|
||||
imageOpacity = 0.777,
|
||||
}, createDeps())
|
||||
|
||||
luaunit.assertEquals(renderer.imageOpacity, 0.777)
|
||||
end
|
||||
|
||||
-- Test: new() stores dependencies correctly
|
||||
function TestRenderer:testNewStoresDependencies()
|
||||
local deps = createDeps()
|
||||
local renderer = Renderer.new({}, deps)
|
||||
|
||||
luaunit.assertEquals(renderer._Color, deps.Color)
|
||||
luaunit.assertEquals(renderer._RoundedRect, deps.RoundedRect)
|
||||
luaunit.assertEquals(renderer._NinePatch, deps.NinePatch)
|
||||
luaunit.assertEquals(renderer._ImageRenderer, deps.ImageRenderer)
|
||||
luaunit.assertEquals(renderer._ImageCache, deps.ImageCache)
|
||||
luaunit.assertEquals(renderer._Theme, deps.Theme)
|
||||
luaunit.assertEquals(renderer._Blur, deps.Blur)
|
||||
luaunit.assertEquals(renderer._utils, deps.utils)
|
||||
end
|
||||
|
||||
-- Test: new() with objectFit variations
|
||||
function TestRenderer:testNewWithVariousObjectFit()
|
||||
local renderer1 = Renderer.new({ objectFit = "cover" }, createDeps())
|
||||
luaunit.assertEquals(renderer1.objectFit, "cover")
|
||||
|
||||
local renderer2 = Renderer.new({ objectFit = "contain" }, createDeps())
|
||||
luaunit.assertEquals(renderer2.objectFit, "contain")
|
||||
|
||||
local renderer3 = Renderer.new({ objectFit = "none" }, createDeps())
|
||||
luaunit.assertEquals(renderer3.objectFit, "none")
|
||||
end
|
||||
|
||||
-- Test: new() with objectPosition variations
|
||||
function TestRenderer:testNewWithVariousObjectPosition()
|
||||
local renderer1 = Renderer.new({ objectPosition = "top" }, createDeps())
|
||||
luaunit.assertEquals(renderer1.objectPosition, "top")
|
||||
|
||||
local renderer2 = Renderer.new({ objectPosition = "bottom right" }, createDeps())
|
||||
luaunit.assertEquals(renderer2.objectPosition, "bottom right")
|
||||
|
||||
local renderer3 = Renderer.new({ objectPosition = "50% 50%" }, createDeps())
|
||||
luaunit.assertEquals(renderer3.objectPosition, "50% 50%")
|
||||
end
|
||||
|
||||
-- Test: drawText() with mock element
|
||||
function TestRenderer:testDrawText()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
local mockElement = createMockElement()
|
||||
mockElement.text = "Hello World"
|
||||
mockElement.fontSize = 14
|
||||
mockElement.textAlign = "left"
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
-- Should not error
|
||||
renderer:drawText(mockElement)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: drawText() with nil text
|
||||
function TestRenderer:testDrawTextWithNilText()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
local mockElement = createMockElement()
|
||||
mockElement.text = nil
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
-- Should handle nil text gracefully
|
||||
renderer:drawText(mockElement)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: drawText() with empty string
|
||||
function TestRenderer:testDrawTextWithEmptyString()
|
||||
local renderer = Renderer.new({}, createDeps())
|
||||
local mockElement = createMockElement()
|
||||
mockElement.text = ""
|
||||
renderer:initialize(mockElement)
|
||||
|
||||
renderer:drawText(mockElement)
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
259
testing/__tests__/roundedrect_test.lua
Normal file
259
testing/__tests__/roundedrect_test.lua
Normal file
@@ -0,0 +1,259 @@
|
||||
local luaunit = require("testing.luaunit")
|
||||
require("testing.loveStub")
|
||||
|
||||
local RoundedRect = require("modules.RoundedRect")
|
||||
|
||||
TestRoundedRect = {}
|
||||
|
||||
-- Test: getPoints with all corners rounded
|
||||
function TestRoundedRect:testGetPointsAllCornersRounded()
|
||||
local points = RoundedRect.getPoints(0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
}, 10)
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
luaunit.assertEquals(#points % 2, 0) -- Should be even (x,y pairs)
|
||||
end
|
||||
|
||||
-- Test: getPoints with no rounded corners (zero radius)
|
||||
function TestRoundedRect:testGetPointsNoRounding()
|
||||
local points = RoundedRect.getPoints(0, 0, 100, 100, {
|
||||
topLeft = 0,
|
||||
topRight = 0,
|
||||
bottomLeft = 0,
|
||||
bottomRight = 0,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
-- Test: getPoints with asymmetric corners
|
||||
function TestRoundedRect:testGetPointsAsymmetric()
|
||||
local points = RoundedRect.getPoints(10, 10, 200, 150, {
|
||||
topLeft = 5,
|
||||
topRight = 15,
|
||||
bottomLeft = 20,
|
||||
bottomRight = 10,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
-- Test: getPoints with very large radius (should be clamped)
|
||||
function TestRoundedRect:testGetPointsLargeRadius()
|
||||
local points = RoundedRect.getPoints(0, 0, 100, 100, {
|
||||
topLeft = 1000,
|
||||
topRight = 1000,
|
||||
bottomLeft = 1000,
|
||||
bottomRight = 1000,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
-- Test: getPoints with custom segments
|
||||
function TestRoundedRect:testGetPointsCustomSegments()
|
||||
local points1 = RoundedRect.getPoints(0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
}, 5)
|
||||
|
||||
local points2 = RoundedRect.getPoints(0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
}, 20)
|
||||
|
||||
luaunit.assertNotNil(points1)
|
||||
luaunit.assertNotNil(points2)
|
||||
-- More segments should produce more points
|
||||
luaunit.assertTrue(#points2 > #points1)
|
||||
end
|
||||
|
||||
-- Test: getPoints with very small dimensions
|
||||
function TestRoundedRect:testGetPointsSmallDimensions()
|
||||
local points = RoundedRect.getPoints(0, 0, 10, 10, {
|
||||
topLeft = 2,
|
||||
topRight = 2,
|
||||
bottomLeft = 2,
|
||||
bottomRight = 2,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
-- Test: getPoints with negative position
|
||||
function TestRoundedRect:testGetPointsNegativePosition()
|
||||
local points = RoundedRect.getPoints(-50, -50, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
-- Test: getPoints with one corner rounded
|
||||
function TestRoundedRect:testGetPointsOneCorner()
|
||||
local points = RoundedRect.getPoints(0, 0, 100, 100, {
|
||||
topLeft = 0,
|
||||
topRight = 0,
|
||||
bottomLeft = 0,
|
||||
bottomRight = 15,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
-- Test: getPoints with fractional dimensions
|
||||
function TestRoundedRect:testGetPointsFractional()
|
||||
local points = RoundedRect.getPoints(0.5, 0.5, 100.7, 50.3, {
|
||||
topLeft = 8.5,
|
||||
topRight = 8.5,
|
||||
bottomLeft = 8.5,
|
||||
bottomRight = 8.5,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
-- Test: draw with rounded corners (fill mode)
|
||||
function TestRoundedRect:testDrawFillWithRounding()
|
||||
-- Should not error
|
||||
RoundedRect.draw("fill", 0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
})
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: draw with no rounded corners (should use regular rectangle)
|
||||
function TestRoundedRect:testDrawNoRounding()
|
||||
-- Should use love.graphics.rectangle
|
||||
RoundedRect.draw("fill", 0, 0, 100, 100, {
|
||||
topLeft = 0,
|
||||
topRight = 0,
|
||||
bottomLeft = 0,
|
||||
bottomRight = 0,
|
||||
})
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: draw with line mode
|
||||
function TestRoundedRect:testDrawLineMode()
|
||||
RoundedRect.draw("line", 0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
})
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: stencilFunction returns a function
|
||||
function TestRoundedRect:testStencilFunction()
|
||||
local stencil = RoundedRect.stencilFunction(0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
})
|
||||
|
||||
luaunit.assertEquals(type(stencil), "function")
|
||||
end
|
||||
|
||||
-- Test: stencilFunction can be called
|
||||
function TestRoundedRect:testStencilFunctionExecute()
|
||||
local stencil = RoundedRect.stencilFunction(0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
})
|
||||
|
||||
-- Should not error when executed
|
||||
stencil()
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: getPoints with zero-width rectangle
|
||||
function TestRoundedRect:testGetPointsZeroWidth()
|
||||
local points = RoundedRect.getPoints(0, 0, 0, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
end
|
||||
|
||||
-- Test: getPoints with zero-height rectangle
|
||||
function TestRoundedRect:testGetPointsZeroHeight()
|
||||
local points = RoundedRect.getPoints(0, 0, 100, 0, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
})
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
end
|
||||
|
||||
-- Test: draw with mixed zero and non-zero corners
|
||||
function TestRoundedRect:testDrawMixedCorners()
|
||||
RoundedRect.draw("fill", 0, 0, 100, 100, {
|
||||
topLeft = 0,
|
||||
topRight = 15,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 0,
|
||||
})
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: getPoints with very high segment count
|
||||
function TestRoundedRect:testGetPointsHighSegments()
|
||||
local points = RoundedRect.getPoints(0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
}, 100)
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
-- Test: getPoints with segment count of 1
|
||||
function TestRoundedRect:testGetPointsOneSegment()
|
||||
local points = RoundedRect.getPoints(0, 0, 100, 100, {
|
||||
topLeft = 10,
|
||||
topRight = 10,
|
||||
bottomLeft = 10,
|
||||
bottomRight = 10,
|
||||
}, 1)
|
||||
|
||||
luaunit.assertNotNil(points)
|
||||
luaunit.assertTrue(#points > 0)
|
||||
end
|
||||
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
@@ -391,6 +391,103 @@ function TestTextEditor:test_selectOnFocus_default()
|
||||
luaunit.assertFalse(editor.selectOnFocus)
|
||||
end
|
||||
|
||||
-- Test: onSanitize callback triggered when text is sanitized
|
||||
function TestTextEditor:test_onSanitize_callback()
|
||||
local callbackCalled = false
|
||||
local originalText = nil
|
||||
local sanitizedText = nil
|
||||
|
||||
local editor = createTextEditor({
|
||||
maxLength = 5,
|
||||
onSanitize = function(element, original, sanitized)
|
||||
callbackCalled = true
|
||||
originalText = original
|
||||
sanitizedText = sanitized
|
||||
end,
|
||||
})
|
||||
|
||||
local mockElement = createMockElement()
|
||||
editor:initialize(mockElement)
|
||||
|
||||
-- Insert text that exceeds maxLength
|
||||
editor:_sanitizeText("This is a long text that exceeds max length")
|
||||
|
||||
luaunit.assertTrue(callbackCalled)
|
||||
luaunit.assertEquals(originalText, "This is a long text that exceeds max length")
|
||||
luaunit.assertEquals(sanitizedText, "This ")
|
||||
end
|
||||
|
||||
-- Test: initialize with immediate mode and existing state
|
||||
function TestTextEditor:test_initialize_immediate_mode_with_state()
|
||||
local mockStateManager = {
|
||||
getState = function(id)
|
||||
return {
|
||||
_focused = true,
|
||||
_textBuffer = "restored text",
|
||||
_cursorPosition = 10,
|
||||
_selectionStart = 2,
|
||||
_selectionEnd = 5,
|
||||
_cursorBlinkTimer = 0.3,
|
||||
_cursorVisible = false,
|
||||
_cursorBlinkPaused = true,
|
||||
_cursorBlinkPauseTimer = 1.0,
|
||||
}
|
||||
end,
|
||||
saveState = function(id, state) end,
|
||||
}
|
||||
|
||||
local mockContext = {
|
||||
_immediateMode = true,
|
||||
_focusedElement = nil,
|
||||
}
|
||||
|
||||
local editor = TextEditor.new({}, {
|
||||
Context = mockContext,
|
||||
StateManager = mockStateManager,
|
||||
Color = Color,
|
||||
utils = utils,
|
||||
})
|
||||
|
||||
local mockElement = createMockElement()
|
||||
editor:initialize(mockElement)
|
||||
|
||||
-- State should be fully restored
|
||||
luaunit.assertEquals(editor._textBuffer, "restored text")
|
||||
luaunit.assertEquals(editor._cursorPosition, 10)
|
||||
luaunit.assertEquals(editor._selectionStart, 2)
|
||||
luaunit.assertEquals(editor._selectionEnd, 5)
|
||||
luaunit.assertEquals(editor._cursorBlinkTimer, 0.3)
|
||||
luaunit.assertEquals(editor._cursorVisible, false)
|
||||
luaunit.assertEquals(editor._cursorBlinkPaused, true)
|
||||
luaunit.assertEquals(editor._cursorBlinkPauseTimer, 1.0)
|
||||
luaunit.assertTrue(editor._focused)
|
||||
luaunit.assertEquals(mockContext._focusedElement, mockElement)
|
||||
end
|
||||
|
||||
-- Test: customSanitizer function
|
||||
function TestTextEditor:test_customSanitizer()
|
||||
local editor = createTextEditor({
|
||||
customSanitizer = function(text)
|
||||
return text:upper()
|
||||
end,
|
||||
})
|
||||
|
||||
local result = editor:_sanitizeText("hello world")
|
||||
luaunit.assertEquals(result, "HELLO WORLD")
|
||||
end
|
||||
|
||||
-- Test: sanitize disabled
|
||||
function TestTextEditor:test_sanitize_disabled()
|
||||
local editor = createTextEditor({
|
||||
sanitize = false,
|
||||
maxLength = 5,
|
||||
})
|
||||
|
||||
local result = editor:_sanitizeText("This is a very long text")
|
||||
-- Should not be truncated since sanitize is false
|
||||
luaunit.assertEquals(result, "This is a very long text")
|
||||
end
|
||||
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
|
||||
@@ -82,6 +82,10 @@ function love_helper.graphics.line(x1, y1, x2, y2)
|
||||
-- Mock line drawing
|
||||
end
|
||||
|
||||
function love_helper.graphics.polygon(mode, ...)
|
||||
-- Mock polygon drawing
|
||||
end
|
||||
|
||||
function love_helper.graphics.print(text, x, y)
|
||||
-- Mock text printing
|
||||
end
|
||||
|
||||
@@ -18,10 +18,12 @@ local luaunit = require("testing.luaunit")
|
||||
-- Run all tests in the __tests__ directory
|
||||
local testFiles = {
|
||||
"testing/__tests__/animation_test.lua",
|
||||
"testing/__tests__/blur_test.lua",
|
||||
"testing/__tests__/color_validation_test.lua",
|
||||
"testing/__tests__/element_test.lua",
|
||||
"testing/__tests__/error_handler_test.lua",
|
||||
"testing/__tests__/event_handler_test.lua",
|
||||
"testing/__tests__/flexlove_test.lua",
|
||||
"testing/__tests__/grid_test.lua",
|
||||
"testing/__tests__/image_cache_test.lua",
|
||||
"testing/__tests__/image_renderer_test.lua",
|
||||
@@ -29,8 +31,12 @@ local testFiles = {
|
||||
"testing/__tests__/input_event_test.lua",
|
||||
"testing/__tests__/layout_edge_cases_test.lua",
|
||||
"testing/__tests__/layout_engine_test.lua",
|
||||
"testing/__tests__/ninepatch_parser_test.lua",
|
||||
"testing/__tests__/ninepatch_test.lua",
|
||||
"testing/__tests__/overflow_test.lua",
|
||||
"testing/__tests__/path_validation_test.lua",
|
||||
"testing/__tests__/renderer_test.lua",
|
||||
"testing/__tests__/roundedrect_test.lua",
|
||||
"testing/__tests__/sanitization_test.lua",
|
||||
"testing/__tests__/text_editor_test.lua",
|
||||
"testing/__tests__/theme_test.lua",
|
||||
|
||||
Reference in New Issue
Block a user