Files
gen1recomp/tests/engine/mart_price_text_bug2291.lua

227 lines
7.7 KiB
Lua

-- engine/events/pokemart.asm:159-169
-- engine/events/pokemart.asm:84-91
-- home/list_menu.asm:89-91
-- luajit tests/engine/mart_price_text_bug2291.lua
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 function glyphs(text)
local n = 0
for _ in tostring(text):gmatch("[%z\1-\127\194-\244][\128-\191]*") do
n = n + 1
end
return n
end
local realFont = package.loaded["src.render.Font"]
package.loaded["src.render.Font"] = {
BORDER = { tl = 1, tr = 2, bl = 3, br = 4, h = 5, v = 6 },
draw = function() end,
drawCode = function() end,
drawBox = function() end,
width = function(text) return glyphs(text) * 8 end,
split = function(text)
local out = {}
for s in tostring(text):gmatch("[%z\1-\127\194-\244][\128-\191]*") do
out[#out + 1] = s
end
return out
end,
spansFitting = function(spans, pixels)
return math.min(#spans, math.floor(pixels / 8))
end,
encode = function(text)
local out = {}
for s in tostring(text):gmatch("[%z\1-\127\194-\244][\128-\191]*") do
out[#out + 1] = s
end
return out
end,
advanceOf = function() return 8 end,
}
local RELOAD = {
"src.ui.QuantityBox", "src.ui.ShopMenu", "src.ui.ListMenu",
"src.ui.ChoiceBox", "src.ui.Menu", "src.ui.Theme", "src.render.TextBox",
}
for _, m in ipairs(RELOAD) do package.loaded[m] = nil end
local ShopMenu = require("src.ui.ShopMenu")
local TextBox = require("src.render.TextBox")
local QuantityBox = require("src.ui.QuantityBox")
local ChoiceBox = require("src.ui.ChoiceBox")
local GREET = "Take your time."
local SELL_GREET = "What would you\nlike to sell?"
local function newGame(money)
local stack, pressed = {}, {}
local game = {
data = {
items = { POKE_BALL = { name = "POKe BALL", price = 200 } },
text = {
_PokemartBuyingGreetingText = GREET,
_PokemonSellingGreetingText = SELL_GREET,
_PokemartTellBuyPriceText = "{RAM:wStringBuffer}?\nThat will be\011¥{NUM:hMoney, 3 | LEADING_ZEROES | LEFT_ALIGN}. OK?{DONE}",
_PokemartTellSellPriceText = "I can pay you\n¥{NUM:hMoney, 3 | LEADING_ZEROES | LEFT_ALIGN} for that.{DONE}",
_PokemartBoughtItemText = "Here you are!\nThank you!{PROMPT}",
},
constants = {},
},
save = { money = money, inventory = {}, bagOrder = {}, options = { textSpeed = 3 } },
input = {
wasPressed = function(_, b) return pressed[b] == true end,
isDown = function() return false end,
},
}
game.stack = {
push = function(_, s) stack[#stack + 1] = s end,
pop = function() return table.remove(stack) end,
top = function() return stack[#stack] end,
}
local function frame(btn)
for k in pairs(pressed) do pressed[k] = nil end
if btn then pressed[btn] = true end
local top = stack[#stack]
top:update(1 / 60)
for k in pairs(pressed) do pressed[k] = nil end
end
return game, stack, frame
end
local function drain(game)
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 flat(box)
local out = {}
for _, page in ipairs(box.pages or {}) do
for _, line in ipairs(page) do out[#out + 1] = line end
end
return out
end
do
local game, stack, frame = newGame(3000)
local menu = ShopMenu.new(game, { "POKE_BALL" }, function() end)
menu.items[1].onSelect()
drain(game)
local list = stack[#stack]
list.index = 1
list.onChoose({ value = "POKE_BALL" })
eq(list.hollowIndex, list.index, "buy: the chosen row shows the hollow cursor")
local qty = stack[#stack]
check(getmetatable(qty) == QuantityBox, "buy: the quantity box opens")
qty.onDone(1)
local box = stack[#stack]
check(getmetatable(box) == TextBox, "buy: the price line is a typed text box, not a bare YES/NO")
check(box.choice ~= nil, "buy: YES/NO waits on the text box")
eq(stack[#stack - 1], qty, "buy: the quantity box stays up under the price text")
eq(stack[#stack - 2], list, "buy: the list is under the quantity box")
eq(list.footer, GREET, "buy: the price line is not dumped into the footer")
local lines = flat(box)
eq(lines[1], "POKe BALL?", "buy: the clerk names the item")
eq(lines[2], "That will be", "buy: line 2")
eq(lines[3], "¥200. OK?", "buy: line 3 carries the price")
frame()
eq(box.done, false, "buy: the price line types, it is not instant")
eq(stack[#stack], box, "buy: no YES/NO while the line is typing")
local sawCont = false
for _ = 1, 300 do
if box.waiting then sawCont = true break end
frame()
end
check(sawCont, "buy: the cont line waits on the arrow")
local vis = box:visibleText() or {}
eq(vis[1], "POKe BALL?", "buy: arrow wait shows the item name")
eq(vis[2], "That will be", "buy: arrow wait shows That will be")
eq(stack[#stack], box, "buy: no YES/NO at the arrow wait")
for _ = 1, 10 do frame() end
frame("a")
local pushed = false
for _ = 1, 300 do
if getmetatable(stack[#stack]) == ChoiceBox then pushed = true break end
frame()
end
check(pushed, "buy: YES/NO opens once the text finishes")
check(box.done, "buy: the text box is done when YES/NO opens")
eq(stack[#stack - 1], box, "buy: YES/NO sits over the price text")
eq(stack[#stack - 2], qty, "buy: the quantity box is still drawn under YES/NO")
game.stack:pop()
game.stack:pop()
box.choice(false)
eq(stack[#stack], list, "buy NO: the quantity box closes back to the list")
eq(list.footer, GREET, "buy NO: the greeting is back")
end
do
local game, stack = newGame(3000)
local menu = ShopMenu.new(game, { "POKE_BALL" }, function() end)
menu.items[1].onSelect()
drain(game)
local list = stack[#stack]
list.onChoose({ value = "POKE_BALL" })
local qty = stack[#stack]
qty.onDone(2)
local box = stack[#stack]
game.stack:pop()
box.choice(true)
eq(game.save.money, 2600, "buy YES: money is paid")
eq(game.save.inventory.POKE_BALL, 2, "buy YES: the items go in the bag")
local bought = stack[#stack]
check(getmetatable(bought) == TextBox and bought.choice == nil,
"buy YES: the receipt text is up")
eq(stack[#stack - 1], qty, "buy YES: the quantity box stays under the receipt")
game.stack:pop()
bought.onDone()
eq(stack[#stack], list, "buy YES: the receipt closes back to the list")
end
do
local game, stack = newGame(0)
game.save.inventory.POKE_BALL = 5
game.save.bagOrder = { "POKE_BALL" }
local menu = ShopMenu.new(game, { "POKE_BALL" }, function() end)
menu.items[2].onSelect()
drain(game)
local list = stack[#stack]
list.index = 1
list.onChoose(list.items[1])
eq(list.hollowIndex, list.index, "sell: the chosen row shows the hollow cursor")
local qty = stack[#stack]
check(getmetatable(qty) == QuantityBox, "sell: the quantity box opens")
qty.onDone(2)
local box = stack[#stack]
check(getmetatable(box) == TextBox and box.choice ~= nil,
"sell: the price line is a typed text box with YES/NO")
eq(stack[#stack - 1], qty, "sell: the quantity box stays up under the price text")
eq(list.footer, SELL_GREET, "sell: the price line is not dumped into the footer")
local lines = flat(box)
eq(lines[1], "I can pay you", "sell: line 1")
eq(lines[2], "¥200 for that.", "sell: line 2 carries the price")
eq(box.done, false, "sell: the price line is not instant")
game.stack:pop()
box.choice(true)
eq(stack[#stack], list, "sell YES: back to the sell list")
eq(game.save.money, 200, "sell YES: money is paid")
eq(game.save.inventory.POKE_BALL, 3, "sell YES: items leave the bag")
end
package.loaded["src.render.Font"] = realFont
for _, m in ipairs(RELOAD) do package.loaded[m] = nil end
require("src.ui.Screens").invalidate()
T.finish()