import json import time from collections.abc import Iterator from typing import Any from unittest import mock import pytest from anydi import Container from ellipticcurve.privateKey import PrivateKey from owsclient import OwsClient from owsclient.test import OwsClientMock from sendgrid.helpers.eventwebhook import EventWebhook from app.adapters.ows_preference_center import OwsPreferenceCenterClient from app.auth import Auth from app.config import Settings from app.handlers import SendgridEventHandler from app.main import container as _container from tests.unit.utils import generate_test_sendgrid_signature @pytest.fixture(scope="session") def container(public_key: str, test_subuser: str) -> Iterator[Container]: with _container.override( Settings, Settings(environment="test", sendgrid_public_keys={test_subuser: public_key}), ): yield _container @pytest.fixture(scope="session") def settings(container: Container) -> Settings: return container.resolve(Settings) @pytest.fixture(scope="function") def s3_client_mock() -> mock.MagicMock: return mock.MagicMock() @pytest.fixture(scope="session") def test_sendgrid_validators( test_subuser: str, public_key: str ) -> dict[str, EventWebhook]: return {test_subuser: EventWebhook(public_key)} @pytest.fixture(scope="session") def test_failed_events_s3_bucket(settings: Settings) -> str: return settings.failed_events_s3_bucket @pytest.fixture(scope="function") def test_handler( ows_preference_center_client_mock: mock.MagicMock, s3_client_mock: mock.MagicMock, test_sendgrid_validators: dict[str, EventWebhook], test_failed_events_s3_bucket: str, ) -> SendgridEventHandler: return SendgridEventHandler( auth=Auth(sendgrid_validators=test_sendgrid_validators), s3_client=s3_client_mock, ows_preference_center_client=ows_preference_center_client_mock, failed_events_s3_bucket=test_failed_events_s3_bucket, ) @pytest.fixture(scope="session") def test_timestamp() -> int: return int(time.time()) @pytest.fixture(scope="session") def private_key() -> PrivateKey: return PrivateKey() @pytest.fixture(scope="session") def public_key(private_key: PrivateKey) -> str: public_key: str = private_key.publicKey().toPem() public_key = public_key.replace("-----BEGIN PUBLIC KEY-----\n", "") public_key = public_key.replace("\n-----END PUBLIC KEY-----\n", "") public_key = public_key.replace("\n", "") return public_key @pytest.fixture(scope="session") def test_event_success(test_timestamp: int) -> list[dict[str, Any]]: return [ { "event": "processed", "email": "test@example.com", "timestamp": test_timestamp, "sg_event_id": "test", "sg_message_id": "test", "campaign_id": "test", "batch_id": "test", "category": ["Mozart"], "is_test": True, } ] @pytest.fixture(scope="session") def test_event_success_with_spamreport(test_timestamp: int) -> list[dict[str, Any]]: return [ { "event": "processed", "email": "test@example.com", "timestamp": test_timestamp, "sg_event_id": "test", "sg_message_id": "test", "campaign_id": "test", "batch_id": "test", "is_test": True, }, { "event": "spamreport", "email": "test-report@example.com", "timestamp": test_timestamp, "sg_event_id": "test", "sg_message_id": "test", "campaign_id": "test_campaign_id", "batch_id": "test", "is_test": True, }, ] @pytest.fixture(scope="session") def test_subuser() -> str: return "test_subuser" @pytest.fixture(scope="session") def test_request_success( test_timestamp: int, test_event_success: dict[str, Any], private_key: PrivateKey, test_subuser: str, ) -> dict[str, Any]: dumped_test_event = json.dumps(test_event_success) request = { "headers": { "x-twilio-email-event-webhook-signature": generate_test_sendgrid_signature( str(test_timestamp) + dumped_test_event, private_key, ), "x-twilio-email-event-webhook-timestamp": test_timestamp, }, "path": test_subuser, "body": dumped_test_event, } return request @pytest.fixture(scope="session") def test_request_success_with_spamreport( test_timestamp: int, test_event_success_with_spamreport: dict[str, Any], private_key: PrivateKey, test_subuser: str, ) -> dict[str, Any]: dumped_test_event = json.dumps(test_event_success_with_spamreport) request = { "headers": { "x-twilio-email-event-webhook-signature": generate_test_sendgrid_signature( str(test_timestamp) + dumped_test_event, private_key, ), "x-twilio-email-event-webhook-timestamp": test_timestamp, }, "path": test_subuser, "body": dumped_test_event, } return request @pytest.fixture(scope="session") def test_event_validation_fail(test_timestamp: int) -> list[dict[str, Any]]: return [ { "event": "processed", "timestamp": test_timestamp, "sg_event_id": "test", "sg_message_id": "test", "campaign_id": "test", "batch_id": "test", "is_test": True, } ] @pytest.fixture(scope="session") def test_request_validation_fail( test_timestamp: int, test_event_validation_fail: dict[str, Any], private_key: PrivateKey, test_subuser: str, ) -> dict[str, Any]: dumped_test_event = json.dumps(test_event_validation_fail) request = { "headers": { "x-twilio-email-event-webhook-signature": generate_test_sendgrid_signature( str(test_timestamp) + dumped_test_event, private_key, ), "x-twilio-email-event-webhook-timestamp": test_timestamp, }, "path": test_subuser, "body": dumped_test_event, } return request @pytest.fixture def ows_client() -> OwsClient: return OwsClient( environment="test", service_name="lambda-audience-export-file", ) @pytest.fixture def ows_client_mock() -> OwsClientMock: return OwsClientMock() @pytest.fixture def ows_preference_center_client(ows_client: OwsClient) -> OwsPreferenceCenterClient: return OwsPreferenceCenterClient(ows_client=ows_client) @pytest.fixture def ows_preference_center_client_mock() -> mock.MagicMock: return mock.MagicMock(spec=OwsPreferenceCenterClient)