mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
231 lines
9.2 KiB
Lua
231 lines
9.2 KiB
Lua
-- Automated test suite for Game 3 Poké Mart system (shop_menu.lua, marts.lua, bag.lua).
|
|
|
|
require("tests.game3_cache").requireData("game3_shop_menu_test")
|
|
local ShopMenu = require("src.ui.game3.shop_menu")
|
|
local Bag = require("src.core.game3.bag")
|
|
local ItemsData = require("src.core.game3.items_data")
|
|
local Marts = require("src.core.game3.marts")
|
|
local Adapters = require("src.core.game3.scripting.adapters")
|
|
local Message = require("src.ui.game3.message")
|
|
local Stack = require("src.ui.game3.stack")
|
|
|
|
local function make_input(pressedMap)
|
|
pressedMap = pressedMap or {}
|
|
return {
|
|
wasPressed = function(self, key)
|
|
return pressedMap[key] == true
|
|
end,
|
|
isDown = function(self, key)
|
|
return pressedMap[key] == true
|
|
end,
|
|
}
|
|
end
|
|
|
|
local function assert_eq(a, b, msg)
|
|
if a ~= b then
|
|
error(string.format("ASSERTION FAILED: %s (expected %s, got %s)", msg or "", tostring(b), tostring(a)), 2)
|
|
end
|
|
end
|
|
|
|
local function assert_true(val, msg)
|
|
if not val then
|
|
error(string.format("ASSERTION FAILED: %s (expected true, got %s)", msg or "", tostring(val)), 2)
|
|
end
|
|
end
|
|
|
|
print("=== [TEST 1] Marts data lookup ===")
|
|
Marts.ensure()
|
|
local viridianItems = Marts.itemsFor(135731380) or Marts.itemsFor("g3:081649b8") or Marts.itemsFor(135678392)
|
|
assert_true(viridianItems ~= nil and #viridianItems > 0, "Marts.itemsFor resolved stock list")
|
|
print("Resolved mart items count:", #viridianItems)
|
|
|
|
print("=== [TEST 2] ShopMenu Opening and Root Navigation ===")
|
|
local closed = false
|
|
local session = {
|
|
money = 5000,
|
|
bag = Bag.new(),
|
|
}
|
|
ShopMenu.show({
|
|
items = { 4, 13, 19, 20 }, -- POKE_BALL, POTION, ANTIDOTE, PARALYZE_HEAL
|
|
session = session,
|
|
onClose = function() closed = true end,
|
|
})
|
|
assert_true(ShopMenu.isOpen(), "Shop is open")
|
|
assert_eq(ShopMenu.mode, "root", "Initial mode is root")
|
|
assert_eq(ShopMenu.cursor, 1, "Initial cursor on BUY")
|
|
|
|
-- Navigate root menu
|
|
ShopMenu.handleInput(make_input({ down = true }))
|
|
assert_eq(ShopMenu.cursor, 2, "Cursor moved to SELL")
|
|
ShopMenu.handleInput(make_input({ down = true }))
|
|
assert_eq(ShopMenu.cursor, 3, "Cursor moved to SEE YA!")
|
|
ShopMenu.handleInput(make_input({ down = true }))
|
|
assert_eq(ShopMenu.cursor, 1, "Cursor wrapped back to BUY")
|
|
|
|
print("=== [TEST 3] Enter Buy Menu & Quantity Fast-Scroll ===")
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy", "Entered BUY mode")
|
|
assert_eq(ShopMenu.cursor, 1, "Cursor at first item (POKE_BALL)")
|
|
|
|
-- Select Poké Ball (ID 4, price 200)
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy_qty", "Entered buy_qty mode")
|
|
assert_eq(ShopMenu.qty, 1, "Initial quantity is 1")
|
|
|
|
-- Fast scroll: Right (+10) -> qty = 11
|
|
ShopMenu.handleInput(make_input({ right = true }))
|
|
assert_eq(ShopMenu.qty, 11, "Fast-scrolled right to 11")
|
|
|
|
-- Left (-10) -> qty = 1
|
|
ShopMenu.handleInput(make_input({ left = true }))
|
|
assert_eq(ShopMenu.qty, 1, "Fast-scrolled left to 1")
|
|
|
|
-- Set qty to 10
|
|
ShopMenu.handleInput(make_input({ right = true }))
|
|
ShopMenu.handleInput(make_input({ down = true }))
|
|
assert_eq(ShopMenu.qty, 10, "Qty set to 10")
|
|
|
|
print("=== [TEST 4] Buy Confirmation ===")
|
|
-- Press A to confirm quantity -> mode is buy_confirm
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy_confirm", "Entered buy_confirm mode")
|
|
assert_eq(ShopMenu.yesNoCursor, 1, "YES selected")
|
|
|
|
-- Confirm purchase: 10 Poké Balls @ 200 = 2000
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy_msg", "Entered buy_msg mode with success message")
|
|
assert_eq(session.money, 3000, "Money deducted correctly (5000 - 2000 = 3000)")
|
|
assert_eq(Bag.get(session.bag, 4), 10, "Bag received 10 Poké Balls")
|
|
assert_eq(Bag.get(session.bag, 12), 0, "FRLG gives no Premier Ball bonus (shop.c:978 BuyMenuTryMakePurchase)")
|
|
assert_eq(ShopMenu._status, "Here you are!\nThank you!", "Status is gText_HereYouGoThankYou")
|
|
|
|
-- Dismiss message with A
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy", "Returned to buy mode")
|
|
|
|
print("=== [TEST 5] 99 Poké Balls ===")
|
|
session.money = 50000
|
|
ShopMenu.cursor = 1 -- Poké Ball
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy_qty", "Entered buy_qty mode")
|
|
|
|
-- Fast scroll to 99
|
|
for _ = 1, 10 do
|
|
ShopMenu.handleInput(make_input({ right = true }))
|
|
end
|
|
assert_eq(ShopMenu.qty, 99, "Qty clamped at 99")
|
|
|
|
-- Confirm quantity
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy_confirm", "Entered buy_confirm")
|
|
|
|
-- Confirm buy
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(session.money, 50000 - (99 * 200), "Money deducted for 99 balls")
|
|
assert_eq(Bag.get(session.bag, 4), 109, "Bag has 109 Poké Balls")
|
|
assert_eq(Bag.get(session.bag, 12), 0, "no Premier Ball for 99 balls either")
|
|
|
|
-- Dismiss message
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy", "Returned to buy mode")
|
|
|
|
print("=== [TEST 6] 10 Great Balls ===")
|
|
-- Add Great Ball (ID 3, price 600) to shop items
|
|
ShopMenu._items = { 3, 4 }
|
|
ShopMenu.cursor = 1 -- Great Ball
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy_qty", "Entered buy_qty for Great Ball")
|
|
ShopMenu.handleInput(make_input({ right = true })) -- +10 -> 11
|
|
ShopMenu.handleInput(make_input({ down = true })) -- -> 10
|
|
assert_eq(ShopMenu.qty, 10, "10 Great Balls selected")
|
|
ShopMenu.handleInput(make_input({ a = true })) -- Confirm qty
|
|
ShopMenu.handleInput(make_input({ a = true })) -- Confirm buy
|
|
assert_eq(Bag.get(session.bag, 3), 10, "Bag received 10 Great Balls")
|
|
assert_eq(Bag.get(session.bag, 12), 0, "Great Balls yield no Premier Ball")
|
|
ShopMenu.handleInput(make_input({ a = true })) -- Dismiss msg
|
|
|
|
print("=== [TEST 7] Insufficient Funds & Full Bag Handlers ===")
|
|
session.money = 100 -- Less than 200 for Poké Ball
|
|
ShopMenu.cursor = 2 -- Poké Ball
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy_msg", "Entered buy_msg for insufficient funds")
|
|
assert_eq(ShopMenu._status, "You don't have enough money.", "Error message set")
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_eq(ShopMenu.mode, "buy", "Returned safely to buy mode without soft-lock")
|
|
|
|
print("=== [TEST 8] 0-Price Sell Filter & Sell Flow ===")
|
|
-- Give player items: Master Ball (ID 1, price 0), Oak's Parcel (ID 360, price 0), Potion (ID 13, price 300, sell 150), Antidote (ID 19, price 100, sell 50)
|
|
Bag.add(session.bag, 1, 1) -- Master Ball
|
|
Bag.add(session.bag, 360, 1) -- Oak's Parcel
|
|
Bag.add(session.bag, 13, 5) -- Potion (5)
|
|
Bag.add(session.bag, 19, 2) -- Antidote (2)
|
|
|
|
-- Cancel out of BUY back to ROOT
|
|
ShopMenu.handleInput(make_input({ b = true }))
|
|
assert_eq(ShopMenu.mode, "root", "Returned to root")
|
|
assert_eq(ShopMenu._status, "Is there anything else I can do?", "Clerk greeting updated")
|
|
|
|
-- Move to SELL and enter
|
|
ShopMenu.handleInput(make_input({ down = true }))
|
|
assert_eq(ShopMenu.cursor, 2, "Cursor on SELL")
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
local Fade = require("src.ui.game3.fade")
|
|
for _ = 1, 240 do
|
|
if not Fade.isActive() then break end
|
|
Fade.tick(1 / 60)
|
|
end
|
|
local BagMenu = require("src.ui.game3.bag_menu")
|
|
-- pokefirered/src/shop.c:288 CB2_GoToSellMenu
|
|
assert_eq(ShopMenu.mode, "sell", "Entered sell mode")
|
|
assert_true(BagMenu.isOpen() and BagMenu._location == "shop", "SELL opened the bag in shop mode")
|
|
|
|
-- pokefirered/src/shop.c:330
|
|
BagMenu.close()
|
|
assert_eq(ShopMenu.mode, "root", "Returned to root from sell")
|
|
assert_eq(ShopMenu._status, "Is there anything else I can do?", "Clerk asks again after selling")
|
|
|
|
print("=== [TEST 9] Close Poké Mart and Resume VM ===")
|
|
-- Exit via SEE YA! (cursor 3)
|
|
ShopMenu.cursor = 3
|
|
ShopMenu.handleInput(make_input({ a = true }))
|
|
assert_false = function(v, m) if v then error(m or "assert false failed") end end
|
|
assert_false(ShopMenu.isOpen(), "Shop is closed")
|
|
assert_true(closed, "onClose callback fired successfully")
|
|
|
|
print("=== [TEST 10] Script Adapter openShop Integration ===")
|
|
local adapterDone = false
|
|
Message.show("Some stayed clerk message...", { stay = true })
|
|
assert_true(Message.isOpen(), "Field message was open before openShop")
|
|
|
|
local adapters = Adapters.host(nil, nil, nil)
|
|
adapters.openShop(135731380, function() adapterDone = true end)
|
|
assert_false(Message.isOpen(), "Field Message was cleanly closed by openShop")
|
|
assert_true(ShopMenu.isOpen(), "ShopMenu is open via adapter")
|
|
|
|
-- Close shop
|
|
ShopMenu.close()
|
|
assert_false(ShopMenu.isOpen(), "ShopMenu closed")
|
|
assert_true(adapterDone, "Adapter done callback invoked")
|
|
|
|
print("=== [TEST 11] Shop Camera Mode State ===")
|
|
ShopMenu.show({ items = { 4, 13 } })
|
|
assert_true(ShopMenu.isOpen(), "Shop open")
|
|
assert_false(ShopMenu.isShopCamera(), "Root mode is not shop camera")
|
|
local inputA = make_input({ a = true })
|
|
ShopMenu.handleInput(inputA)
|
|
assert_eq(ShopMenu.mode, "buy", "Switched to buy mode")
|
|
assert_true(ShopMenu.isShopCamera(), "Buy mode activates shop camera")
|
|
ShopMenu.close()
|
|
assert_false(ShopMenu.isShopCamera(), "Closed shop deactivates shop camera")
|
|
|
|
print("=== [TEST 12] MoneyBox Cleanup on Shop Close ===")
|
|
local MoneyBox = require("src.ui.game3.money_box")
|
|
MoneyBox.show(19, 1, 1000)
|
|
assert_true(MoneyBox.isVisible(), "MoneyBox initially visible")
|
|
ShopMenu.show({ items = { 4, 13 } })
|
|
assert_false(MoneyBox.isVisible(), "MoneyBox hidden when ShopMenu opens")
|
|
ShopMenu.close()
|
|
assert_false(MoneyBox.isVisible(), "MoneyBox remains hidden after ShopMenu closes")
|
|
|
|
print("\nALL 12 POKÉ MART TESTS PASSED!")
|