initial: inventory-list-display-test v0.1.0 — 9 assertions
Covers: create round-trip, non-container loud-error, action register/unregister lifecycle, duplicate label + non-function callback loud-errors, empty default action-set, contents ordering via _test_get_rows, default icon-resolver property reads, custom icon-resolver override via set_icon_resolver.
This commit is contained in:
138
init.lua
Normal file
138
init.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
-- lib-core.inventory-list-display-test — v0.1.0
|
||||
-- 9 assertions covering widget creation, action lifecycle, resolver
|
||||
-- overrides, and content ordering.
|
||||
-- Pattern follows P.2.4 Test-Module-Pattern; TAP output via engine.test.*
|
||||
|
||||
local panel = require("lib-core.panel")
|
||||
local composition = require("lib-core.composition")
|
||||
local inventory = require("lib-core.inventory-list")
|
||||
local display = require("lib-core.inventory-list-display")
|
||||
local T = engine.test
|
||||
|
||||
local M = {}
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- Template definitions (shared across all assertions in this run)
|
||||
-- All template IDs are unique to this test lib to avoid clashes.
|
||||
-- ----------------------------------------------------------------
|
||||
|
||||
-- Container template: kind="list", no constraints.
|
||||
composition.define_template{
|
||||
id = "test_backpack",
|
||||
properties = { position = {x = 0, y = 0} },
|
||||
tags = {"renderable"},
|
||||
container = { kind = "list" },
|
||||
}
|
||||
|
||||
-- Item template: individual stack_mode + Atlas-UV properties for icon tests.
|
||||
composition.define_template{
|
||||
id = "test_item",
|
||||
properties = {
|
||||
stack_mode = "individual",
|
||||
sprite_atlas = "tex.png",
|
||||
sprite_uv = {x = 0, y = 0, w = 8, h = 8},
|
||||
position = {x = 0, y = 0},
|
||||
},
|
||||
tags = {"renderable", "item"},
|
||||
}
|
||||
|
||||
function M.run_tests(ctx)
|
||||
local bp = composition.create{template = "test_backpack"}
|
||||
|
||||
-- ================================================================
|
||||
-- 1. create returns widget_def with render + handle_input + title
|
||||
-- ================================================================
|
||||
|
||||
local widget = display.create(bp, { title = "Backpack" })
|
||||
T.assert(widget ~= nil, "create returns non-nil")
|
||||
T.equals(type(widget.render), "function", "widget has render fn")
|
||||
T.equals(type(widget.handle_input), "function", "widget has handle_input")
|
||||
T.equals(widget.title, "Backpack", "title set from opts")
|
||||
|
||||
-- ================================================================
|
||||
-- 2. create with non-container entity -> loud-error
|
||||
-- test_item has no container block, so composition.get_container
|
||||
-- returns nil, and display.create loud-errors.
|
||||
-- ================================================================
|
||||
|
||||
local plain = composition.create{template = "test_item"}
|
||||
local ok2 = pcall(display.create, plain)
|
||||
T.assert(not ok2, "create(non_container) loud-errors")
|
||||
|
||||
-- ================================================================
|
||||
-- 3. register_action + unregister_action round-trip (no error)
|
||||
-- ================================================================
|
||||
|
||||
display.register_action(widget, "Drop", function(item, c) end)
|
||||
display.register_action(widget, "Inspect", function(item, c) end)
|
||||
display.unregister_action(widget, "Drop")
|
||||
T.assert(true, "register/unregister round-trip completes without error")
|
||||
|
||||
-- ================================================================
|
||||
-- 4. Duplicate action label -> loud-error
|
||||
-- "Drop" was unregistered above; re-register then attempt duplicate.
|
||||
-- ================================================================
|
||||
|
||||
display.register_action(widget, "Drop", function() end)
|
||||
local ok4 = pcall(display.register_action, widget, "Drop", function() end)
|
||||
T.assert(not ok4, "duplicate action label loud-errors")
|
||||
|
||||
-- ================================================================
|
||||
-- 5. Non-function callback -> loud-error
|
||||
-- ================================================================
|
||||
|
||||
local ok5 = pcall(display.register_action, widget, "X", "not_fn")
|
||||
T.assert(not ok5, "non-function callback loud-errors")
|
||||
|
||||
-- ================================================================
|
||||
-- 6. Default action-set is empty; unregister of unknown label is no-op
|
||||
-- A fresh widget has no implicit actions. Unregistering a missing
|
||||
-- label must not error (idempotent).
|
||||
-- ================================================================
|
||||
|
||||
local widget2 = display.create(composition.create{template = "test_backpack"})
|
||||
display.unregister_action(widget2, "Drop") -- no-op: not registered
|
||||
T.assert(true, "default action-set empty; unregister of unknown label is no-op")
|
||||
|
||||
-- ================================================================
|
||||
-- 7. Rows match inventory.contents order (_test_get_rows)
|
||||
-- ================================================================
|
||||
|
||||
local item_a = composition.create{template = "test_item"}
|
||||
local item_b = composition.create{template = "test_item"}
|
||||
inventory.add(bp, item_a)
|
||||
inventory.add(bp, item_b)
|
||||
local rows = display._test_get_rows(widget)
|
||||
T.assert(#rows == 2, "rows reflect inventory.contents count")
|
||||
|
||||
-- Verify ordering: item_a was added first, must appear first.
|
||||
-- Compare by composition.reg_id (stable identity; entity userdata has no __eq).
|
||||
local rid_a = item_a:get_property("composition.reg_id")
|
||||
local rid_r1 = rows[1]:get_property("composition.reg_id")
|
||||
T.assert(rid_a ~= nil and rid_r1 == rid_a,
|
||||
"rows[1] matches item_a (insertion order preserved)")
|
||||
|
||||
-- ================================================================
|
||||
-- 8. Default icon-resolver reads sprite_atlas + sprite_uv from properties
|
||||
-- ================================================================
|
||||
|
||||
local icon = display._test_resolve_icon(widget, item_a)
|
||||
T.assert(icon ~= nil, "default icon-resolver returns non-nil table")
|
||||
T.equals(icon.atlas, "tex.png", "icon.atlas matches sprite_atlas property")
|
||||
T.equals(icon.uv.x, 0, "icon.uv.x matches sprite_uv.x property")
|
||||
|
||||
-- ================================================================
|
||||
-- 9. Custom icon-resolver invoked after set_icon_resolver
|
||||
-- ================================================================
|
||||
|
||||
local custom_called = false
|
||||
display.set_icon_resolver(widget, function(item)
|
||||
custom_called = true
|
||||
return {atlas = "custom.png", uv = {x = 1, y = 2, w = 3, h = 4}}
|
||||
end)
|
||||
local icon2 = display._test_resolve_icon(widget, item_a)
|
||||
T.assert(custom_called, "custom icon-resolver was invoked after set_icon_resolver")
|
||||
T.equals(icon2.atlas, "custom.png", "custom resolver returns custom atlas")
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user