from collections.abc import Iterator from pathlib import Path from unittest import mock import fakeredis import pytest from fansifter_common.adapters.db import Database from fansifter_common.adapters.db.models.utils import autodiscover_models from pytest_mock import MockerFixture from app.adapters.aws import LambdaClient from app.adapters.db import Model, db from app.adapters.ows_dmp import OwsDmpClient from app.adapters.ows_text_campaigns import OwsTextCampaignsClient @pytest.fixture(scope="session", autouse=True) def _db(session_mocker: MockerFixture) -> Iterator[None]: db_path = Path(__file__).parent.parent.parent / "test.db" session_mocker.patch( "app.adapters.db.db.__wrapped__", new=Database( url="sqlite:///" + str(db_path), session_args={ "expire_on_commit": False, "autoflush": True, }, ), ) yield db_path.unlink(missing_ok=True) @pytest.fixture(scope="session") def _db_setup() -> Iterator[None]: autodiscover_models("app") Model.metadata.create_all(bind=db.engine) yield Model.metadata.drop_all(bind=db.engine) @pytest.fixture(autouse=True) def _db_marker(request: pytest.FixtureRequest) -> Iterator[None]: """Use the `db` marker to run a test in a transaction.""" marker = request.node.get_closest_marker("db") if not marker: yield return _ = request.getfixturevalue("_db_setup") with db.global_context(), db.rollback_transaction(): yield @pytest.fixture(scope="session", autouse=True) def lambda_client_mock(session_mocker: MockerFixture) -> mock.MagicMock: mocked_lambda_client = session_mocker.MagicMock(spec=LambdaClient) session_mocker.patch( "app.adapters.aws.lambda_client.__wrapped__", new=mocked_lambda_client ) return mocked_lambda_client @pytest.fixture(autouse=True) def _reset_lambda_client_mock(lambda_client_mock: mock.MagicMock) -> None: lambda_client_mock.reset_mock(return_value=True, side_effect=True) lambda_client_mock.invoke.return_value = True @pytest.fixture(scope="session", autouse=True) def ows_text_campaigns_client_mock(session_mocker: MockerFixture) -> mock.MagicMock: mocked_ows_text_campaigns_client = session_mocker.MagicMock( spec=OwsTextCampaignsClient ) session_mocker.patch( "app.adapters.ows_text_campaigns.ows_text_campaigns_client.__wrapped__", new=mocked_ows_text_campaigns_client, ) return mocked_ows_text_campaigns_client @pytest.fixture(autouse=True) def _reset_ows_text_campaigns_client_mock( ows_text_campaigns_client_mock: mock.MagicMock, ) -> None: ows_text_campaigns_client_mock.reset_mock(return_value=True, side_effect=True) @pytest.fixture(scope="session", autouse=True) def ows_dmp_client_mock(session_mocker: MockerFixture) -> mock.MagicMock: mocked_ows_dmp_client = session_mocker.MagicMock(spec=OwsDmpClient) session_mocker.patch( "app.adapters.ows_dmp.ows_dmp_client.__wrapped__", new=mocked_ows_dmp_client ) return mocked_ows_dmp_client @pytest.fixture(autouse=True) def _reset_ows_dmp_client_mock(ows_dmp_client_mock: mock.MagicMock) -> None: ows_dmp_client_mock.reset_mock(return_value=True, side_effect=True) # Non-zero by default so `_prepare_campaign` proceeds past the fan_count # check; tests for the "no fans" path override this explicitly. ows_dmp_client_mock.upsert_audience_fans.return_value = 1 @pytest.fixture(scope="session", autouse=True) def redis_client(session_mocker: MockerFixture) -> fakeredis.FakeRedis: fake_redis_client = fakeredis.FakeRedis() session_mocker.patch( "app.adapters.redis.redis_client.__wrapped__", new=fake_redis_client ) return fake_redis_client @pytest.fixture(autouse=True) def _reset_redis_client(redis_client: fakeredis.FakeRedis) -> None: redis_client.flushall()