Files
thejayman77 c25e14ed6a Add a permanent "Latest" lane beside "Highlights"
Restructure the nav around two permanent lanes, then the reader's chosen ones:
"Highlights" (the curated daily brief — formerly "Today") and "Latest" (the
freshest accepted stories, newest-first). Now that the gate is tight, a
chronological "incoming" feed is safe to expose.

* feed(): new sort="latest" (pure recency) alongside the default best-first
  rank; /api/feed exposes sort=ranked|latest (validated). Still accepted-only
  and boundary-respecting either way.
* lanes.py: two pinned lanes (Highlights + Latest) instead of one.
* Home: "Latest" view + "Load more" pagination for every feed view (offset-
  paged, de-duped). Mobile bottom bar gains a Latest tab.
* LanePicker shows both pinned lanes; nav rail renders them first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 15:56:48 -04:00

37 lines
1.9 KiB
Python

from goodnews.lanes import build_lane_pool, known_lane_keys, DEFAULT_LANES
def test_pool_shape_and_pinned():
pool = build_lane_pool({"science": 100}, {"space": 200, "food": 0, "innovation": 99})
pinned_keys = [p["key"] for p in pool["pinned"]]
assert pinned_keys == ["today", "latest"] # Highlights + Latest, always first
assert pool["default"] == DEFAULT_LANES
names = [g["name"] for g in pool["groups"]]
assert names == ["Moods", "Topics", "Discovery"]
# pinned lanes are never part of the selectable pool.
assert "today" not in known_lane_keys(pool) and "latest" not in known_lane_keys(pool)
def test_topics_are_bare_keys_tags_are_prefixed():
pool = build_lane_pool({"science": 5}, {})
topics = next(g for g in pool["groups"] if g["name"] == "Topics")["lanes"]
assert any(l["key"] == "science" for l in topics) # bare topic key
disc = next(g for g in pool["groups"] if g["name"] == "Discovery")["lanes"]
assert all(l["key"].startswith("tag:") for l in disc)
def test_volume_gate_and_always_offer():
# space/food are always offered; a low-volume non-curated tag is dropped.
pool = build_lane_pool({}, {"space": 1, "food": 0, "resilience": 3, "innovation": 999})
disc_keys = {l["key"] for l in next(g for g in pool["groups"] if g["name"] == "Discovery")["lanes"]}
assert "tag:space" in disc_keys and "tag:food" in disc_keys
assert "tag:innovation" in disc_keys # over threshold
assert "tag:resilience" not in disc_keys # under threshold, not curated
def test_topic_named_tags_excluded_from_discovery():
# a tag that duplicates a primary topic must not appear as a Discovery lane
pool = build_lane_pool({}, {"science": 999, "technology": 999})
disc_keys = {l["key"] for l in next(g for g in pool["groups"] if g["name"] == "Discovery")["lanes"]}
assert "tag:science" not in disc_keys and "tag:technology" not in disc_keys