import json import time from collections.abc import Iterator from typing import Any from unittest import mock import pytest from anydi import Container from confluent_kafka import Producer from ellipticcurve.privateKey import PrivateKey from sendgrid.helpers.eventwebhook import EventWebhook from app.auth import Auth from app.config import Settings from app.handlers import SendgridEventHandler from app.modules import container as global_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 global_container.override( Settings, Settings(sendgrid_public_keys={test_subuser: public_key}), ): yield global_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="function") def kafka_producer_mock() -> mock.MagicMock: return mock.MagicMock(spec=Producer) @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( kafka_producer_mock: mock.MagicMock, s3_client_mock: mock.MagicMock, test_sendgrid_validators: dict[str, EventWebhook], test_failed_events_s3_bucket: str, settings: Settings, ) -> SendgridEventHandler: return SendgridEventHandler( auth=Auth(sendgrid_validators=test_sendgrid_validators), kafka_producer=kafka_producer_mock, kafka_sendgrid_events_topic=settings.kafka_sendgrid_events_topic, s3_client=s3_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", "email_id": "test", "email_type": "CAMPAIGN", "trigger_id": "test", "batch_id": "test", "category": ["Mozart"], "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_event_validation_fail(test_timestamp: int) -> list[dict[str, Any]]: return [ { "event": "processed", "timestamp": test_timestamp, "sg_event_id": "test", "sg_message_id": "test", "email_id": "test", "email_type": "CAMPAIGN", "trigger_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, ) -> 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, }, "body": dumped_test_event, } return request @pytest.fixture(scope="function") def test_event_fan_reply_forwarding(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", "send_type": "fan_reply_forwarding", } ] @pytest.fixture(scope="function") def test_request_fan_reply_forwarding( test_timestamp: int, test_event_fan_reply_forwarding: list[dict[str, Any]], private_key: PrivateKey, test_subuser: str, ) -> dict[str, Any]: dumped_test_event = json.dumps(test_event_fan_reply_forwarding) 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