campaign version refinment, user locks, db repair

This commit is contained in:
2026-06-13 19:25:23 +02:00
parent fe5ac084b7
commit ffbddfc773
18 changed files with 896 additions and 39 deletions

View File

@@ -160,6 +160,67 @@ class ApiSmokeTests(unittest.TestCase):
self.assertEqual(sorted(bundle.namelist()), ["inbox/report-copy.txt", "inbox/report.txt"])
self.assertEqual(bundle.read("inbox/report.txt"), b"first report")
def test_temporary_and_permanent_user_lock_lifecycle(self) -> None:
headers, _ = self._login()
created = self.client.post(
"/api/v1/campaigns/new",
headers=headers,
json={"external_id": "lock-lifecycle", "name": "Lock lifecycle"},
)
self.assertEqual(created.status_code, 200, created.text)
campaign_id = created.json()["campaign"]["id"]
version_id = created.json()["version"]["id"]
temporary = self.client.post(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}/lock-temporarily",
headers=headers,
)
self.assertEqual(temporary.status_code, 200, temporary.text)
self.assertEqual(temporary.json()["user_lock_state"], "temporary")
self.assertTrue(temporary.json()["user_locked_at"])
blocked_update = self.client.put(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
headers=headers,
json={"current_step": "fields"},
)
self.assertEqual(blocked_update.status_code, 409, blocked_update.text)
unlocked = self.client.post(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}/unlock-user-lock",
headers=headers,
)
self.assertEqual(unlocked.status_code, 200, unlocked.text)
self.assertIsNone(unlocked.json()["user_lock_state"])
updated = self.client.put(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
headers=headers,
json={"current_step": "fields"},
)
self.assertEqual(updated.status_code, 200, updated.text)
self.assertEqual(updated.json()["current_step"], "fields")
relocked = self.client.post(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}/lock-temporarily",
headers=headers,
)
self.assertEqual(relocked.status_code, 200, relocked.text)
permanent = self.client.post(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}/lock-permanently",
headers=headers,
)
self.assertEqual(permanent.status_code, 200, permanent.text)
self.assertEqual(permanent.json()["user_lock_state"], "permanent")
self.assertTrue(permanent.json()["published_at"])
refused_unlock = self.client.post(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}/unlock-user-lock",
headers=headers,
)
self.assertEqual(refused_unlock.status_code, 409, refused_unlock.text)
def test_campaign_create_validate_build_and_mock_send(self) -> None:
headers, _ = self._login()
campaign_json = {
@@ -377,10 +438,59 @@ class ApiSmokeTests(unittest.TestCase):
self.assertEqual(built.status_code, 200, built.text)
self.assertEqual(built.json()["built_count"], 1)
self.assertEqual(built.json()["messages"][0]["attachment_count"], 2)
self.assertTrue(built.json().get("built_at"))
self.assertTrue(built.json().get("build_token"))
self.assertEqual(
sum(len(item["managed_matches"]) for item in built.json()["messages"][0]["attachments"]),
2,
)
resolved_paths = {
match
for attachment in built.json()["messages"][0]["attachments"]
for match in attachment["matches"]
}
self.assertEqual(resolved_paths, {
"invoices/archive/202605-010001-report.XLSX",
"invoices/202605-010001-90100010-9601741.XLSX",
})
self.assertFalse(any("multimailer-managed-build" in value for value in resolved_paths))
jobs = self.client.get(
f"/api/v1/campaigns/{campaign_id}/jobs",
headers=headers,
params={"version_id": version_id},
)
self.assertEqual(jobs.status_code, 200, jobs.text)
self.assertEqual(len(jobs.json()["jobs"]), 1)
job = jobs.json()["jobs"][0]
self.assertEqual(job["campaign_version_id"], version_id)
self.assertEqual(job["resolved_recipients"]["to"][0]["email"], "recipient@example.org")
self.assertEqual(
{
match
for attachment in job["attachments"]
for match in attachment["matches"]
},
resolved_paths,
)
review_state = self.client.post(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}/review-state",
headers=headers,
json={"inspection_complete": True, "reviewed_message_keys": ["recipient-1"]},
)
self.assertEqual(review_state.status_code, 200, review_state.text)
stored_review = review_state.json()["editor_state"]["review_send"]
self.assertTrue(stored_review["inspection_complete"])
self.assertEqual(stored_review["reviewed_message_keys"], ["recipient-1"])
self.assertEqual(stored_review["build_token"], built.json()["build_token"])
reloaded_version = self.client.get(
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
headers=headers,
)
self.assertEqual(reloaded_version.status_code, 200, reloaded_version.text)
self.assertTrue(reloaded_version.json()["editor_state"]["review_send"]["inspection_complete"])
mocked = self.client.post(
f"/api/v1/campaigns/{campaign_id}/mock-send",