edit sources

This commit is contained in:
Abel Luck 2026-03-30 13:49:00 +02:00
parent 847aeae772
commit 328a70ff9b
7 changed files with 512 additions and 38 deletions

View file

@ -5,12 +5,13 @@ from pathlib import Path
from typing import Any, cast
from repub.datastar import RefreshBroker, render_sse_event, render_stream
from repub.model import Job, Source, SourceFeed, SourcePangea
from repub.model import Job, Source, SourceFeed, SourcePangea, create_source
from repub.web import (
create_app,
get_refresh_broker,
render_create_source,
render_dashboard,
render_edit_source,
render_execution_logs,
render_runs,
render_sources,
@ -171,7 +172,7 @@ def test_render_create_source_shows_dedicated_form_page() -> None:
async def run() -> None:
body = str(await render_create_source())
assert "Dedicated create page for the source form" in body
assert "Create a new source and its paired job configuration." in body
assert "Source and job setup" in body
assert "data-signals__ifmissing" in body
assert "/actions/sources/create" in body
@ -206,6 +207,55 @@ def test_render_create_source_shows_dedicated_form_page() -> None:
asyncio.run(run())
def test_render_edit_source_shows_existing_values(monkeypatch, tmp_path: Path) -> None:
db_path = tmp_path / "edit-page.db"
monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path))
create_app()
create_source(
name="Kenya health desk",
slug="kenya-health",
source_type="pangea",
notes="Regional health alerts.",
spider_arguments="language=en\ndownload_media=true",
enabled=True,
cron_minute="0",
cron_hour="*/6",
cron_day_of_month="*",
cron_day_of_week="*",
cron_month="*",
pangea_domain="example.org",
pangea_category="Health",
content_type="breakingnews",
only_newest=True,
max_articles=12,
oldest_article=5,
include_authors=True,
exclude_media=False,
include_content=True,
content_format="MOBILE_3",
)
async def run() -> None:
body = str(await render_edit_source("kenya-health"))
assert "Edit source" in body
assert "/actions/sources/kenya-health/edit" in body
assert "Kenya health desk" in body
assert "kenya-health" in body
assert 'id="source-slug"' in body
assert (
'id="source-slug" name="source-slug" type="text" value="kenya-health"'
in body
)
assert " disabled " in body
assert "cursor-not-allowed bg-slate-100 text-slate-500" in body
assert "example.org" in body
assert "Health" in body
assert "language=en\ndownload_media=true" in body
asyncio.run(run())
def test_create_source_action_creates_pangea_source_and_job_in_database(
monkeypatch, tmp_path: Path
) -> None:
@ -314,6 +364,163 @@ def test_create_source_action_creates_feed_source_and_job_in_database(
asyncio.run(run())
def test_edit_source_action_updates_existing_source_and_job_in_database(
monkeypatch, tmp_path: Path
) -> None:
db_path = tmp_path / "edit-source.db"
monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path))
create_app()
create_source(
name="Kenya health desk",
slug="kenya-health",
source_type="pangea",
notes="Regional health alerts.",
spider_arguments="language=en\ndownload_media=true",
enabled=True,
cron_minute="0",
cron_hour="*/6",
cron_day_of_month="*",
cron_day_of_week="*",
cron_month="*",
pangea_domain="example.org",
pangea_category="Health",
content_type="breakingnews",
only_newest=True,
max_articles=12,
oldest_article=5,
include_authors=True,
exclude_media=False,
include_content=True,
content_format="MOBILE_3",
)
async def run() -> None:
app = create_app()
client = app.test_client()
response = await client.post(
"/actions/sources/kenya-health/edit",
headers={"Datastar-Request": "true"},
json={
"sourceName": "Kenya health desk nightly",
"sourceSlug": "kenya-health",
"sourceType": "pangea",
"pangeaDomain": "example.org",
"pangeaCategory": "Nightly",
"contentFormat": "TEXT_ONLY",
"contentType": "articles",
"maxArticles": "25",
"oldestArticle": "7",
"sourceNotes": "Updated nightly run.",
"spiderArguments": "language=sw\ninclude_audio=false",
"cronMinute": "15",
"cronHour": "2",
"cronDayOfMonth": "*",
"cronDayOfWeek": "*",
"cronMonth": "*",
"jobEnabled": False,
"onlyNewest": False,
"includeAuthors": False,
"excludeMedia": True,
"includeContent": True,
},
)
body = await response.get_data(as_text=True)
assert response.status_code == 200
assert "window.location = '/sources'" in body
source = Source.get(Source.slug == "kenya-health")
pangea = SourcePangea.get(SourcePangea.source == source)
job = Job.get(Job.source == source)
rendered_sources = str(await render_sources(app))
assert source.name == "Kenya health desk nightly"
assert source.notes == "Updated nightly run."
assert pangea.category_name == "Nightly"
assert pangea.content_format == "TEXT_ONLY"
assert pangea.max_articles == 25
assert pangea.include_authors is False
assert pangea.exclude_media is True
assert job.enabled is False
assert job.spider_arguments == "language=sw\ninclude_audio=false"
assert job.cron_hour == "2"
assert "Kenya health desk nightly" in rendered_sources
assert "example.org / Nightly" in rendered_sources
assert "Disabled" in rendered_sources
asyncio.run(run())
def test_edit_source_action_rejects_slug_changes(monkeypatch, tmp_path: Path) -> None:
db_path = tmp_path / "edit-invalid.db"
monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path))
create_app()
create_source(
name="Kenya health desk",
slug="kenya-health",
source_type="pangea",
notes="Regional health alerts.",
spider_arguments="language=en\ndownload_media=true",
enabled=True,
cron_minute="0",
cron_hour="*/6",
cron_day_of_month="*",
cron_day_of_week="*",
cron_month="*",
pangea_domain="example.org",
pangea_category="Health",
content_type="breakingnews",
only_newest=True,
max_articles=12,
oldest_article=5,
include_authors=True,
exclude_media=False,
include_content=True,
content_format="MOBILE_3",
)
async def run() -> None:
app = create_app()
client = app.test_client()
response = await client.post(
"/actions/sources/kenya-health/edit",
headers={"Datastar-Request": "true"},
json={
"sourceName": "Kenya health desk",
"sourceSlug": "kenya-health-renamed",
"sourceType": "pangea",
"pangeaDomain": "example.org",
"pangeaCategory": "Health",
"contentFormat": "MOBILE_3",
"contentType": "breakingnews",
"maxArticles": "12",
"oldestArticle": "5",
"sourceNotes": "Regional health alerts.",
"spiderArguments": "language=en\ndownload_media=true",
"cronMinute": "0",
"cronHour": "*/6",
"cronDayOfMonth": "*",
"cronDayOfWeek": "*",
"cronMonth": "*",
"jobEnabled": True,
"onlyNewest": True,
"includeAuthors": True,
"excludeMedia": False,
"includeContent": True,
},
)
body = await response.get_data(as_text=True)
assert response.status_code == 200
assert "Slug is immutable." in body
assert Source.get(Source.slug == "kenya-health").name == "Kenya health desk"
assert Source.select().where(Source.slug == "kenya-health-renamed").count() == 0
asyncio.run(run())
def test_create_source_action_validates_duplicate_slug_and_pangea_type(
monkeypatch, tmp_path: Path
) -> None: