mirror of
https://github.com/Insality/druid.git
synced 2025-06-27 10:27:47 +02:00
Update tests
This commit is contained in:
parent
f42211782a
commit
ebd604b29b
@ -175,7 +175,6 @@ end)
|
|||||||
- Druid automatically calls `acquire_input_focus` if you have input components. Therefore, manual calling of `acquire_input_focus` is not required.
|
- Druid automatically calls `acquire_input_focus` if you have input components. Therefore, manual calling of `acquire_input_focus` is not required.
|
||||||
- When deleting a **Druid** component node, make sure to remove it using `druid:remove(component)`.
|
- When deleting a **Druid** component node, make sure to remove it using `druid:remove(component)`.
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
Try the [**HTML5 version**](https://insality.github.io/druid/) of the **Druid** example app.
|
Try the [**HTML5 version**](https://insality.github.io/druid/) of the **Druid** example app.
|
||||||
@ -196,6 +195,7 @@ To better understand **Druid**, read the following documentation:
|
|||||||
- [Druid styles](wiki/styles.md)
|
- [Druid styles](wiki/styles.md)
|
||||||
- [Advanced Setup](wiki/advanced-setup.md)
|
- [Advanced Setup](wiki/advanced-setup.md)
|
||||||
- [Optimize Druid Size](wiki/optimize_druid_size.md)
|
- [Optimize Druid Size](wiki/optimize_druid_size.md)
|
||||||
|
- [Creating Custom Components](wiki/creating_custom_components.md)
|
||||||
- [Changelog](wiki/changelog.md)
|
- [Changelog](wiki/changelog.md)
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@ function init(self)
|
|||||||
deftest.add(require("test.tests.test_helper"))
|
deftest.add(require("test.tests.test_helper"))
|
||||||
deftest.add(require("test.tests.test_text"))
|
deftest.add(require("test.tests.test_text"))
|
||||||
deftest.add(require("test.tests.test_input"))
|
deftest.add(require("test.tests.test_input"))
|
||||||
|
deftest.add(require("test.tests.test_layout"))
|
||||||
|
deftest.add(require("test.tests.test_container"))
|
||||||
|
deftest.add(require("test.tests.test_rich_text"))
|
||||||
deftest.add(require("test.tests.test_druid_instance"))
|
deftest.add(require("test.tests.test_druid_instance"))
|
||||||
|
|
||||||
local is_report = (sys.get_config_int("test.report", 0) == 1)
|
local is_report = (sys.get_config_int("test.report", 0) == 1)
|
||||||
|
319
test/tests/test_container.lua
Normal file
319
test/tests/test_container.lua
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
return function()
|
||||||
|
describe("Container Component", function()
|
||||||
|
local mock_time
|
||||||
|
local mock_input
|
||||||
|
local druid_system
|
||||||
|
local const
|
||||||
|
|
||||||
|
local druid
|
||||||
|
local context
|
||||||
|
|
||||||
|
before(function()
|
||||||
|
mock_time = require("deftest.mock.time")
|
||||||
|
mock_input = require("test.helper.mock_input")
|
||||||
|
druid_system = require("druid.druid")
|
||||||
|
const = require("druid.const")
|
||||||
|
|
||||||
|
mock_time.mock()
|
||||||
|
mock_time.set(0)
|
||||||
|
|
||||||
|
context = vmath.vector3()
|
||||||
|
druid = druid_system.new(context)
|
||||||
|
end)
|
||||||
|
|
||||||
|
after(function()
|
||||||
|
mock_time.unmock()
|
||||||
|
druid:final()
|
||||||
|
druid = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
it("Should initialize container with default settings", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
assert(container ~= nil)
|
||||||
|
assert(container.node == container_node)
|
||||||
|
assert(container.origin_size.x == 100)
|
||||||
|
assert(container.origin_size.y == 100)
|
||||||
|
assert(container.size.x == 100)
|
||||||
|
assert(container.size.y == 100)
|
||||||
|
assert(container.mode == const.LAYOUT_MODE.FIT)
|
||||||
|
assert(container.min_size_x == 0)
|
||||||
|
assert(container.min_size_y == 0)
|
||||||
|
assert(container._containers ~= nil)
|
||||||
|
assert(#container._containers == 0)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should get and set size", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
local size = container:get_size()
|
||||||
|
assert(size.x == 100)
|
||||||
|
assert(size.y == 100)
|
||||||
|
|
||||||
|
container:set_size(200, 150)
|
||||||
|
|
||||||
|
size = container:get_size()
|
||||||
|
assert(size.x == 200)
|
||||||
|
assert(size.y == 150)
|
||||||
|
|
||||||
|
local node_size = gui.get_size(container_node)
|
||||||
|
assert(node_size.x == 200)
|
||||||
|
assert(node_size.y == 150)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should get and set position", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
local position = container:get_position()
|
||||||
|
assert(position.x == 50)
|
||||||
|
assert(position.y == 50)
|
||||||
|
|
||||||
|
container:set_position(100, 200)
|
||||||
|
|
||||||
|
position = container:get_position()
|
||||||
|
assert(position.x == 100)
|
||||||
|
assert(position.y == 200)
|
||||||
|
|
||||||
|
local node_position = gui.get_position(container_node)
|
||||||
|
assert(node_position.x == 100)
|
||||||
|
assert(node_position.y == 200)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set pivot", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
-- Default pivot is typically PIVOT_CENTER
|
||||||
|
local initial_pivot = gui.get_pivot(container_node)
|
||||||
|
|
||||||
|
container:set_pivot(gui.PIVOT_NW)
|
||||||
|
assert(gui.get_pivot(container_node) == gui.PIVOT_NW)
|
||||||
|
|
||||||
|
container:set_pivot(gui.PIVOT_SE)
|
||||||
|
assert(gui.get_pivot(container_node) == gui.PIVOT_SE)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set min size", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
assert(container.min_size_x == 0)
|
||||||
|
assert(container.min_size_y == 0)
|
||||||
|
|
||||||
|
container:set_min_size(50, 75)
|
||||||
|
|
||||||
|
assert(container.min_size_x == 50)
|
||||||
|
assert(container.min_size_y == 75)
|
||||||
|
|
||||||
|
-- Should respect min size when setting smaller size
|
||||||
|
container:set_size(25, 25)
|
||||||
|
local size = container:get_size()
|
||||||
|
assert(size.x == 50)
|
||||||
|
assert(size.y == 75)
|
||||||
|
|
||||||
|
-- Should allow larger size
|
||||||
|
container:set_size(200, 200)
|
||||||
|
size = container:get_size()
|
||||||
|
assert(size.x == 200)
|
||||||
|
assert(size.y == 200)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should fire on_size_changed event", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
local on_size_changed_calls = 0
|
||||||
|
local last_size = nil
|
||||||
|
|
||||||
|
container.on_size_changed:subscribe(function(instance, new_size)
|
||||||
|
on_size_changed_calls = on_size_changed_calls + 1
|
||||||
|
last_size = new_size
|
||||||
|
end)
|
||||||
|
|
||||||
|
container:set_size(200, 150)
|
||||||
|
|
||||||
|
assert(on_size_changed_calls == 1)
|
||||||
|
assert(last_size ~= nil)
|
||||||
|
assert(last_size.x == 200)
|
||||||
|
assert(last_size.y == 150)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should fit into custom size", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node, const.LAYOUT_MODE.STRETCH)
|
||||||
|
|
||||||
|
local fit_size = vmath.vector3(200, 150, 0)
|
||||||
|
container:fit_into_size(fit_size)
|
||||||
|
|
||||||
|
assert(container.fit_size == fit_size)
|
||||||
|
|
||||||
|
-- The exact result will depend on the implementation and screen aspect ratio,
|
||||||
|
-- but we can at least verify it changes the size
|
||||||
|
local size = container:get_size()
|
||||||
|
assert(size.x > 100 or size.y > 100)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should create and manage parent-child container relationships", function()
|
||||||
|
local parent_node = gui.new_box_node(vmath.vector3(400, 300, 0), vmath.vector3(800, 600, 0))
|
||||||
|
local child_node = gui.new_box_node(vmath.vector3(100, 100, 0), vmath.vector3(200, 200, 0))
|
||||||
|
|
||||||
|
local parent_container = druid:new_container(parent_node)
|
||||||
|
|
||||||
|
-- Add a child container through the parent
|
||||||
|
local child_container = parent_container:add_container(child_node)
|
||||||
|
|
||||||
|
assert(child_container ~= nil)
|
||||||
|
assert(child_container.node == child_node)
|
||||||
|
assert(child_container._parent_container == parent_container)
|
||||||
|
assert(#parent_container._containers == 1)
|
||||||
|
assert(parent_container._containers[1] == child_container)
|
||||||
|
|
||||||
|
-- Verify the child's node has been parented correctly
|
||||||
|
assert(gui.get_parent(child_node) == parent_node)
|
||||||
|
|
||||||
|
-- Remove the child container
|
||||||
|
parent_container:remove_container_by_node(child_node)
|
||||||
|
|
||||||
|
assert(#parent_container._containers == 0)
|
||||||
|
|
||||||
|
druid:remove(parent_container)
|
||||||
|
gui.delete_node(parent_node)
|
||||||
|
gui.delete_node(child_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle different layout modes", function()
|
||||||
|
local parent_node = gui.new_box_node(vmath.vector3(400, 300, 0), vmath.vector3(800, 600, 0))
|
||||||
|
local child_node = gui.new_box_node(vmath.vector3(100, 100, 0), vmath.vector3(200, 200, 0))
|
||||||
|
|
||||||
|
local parent_container = druid:new_container(parent_node)
|
||||||
|
|
||||||
|
-- Test FIT mode
|
||||||
|
local child_fit = parent_container:add_container(child_node, const.LAYOUT_MODE.FIT)
|
||||||
|
assert(child_fit.mode == const.LAYOUT_MODE.FIT)
|
||||||
|
|
||||||
|
local size_fit = child_fit:get_size()
|
||||||
|
local original_size = vmath.vector3(200, 200, 0)
|
||||||
|
|
||||||
|
-- Size should remain the same in FIT mode
|
||||||
|
assert(math.abs(size_fit.x - original_size.x) < 0.001)
|
||||||
|
assert(math.abs(size_fit.y - original_size.y) < 0.001)
|
||||||
|
|
||||||
|
-- Set to STRETCH mode
|
||||||
|
parent_container:remove_container_by_node(child_node)
|
||||||
|
local child_stretch = parent_container:add_container(child_node, const.LAYOUT_MODE.STRETCH)
|
||||||
|
assert(child_stretch.mode == const.LAYOUT_MODE.STRETCH)
|
||||||
|
|
||||||
|
-- Set to STRETCH_X mode
|
||||||
|
parent_container:remove_container_by_node(child_node)
|
||||||
|
local child_stretch_x = parent_container:add_container(child_node, const.LAYOUT_MODE.STRETCH_X)
|
||||||
|
assert(child_stretch_x.mode == const.LAYOUT_MODE.STRETCH_X)
|
||||||
|
|
||||||
|
-- Set to STRETCH_Y mode
|
||||||
|
parent_container:remove_container_by_node(child_node)
|
||||||
|
local child_stretch_y = parent_container:add_container(child_node, const.LAYOUT_MODE.STRETCH_Y)
|
||||||
|
assert(child_stretch_y.mode == const.LAYOUT_MODE.STRETCH_Y)
|
||||||
|
|
||||||
|
druid:remove(parent_container)
|
||||||
|
gui.delete_node(parent_node)
|
||||||
|
gui.delete_node(child_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should create and clear draggable corners", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
container:create_draggable_corners()
|
||||||
|
|
||||||
|
assert(#container._draggable_corners > 0)
|
||||||
|
|
||||||
|
container:clear_draggable_corners()
|
||||||
|
|
||||||
|
assert(#container._draggable_corners == 0)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set size and maintain anchor pivot position", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
-- Set pivot to NW corner
|
||||||
|
container:set_pivot(gui.PIVOT_NW)
|
||||||
|
local initial_position = gui.get_position(container_node)
|
||||||
|
|
||||||
|
-- Change size with anchor_pivot=PIVOT_NW - the NW corner should stay at the same position
|
||||||
|
container:set_size(200, 150, gui.PIVOT_NW)
|
||||||
|
|
||||||
|
local new_position = gui.get_position(container_node)
|
||||||
|
assert(math.abs(new_position.x - initial_position.x) < 0.001)
|
||||||
|
assert(math.abs(new_position.y - initial_position.y) < 0.001)
|
||||||
|
|
||||||
|
-- Set pivot to SE corner
|
||||||
|
container:set_pivot(gui.PIVOT_SE)
|
||||||
|
initial_position = gui.get_position(container_node)
|
||||||
|
|
||||||
|
-- Change size with anchor_pivot=PIVOT_SE - the SE corner should stay at the same position
|
||||||
|
container:set_size(300, 250, gui.PIVOT_SE)
|
||||||
|
|
||||||
|
new_position = gui.get_position(container_node)
|
||||||
|
assert(math.abs(new_position.x - initial_position.x) < 0.001)
|
||||||
|
assert(math.abs(new_position.y - initial_position.y) < 0.001)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should refresh origins", function()
|
||||||
|
local container_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local container = druid:new_container(container_node)
|
||||||
|
|
||||||
|
-- Change the node size and position directly
|
||||||
|
gui.set_size(container_node, vmath.vector3(200, 150, 0))
|
||||||
|
gui.set_position(container_node, vmath.vector3(75, 75, 0))
|
||||||
|
|
||||||
|
-- The container's internal origin values should not have updated yet
|
||||||
|
assert(container.origin_size.x == 100)
|
||||||
|
assert(container.origin_size.y == 100)
|
||||||
|
assert(container.origin_position.x == 50)
|
||||||
|
assert(container.origin_position.y == 50)
|
||||||
|
|
||||||
|
-- Refresh origins
|
||||||
|
container:refresh_origins()
|
||||||
|
|
||||||
|
-- Now the origin values should match the node
|
||||||
|
assert(container.origin_size.x == 200)
|
||||||
|
assert(container.origin_size.y == 150)
|
||||||
|
assert(container.origin_position.x == 75)
|
||||||
|
assert(container.origin_position.y == 75)
|
||||||
|
|
||||||
|
druid:remove(container)
|
||||||
|
gui.delete_node(container_node)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
487
test/tests/test_layout.lua
Normal file
487
test/tests/test_layout.lua
Normal file
@ -0,0 +1,487 @@
|
|||||||
|
return function()
|
||||||
|
describe("Layout Component", function()
|
||||||
|
local mock_time
|
||||||
|
local mock_input
|
||||||
|
local druid_system
|
||||||
|
|
||||||
|
local druid
|
||||||
|
local context
|
||||||
|
|
||||||
|
before(function()
|
||||||
|
mock_time = require("deftest.mock.time")
|
||||||
|
mock_input = require("test.helper.mock_input")
|
||||||
|
druid_system = require("druid.druid")
|
||||||
|
|
||||||
|
mock_time.mock()
|
||||||
|
mock_time.set(0)
|
||||||
|
|
||||||
|
context = vmath.vector3()
|
||||||
|
druid = druid_system.new(context)
|
||||||
|
end)
|
||||||
|
|
||||||
|
after(function()
|
||||||
|
mock_time.unmock()
|
||||||
|
druid:final()
|
||||||
|
druid = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
it("Should initialize layout with default settings", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
assert(layout ~= nil)
|
||||||
|
assert(layout.node == layout_node)
|
||||||
|
assert(layout.type == "horizontal")
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
assert(layout.entities ~= nil)
|
||||||
|
assert(#layout.entities == 0)
|
||||||
|
assert(layout.is_resize_width == false)
|
||||||
|
assert(layout.is_resize_height == false)
|
||||||
|
assert(layout.is_justify == false)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should add and remove nodes", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(20, 20, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(20, 20, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
assert(#layout.entities == 1)
|
||||||
|
assert(layout.entities[1] == child1)
|
||||||
|
|
||||||
|
layout:add(child2)
|
||||||
|
assert(#layout.entities == 2)
|
||||||
|
assert(layout.entities[2] == child2)
|
||||||
|
|
||||||
|
layout:remove(child1)
|
||||||
|
assert(#layout.entities == 1)
|
||||||
|
assert(layout.entities[1] == child2)
|
||||||
|
|
||||||
|
layout:clear_layout()
|
||||||
|
assert(#layout.entities == 0)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set node index", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(20, 20, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(20, 20, 0))
|
||||||
|
local child3 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(20, 20, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
layout:add(child2)
|
||||||
|
layout:add(child3)
|
||||||
|
|
||||||
|
assert(layout.entities[1] == child1)
|
||||||
|
assert(layout.entities[2] == child2)
|
||||||
|
assert(layout.entities[3] == child3)
|
||||||
|
|
||||||
|
layout:set_node_index(child3, 1)
|
||||||
|
|
||||||
|
assert(layout.entities[1] == child3)
|
||||||
|
assert(layout.entities[2] == child1)
|
||||||
|
assert(layout.entities[3] == child2)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
gui.delete_node(child3)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set layout type", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
assert(layout.type == "horizontal")
|
||||||
|
|
||||||
|
layout:set_type("vertical")
|
||||||
|
assert(layout.type == "vertical")
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
layout:set_type("horizontal_wrap")
|
||||||
|
assert(layout.type == "horizontal_wrap")
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set margin", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
local initial_margin_x = layout.margin.x
|
||||||
|
local initial_margin_y = layout.margin.y
|
||||||
|
|
||||||
|
layout:set_margin(10, 20)
|
||||||
|
|
||||||
|
assert(layout.margin.x == 10)
|
||||||
|
assert(layout.margin.y == 20)
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
-- Test partial update
|
||||||
|
layout:set_margin(15)
|
||||||
|
assert(layout.margin.x == 15)
|
||||||
|
assert(layout.margin.y == 20)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set padding", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
layout:set_padding(5, 10, 15, 20)
|
||||||
|
|
||||||
|
assert(layout.padding.x == 5) -- left
|
||||||
|
assert(layout.padding.y == 10) -- top
|
||||||
|
assert(layout.padding.z == 15) -- right
|
||||||
|
assert(layout.padding.w == 20) -- bottom
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
-- Test partial update
|
||||||
|
layout:set_padding(25)
|
||||||
|
assert(layout.padding.x == 25)
|
||||||
|
assert(layout.padding.y == 10)
|
||||||
|
assert(layout.padding.z == 15)
|
||||||
|
assert(layout.padding.w == 20)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set justify", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
assert(layout.is_justify == false)
|
||||||
|
|
||||||
|
layout:set_justify(true)
|
||||||
|
assert(layout.is_justify == true)
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
layout:set_justify(false)
|
||||||
|
assert(layout.is_justify == false)
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should set hug content", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
assert(layout.is_resize_width == false)
|
||||||
|
assert(layout.is_resize_height == false)
|
||||||
|
|
||||||
|
layout:set_hug_content(true, false)
|
||||||
|
assert(layout.is_resize_width == true)
|
||||||
|
assert(layout.is_resize_height == false)
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
layout:set_hug_content(false, true)
|
||||||
|
assert(layout.is_resize_width == false)
|
||||||
|
assert(layout.is_resize_height == true)
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
layout:set_hug_content(true, true)
|
||||||
|
assert(layout.is_resize_width == true)
|
||||||
|
assert(layout.is_resize_height == true)
|
||||||
|
assert(layout.is_dirty == true)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should fire on_size_changed event", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
|
||||||
|
local on_size_changed_calls = 0
|
||||||
|
local last_size = nil
|
||||||
|
|
||||||
|
layout.on_size_changed:subscribe(function(new_size)
|
||||||
|
on_size_changed_calls = on_size_changed_calls + 1
|
||||||
|
last_size = new_size
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Set to hug content
|
||||||
|
layout:set_hug_content(true, true)
|
||||||
|
|
||||||
|
-- Add some nodes
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(30, 20, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(30, 20, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
layout:add(child2)
|
||||||
|
|
||||||
|
-- Force refresh to trigger the event
|
||||||
|
layout:refresh_layout()
|
||||||
|
|
||||||
|
assert(on_size_changed_calls >= 1)
|
||||||
|
assert(last_size ~= nil)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle horizontal layout correctly", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(300, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
layout:set_type("horizontal")
|
||||||
|
layout:set_margin(10, 0)
|
||||||
|
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child3 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
layout:add(child2)
|
||||||
|
layout:add(child3)
|
||||||
|
|
||||||
|
layout:refresh_layout()
|
||||||
|
|
||||||
|
-- Check positions - in horizontal layout, nodes should be arranged left to right
|
||||||
|
local pos1 = gui.get_position(child1)
|
||||||
|
local pos2 = gui.get_position(child2)
|
||||||
|
local pos3 = gui.get_position(child3)
|
||||||
|
|
||||||
|
assert(pos2.x > pos1.x)
|
||||||
|
assert(pos3.x > pos2.x)
|
||||||
|
|
||||||
|
-- Y positions should be approximately the same
|
||||||
|
assert(math.abs(pos1.y - pos2.y) < 0.001)
|
||||||
|
assert(math.abs(pos2.y - pos3.y) < 0.001)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
gui.delete_node(child3)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle vertical layout correctly", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 300, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
layout:set_type("vertical")
|
||||||
|
layout:set_margin(0, 10)
|
||||||
|
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child3 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
layout:add(child2)
|
||||||
|
layout:add(child3)
|
||||||
|
|
||||||
|
layout:refresh_layout()
|
||||||
|
|
||||||
|
-- Check positions - in vertical layout, nodes should be arranged top to bottom
|
||||||
|
local pos1 = gui.get_position(child1)
|
||||||
|
local pos2 = gui.get_position(child2)
|
||||||
|
local pos3 = gui.get_position(child3)
|
||||||
|
|
||||||
|
assert(pos2.y < pos1.y)
|
||||||
|
assert(pos3.y < pos2.y)
|
||||||
|
|
||||||
|
-- X positions should be approximately the same
|
||||||
|
assert(math.abs(pos1.x - pos2.x) < 0.001)
|
||||||
|
assert(math.abs(pos2.x - pos3.x) < 0.001)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
gui.delete_node(child3)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle horizontal_wrap layout correctly", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(120, 200, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
layout:set_type("horizontal_wrap")
|
||||||
|
layout:set_margin(10, 10)
|
||||||
|
|
||||||
|
-- Create nodes that will need to wrap
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child3 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child4 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
layout:add(child2)
|
||||||
|
layout:add(child3)
|
||||||
|
layout:add(child4)
|
||||||
|
|
||||||
|
layout:refresh_layout()
|
||||||
|
|
||||||
|
-- Check positions - in horizontal_wrap layout, nodes should wrap to new line
|
||||||
|
local pos1 = gui.get_position(child1)
|
||||||
|
local pos2 = gui.get_position(child2)
|
||||||
|
local pos3 = gui.get_position(child3)
|
||||||
|
local pos4 = gui.get_position(child4)
|
||||||
|
|
||||||
|
-- First two nodes should be on the same row
|
||||||
|
assert(math.abs(pos1.y - pos2.y) < 0.001)
|
||||||
|
|
||||||
|
-- child3 should be on a new row
|
||||||
|
assert(pos3.y < pos1.y)
|
||||||
|
|
||||||
|
-- child3 and child4 should be on the same row
|
||||||
|
assert(math.abs(pos3.y - pos4.y) < 0.001)
|
||||||
|
|
||||||
|
-- X position should flow left to right on each row
|
||||||
|
assert(pos2.x > pos1.x)
|
||||||
|
assert(pos4.x > pos3.x)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
gui.delete_node(child3)
|
||||||
|
gui.delete_node(child4)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should correctly calculate size with content hugging", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(100, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
layout:set_type("vertical")
|
||||||
|
layout:set_hug_content(true, true)
|
||||||
|
layout:set_margin(0, 10)
|
||||||
|
layout:set_padding(5, 5, 5, 5)
|
||||||
|
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(60, 30, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(70, 30, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
layout:add(child2)
|
||||||
|
|
||||||
|
layout:refresh_layout()
|
||||||
|
|
||||||
|
-- Size should be adjusted to fit content plus padding
|
||||||
|
local size = gui.get_size(layout_node)
|
||||||
|
|
||||||
|
-- Expected width: width of widest child (70) + left and right padding (5+5)
|
||||||
|
assert(math.abs(size.x - 80) < 1)
|
||||||
|
|
||||||
|
-- Expected height: sum of child heights (30+30) + margin (10) + top and bottom padding (5+5)
|
||||||
|
assert(math.abs(size.y - 80) < 1)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should justify content horizontally", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(300, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
layout:set_type("horizontal")
|
||||||
|
layout:set_justify(true)
|
||||||
|
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
layout:add(child2)
|
||||||
|
|
||||||
|
layout:refresh_layout()
|
||||||
|
|
||||||
|
-- Check positions - in justified horizontal layout, nodes should be spaced far apart
|
||||||
|
local pos1 = gui.get_position(child1)
|
||||||
|
local pos2 = gui.get_position(child2)
|
||||||
|
|
||||||
|
-- Get the layout size and calculate expected positions
|
||||||
|
local size = gui.get_size(layout_node)
|
||||||
|
|
||||||
|
-- In justified layout, the distance between nodes should be larger than with normal layout
|
||||||
|
assert((pos2.x - pos1.x) > 100)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle disabled nodes", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(300, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
layout:set_type("horizontal")
|
||||||
|
layout:set_margin(10, 0)
|
||||||
|
|
||||||
|
local child1 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child2 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
local child3 = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
|
||||||
|
layout:add(child1)
|
||||||
|
layout:add(child2)
|
||||||
|
layout:add(child3)
|
||||||
|
|
||||||
|
-- Disable the middle node
|
||||||
|
gui.set_enabled(child2, false)
|
||||||
|
|
||||||
|
layout:refresh_layout()
|
||||||
|
|
||||||
|
-- Check positions - the disabled node should be ignored in the layout
|
||||||
|
local pos1 = gui.get_position(child1)
|
||||||
|
local pos3 = gui.get_position(child3)
|
||||||
|
|
||||||
|
-- child3 should be positioned right after child1 (as if child2 doesn't exist)
|
||||||
|
local node_width = gui.get_size(child1).x
|
||||||
|
local expected_gap = node_width + layout.margin.x
|
||||||
|
|
||||||
|
-- The distance should be approximately the width of a node plus margin
|
||||||
|
assert(math.abs((pos3.x - pos1.x) - expected_gap) < 1)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(child1)
|
||||||
|
gui.delete_node(child2)
|
||||||
|
gui.delete_node(child3)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle text nodes correctly", function()
|
||||||
|
local layout_node = gui.new_box_node(vmath.vector3(50, 50, 0), vmath.vector3(300, 100, 0))
|
||||||
|
local layout = druid:new_layout(layout_node)
|
||||||
|
layout:set_type("horizontal")
|
||||||
|
layout:set_margin(10, 0)
|
||||||
|
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(0, 0, 0), "Hello World")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local box_node = gui.new_box_node(vmath.vector3(0, 0, 0), vmath.vector3(50, 30, 0))
|
||||||
|
|
||||||
|
layout:add(text_node)
|
||||||
|
layout:add(box_node)
|
||||||
|
|
||||||
|
layout:refresh_layout()
|
||||||
|
|
||||||
|
-- Check positions - the text node should be positioned based on its text size
|
||||||
|
local pos_text = gui.get_position(text_node)
|
||||||
|
local pos_box = gui.get_position(box_node)
|
||||||
|
|
||||||
|
assert(pos_box.x > pos_text.x)
|
||||||
|
|
||||||
|
druid:remove(layout)
|
||||||
|
gui.delete_node(layout_node)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
gui.delete_node(box_node)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
322
test/tests/test_rich_text.lua
Normal file
322
test/tests/test_rich_text.lua
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
return function()
|
||||||
|
describe("Rich Text Component", function()
|
||||||
|
local mock_time
|
||||||
|
local mock_input
|
||||||
|
local druid_system
|
||||||
|
|
||||||
|
local druid
|
||||||
|
local context
|
||||||
|
|
||||||
|
before(function()
|
||||||
|
mock_time = require("deftest.mock.time")
|
||||||
|
mock_input = require("test.helper.mock_input")
|
||||||
|
druid_system = require("druid.druid")
|
||||||
|
|
||||||
|
mock_time.mock()
|
||||||
|
mock_time.set(0)
|
||||||
|
|
||||||
|
context = vmath.vector3()
|
||||||
|
druid = druid_system.new(context)
|
||||||
|
end)
|
||||||
|
|
||||||
|
after(function()
|
||||||
|
mock_time.unmock()
|
||||||
|
druid:final()
|
||||||
|
druid = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
it("Should initialize with default settings", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "Initial Text")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
assert(rich_text ~= nil)
|
||||||
|
assert(rich_text.root == text_node)
|
||||||
|
assert(rich_text.text_prefab == text_node)
|
||||||
|
assert(rich_text:get_text() == "Initial Text")
|
||||||
|
|
||||||
|
-- Check that the original text node is cleared
|
||||||
|
assert(gui.get_text(text_node) == "")
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should initialize with custom text", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "Initial Text")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node, "Custom Text")
|
||||||
|
|
||||||
|
assert(rich_text:get_text() == "Custom Text")
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle basic text setting and getting", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
assert(rich_text:get_text() == "")
|
||||||
|
|
||||||
|
rich_text:set_text("Hello, World!")
|
||||||
|
assert(rich_text:get_text() == "Hello, World!")
|
||||||
|
|
||||||
|
rich_text:set_text("New text")
|
||||||
|
assert(rich_text:get_text() == "New text")
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle color tag", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Test color tag with named color
|
||||||
|
local words = rich_text:set_text("<color=red>Colored Text</color>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
-- Word should have a tags field with color tag
|
||||||
|
assert(words[1].tags.color)
|
||||||
|
|
||||||
|
-- Test color tag with RGB values
|
||||||
|
words = rich_text:set_text("<color=1.0,0,0,1.0>Colored Text</color>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].tags.color)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle shadow tag", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Test shadow tag with named color
|
||||||
|
local words = rich_text:set_text("<shadow=black>Shadowed Text</shadow>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].shadow ~= nil)
|
||||||
|
|
||||||
|
-- Test shadow tag with RGBA values
|
||||||
|
words = rich_text:set_text("<shadow=0,0,0,1.0>Shadowed Text</shadow>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].shadow ~= nil)
|
||||||
|
assert(words[1].shadow.x < 0.1) -- Black shadow should have low RGB values
|
||||||
|
assert(words[1].shadow.y < 0.1)
|
||||||
|
assert(words[1].shadow.z < 0.1)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle outline tag", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Test outline tag with named color
|
||||||
|
local words = rich_text:set_text("<outline=black>Outlined Text</outline>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].outline ~= nil)
|
||||||
|
|
||||||
|
-- Test outline tag with RGBA values
|
||||||
|
words = rich_text:set_text("<outline=0,0,0,1.0>Outlined Text</outline>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].outline ~= nil)
|
||||||
|
assert(words[1].outline.x < 0.1) -- Black outline should have low RGB values
|
||||||
|
assert(words[1].outline.y < 0.1)
|
||||||
|
assert(words[1].outline.z < 0.1)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle size tag", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Test size tag with value of 2 (twice as large)
|
||||||
|
local words = rich_text:set_text("<size=2>Large Text</size>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].relative_scale == 2)
|
||||||
|
|
||||||
|
-- Test size tag with value of 0.5 (half as large)
|
||||||
|
words = rich_text:set_text("<size=0.5>Small Text</size>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].relative_scale == 0.5)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle line break tag", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
gui.set_line_break(text_node, true) -- Enable multiline
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Test line break tag
|
||||||
|
local words, line_metrics = rich_text:set_text("Line 1<br/>Line 2")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(line_metrics.lines ~= nil)
|
||||||
|
assert(#line_metrics.lines >= 2) -- Should have at least 2 lines
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle nobr tag", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
gui.set_line_break(text_node, true) -- Enable multiline
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Test no break tag
|
||||||
|
local words = rich_text:set_text("<nobr>This text should not break to multiple lines</nobr>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].nobr == true)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle image tag", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Testing with a default texture with a fixed width and height to avoid nil errors
|
||||||
|
-- (This ensures image.width and image.height are numbers, not nil)
|
||||||
|
local words = rich_text:set_text("<img=druid:pixel,50,50/>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].tags.img)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle multiple tags", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Test combined tags
|
||||||
|
local words = rich_text:set_text("<color=red><size=2>Big Red Text</size></color>")
|
||||||
|
|
||||||
|
assert(#words > 0)
|
||||||
|
assert(words[1].tags.color)
|
||||||
|
assert(words[1].tags.size)
|
||||||
|
assert(words[1].relative_scale == 2)
|
||||||
|
|
||||||
|
-- Test nested tags
|
||||||
|
words = rich_text:set_text("<color=red>Red <size=2>Big Red</size> Red</color>")
|
||||||
|
|
||||||
|
assert(#words >= 3)
|
||||||
|
-- All words should have color tag
|
||||||
|
assert(words[1].tags.color)
|
||||||
|
assert(words[2].tags.color)
|
||||||
|
assert(words[3].tags.color)
|
||||||
|
|
||||||
|
-- Middle word should also have size tag
|
||||||
|
assert(words[2].tags.size)
|
||||||
|
assert(words[2].relative_scale == 2)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should handle tagged words", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Set text with a custom tag
|
||||||
|
rich_text:set_text("<mytag>Tagged Text</mytag> Normal Text")
|
||||||
|
|
||||||
|
-- Get words with the custom tag
|
||||||
|
local tagged_words = rich_text:tagged("mytag")
|
||||||
|
|
||||||
|
assert(#tagged_words > 0)
|
||||||
|
assert(tagged_words[1].tags.mytag == true)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should clear text", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Set some text first
|
||||||
|
rich_text:set_text("Hello, World!")
|
||||||
|
|
||||||
|
assert(rich_text:get_text() == "Hello, World!")
|
||||||
|
assert(rich_text:get_words() ~= nil)
|
||||||
|
|
||||||
|
-- Clear text
|
||||||
|
rich_text:clear()
|
||||||
|
|
||||||
|
assert(rich_text:get_text() == nil)
|
||||||
|
assert(rich_text:get_words() == nil)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should get words and line metrics", function()
|
||||||
|
local text_node = gui.new_text_node(vmath.vector3(50, 50, 0), "")
|
||||||
|
gui.set_font(text_node, "druid_text_bold")
|
||||||
|
|
||||||
|
local rich_text = druid:new_rich_text(text_node)
|
||||||
|
|
||||||
|
-- Set text
|
||||||
|
rich_text:set_text("Hello, World!")
|
||||||
|
|
||||||
|
-- Get words
|
||||||
|
local words = rich_text:get_words()
|
||||||
|
|
||||||
|
assert(words ~= nil)
|
||||||
|
assert(#words > 0)
|
||||||
|
|
||||||
|
-- Get line metrics
|
||||||
|
local line_metrics = rich_text:get_line_metric()
|
||||||
|
|
||||||
|
assert(line_metrics ~= nil)
|
||||||
|
-- Just check line_metrics exists, don't assume values
|
||||||
|
assert(line_metrics.lines ~= nil)
|
||||||
|
|
||||||
|
druid:remove(rich_text)
|
||||||
|
gui.delete_node(text_node)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user