Files
copykar/tests/test_auto_routing.py

100 lines
3.5 KiB
Python

"""Auto-routing must queue to subscribed targets WITHOUT replacing the admin review card."""
import asyncio
import sys
sys.path.insert(0, "/app")
from db.database import init_db, close_db_pool
from db.repository import Repository
from services.admin_bot import AdminBotService
SRC_A = -1009999000020
SRC_B = -1009999000021
TRG = -1009999000022
class FakeQueue:
def __init__(self):
self.pushed = []
async def push_target_post(self, target_id, payload):
self.pushed.append((target_id, payload))
async def get_target_queue_size(self, target_id):
return 0
class FakeAI:
async def rewrite_for_target(self, raw_text, target, has_media=False, *args, **kwargs):
return f"[{target.title}] {raw_text}"
async def _cleanup(repo):
pool = await repo._get_pool()
async with pool.acquire() as conn:
for cid in (SRC_A, SRC_B):
await conn.execute("DELETE FROM posts WHERE source_channel_id = $1;", cid)
await conn.execute("DELETE FROM sources WHERE channel_id = $1;", cid)
await conn.execute("DELETE FROM targets WHERE channel_id = $1;", TRG)
async def run_tests():
await init_db()
repo = Repository()
await _cleanup(repo)
await repo.add_source(SRC_A, "Source A", None)
await repo.add_source(SRC_B, "Source B", None)
target_id = await repo.add_target(TRG, "Auto Target", None)
# A brand new target routes nothing.
assert await repo.get_targets_auto_routed_from(SRC_A) == []
# Toggle is a switch, not a one-way door.
assert await repo.toggle_target_auto_source(target_id, SRC_A) is True
routed = await repo.get_targets_auto_routed_from(SRC_A)
assert len(routed) == 1 and routed[0].id == target_id
assert routed[0].auto_source_ids == [SRC_A]
assert await repo.toggle_target_auto_source(target_id, SRC_A) is False
assert await repo.get_targets_auto_routed_from(SRC_A) == []
# Subscribe to A only; B must stay manual.
await repo.set_target_auto_sources(target_id, [SRC_A])
queue = FakeQueue()
bot = AdminBotService(repo=repo, ai_processor=FakeAI(), queue=queue,
review_channel_id=0, admin_user_ids=[1])
post_a = await repo.create_raw_post(SRC_A, 1, "post from A", content_hash="auto_a")
post_b = await repo.create_raw_post(SRC_B, 2, "post from B", content_hash="auto_b")
assert await bot.auto_route_post(post_a) == 1, "subscribed source must route"
assert await bot.auto_route_post(post_b) == 0, "unsubscribed source must not route"
assert len(queue.pushed) == 1, f"expected 1 enqueue, got {queue.pushed}"
tid, payload = queue.pushed[0]
assert tid == target_id
assert payload["text"] == "[Auto Target] post from A", f"AI rewrite not applied: {payload['text']}"
assert payload["post_id"] == post_a
# The post is recorded against the target but must NOT be marked published yet.
stored = await repo.get_post_by_id(post_a)
assert stored.status == "pending_review", f"auto-routing must not publish, got {stored.status}"
assert len(stored.published_to) == 1
assert stored.published_to[0]["target_id"] == target_id
assert stored.published_to[0]["published_at"] is None
# A soft-deleted post is never auto-routed.
await repo.soft_delete_post(post_b)
await repo.set_target_auto_sources(target_id, [SRC_A, SRC_B])
assert await bot.auto_route_post(post_b) == 0, "deleted posts must not route"
await _cleanup(repo)
await close_db_pool()
print("All auto-routing tests passed successfully!")
if __name__ == "__main__":
asyncio.run(run_tests())