1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
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"),
)
|