Release govoplan-campaign v0.1.28: stabilize saving, review and delivery recovery
Module Package Release / publish-packages (push) Successful in 12s

This commit is contained in:
2026-09-08 01:32:26 +02:00
parent 1b32427813
commit c51fc180fb
111 changed files with 6905 additions and 980 deletions
+37 -2
View File
@@ -159,9 +159,9 @@ class CampaignAttachmentBuildTests(unittest.TestCase):
cases = {
"block": ("build_failed", "blocked", 0, "block", False),
"ask": ("built", "needs_review", 0, "ask", True),
"drop": ("built", "needs_review", 0, "ask", True),
"drop": ("built", "excluded", 0, "drop", True),
"warn": ("built", "warning", 1, "warn", True),
"continue": ("built", "warning", 1, None, True),
"continue": ("built", "ready", 1, None, True),
}
for behavior, (build_status, validation_status, queueable_count, issue_behavior, has_mime) in cases.items():
with self.subTest(behavior=behavior):
@@ -257,6 +257,41 @@ class CampaignAttachmentBuildTests(unittest.TestCase):
)
self.assertEqual(issue.behavior, "warn")
def test_explicit_optional_empty_rule_is_information_unless_hard_blocked(self) -> None:
for policy, expected in (("warn", "ready"), ("ask", "ready"), ("block", "blocked")):
with self.subTest(policy=policy), tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
campaign_file = root / "campaign.json"
campaign_file.write_text("{}", encoding="utf-8")
config = self._no_attachment_config(behavior="continue", configure_missing_rule=True)
config.validation_policy.missing_optional_attachment = policy
result = build_campaign_messages(config, campaign_file=campaign_file, output_dir=root / "out", write_eml=True)
message = result.report.messages[0]
self.assertEqual(message.validation_status.value, expected)
issue = next(item for item in message.issues if item.code == "missing_optional_attachment")
self.assertEqual(issue.behavior, "block" if policy == "block" else "continue")
self.assertEqual(issue.severity, "error" if policy == "block" else "info")
self.assertEqual(message.attachments[0].matches, [])
def test_deliberate_rule_drop_is_excluded_but_cannot_override_required_block(self) -> None:
for required, expected in ((False, "excluded"), (True, "blocked")):
with self.subTest(required=required), tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
campaign_file = root / "campaign.json"
campaign_file.write_text("{}", encoding="utf-8")
config = self._no_attachment_config(behavior="continue", configure_missing_rule=True)
rule = config.attachments.global_[0]
rule.missing_behavior = "drop"
rule.required = required
result = build_campaign_messages(config, campaign_file=campaign_file, output_dir=root / "out", write_eml=True)
message = result.report.messages[0]
self.assertEqual(message.validation_status.value, expected)
self.assertEqual(result.report.queueable_count, 0)
if not required:
self.assertEqual(message.send_status.value, "skipped")
self.assertEqual(message.imap_status.value, "skipped")
self.assertEqual(message.issues[0].behavior, "drop")
def test_missing_pattern_does_not_create_zip_member_or_count_as_attachment(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)