test: cover testContainerMenu

This commit is contained in:
dualfroz committed 2026-09-11 14:59:01 +02:00
1 parent cf8fa13be9
commit 7f30b2797b
1 file changed
+159
+159
View File
@@ -156,3 +156,162 @@ VF_TEST(aResultSlotCanBeEmptiedButNeverFilledByHand) {
ContainerMenu menu(MenuKind::CraftingTable, &sharedRegistry()); ContainerMenu menu(MenuKind::CraftingTable, &sharedRegistry());
int result = menu.layout().resultSlot; int result = menu.layout().resultSlot;
CHECK(menu.slot(result).takeOnly);
CHECK(!menu.canPlace(result, makeStack(ItemId::Stone, 1)));
MetaStack stone = makeStack(ItemId::Stone, 1);
CHECK_EQ(menu.insertAt(result, stone), 0);
CHECK_EQ(stone.count, 1);
CHECK(menu.stackAt(result).empty());
// The furnace, anvil and trade outputs answer the same way.
ContainerMenu furnace(MenuKind::Furnace, &sharedRegistry());
int output = furnace.slotsWithRole(MenuSlot::Role::SmeltOutput)[0];
CHECK(!furnace.canPlace(output, makeStack(ItemId::IronIngot, 1)));
ContainerMenu villager(MenuKind::Villager, &sharedRegistry());
int trade = villager.slotsWithRole(MenuSlot::Role::TradeResult)[0];
CHECK(!villager.canPlace(trade, makeStack(ItemId::EmeraldGem, 1)));
}
VF_TEST(theCraftingViewRecomputesTheResultAfterEveryGridChange) {
ContainerMenu menu(MenuKind::CraftingTable, &sharedRegistry());
CraftingView grid = menu.crafting();
CHECK_EQ(grid.cellCount(), 9);
CHECK(!grid.hasResult());
grid.inputAt(0) = makeStack(ItemId::Wood, 1);
grid.refresh();
CHECK(grid.hasResult());
CHECK(grid.result().item == ItemId::Planks);
CHECK_EQ(grid.result().count, 4);
grid.inputAt(0).clear();
grid.refresh();
CHECK(!grid.hasResult());
grid.input(0, 0) = makeStack(ItemId::Planks, 3);
grid.input(0, 1) = makeStack(ItemId::Planks, 3);
grid.refresh();
CHECK(grid.result().item == ItemId::Stick);
CHECK_EQ(grid.result().count, 4);
}
VF_TEST(takingTheResultSpendsExactlyOneItemFromEachFilledInputSlot) {
ContainerMenu menu(MenuKind::CraftingTable, &sharedRegistry());
CraftingView grid = menu.crafting();
grid.input(0, 0) = makeStack(ItemId::Planks, 5);
grid.input(0, 1) = makeStack(ItemId::Planks, 3);
grid.refresh();
CHECK_EQ(grid.maxCrafts(), 3);
MetaStack sticks = grid.takeResult();
CHECK(sticks.item == ItemId::Stick);
CHECK_EQ(sticks.count, 4);
CHECK_EQ(grid.input(0, 0).count, 4);
CHECK_EQ(grid.input(0, 1).count, 2);
CHECK(grid.hasResult());
grid.takeResult();
grid.takeResult();
CHECK_EQ(grid.input(0, 0).count, 2);
CHECK(grid.input(0, 1).empty());
CHECK(!grid.hasResult());
CHECK(grid.takeResult().empty());
}
VF_TEST(aDamageableIngredientStaysInTheGridOnePointWorse) {
CraftingRegistry registry = registryWithToolRecipe();
ContainerMenu menu(MenuKind::CraftingTable, &registry);
CraftingView grid = menu.crafting();
grid.input(0, 0) = makeTool(ItemId::IronShovel);
grid.input(0, 1) = makeStack(ItemId::Planks, 4);
grid.refresh();
CHECK(grid.hasResult());
CHECK(grid.result().item == ItemId::Stick);
MetaStack sticks = grid.takeResult();
CHECK_EQ(sticks.count, 4);
CHECK(!grid.input(0, 0).empty());
CHECK(grid.input(0, 0).item == ItemId::IronShovel);
CHECK_EQ(grid.input(0, 0).meta.durability.used, 1);
CHECK_EQ(grid.input(0, 1).count, 3);
// A shovel one point from death is spent by the craft instead of surviving.
grid.input(0, 0).meta.durability.used = grid.input(0, 0).meta.durability.max - 1;
grid.refresh();
grid.takeResult();
CHECK(grid.input(0, 0).empty());
}
VF_TEST(shiftCraftingRepeatsUntilTheGridRunsDry) {
ContainerMenu menu(MenuKind::CraftingTable, &sharedRegistry());
CraftingView grid = menu.crafting();
grid.input(0, 0) = makeStack(ItemId::Planks, 6);
grid.input(0, 1) = makeStack(ItemId::Planks, 6);
grid.refresh();
int rounds = grid.craftAll(grid.maxCrafts());
CHECK_EQ(rounds, 6);
CHECK(grid.input(0, 0).empty());
CHECK(grid.input(0, 1).empty());
CHECK(!grid.hasResult());
CHECK_EQ(menu.totalOf(ItemId::Stick), 24);
CHECK_EQ(menu.totalOf(ItemId::Planks), 0);
}
VF_TEST(craftingStopsWhenThePlayerSectionsHaveNoRoomLeft) {
ContainerMenu menu(MenuKind::CraftingTable, &sharedRegistry());
for (int index : menu.playerSectionSlots()) {
menu.slot(index).cell.stack = makeStack(ItemId::Obsidian, 64);
}
CraftingView grid = menu.crafting();
grid.input(0, 0) = makeStack(ItemId::Planks, 4);
grid.input(0, 1) = makeStack(ItemId::Planks, 4);
grid.refresh();
int rounds = grid.craftAll(grid.maxCrafts());
CHECK_EQ(rounds, 1);
CHECK_EQ(menu.totalOf(ItemId::Stick), 4);
CHECK_EQ(menu.stackAt(menu.layout().resultSlot).count, 4);
CHECK_EQ(menu.totalOf(ItemId::Planks), 6);
}
VF_TEST(distributingFillsPartialStacksBeforeReachingForAnEmptySlot) {
ContainerMenu menu(MenuKind::Chest, &sharedRegistry());
std::vector<int> storage = menu.containerSectionSlots();
menu.slot(storage[0]).cell.stack = makeStack(ItemId::Sand, 60);
menu.slot(storage[3]).cell.stack = makeStack(ItemId::Sand, 50);
MetaStack incoming = makeStack(ItemId::Sand, 20);
int moved = menu.distributeInto(storage, incoming);
CHECK_EQ(moved, 20);
CHECK(incoming.empty());
CHECK_EQ(menu.stackAt(storage[0]).count, 64);
CHECK_EQ(menu.stackAt(storage[3]).count, 64);
CHECK_EQ(menu.stackAt(storage[1]).count, 2);
CHECK(menu.stackAt(storage[2]).empty());
}
VF_TEST(distributingReportsWhatItCouldNotPlace) {
ContainerMenu menu(MenuKind::Hopper, &sharedRegistry());
std::vector<int> storage = menu.containerSectionSlots();
for (int index : storage) menu.slot(index).cell.stack = makeStack(ItemId::Obsidian, 64);
MetaStack incoming = makeStack(ItemId::Sand, 30);
CHECK_EQ(menu.distributeInto(storage, incoming), 0);
CHECK_EQ(incoming.count, 30);
}
VF_TEST(aBoundContainerLoadsIntoTheStorageSectionAndIsWrittenBackOnClose) {
Container chest(27);
chest.insert(ItemId::Cobblestone, 90);
chest.setSlot(5, ItemSlot{ItemId::IronPickaxe, 1, 100});
ContainerMenu menu(MenuKind::Chest, &sharedRegistry());
menu.bindContainer(chest);
CHECK(menu.hasContainer());
CHECK_EQ(menu.totalOf(ItemId::Cobblestone), 90);