Files
siftlode/backend/tests/test_titles.py
T
peter 33dbf70313 test(backend): pure-logic pytest harness, run in an isolated test image
The backend had zero tests. This adds 33, all pure (no DB, no network), plus the
harness to run them in the gate:

- backend/Dockerfile.test: the app's deps + pinned pytest/ruff, code bind-mounted at
  run time so it always tests the working tree. Isolated from the prod Dockerfile, so
  the published image never carries test tooling.
- requirements-dev.txt: pytest==8.4.2, ruff==0.15.21 (the version the gate already
  runs) — the backend lane is now pinned, not just host-global.
- tests: normalize_title (de-shout, hashtag strip, emoji drop, trilingual letters
  survive); storage sanitize/rel_path/download_filename and the safe_abs_path
  traversal guard (../ and absolute-path escapes rejected — verified by mutation);
  links HMAC grants (round-trip, wrong-token, tampered sig/exp, expiry) + is_expired;
  a DB-free app-assembly smoke (every router wires up, OpenAPI generates).

DB-backed router smoke (auth/feed/downloads) needs a test Postgres + migrations —
deferred. useCardPager needs hook-test infra (jsdom/renderHook) — deferred.
2026-07-21 03:29:24 +02:00

42 lines
1.5 KiB
Python

"""normalize_title: de-shout / de-clutter video titles without mangling non-English text."""
from app.titles import normalize_title
def test_empty_and_whitespace_pass_through_unchanged():
assert normalize_title(None) is None
assert normalize_title("") == ""
assert normalize_title(" ") == " "
def test_plain_title_is_left_alone():
assert normalize_title("How I built a boat") == "How I built a boat"
def test_shouting_title_is_de_capsed_and_first_letter_kept_upper():
# >=2 all-caps runs and >=50% caps → treated as shouting: title-case the long words.
out = normalize_title("THIS IS A HUGE ANNOUNCEMENT")
assert out is not None
assert out == out[0].upper() + out[1:] # first alpha char stays capitalized
assert "HUGE" not in out and "ANNOUNCEMENT" not in out
def test_trailing_hashtags_are_stripped():
assert normalize_title("Great cooking video #food #yummy") == "Great cooking video"
def test_emoji_and_symbols_are_dropped():
assert "🔥" not in (normalize_title("Fire recipe 🔥🔥") or "")
def test_repeated_punctuation_is_collapsed():
assert normalize_title("Wait what!!!!") == "Wait what!"
def test_accented_non_english_letters_survive():
# Siftlode is trilingual — Hungarian/German letters must not be ASCII-folded away.
for title in ["Gulyásleves főzés", "Über die Straße"]:
out = normalize_title(title) or ""
for ch in "áöüőűé":
if ch in title:
assert ch in out