Files
gen1recomp/tests/engine/mart_list_box_bug1887.lua

170 lines
5.6 KiB
Lua

-- engine/events/pokemart.asm (#1887)
package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
love = love or require("tests.love_stub")
local realFont = package.loaded["src.render.Font"]
local calls = {}
local FontStub
FontStub = {
BORDER = { tl = 1, tr = 2, bl = 3, br = 4, h = 5, v = 6 },
draw = function(text, x, y) calls[#calls + 1] = { "draw", text, x, y } end,
drawCode = function(code, x, y) calls[#calls + 1] = { "code", code, x, y } end,
drawBox = function(tx, ty, tw, th) calls[#calls + 1] = { "box", tx, ty, tw, th } end,
width = function(text) return #tostring(text) * 8 end,
split = function(text)
local out = {}
for i = 1, #tostring(text) do out[i] = i end
return out
end,
encode = function() return {} end,
spansFitting = function(spans) return #spans end,
advanceOf = function() return 8 end,
}
package.loaded["src.render.Font"] = FontStub
for _, mod in ipairs({ "src.ui.ListMenu", "src.ui.Theme", "src.ui.Menu",
"src.ui.ShopMenu", "src.render.TextBox" }) do
package.loaded[mod] = nil
end
local ShopMenu = require("src.ui.ShopMenu")
local ListMenu = require("src.ui.ListMenu")
local function found(kind, pred)
for _, c in ipairs(calls) do
if c[1] == kind and pred(c) then return c end
end
return nil
end
local pressed
local game
game = {
data = {
text = {},
items = {
POKE_BALL = { name = "POKe BALL", price = 200 },
GREAT_BALL = { name = "GREAT BALL", price = 600 },
TOWN_MAP = { name = "TOWN MAP", price = 0, keyItem = true },
HM_CUT = { name = "HM01", price = 0 },
POTION = { name = "POTION", price = 300 },
},
},
save = { money = 3000, inventory = {}, bagOrder = {} },
input = {
wasPressed = function(_, b) return pressed == b end,
isDown = function() return false end,
},
stack = {
states = {},
push = function(self, s) self.states[#self.states + 1] = s end,
pop = function(self) table.remove(self.states) end,
top = function(self) return self.states[#self.states] end,
},
}
local function drain()
for _ = 1, 600 do
local top = game.stack:top()
if not (top and top.stay and not top.stayShown) then return end
top:update(1 / 60)
end
end
local function openList(which)
game.stack.states = {}
local menu = ShopMenu.new(game, { "POKE_BALL", "GREAT_BALL" }, function() end)
game.stack:push(menu)
menu.index = which
pressed = "a"
menu:update(1 / 60)
pressed = nil
drain()
return menu, game.stack:top()
end
do
local menu = ShopMenu.new(game, { "POKE_BALL" }, function() end)
eq(menu.tx, 0, "BUY/SELL/QUIT sits at column 0")
eq(menu.ty, 0, "and row 0")
eq(menu.tw, 11, "11 tiles wide, flush with the money box at column 11")
eq(menu.th, 7, "7 tiles tall (data/text_boxes.asm:34)")
calls = {}
menu:draw()
check(found("draw", function(c)
return c[2] == "BUY" and c[4] == 8
end) ~= nil, "BUY prints on interior row 1 (wTopMenuItemY 1)")
-- text_boxes.asm:35
check(found("box", function(c)
return c[2] == 11 and c[3] == 0 and c[4] == 9 and c[5] == 3
end) ~= nil, "the money box is MONEY_BOX 11,0 - 19,2")
check(found("draw", function(c)
return c[2] == "MONEY" and c[3] == 104 and c[4] == 0
end) ~= nil, "with MONEY captioned on its top border at column 13")
end
do
local menu, list = openList(1)
check(getmetatable(list) == ListMenu, "BUY opens a list menu")
eq(list.itemBox, true, "PRICEDITEMLISTMENU draws LIST_MENU_BOX")
eq(list.isOpaque, false, "so the mart floor and clerk keep drawing")
eq(list.title, nil, "no BUY header row: the ROM list has no title")
eq(list.items[#list.items].cancel, true, "the terminator's CANCEL row")
eq(list.items[2].price, "¥600", "prices ride item.price, not the name row")
calls = {}
list:draw()
check(found("box", function(c)
return c[2] == 4 and c[3] == 2 and c[4] == 16 and c[5] == 11
end) ~= nil, "LIST_MENU_BOX 4,2 - 19,12")
check(found("draw", function(c)
return c[2] == "GREAT BALL" and c[3] == 48 and c[4] == 48
end) ~= nil, "the second name sits at (48, 48)")
check(found("draw", function(c)
return c[2] == "¥600" and c[4] == 56
end) ~= nil, "its price is one tile row below the name")
local price = found("draw", function(c) return c[2] == "¥600" end)
if price then
eq(price[3] + FontStub.width("¥600"), 136,
"right-aligned through the BCD field (home/list_menu.asm:410-424)")
end
check(found("draw", function(c) return c[2] == "CANCEL" end) ~= nil,
"CANCEL is a real row (home/list_menu.asm:523-528)")
list.index = #list.items
pressed = "a"
list:update(1 / 60)
pressed = nil
drain()
eq(game.stack:top(), menu, "A on CANCEL returns to the mart menu")
end
do
game.save.inventory = { POTION = 3, TOWN_MAP = 1, HM_CUT = 1 }
local _, list = openList(2)
check(getmetatable(list) == ListMenu, "SELL opens a list menu")
eq(list.itemBox, true, "ITEMLISTMENU draws the same box")
eq(list.title, nil, "and carries no SELL header")
local byId = {}
for _, it in ipairs(list.items) do
if it.value then byId[it.value] = it end
end
eq(byId.POTION.count, 3, "ordinary stock keeps its quantity")
eq(byId.TOWN_MAP.count, nil, "IsKeyItem_ skips the quantity")
eq(byId.HM_CUT.right, nil, "and so do the HMs")
eq(list.items[#list.items].cancel, true, "CANCEL closes the sell list too")
game.save.inventory = {}
end
package.loaded["src.render.Font"] = realFont
for _, mod in ipairs({ "src.ui.ListMenu", "src.ui.Theme", "src.ui.Menu",
"src.ui.ShopMenu", "src.render.TextBox" }) do
package.loaded[mod] = nil
end
require("src.ui.Screens").invalidate()
T.finish()