#19 — link_url on campaign variants (migration 019) - ADD COLUMN link_url TEXT on campaign_variants - create_variant, upsert_variant, update_variant all carry link_url - RedditClient.post() supports kind=link when link_url set + body empty - RedditPostStrategy passes link_url from extra dict - poster.py merges link_url from variant into extra (same as slug/tags) - API VariantCreate/VariantUpdate schemas include link_url - CampaignDetail: link_url field in Add Variant form with copy button; link_url shown in variant list with clickable link + copy button - Variant button disabled if neither body nor link_url is set #18 — Multi-user team accounts (migrations 020-022) - 020: team_accounts table (display_name, platform, username, session_file) - 021: opportunities.assigned_to + post_as FK → team_accounts - 022: posts.posted_by_account_id FK → team_accounts - Store: list/get/get_by_username/create_team_account, assign_opportunity - API: GET/POST /api/v1/team; POST /api/v1/team/{id}/assign - config.py: sessions_dir added; reddit_session_file now points to sessions/alan_reddit.json (backward compat path kept) - scripts/migrate_sessions.py: one-shot move session.json → sessions/alan_reddit.json + creates placeholder files for future accounts - manage.sh: build (VITE_BASE_URL=/magpie/ npm build), serve (static), migrate-sessions subcommands added; login updated to new session path - Caddy: @magpie_no_session gate + handle /magpie/api* and /magpie* blocks added to menagerie.circuitforge.tech site block
59 lines
2.2 KiB
Python
59 lines
2.2 KiB
Python
from unittest.mock import MagicMock, patch
|
|
|
|
from app.services.platforms.reddit_post import RedditPostStrategy
|
|
from app.services.platforms.base import PostResult
|
|
|
|
|
|
def test_execute_delegates_to_reddit_client(tmp_path):
|
|
session_file = tmp_path / "session.json"
|
|
session_file.write_text('{"cookies": [], "origins": []}')
|
|
|
|
mock_client = MagicMock()
|
|
mock_client.post.return_value = "https://reddit.com/r/test/comments/abc/title/"
|
|
|
|
with patch("app.services.platforms.reddit_post.RedditClient", return_value=mock_client):
|
|
with patch("app.services.platforms.reddit_post.get_settings") as mock_settings:
|
|
mock_settings.return_value.reddit_session_file = str(session_file)
|
|
strategy = RedditPostStrategy()
|
|
result = strategy.execute(
|
|
target="selfhosted",
|
|
title="Test Title",
|
|
body="Test body",
|
|
flair="Showcase",
|
|
)
|
|
|
|
mock_client.post.assert_called_once_with(
|
|
sub="selfhosted",
|
|
title="Test Title",
|
|
body="Test body",
|
|
flair="Showcase",
|
|
link_url=None,
|
|
)
|
|
assert isinstance(result, PostResult)
|
|
assert result.url == "https://reddit.com/r/test/comments/abc/title/"
|
|
|
|
|
|
def test_execute_propagates_client_error(tmp_path):
|
|
session_file = tmp_path / "session.json"
|
|
session_file.write_text('{"cookies": [], "origins": []}')
|
|
|
|
mock_client = MagicMock()
|
|
mock_client.post.side_effect = RuntimeError("Playwright timeout")
|
|
|
|
with patch("app.services.platforms.reddit_post.RedditClient", return_value=mock_client):
|
|
with patch("app.services.platforms.reddit_post.get_settings") as mock_settings:
|
|
mock_settings.return_value.reddit_session_file = str(session_file)
|
|
strategy = RedditPostStrategy()
|
|
try:
|
|
strategy.execute(target="selfhosted", title="T", body="B")
|
|
assert False, "Expected RuntimeError"
|
|
except RuntimeError as e:
|
|
assert "Playwright timeout" in str(e)
|
|
|
|
|
|
def test_campaign_type():
|
|
assert RedditPostStrategy.campaign_type == "reddit_post"
|
|
|
|
|
|
def test_supports_dupe_guard():
|
|
assert RedditPostStrategy().supports_dupe_guard() is True
|