feat(workflow): simplify article flow and add automated rewrite step

This commit is contained in:
Oliver 2026-02-21 13:43:22 +01:00
parent 8d7375c99f
commit 35ccceb260
No known key found for this signature in database
11 changed files with 332 additions and 107 deletions

View file

@ -4,6 +4,7 @@ import unittest
from pathlib import Path
from fastapi.testclient import TestClient
from unittest.mock import patch
from backend.app import config as config_module
from backend.app.db import init_db
@ -66,39 +67,40 @@ class TestArticleWorkflow(unittest.TestCase):
def test_valid_transition_chain(self) -> None:
article_id = self._create_article()
t1 = self.client.post(f"/api/articles/{article_id}/transition", json={"target_status": "review"})
t1 = self.client.post(f"/api/articles/{article_id}/transition", json={"target_status": "rewrite"})
self.assertEqual(t1.status_code, 200)
r1 = self.client.post(f"/api/articles/{article_id}/review", json={"decision": "approve", "note": "ok"})
self.assertEqual(r1.status_code, 200)
self.assertEqual(r1.json()["to_status"], "approved")
blocked_publish = self.client.post(f"/api/articles/{article_id}/transition", json={"target_status": "published"})
self.assertEqual(blocked_publish.status_code, 400)
legal = self.client.post(
f"/api/articles/{article_id}/legal-review",
json={"approved": True, "note": "Rechte geprueft"},
)
self.assertEqual(legal.status_code, 200)
t2 = self.client.post(f"/api/articles/{article_id}/transition", json={"target_status": "published"})
t2 = self.client.post(f"/api/articles/{article_id}/transition", json={"target_status": "publish"})
self.assertEqual(t2.status_code, 200)
t3 = self.client.post(f"/api/articles/{article_id}/transition", json={"target_status": "published"})
self.assertEqual(t3.status_code, 200)
final = self.client.get(f"/api/articles/{article_id}")
self.assertEqual(final.status_code, 200)
self.assertEqual(final.json()["item"]["status"], "published")
self.assertEqual(final.json()["item"]["legal_checked"], 1)
self.assertEqual(final.json()["item"]["status_ui"], "published")
def test_invalid_transition_rejected(self) -> None:
article_id = self._create_article()
bad = self.client.post(f"/api/articles/{article_id}/transition", json={"target_status": "published"})
self.assertEqual(bad.status_code, 400)
def test_review_only_allowed_in_review_status(self) -> None:
def test_legacy_review_endpoint_is_gone(self) -> None:
article_id = self._create_article()
bad = self.client.post(f"/api/articles/{article_id}/review", json={"decision": "approve"})
self.assertEqual(bad.status_code, 400)
self.assertEqual(bad.status_code, 410)
@patch("backend.app.main.rewrite_article_text")
def test_rewrite_run_sets_publish_status(self, mock_rewrite) -> None:
mock_rewrite.return_value = "<h2>Neu</h2><p>Umschreibung</p>"
article_id = self._create_article()
self.client.post(f"/api/articles/{article_id}/transition", json={"target_status": "rewrite"})
r = self.client.post(f"/api/articles/{article_id}/rewrite-run")
self.assertEqual(r.status_code, 200)
self.assertEqual(r.json()["status"], "publish")
final = self.client.get(f"/api/articles/{article_id}")
self.assertEqual(final.json()["item"]["status_ui"], "publish")
if __name__ == "__main__":

View file

@ -62,6 +62,24 @@ class TestWordpressPublish(unittest.TestCase):
self.assertNotIn("featured_media", payload)
self.assertIn("<p>Inhalt</p>", payload.get("content", ""))
@patch("backend.app.wordpress._upload_featured_media")
@patch("backend.app.wordpress._wp_request")
def test_publish_strips_feed_header_and_press_contact(self, mock_wp_request, mock_upload_media) -> None:
mock_wp_request.return_value = {"id": 100, "link": "https://example.org/?p=100"}
article = {
"title": "Header Test",
"content_raw": "21.02.2026 10:00\nFirma GmbH\n(ots)\nDas ist der eigentliche Text.\nPressekontakt: Test Person",
"source_url": "https://example.com/source",
"canonical_url": "https://example.com/source",
"meta_json": "{}",
}
publish_article_draft(article)
payload = mock_wp_request.call_args.kwargs["payload"]
content = payload.get("content", "")
self.assertNotIn("Firma GmbH", content)
self.assertNotIn("Pressekontakt", content)
self.assertIn("eigentliche Text", content)
if __name__ == "__main__":
unittest.main()