Files
upbeatBytes/tests/test_share.py
T
thejayman77 3d9900cdfc Article sharing: branded /a/<id> page + share menu
- Server-rendered /a/<id> "pointer" page (FastAPI): OG/Twitter meta from the
  article's title/why/image, self-canonical (UB pages are the canonical for
  themselves), a prominent "Read the full story at {source}" button and a quiet
  "Explore more on Upbeat Bytes". No article body. Unknown/rejected/duplicate/
  malformed ids → a calm 404 (no stack traces). Text-card preview when no image.
- Caddy routes /a/* to the API.
- Card Share control → menu: native Share… (where available), Copy link (the UB
  card page), Copy source link. Boundary actions now hide-on-hover via a .mute
  class so Save/Replace/Share stay visible. 122 tests pass.

(Event tracking for shares/opens lands with the analytics step next.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 15:27:30 +00:00

51 lines
2.4 KiB
Python

import pytest
from fastapi.testclient import TestClient
@pytest.fixture
def client(tmp_path, monkeypatch):
db = tmp_path / "t.sqlite3"
monkeypatch.setenv("GOODNEWS_DB", str(db))
monkeypatch.setenv("GOODNEWS_PUBLIC_BASE_URL", "https://upbeatbytes.com")
import importlib
import goodnews.api as api
importlib.reload(api)
from goodnews.db import connect, init_db
c = connect(str(db)); init_db(c)
c.execute("INSERT INTO sources (id,name,feed_url,trust_score) VALUES (1,'BBC','http://s/f',5)")
# 1: accepted (renders), 2: rejected, 3: duplicate
c.execute("INSERT INTO articles (id,source_id,canonical_url,title,url_hash,image_url) "
"VALUES (1,1,'https://bbc.com/x','Water voles return','h1','https://img/v.jpg')")
c.execute("INSERT INTO articles (id,source_id,canonical_url,title,url_hash) VALUES (2,1,'https://bbc.com/y','Meh','h2')")
c.execute("INSERT INTO articles (id,source_id,canonical_url,title,url_hash,duplicate_of) VALUES (3,1,'https://bbc.com/z','Dup','h3',1)")
c.execute("INSERT INTO article_scores (article_id,accepted,reason_text) VALUES (1,1,'A hopeful restoration story.')")
c.execute("INSERT INTO article_scores (article_id,accepted) VALUES (2,0)")
c.execute("INSERT INTO article_scores (article_id,accepted) VALUES (3,1)")
c.commit(); c.close()
return api.create_app()
def test_share_page_renders(client):
r = TestClient(client).get("/a/1")
assert r.status_code == 200
html = r.text
assert "Water voles return" in html
assert 'property="og:title"' in html and 'name="twitter:card"' in html
assert 'rel="canonical" href="https://upbeatbytes.com/a/1"' in html
assert 'https://bbc.com/x' in html # source link present
assert "A hopeful restoration story." in html
assert 'content="https://img/v.jpg"' in html # og image
def test_share_page_missing_and_malformed(client):
tc = TestClient(client)
assert tc.get("/a/999").status_code == 404 # unknown
assert tc.get("/a/not-a-number").status_code == 404 # malformed → calm 404
assert tc.get("/a/2").status_code == 404 # rejected article
assert tc.get("/a/3").status_code == 404 # duplicate
def test_share_page_no_image_uses_summary_card(client, tmp_path, monkeypatch):
# article 1 has an image → large card
assert 'summary_large_image' in TestClient(client).get("/a/1").text