Files
slate32/test/header_dirty.lua
T
2026-08-07 20:12:54 -04:00

104 lines
3.7 KiB
Lua

-- Run: lua test/header_dirty.lua
-- The bar is part of the tree, so a tick has to repaint the field that changed and leave
-- the rest of the screen alone. The clock is pinned unsynced so its text is constant and
-- every other field can be steered on its own.
package.path = "sdcard/.lua/lib/?.lua;lib/esp32-lua-api/lua/lib/?.lua;test/?.lua;" .. package.path
local device = require("fake_device").install()
local ui = require "ui"
local nav = require "nav"
local header = require "ui.header"
local footer = require "ui.footer"
device.clockSynced = false
-- History is the arguments this state was started with, so a route to go back to is
-- stated the way main.lua would have received it.
nav.start { app = "Settings", history = { { app = "Home" } } }
-- What main.lua builds, minus the app: chrome above and below, whatever is left between.
local function screen()
if not header.isVisible() then
return ui.box { w = "fill", h = "fill" }
end
return ui.box { w = "fill", h = "fill", header.node(), ui.box { w = "fill", h = "fill" }, footer.node() }
end
ui.mount(screen)
local built = tree.getCount()
assert(device.labelled "--:--:--", "the bar built no clock")
assert(device.labelled "117kB", "the bar built no memory slot")
assert(device.labelled(nav.getTitle()), "the bar built no title")
-- The Lua heap moves under the test itself, so the usage slot below the free one is
-- excluded from the count and asserted on its own.
local function luaSlot()
local found
for id, entry in ipairs(device.nodes) do
if entry.label and entry.label:match "^%d+kB$" then
found = id
end
end
return found
end
assert(luaSlot() ~= device.labelled "117kB", "the bar built no Lua usage slot")
local function tick()
device.invalidated = {}
header.tick()
local ignored, count = luaSlot(), 0
for _, id in ipairs(device.invalidated) do
if id ~= ignored then
count = count + 1
end
end
return count
end
assert(tick() == 0, "an unchanged bar repaints nothing")
device.freeHeap = device.freeHeap - 32000
assert(tick() == 1, "only the memory slot repaints")
assert(device.labelled "148kB", "the memory slot kept its old text")
assert(tree.getCount() == built, "a field update rebuilt the screen")
device.status = { state = "connected", ssid = "x", ip = "", rssi = -50 }
assert(tick() == 1, "the signal strength repaints the icon and nothing else")
assert(tick() == 0, "and settles again afterwards")
device.bleInitialized = true
assert(tick() == 1, "the BLE radio coming up repaints the icon and nothing else")
assert(tick() == 0, "and settles again afterwards")
-- A longer title needs a wider box, which only a rebuild can give it.
nav.setTitle "settings - wifi"
header.tick()
assert(device.labelled "settings - wifi", "a renamed app did not reach the bar")
assert(tick() == 0, "and settles again afterwards")
-- Navigation is the footer's: home is always offered, back only when there is somewhere
-- to go back to. Neither carries a label, so they are counted rather than named.
local function pressable()
local count = 0
for _, entry in ipairs(device.nodes) do
if entry.interactive then
count = count + 1
end
end
return count
end
assert(pressable() == 2, "the footer offered no back control with history behind it")
nav.start { app = "Settings" }
ui.rebuild()
assert(pressable() == 1, "the footer offered back with no history behind it")
-- Fullscreen is chrome choosing not to build itself, so the app's node is the whole tree.
header.setFullscreen(true)
assert(not device.labelled "--:--:--", "the bar survived fullscreen")
assert(pressable() == 0, "the footer survived fullscreen")
header.setFullscreen(false)
assert(device.labelled "--:--:--", "the bar did not come back")
print "ok"