diff --git a/tests/samples/slay-the-spire-like/grid-inventory.test.ts b/tests/samples/slay-the-spire-like/grid-inventory.test.ts index 94077cf..5d7ed1d 100644 --- a/tests/samples/slay-the-spire-like/grid-inventory.test.ts +++ b/tests/samples/slay-the-spire-like/grid-inventory.test.ts @@ -15,6 +15,48 @@ import { type GridInventory, type InventoryItem, } from "@/samples/slay-the-spire-like/system/grid-inventory"; +import { createItemIn } from "@/samples/slay-the-spire-like/system/grid-inventory/factory"; +import type { GameItemMeta } from "@/samples/slay-the-spire-like/system/grid-inventory/types"; +import type { + CardData, + ItemData, +} from "@/samples/slay-the-spire-like/system/types"; + +/** + * Helper: create a minimal CardData for testing. + */ +function createTestCardData(id: string, name: string, desc: string): CardData { + return { + id, + name, + desc, + type: "item", + costType: "energy", + costCount: 1, + targetType: "single", + effects: [], + }; +} + +/** + * Helper: create a minimal ItemData for testing. + */ +function createTestItemData( + id: string, + name: string, + shapeStr: string, + desc: string, +): ItemData { + return { + id, + type: "weapon", + name, + shape: shapeStr, + card: createTestCardData(id, name, desc), + price: 10, + description: desc, + }; +} /** * Helper: create a test inventory item. @@ -535,4 +577,81 @@ describe("grid-inventory", () => { expect(adjShield.has("sword")).toBe(true); }); }); + + describe("createItemIn", () => { + it("should place item at first valid position", () => { + const inv = createGridInventory(6, 4); + const itemData = createTestItemData("sword", "长剑", "oee", "攻击"); + + const result = createItemIn(inv, "sword-1", itemData); + + expect(result).toEqual({ success: true }); + expect(inv.items.size).toBe(1); + expect(inv.occupiedCells.size).toBe(3); // shape "oee" has 3 cells + expect(inv.items.get("sword-1")?.meta?.itemData.id).toBe("sword"); + }); + + it("should skip occupied cells and find next valid position", () => { + const inv = createGridInventory(6, 4); + + // Place first item manually at origin + const firstItem = createTestItem("existing", "oee"); + placeItem(inv, firstItem); + + const itemData = createTestItemData("shield", "盾牌", "o", "防御"); + + const result = createItemIn(inv, "shield-1", itemData); + + expect(result).toEqual({ success: true }); + // Shield should be at x=3, y=0 (first available spot after "oee" at x=0-2) + const placedItem = inv.items.get("shield-1"); + expect(placedItem?.transform.offset).toEqual({ x: 3, y: 0 }); + }); + + it("should return error when no valid placement exists", () => { + const inv = createGridInventory(3, 3); + + // Fill the grid completely with 1x1 items + for (let i = 0; i < 9; i++) { + const itemData = createTestItemData(`item${i}`, `物品${i}`, "o", ""); + createItemIn(inv, `item-${i}`, itemData); + } + + // Try to place one more item + const itemData = createTestItemData("overflow", "溢出", "oee", ""); + const result = createItemIn(inv, "overflow-1", itemData); + + expect(result).toEqual({ success: false, reason: "无可用位置" }); + }); + + it("should handle multi-cell items correctly", () => { + const inv = createGridInventory(4, 4); + const itemData = createTestItemData("lshape", "L形", "oes", "特殊"); + + const result = createItemIn(inv, "lshape-1", itemData); + + expect(result).toEqual({ success: true }); + expect(inv.items.size).toBe(1); + // Shape "oes" has 3 cells + expect(inv.occupiedCells.size).toBe(3); + }); + + it("should not place item when inventory is completely full", () => { + const inv = createGridInventory(2, 2); + + // Fill with 1x1 items + const itemData = createTestItemData("small", "小物品", "o", ""); + createItemIn(inv, "small-1", itemData); + createItemIn(inv, "small-2", itemData); + createItemIn(inv, "small-3", itemData); + createItemIn(inv, "small-4", itemData); + + // Grid is now full + const overflowItem = createTestItemData("overflow", "溢出", "o", ""); + const result = createItemIn(inv, "overflow-5", overflowItem); + + expect(result).toEqual({ success: false, reason: "无可用位置" }); + expect(inv.items.size).toBe(4); + }); + }); });