393ce3c0ed
lua_app.cpp had grown to 701 lines holding every binding, the module loader and the app lifecycle, so new bindings landed wherever the cursor was. Each Lua table now has its own file under bindings/, and the app is recovered from the lua_State's extra space instead of a file-static, so a second state cannot reach the wrong app. Three tests each redeclared the binding surface, which broke twice this session when a binding changed; test/fake_device.lua is now the single stub. `make test` runs all four suites and pins Lua 5.4, matching the vendored interpreter rather than the 5.2 the tests had silently been using.
64 lines
2.8 KiB
Lua
64 lines
2.8 KiB
Lua
-- Run: lua test/ui_theme.lua
|
|
-- Asserts the palette ui.lua derives from a theme's three seed colors. The fake packs
|
|
-- channels into one integer, so contrast between roles stays checkable.
|
|
package.path = "sdcard/lib/?.lua;test/?.lua;" .. package.path
|
|
|
|
local device = require("fake_device").install()
|
|
local ui = require("ui")
|
|
|
|
local BLACK, WHITE = gui.color(0, 0, 0), gui.color(255, 255, 255)
|
|
|
|
local function reload(name)
|
|
device.theme = name
|
|
return ui.reloadTheme()
|
|
end
|
|
|
|
-- Seeds pass through untouched.
|
|
local light = reload("light")
|
|
assert(light.bg == WHITE, "light bg")
|
|
assert(light.fg == BLACK, "light fg")
|
|
assert(light.accent == gui.color(0, 120, 255), "light accent")
|
|
|
|
-- Muted sits between the text and the surface, so it reads as secondary on both.
|
|
assert(light.muted > BLACK and light.muted < WHITE, "muted between fg and bg")
|
|
|
|
-- Contrast is derived, never configured: text on a dark accent must be light.
|
|
assert(light.accent_fg == WHITE, "white text on the blue accent")
|
|
assert(reload("mono").accent_fg == WHITE, "white text on the black accent")
|
|
|
|
-- A pale accent has to flip the label to black; no theme file can get this wrong.
|
|
local pale = ui.themeNames() -- force the module to be loaded before patching it
|
|
assert(#pale >= 3, "expected the canned themes")
|
|
package.loaded["theme"].pale = {bg = {255, 255, 255}, fg = {0, 0, 0}, accent = {255, 235, 120}}
|
|
assert(reload("pale").accent_fg == BLACK, "black text on a pale accent")
|
|
|
|
-- Dark inverts the surface without any per-component configuration.
|
|
local dark = reload("dark")
|
|
assert(dark.bg < dark.fg, "dark theme keeps light text on a dark surface")
|
|
assert(#dark.face == 2 and #dark.face_pressed == 2, "button gradients are pairs")
|
|
|
|
-- Pinned roles win over derived ones, which is the deviation hatch.
|
|
assert(reload("mono").radius == 0, "mono pins radius")
|
|
assert(light.radius == 6, "light keeps the derived radius")
|
|
|
|
-- An unknown name must not leave an app without colors.
|
|
local missing = reload("does-not-exist")
|
|
assert(missing.bg == WHITE and missing.fg == BLACK, "unknown theme falls back to light")
|
|
|
|
-- The root seeds the tree, so an app naming no colors still gets themed.
|
|
reload("dark")
|
|
local button = ui.button{label = "go", on_press = function() end}
|
|
local screen = ui.screen(ui.box{pad = 12, button})
|
|
assert(screen.root.bg == ui.theme.bg, "root takes the theme surface")
|
|
assert(screen.root.color == ui.theme.fg, "root takes the theme text")
|
|
screen:draw()
|
|
assert(button.color == ui.theme.fg, "the button inherited the theme")
|
|
assert(button.press_bg == ui.theme.accent, "the button inherited the accent")
|
|
|
|
-- An explicit value still wins over the theme.
|
|
local custom = ui.button{label = "delete", press_bg = 123, on_press = function() end}
|
|
ui.screen(ui.box{pad = 12, custom}):draw()
|
|
assert(custom.press_bg == 123, "explicit styling overrides the theme")
|
|
|
|
print("ok")
|