Files
spoopyghosty0--frameport/tests/test_ui_extras.py
T
spoopyghosty0 04de05cff4 Settings: most users' options first; game updates switch
Sections now run from what most users need to what only some need:
Updates, Installing, Library folders, Appearance, Data, Problems and
feedback, Install links, Tools, This PC, About, Uninstall. Updates gains a
Games part: game recipes from GitHub (moved from Data) and the new
"Check games from install links for new versions" switch with its last
check and Check now. Inside sections the common options come first
(Installing: parallel uploads and video before keep-copies; Updates: dev
build last; Appearance: language first when a translation exists).

The demo manifest (site + built-in copy) names version 1.0.0 as an example;
the demo link is still never fetched or checked (test).
2026-10-17 01:12:08 -04:00

95 lines
3.8 KiB
Python

"""Setup checklist items, the Settings index and the Reduce motion setting."""
import flet as ft
from frameport.core import library
from frameport.ui import components as C
from frameport.ui import theme as T
from frameport.ui.views import settings
def fix():
return ("Install", ft.Icons.DOWNLOAD_ROUNDED, lambda: None)
def test_check_defaults_and_tuples():
c = C.Check(True, "Steam")
assert (c.detail, c.help, c.fix, c.extra) == ("", None, None, None)
assert C.Check(*(False, "Java", "missing", "java")).help == "java"
def test_check_marks():
assert C.check_look(True) == (ft.Icons.CHECK_CIRCLE_ROUNDED, T.OK)
assert C.check_look(False) == (ft.Icons.ERROR_ROUNDED, T.ERROR)
assert C.check_look("warn")[1] == T.WARN
assert C.check_look(None)[0] is None # pending: a spinner
def test_fix_only_while_not_ready():
f = fix()
assert C.check_fix(C.Check(False, "x", fix=f)) is f
assert C.check_fix(C.Check("warn", "x", fix=f)) is f
assert C.check_fix(C.Check(True, "x", fix=f)) is None
assert C.check_fix(C.Check(None, "x", fix=f)) is None
def test_checklist_builds_rows_with_fix_and_extra():
calls = []
col = C.checklist([C.Check(False, "Lepton", "missing", None, ("Install", None, lambda: calls.append(1))),
(True, "Proton", "ready", "proton", None, C.secondary("Test")),
C.Check(None, "Checking…")])
assert len(col.controls) == 3
first = col.controls[0].content.controls
button = first[-1]
button.on_click(None)
assert calls == [1]
assert len(col.controls[1].content.controls) == 3 # mark, text, the extra button (no fix: ready)
assert isinstance(col.controls[2].content.controls[0].content, ft.ProgressRing)
def test_settings_sections_order():
s = settings.SECTIONS
assert s[0] == "updates" and s[-1] == "remove"
# what most users need before what only some need
assert s.index("installing") < s.index("appearance") < s.index("links") < s.index("tools")
assert len(set(s)) == len(s)
assert set(settings.section_titles()) == set(s)
assert s.index("data") < s.index("tools") < s.index("pc") < s.index("about")
def test_reduce_motion_default_off():
from frameport.ui.app import REDUCE_MOTION, reduce_motion_setting
assert reduce_motion_setting() is False
library.set_setting(REDUCE_MOTION, True)
assert reduce_motion_setting() is True
def test_callout_icon_alignment():
"""A bar (text + buttons in a Row) centres its icon; wrapping text keeps it at the first line."""
bar = C.callout(ft.Row([C.body("Update available"), C.ghost("Not now")]), "info")
assert bar.content.vertical_alignment == ft.CrossAxisAlignment.CENTER
text = C.callout("A long note that wraps over several lines.", "warn")
assert text.content.vertical_alignment == ft.CrossAxisAlignment.START
def test_solid_glyph_for_filled_buttons():
"""Filled (accent) buttons use a glyph's filled variant: the thin outline faded into the orange."""
from frameport.ui import glyphs
assert glyphs.solid(glyphs.FRAME) == "fp:frame-solid"
assert glyphs.solid(glyphs.PATCH) == glyphs.PATCH # no filled variant: unchanged
assert glyphs.solid(ft.Icons.PLAY_ARROW_ROUNDED) == ft.Icons.PLAY_ARROW_ROUNDED
def test_cover_button_states():
"""The cover button springs in on hover, hides while a game starts and only Play buttons launch."""
play = C.CoverButton(ft.Icons.PLAY_ARROW_ROUNDED, "Play on Frame", lambda e: None, 72, launch="Starting…")
assert play.circle.scale < 1 and play.status.visible is False and len(play.rings) == 2
play.show(True)
assert play.circle.scale == 1.0
play.starting = True
play.show(True)
assert play.circle.scale == 0 # the "Starting…" pill stands in for it
install = C.CoverButton(ft.Icons.DOWNLOAD_ROUNDED, "Install", lambda e: None, 72)
assert install.launch is None