import uuid from collections.abc import Callable, Iterator from types import ModuleType import httpx import pytest from flask import Flask from flask.testing import FlaskClient from webmentions_ssg import DATABASE as db from webmentions_ssg import create_app from webmentions_ssg.config import TestingConfig from webmentions_ssg.models import ReceivedWebmention HTTPHandler = Callable[ [httpx.Request], httpx.Response, ] class FakeHostAnswers: def __init__(self, *addresses: str): self._addresses = addresses def addresses(self): return iter(self._addresses) @pytest.fixture def app() -> Iterator[Flask]: """ Create a new Flask application and in-memory database for every test. """ application = create_app(TestingConfig) with application.app_context(): db.create_all() yield application with application.app_context(): db.session.remove() db.drop_all() db.engine.dispose() @pytest.fixture def client(app: Flask) -> FlaskClient: return app.test_client() @pytest.fixture def receiver_module(app: Flask) -> ModuleType: """ Ensure the application and Huey extension are initialized before retrieving the tasks module. """ from webmentions_ssg.tasks import receiver return receiver @pytest.fixture def views_module(app: Flask) -> ModuleType: from webmentions_ssg import views return views @pytest.fixture def make_webmention( app: Flask, ) -> Callable[..., uuid.UUID]: def create( *, source: str = "https://source.example/post", target: str = ("https://dennisfink.me/blog/example/"), status: str = "received", failure_reason: str | None = None, ) -> uuid.UUID: identifier = uuid.uuid7() with app.app_context(): webmention = ReceivedWebmention( uuid=identifier, source=source, target=target, status=status, failure_reason=failure_reason, ) db.session.add(webmention) db.session.commit() return identifier return create @pytest.fixture def install_httpx_mock( monkeypatch: pytest.MonkeyPatch, receiver_module: ModuleType, ) -> Callable[[HTTPHandler], None]: """ Replace the HTTPX transport without replacing HTTPX itself. """ monkeypatch.setattr( receiver_module, "ensure_public_url", lambda url: None, ) real_client = httpx.Client def install(handler: HTTPHandler) -> None: transport = httpx.MockTransport(handler) def create_client( *args, **kwargs, ) -> httpx.Client: return real_client( *args, transport=transport, **kwargs, ) monkeypatch.setattr( receiver_module.httpx, "Client", create_client, ) return install @pytest.fixture def public_dns( monkeypatch: pytest.MonkeyPatch, ) -> None: monkeypatch.setattr( "webmentions_ssg.url_security.dns.resolver.resolve_name", lambda hostname: FakeHostAnswers("93.184.216.34"), )