feat(tower): routines truth model load and save
TDD: test_routines_seed_and_roundtrip tests routines_load() seeding default (matin/soir), round-trip save/load, and verifies json structure with all required fields (id, title, emoji, steps). All tests GREEN.
This commit is contained in:
@@ -11,6 +11,7 @@ STAGING = os.environ.get("LISAEL_STAGING", os.path.join(BASE, "podcasts"))
|
||||
STAGING_ROUTINES = os.environ.get("LISAEL_STAGING_ROUTINES", os.path.join(BASE, "routines"))
|
||||
LVGLIMG = os.environ.get("LISAEL_LVGLIMG", os.path.join(BASE, "LVGLImage.py"))
|
||||
FEEDS_JSON = os.path.join(BASE, "feeds.json")
|
||||
ROUTINES_JSON = os.path.join(BASE, "routines.json")
|
||||
BOX_JSON = os.path.join(BASE, "box-state.json")
|
||||
BOX_PORT = int(os.environ.get("LISAEL_BOX_PORT", "8080"))
|
||||
TTS_URL = os.environ.get("LISAEL_TTS_URL", "http://100.78.6.122:9300/v1/audio/speech")
|
||||
@@ -71,6 +72,31 @@ def add_feed(key, name, rss, n=2):
|
||||
def remove_feed(key):
|
||||
save_feeds([f for f in load_feeds() if f["key"] != key])
|
||||
|
||||
# ---- routines (truth) ----
|
||||
DEFAULT_ROUTINES = [
|
||||
{"id": "matin", "title": "Le matin", "emoji": "☀️", "steps": [
|
||||
{"text": "Habille-toi", "emoji": "\U0001F455"},
|
||||
{"text": "Petit-déjeuner", "emoji": "\U0001F950"},
|
||||
{"text": "Brosse tes dents", "emoji": "\U0001FAA5"},
|
||||
{"text": "Prépare ton cartable", "emoji": "\U0001F392"}]},
|
||||
{"id": "soir", "title": "Le soir", "emoji": "\U0001F319", "steps": [
|
||||
{"text": "Mets ton pyjama", "emoji": "\U0001F476"},
|
||||
{"text": "Brosse tes dents", "emoji": "\U0001FAA5"},
|
||||
{"text": "Lis une histoire", "emoji": "\U0001F4D6"}]},
|
||||
]
|
||||
|
||||
def routines_load():
|
||||
if os.path.exists(ROUTINES_JSON):
|
||||
try:
|
||||
return json.load(open(ROUTINES_JSON, encoding="utf-8")).get("routines", [])
|
||||
except Exception:
|
||||
pass
|
||||
routines_save([dict(r) for r in DEFAULT_ROUTINES])
|
||||
return [dict(r) for r in DEFAULT_ROUTINES]
|
||||
|
||||
def routines_save(routines):
|
||||
_atomic_write_json(ROUTINES_JSON, {"routines": routines})
|
||||
|
||||
# ---- RSS ----
|
||||
def cover_url(root):
|
||||
el = root.find(".//channel/itunes:image", NS)
|
||||
|
||||
@@ -12,6 +12,17 @@ def test_emoji_cp_strips_vs16():
|
||||
# multi-codepoint (no VS16): joined by '-' — full ZWJ sequence check
|
||||
assert C.emoji_cp("\U0001F468\U0001F4BB") == "1f468-200d-1f4bb"
|
||||
|
||||
def test_routines_seed_and_roundtrip():
|
||||
r = C.routines_load() # seeds default if missing
|
||||
ids = [x["id"] for x in r]
|
||||
assert ids == ["matin", "soir"]
|
||||
assert os.path.exists(C.ROUTINES_JSON)
|
||||
assert all("emoji" in x and "title" in x and "steps" in x for x in r)
|
||||
r[0]["steps"].append({"text": "Cartable", "emoji": "\U0001F392"})
|
||||
C.routines_save(r)
|
||||
r2 = C.routines_load()
|
||||
assert r2[0]["steps"][-1]["text"] == "Cartable"
|
||||
|
||||
if __name__ == "__main__":
|
||||
for name, fn in sorted(globals().items()):
|
||||
if name.startswith("test_"):
|
||||
|
||||
Reference in New Issue
Block a user