diff --git a/init.lua b/init.lua index aaf7b02..02ca077 100644 --- a/init.lua +++ b/init.lua @@ -1,13 +1,16 @@ --- lib-core.crafting-display-test — v0.1.0 --- 9 assertions covering widget creation, action lifecycle, default-empty, --- row visibility (is_known filter), per-row availability, resolver overrides, --- and the panel widget-contract (render(ctx) populating _render_rows). +-- lib-core.crafting-display-test — v0.2.0 +-- 12 assertions: 9 v0.1 existing (widget creation, action lifecycle, +-- default-empty, row visibility, per-row availability, resolver +-- overrides, panel widget-contract) + 3 v0.2 new (Form-1 bw-compat +-- entity-handle, Form-2 locale-factory with multi-source aggregate +-- availability, ctx_inner.locale + container alias propagation). -- Pattern follows P.2.4 Test-Module-Pattern; TAP output via engine.test.* local composition = require("lib-core.composition") local inventory = require("lib-core.inventory-list") local crafting = require("lib-core.crafting") local display = require("lib-core.crafting-display") +local panel = require("lib-core.panel") local T = engine.test local M = {} @@ -74,6 +77,22 @@ local function setup_container(items) return container end +-- fresh_container builds a populated container without touching the +-- recipe-registry. Used in §11 to create a second container after +-- setup_container has already been called for the first one (so the +-- multi-source locale test has two distinct containers without losing +-- the just-defined recipe). +local function fresh_container(items) + local container = composition.create{ template = "craft_display_test.container" } + for _, spec in ipairs(items) do + for _ = 1, spec.count do + local e = composition.create{ template = spec.template } + inventory.add(container, e) + end + end + return container +end + -- --------------------------------------------------------------------- -- Tests -- --------------------------------------------------------------------- @@ -261,6 +280,143 @@ function M.run_tests(_ctx) and widget9._render_rows[1].recipe_id == "render_r9", "9. widget.render(ctx) per panel widget contract populates _render_rows" .. (render_ok and "" or (" (render errored: " .. tostring(render_err) .. ")"))) + + -- ================================================================ + -- §10 (v0.2): Form-1 bw-compat — create(container, opts) with bare + -- handle. _test_get_locale returns the same handle; _test_get_rows + -- still works (single-source availability via Form-1 shim). + -- ================================================================ + local container10 = setup_container{ + { template = "craft_display_test.rock", count = 1 }, + } + crafting.define_recipe{ + id = "form1_r10", + inputs = { { template = "craft_display_test.rock", count = 1 } }, + output = { template = "craft_display_test.rock_pick", count = 1 }, + name = "Form-1 Recipe", + } + local widget10 = display.create(container10) + local locale10 = display._test_get_locale(widget10) + local rows10 = display._test_get_rows(widget10) + T.assert(locale10 == container10 + and #rows10 == 1 + and rows10[1].recipe.id == "form1_r10" + and rows10[1].available == true, + "10. Form-1 bw-compat: _test_get_locale returns bare handle; " + .. "rows resolve via Form-1 shim with correct availability") + + -- ================================================================ + -- §11 (v0.2): Form-2 locale-factory — create(function() -> locale). + -- locale = {sources={c1,c2}, sink=c1}. Recipe needs rock + stick; + -- rock lives in c1, stick in c2. Aggregate availability across + -- sources => row.available == true. + -- ================================================================ + -- Re-initialise registry, define recipe first so both containers + -- can be created after via fresh_container without recipe loss. + crafting._test_clear_all() + crafting.define_recipe{ + id = "form2_r11", + inputs = { + { template = "craft_display_test.rock", count = 1 }, + { template = "craft_display_test.stick", count = 1 }, + }, + output = { template = "craft_display_test.rock_pick", count = 1 }, + name = "Form-2 Recipe", + } + local c11_a = fresh_container{ + { template = "craft_display_test.rock", count = 1 }, + } + local c11_b = fresh_container{ + { template = "craft_display_test.stick", count = 1 }, + } + local locale_table11 = { sources = { c11_a, c11_b }, sink = c11_a } + local widget11 = display.create(function() return locale_table11 end) + local got_locale11 = display._test_get_locale(widget11) + local rows11 = display._test_get_rows(widget11) + T.assert(type(got_locale11) == "table" + and got_locale11.sources ~= nil + and #got_locale11.sources == 2 + and got_locale11.sources[1] == c11_a + and got_locale11.sources[2] == c11_b + and got_locale11.sink == c11_a + and #rows11 == 1 + and rows11[1].recipe.id == "form2_r11" + and rows11[1].available == true, + "11. Form-2 locale-factory: _test_get_locale returns the locale " + .. "table; aggregate availability across sources is true") + + -- ================================================================ + -- §12 (v0.2): ctx_inner.locale + container alias propagation. + -- + -- The panel.show_context_menu callback path is hard to fire in + -- headless test mode (no real click events + no panel-spy hook). + -- Pragmatic substitute: monkey-patch panel.show_context_menu to + -- capture the entries-table, then invoke the first entry's + -- callback directly with a dummy menu_ctx. The captured ctx_inner + -- must carry locale + the sink-alias. + -- + -- Covers both Form-1 (locale == container, alias == container) + -- and Form-2 (locale == table, alias == locale.sink). + -- ================================================================ + crafting._test_clear_all() + crafting.define_recipe{ + id = "alias_r12", + inputs = { { template = "craft_display_test.rock", count = 1 } }, + output = { template = "craft_display_test.rock_pick", count = 1 }, + name = "Alias Recipe", + } + local saved_show = panel.show_context_menu + local captured_entries + panel.show_context_menu = function(_x, _y, entries) + captured_entries = entries + end + + -- Form-1 path + local container12a = fresh_container{ + { template = "craft_display_test.rock", count = 1 }, + } + local widget12a = display.create(container12a) + display.register_action(widget12a, "Craft", function(rid, ctx_inner) + widget12a._captured = { rid = rid, ctx_inner = ctx_inner } + end) + display._invoke_context_menu(widget12a, "alias_r12", 0, 0) + local f1_ok = false + if captured_entries and #captured_entries == 1 then + captured_entries[1].callback({ close_menu = function() end }) + local cap = widget12a._captured + f1_ok = cap ~= nil + and cap.rid == "alias_r12" + and cap.ctx_inner.locale == container12a + and cap.ctx_inner.container == container12a + end + + -- Form-2 path + captured_entries = nil + local c12b_src1 = fresh_container{ + { template = "craft_display_test.rock", count = 1 }, + } + local c12b_src2 = fresh_container{} + local locale_table12 = { sources = { c12b_src1, c12b_src2 }, sink = c12b_src2 } + local widget12b = display.create(function() return locale_table12 end) + display.register_action(widget12b, "Craft", function(rid, ctx_inner) + widget12b._captured = { rid = rid, ctx_inner = ctx_inner } + end) + display._invoke_context_menu(widget12b, "alias_r12", 0, 0) + local f2_ok = false + if captured_entries and #captured_entries == 1 then + captured_entries[1].callback({ close_menu = function() end }) + local cap = widget12b._captured + f2_ok = cap ~= nil + and cap.rid == "alias_r12" + and cap.ctx_inner.locale == locale_table12 + and cap.ctx_inner.container == c12b_src2 -- sink alias + end + + panel.show_context_menu = saved_show + + T.assert(f1_ok and f2_ok, + "12. ctx_inner carries locale + container alias: Form-1 (handle == " + .. "locale == container); Form-2 (locale==table, container==sink)") end return M diff --git a/manifest.lib b/manifest.lib index 4683814..2bd9b84 100644 --- a/manifest.lib +++ b/manifest.lib @@ -1,11 +1,11 @@ { "id": "lib-core.crafting-display-test", "role": "test", - "version": "0.1.0", + "version": "0.2.0", "api_min": "0.1", "deps": [ - {"id": "lib-core.crafting-display", "version": "0.1.0"}, - {"id": "lib-core.crafting", "version": "0.1.0"}, + {"id": "lib-core.crafting-display", "version": "0.2.0"}, + {"id": "lib-core.crafting", "version": "0.2.0"}, {"id": "lib-core.panel", "version": "0.1.1"}, {"id": "lib-core.inventory-list", "version": "0.1.0"}, {"id": "lib-core.composition", "version": "0.3.0"}