Small joys: Quote of the Day + Word of the Day engines
- quote.py: curated public-domain quote pool (16 seeded, admin-grows), deterministic daily
pick, lazy AI "what it means" explainer of the real quote (cached). No LLM-invented quotes.
- wotd.py: LLM proposes positive words → validated/enriched against dictionaryapi.dev (real
definition, IPA, examples, audio) → audio clip cached to our origin (TTS fallback) →
deterministic daily pick. Tops the pool up toward 30/day.
- db.py: quote_pool/daily_quote + wotd_pool/daily_wotd tables.
- api.py: /api/quote/today, /api/word/today, /api/word/audio/{word} (GET+HEAD).
- cli.py: cycle steps for both (under --no-joys), shared LLM client.
- tests: test_quote.py (6) + test_wotd.py (5). 393 backend tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"""Quote of the Day: curated seed (idempotent), deterministic pick (idempotent,
|
||||
blocked/featured), lazy AI meaning, never-empty get_today."""
|
||||
import pytest
|
||||
|
||||
from goodnews import quote
|
||||
from goodnews.db import connect, init_db
|
||||
|
||||
|
||||
class FakeClient:
|
||||
def chat_text(self, messages):
|
||||
return "It means contentment is built from within, not from circumstance."
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def conn():
|
||||
c = connect(":memory:"); init_db(c)
|
||||
yield c
|
||||
c.close()
|
||||
|
||||
|
||||
def test_seed_idempotent(conn):
|
||||
assert quote.seed(conn) == len(quote.SEED)
|
||||
assert quote.seed(conn) == 0
|
||||
assert conn.execute("SELECT COUNT(*) FROM quote_pool").fetchone()[0] == len(quote.SEED)
|
||||
|
||||
|
||||
def test_pick_caches_marks_shown_idempotent(conn):
|
||||
quote.seed(conn)
|
||||
a = quote.pick_daily(conn, feature_date="2026-06-22")
|
||||
assert a and a["text"] and a["author"]
|
||||
shown = conn.execute("SELECT shown_at FROM quote_pool WHERE id=?", (a["pool_id"],)).fetchone()[0]
|
||||
assert shown == "2026-06-22"
|
||||
assert quote.pick_daily(conn, feature_date="2026-06-22")["pool_id"] == a["pool_id"]
|
||||
|
||||
|
||||
def test_meaning_generated_lazily_and_cached(conn):
|
||||
quote.seed(conn)
|
||||
a = quote.pick_daily(conn, feature_date="2026-06-22", client=FakeClient())
|
||||
assert a["meaning"].startswith("It means")
|
||||
pool_meaning = conn.execute("SELECT meaning FROM quote_pool WHERE id=?", (a["pool_id"],)).fetchone()[0]
|
||||
assert pool_meaning == a["meaning"] # cached on the pool row, not regenerated
|
||||
|
||||
|
||||
def test_featured_pinned(conn):
|
||||
quote.seed(conn)
|
||||
conn.execute("UPDATE quote_pool SET featured=1 WHERE author='Rumi'"); conn.commit()
|
||||
assert quote.pick_daily(conn, feature_date="2026-06-22", force=True)["author"] == "Rumi"
|
||||
|
||||
|
||||
def test_get_today_never_empty(conn):
|
||||
quote.seed(conn)
|
||||
a = quote.pick_daily(conn, feature_date="2026-06-22")
|
||||
assert quote.get_today(conn, "2099-01-01")["pool_id"] == a["pool_id"]
|
||||
|
||||
|
||||
def test_run_daily_seeds_then_picks(conn):
|
||||
r = quote.run_daily(conn)
|
||||
assert r["pool"] == len(quote.SEED) and r["picked"]
|
||||
Reference in New Issue
Block a user