-- sporel-module-map-editor-test v0.1.0 -- Headless asserts for the editor's API chain: -- load → paint → erase → roof → save → re-load → verify. -- -- Pattern: kind=test-module; all assertions run in init(), engine exits after. local maps = require("lib-core.maps") function init() -- 1. Load fresh test map. -- "maps/test_work.map.json" resolves relative to this module's dir via the -- asset sandbox (engine_path_resolve_asset tries loaded_module.path/). local map_id = maps.load("maps/test_work.map.json") maps.set_current(map_id) -- 2. Paint a surface cell at (2,3) with atlas=0, tile=1, rot=0. local gid_grass = maps.encode_gid(0, 1, 0) maps.set_cell_gid("surface", 2, 3, gid_grass) engine.test.equals(maps.cell_gid("surface", 2, 3), gid_grass, "paint surface (2,3) with grass round-trips via cell_gid") -- 3. Paint with rotation=2. local gid_rotated = maps.encode_gid(0, 1, 2) maps.set_cell_gid("surface", 0, 0, gid_rotated) engine.test.equals(maps.cell_gid("surface", 0, 0), gid_rotated, "paint surface (0,0) with rotated grass round-trips") -- 4. Auto-allocate wall layer. engine.test.equals(maps.cell_gid("wall", 1, 1), 0, "wall layer empty before any write") maps.set_cell_gid("wall", 1, 1, gid_grass) engine.test.equals(maps.cell_gid("wall", 1, 1), gid_grass, "wall layer auto-allocated by set_cell_gid") -- 5. Roof set. maps.set_roof(1, 1, 1) maps.set_roof(2, 2, 1) -- 6. Erase one of the surface cells. maps.set_cell_gid("surface", 2, 3, 0) engine.test.equals(maps.cell_gid("surface", 2, 3), 0, "erase surface (2,3) sets it back to 0") -- 7. Save to a path inside the module's writeable area. -- engine.module.dir_of returns ctx->loaded_module.path — the installed dir -- of this module. io.open with an absolute path bypasses the asset sandbox. local module_dir = engine.module.dir_of("map-editor-test") local out_path = module_dir .. "/maps/test_work_saved.map.json" maps.save_to_disk(map_id, out_path) -- 8. Verify the saved file is readable and contains expected keys. local f = io.open(out_path, "r") engine.test.assert(f ~= nil, "saved file is readable") local content = f:read("*a") f:close() engine.test.assert(content:find('"schema_version"') ~= nil, "saved file has schema_version key") engine.test.assert(content:find('"surface"') ~= nil, "saved file has surface key") engine.test.assert(content:find('"wall"') ~= nil, "saved file has wall key (auto-allocated)") engine.test.assert(content:find('"roof"') ~= nil, "saved file has roof key (auto-allocated)") -- 9. Re-load under a patched id to avoid registry collision. -- Write via absolute path (bypasses sandbox); load via relative path -- (engine.asset.load_json resolves against loaded_module.path == module_dir). local rewritten = content:gsub('"id"%s*:%s*"test_work"', '"id":"test_work_reloaded"') local rl_path = module_dir .. "/maps/test_work_reloaded.map.json" local rf = io.open(rl_path, "w") rf:write(rewritten) rf:close() maps.load("maps/test_work_reloaded.map.json") -- 10. Verify state round-trips. engine.test.equals(maps.cell_gid("surface", 0, 0, "test_work_reloaded"), gid_rotated, "save+reload preserves surface (0,0) rotated grass") engine.test.equals(maps.cell_gid("wall", 1, 1, "test_work_reloaded"), gid_grass, "save+reload preserves wall (1,1) grass") engine.test.equals(maps.cell_gid("surface", 2, 3, "test_work_reloaded"), 0, "save+reload preserves erased cell (0)") -- Cleanup temp files. os.remove(out_path) os.remove(rl_path) engine.print("map-editor-test: all asserts passed") end