174 tests covering URL normalization, FTS5 query sanitization, SSRF/CSRF guards, sharing-mode logic, DB schema and upsert paths, handler end-to-end flows, and gateway body-size / mesh-whitelist guards. Each recent bug-fix commit (6ffd38d,1bc695f,8dffd8c) has an explicit regression test in test_regressions.py. One xfail documents a minor latent bug in clean_url where port 80 is not stripped from upgraded https URLs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8dffd8ccea
commit
44a16dea98
18 changed files with 1673 additions and 0 deletions
112
tests/test_handlers_subs.py
Normal file
112
tests/test_handlers_subs.py
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
"""Tests for subscription handlers.
|
||||
|
||||
Subscription add validates the destination hash (32-char hex) locally
|
||||
before calling `fetch_remote_sites`; browse uses cached remote_pages when
|
||||
available and falls back to a live fetch otherwise.
|
||||
"""
|
||||
from unittest.mock import patch
|
||||
|
||||
import handlers as handlers_module
|
||||
from db import get_db, return_db
|
||||
from handlers import handle_subscription_add, handle_subscription_browse
|
||||
|
||||
|
||||
VALID_HASH = "a" * 32
|
||||
|
||||
|
||||
def _subscription_count():
|
||||
db = get_db()
|
||||
try:
|
||||
return db.execute("SELECT count(*) FROM subscriptions").fetchone()[0]
|
||||
finally:
|
||||
return_db(db)
|
||||
|
||||
|
||||
def test_rejects_empty_dest_hash(temp_db, csrf_session):
|
||||
resp = handle_subscription_add({"dest_hash": [""]})
|
||||
assert "32-character" in resp["body"]
|
||||
assert _subscription_count() == 0
|
||||
|
||||
|
||||
def test_rejects_wrong_length(temp_db, csrf_session):
|
||||
resp = handle_subscription_add({"dest_hash": ["abc123"]})
|
||||
assert "32-character" in resp["body"]
|
||||
assert _subscription_count() == 0
|
||||
|
||||
|
||||
def test_rejects_non_hex(temp_db, csrf_session):
|
||||
resp = handle_subscription_add({"dest_hash": ["z" * 32]})
|
||||
assert "hex" in resp["body"].lower()
|
||||
assert _subscription_count() == 0
|
||||
|
||||
|
||||
def test_rejects_unreachable_peer(temp_db, csrf_session):
|
||||
with patch.object(handlers_module, "fetch_remote_sites") as fetch:
|
||||
fetch.side_effect = ConnectionError("unreachable")
|
||||
resp = handle_subscription_add({"dest_hash": [VALID_HASH]})
|
||||
assert "Could not reach" in resp["body"]
|
||||
assert _subscription_count() == 0
|
||||
|
||||
|
||||
def test_rejects_peer_with_sharing_disabled(temp_db, csrf_session):
|
||||
with patch.object(handlers_module, "fetch_remote_sites") as fetch:
|
||||
fetch.side_effect = PermissionError("sharing disabled")
|
||||
resp = handle_subscription_add({"dest_hash": [VALID_HASH]})
|
||||
assert "sharing disabled" in resp["body"]
|
||||
assert _subscription_count() == 0
|
||||
|
||||
|
||||
def test_successful_add_records_subscription(temp_db, csrf_session):
|
||||
with patch.object(handlers_module, "fetch_remote_sites") as fetch:
|
||||
fetch.return_value = {"name": "alice", "sites": []}
|
||||
resp = handle_subscription_add({"dest_hash": [VALID_HASH]})
|
||||
assert "Subscribed to alice" in resp["body"]
|
||||
assert _subscription_count() == 1
|
||||
|
||||
|
||||
def test_dest_hash_strips_angle_brackets(temp_db, csrf_session):
|
||||
"""Users often paste hashes as `<aaa...>` from RNS log output; strip them."""
|
||||
with patch.object(handlers_module, "fetch_remote_sites") as fetch:
|
||||
fetch.return_value = {"name": "bob", "sites": []}
|
||||
resp = handle_subscription_add({"dest_hash": [f"<{VALID_HASH}>"]})
|
||||
assert _subscription_count() == 1
|
||||
|
||||
|
||||
def test_browse_unknown_subscription_is_404(temp_db, csrf_session):
|
||||
resp = handle_subscription_browse(99999)
|
||||
assert resp["status"] == 404
|
||||
|
||||
|
||||
def test_browse_marks_already_indexed_urls(seeded_db, csrf_session):
|
||||
# Insert a subscription + some remote pages (one duplicate of local, one new).
|
||||
db = get_db()
|
||||
try:
|
||||
db.execute(
|
||||
"INSERT INTO subscriptions (dest_hash, name) VALUES (?, ?)",
|
||||
(VALID_HASH, "alice"),
|
||||
)
|
||||
sub_id = db.execute("SELECT id FROM subscriptions").fetchone()["id"]
|
||||
db.execute(
|
||||
"INSERT INTO remote_pages (subscription_id, url, title, note, tags) "
|
||||
"VALUES (?, ?, ?, ?, ?)",
|
||||
(sub_id, "https://example.com/rust-intro", "Alice rust pick", "", ""),
|
||||
)
|
||||
db.execute(
|
||||
"INSERT INTO remote_pages (subscription_id, url, title, note, tags) "
|
||||
"VALUES (?, ?, ?, ?, ?)",
|
||||
(sub_id, "https://new.example.com/shiny", "Shiny New Link", "note", "tag1"),
|
||||
)
|
||||
db.commit()
|
||||
finally:
|
||||
return_db(db)
|
||||
|
||||
resp = handle_subscription_browse(sub_id)
|
||||
body = resp["body"]
|
||||
assert resp["status"] == 200
|
||||
assert "already indexed" in body
|
||||
# The duplicate URL should appear in the "already indexed" section.
|
||||
assert "Alice rust pick" in body
|
||||
# The new URL should be in the selectable section.
|
||||
assert "Shiny New Link" in body
|
||||
# Count summary: "2 site(s) available, 1 new"
|
||||
assert "1 new" in body
|
||||
Loading…
Add table
Add a link
Reference in a new issue