Release govoplan-campaign v0.1.28: stabilize saving, review and delivery recovery
Module Package Release / publish-packages (push) Successful in 12s
Module Package Release / publish-packages (push) Successful in 12s
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import create_engine
|
||||
@@ -12,6 +14,8 @@ from govoplan_campaign.backend.services.job_queries import (
|
||||
_campaign_jobs_grid_filter_expressions,
|
||||
_campaign_jobs_ordering,
|
||||
_campaign_jobs_page_response,
|
||||
_campaign_jobs_query_context,
|
||||
_public_recipient_groups,
|
||||
)
|
||||
from govoplan_core.core.change_sequence import ChangeSequenceEntry
|
||||
from govoplan_core.db.base import Base
|
||||
@@ -119,6 +123,56 @@ class CampaignJobListQueryTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(raised.exception.status_code, 422)
|
||||
|
||||
def test_recipient_projection_preserves_each_group_order_without_extra_fields(self) -> None:
|
||||
recipients = {"to": [{"email": "second@example.test", "name": "Second", "secret": "never-project"},
|
||||
{"email": "first@example.test"}],
|
||||
"cc": [{"email": "copy@example.test"}], "bcc": [{"email": "blind@example.test"}],
|
||||
"from": {"email": "sender@example.test"}, "private": "never-project"}
|
||||
result = _public_recipient_groups(recipients)
|
||||
self.assertEqual(list(result), ["to", "cc", "bcc"])
|
||||
self.assertEqual([value["email"] for value in result["to"]], ["second@example.test", "first@example.test"])
|
||||
self.assertNotIn("never-project", str(result))
|
||||
|
||||
def test_each_frozen_recipient_group_is_searchable_before_pagination(self) -> None:
|
||||
row = self.session.get(CampaignJob, "job-0")
|
||||
row.resolved_recipients = {"to": [{"email": "second-to@example.test"}],
|
||||
"cc": [{"email": "copy@example.test"}], "bcc": [{"email": "blind@example.test"}]}
|
||||
self.session.commit()
|
||||
for recipient in ("second-to", "copy@", "blind@"):
|
||||
with self.subTest(recipient=recipient):
|
||||
filters = _campaign_jobs_grid_filter_expressions({"recipient": recipient})
|
||||
page = _campaign_jobs_page_response(self.session, campaign_id="campaign-1", version_id="version-1",
|
||||
base_filters=[CampaignJob.tenant_id == "tenant-1"], filtered=filters,
|
||||
reviewed_keys=set(), review_metadata={}, page=1, page_size=1, grid_filters={"recipient": recipient})
|
||||
self.assertEqual(page.total, 1)
|
||||
self.assertEqual(page.jobs[0]["id"], "job-0")
|
||||
self.assertEqual(page.jobs[0]["resolved_recipients"]["bcc"], [{"email": "blind@example.test"}])
|
||||
|
||||
def test_free_search_also_matches_additional_recipients_and_keeps_tenant_scope(self) -> None:
|
||||
row = self.session.get(CampaignJob, "job-0")
|
||||
row.resolved_recipients = {"bcc": [{"email": "additional@example.test"}]}
|
||||
other = self.session.get(CampaignJob, "job-1")
|
||||
other.tenant_id = "other-tenant"
|
||||
other.resolved_recipients = row.resolved_recipients
|
||||
self.session.commit()
|
||||
principal = SimpleNamespace(tenant_id="tenant-1", has=lambda scope: scope == "campaigns:recipient:read")
|
||||
with patch("govoplan_campaign.backend.services.job_queries._get_campaign_for_principal"), \
|
||||
patch("govoplan_campaign.backend.services.job_queries._get_campaign_for_tenant", return_value=SimpleNamespace(id="campaign-1")), \
|
||||
patch("govoplan_campaign.backend.services.job_queries._review_metadata", return_value=({}, set())):
|
||||
_, _, filters, _, _ = _campaign_jobs_query_context(self.session, principal, campaign_id="campaign-1", version_id=None,
|
||||
send_status=None, validation_status=None, imap_status=None, query_text="additional@example.test")
|
||||
self.assertEqual([job.id for job in self.session.query(CampaignJob).filter(*filters)], ["job-0"])
|
||||
|
||||
def test_recipient_read_is_required_before_additional_addresses_are_queried(self) -> None:
|
||||
principal = SimpleNamespace(tenant_id="tenant-1", has=lambda _scope: False)
|
||||
with patch("govoplan_campaign.backend.services.job_queries._get_campaign_for_principal"), \
|
||||
patch("govoplan_campaign.backend.services.job_queries._get_campaign_for_tenant") as lookup:
|
||||
with self.assertRaises(HTTPException) as raised:
|
||||
_campaign_jobs_query_context(self.session, principal, campaign_id="campaign-1", version_id=None,
|
||||
send_status=None, validation_status=None, imap_status=None, query_text="blind@example.test")
|
||||
self.assertEqual(raised.exception.status_code, 403)
|
||||
lookup.assert_not_called()
|
||||
|
||||
def test_skipped_transport_filters_and_counts_remain_separate(self) -> None:
|
||||
base_filters = [CampaignJob.tenant_id == "tenant-1", CampaignJob.campaign_id == "campaign-1"]
|
||||
grid_filters = {"send": 'list:["skipped"]', "imap": 'list:["skipped"]'}
|
||||
|
||||
Reference in New Issue
Block a user