aboutsummaryrefslogtreecommitdiff
path: root/tests/test_views.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_views.py')
-rw-r--r--tests/test_views.py117
1 files changed, 72 insertions, 45 deletions
diff --git a/tests/test_views.py b/tests/test_views.py
index 0de8b9b..844da2e 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -4,7 +4,8 @@
import uuid
from datetime import UTC, datetime
-from unittest.mock import Mock, call, patch
+from types import ModuleType
+from unittest.mock import Mock, call
import pytest
import sqlalchemy as sa
@@ -20,6 +21,36 @@ from webmentions_ssg.models import (
User,
)
+SOURCE_URL = "https://source.example/post"
+TARGET_URL = "https://dennisfink.me/blog/example/"
+
+
+@pytest.fixture
+def views_module(app: Flask) -> ModuleType:
+ _ = app
+ from webmentions_ssg import views
+
+ return views
+
+
+def mock_endpoint_form(
+ views_module: ModuleType,
+ monkeypatch: pytest.MonkeyPatch,
+ *,
+ valid: bool,
+ source: str = SOURCE_URL,
+ target: str = TARGET_URL,
+ errors: dict[str, list[str]] | None = None,
+) -> Mock:
+ form = Mock()
+ form.validate_on_submit.return_value = valid
+ form.source.data = source
+ form.target.data = target
+ form.errors = errors or {}
+
+ monkeypatch.setattr(views_module.forms, "EndpointForm", Mock(return_value=form))
+ return form
+
def log_in(app: Flask, client: FlaskClient) -> None:
with app.app_context():
@@ -82,46 +113,42 @@ def create_sent_source(app: Flask) -> uuid.UUID:
def test_endpoint_only_accepts_post(client: FlaskClient) -> None:
response = client.get("/endpoint")
-
assert response.status_code == 405
-@patch("webmentions_ssg.forms.validators.is_public_url", new=lambda url: True)
-def test_endpoint_returns_form_errors(client: FlaskClient) -> None:
- response = client.post(
- "/endpoint",
- data={
- "source": "https://source.example/post",
- "target": "https://example.com/post",
- },
- )
-
- assert response.status_code == 400
+def test_endpoint_returns_form_errors(
+ client: FlaskClient, views_module: ModuleType, monkeypatch: pytest.MonkeyPatch
+) -> None:
+ errors = {"source": ["Invalid source"]}
+ mock_endpoint_form(views_module, monkeypatch, valid=False, errors=errors)
- errors = response.get_json()
+ response = client.post("/endpoint")
- assert errors is not None
- assert "target" in errors
+ assert response.status_code == 400
+ assert response.get_json() == errors
-@patch("webmentions_ssg.forms.validators.is_public_url", new=lambda url: True)
-@patch("webmentions_ssg.views.verify_webmention")
def test_endpoint_creates_webmention(
- verify_webmention: Mock, app: Flask, client: FlaskClient
+ app: Flask,
+ client: FlaskClient,
+ views_module: ModuleType,
+ monkeypatch: pytest.MonkeyPatch,
) -> None:
- source = "https://source.example/post"
- target = "https://dennisfink.me/blog/example/"
+ form = mock_endpoint_form(views_module, monkeypatch, valid=True)
+ verify_webmention = Mock()
+ monkeypatch.setattr(views_module, "verify_webmention", verify_webmention)
- response = client.post("/endpoint", data={"source": source, "target": target})
+ response = client.post("/endpoint")
assert response.status_code == 201
+ form.validate_on_submit.assert_called_once_with()
with app.app_context():
webmention = db.session.scalar(sa.select(ReceivedWebmention))
assert webmention is not None
- assert webmention.source == source
- assert webmention.target == target
+ assert webmention.source == SOURCE_URL
+ assert webmention.target == TARGET_URL
assert webmention.status == "received"
assert webmention.failure_reason is None
@@ -131,18 +158,18 @@ def test_endpoint_creates_webmention(
verify_webmention.assert_called_once_with(identifier)
-@patch("webmentions_ssg.forms.validators.is_public_url", new=lambda url: True)
-@patch("webmentions_ssg.views.verify_webmention")
def test_endpoint_is_idempotent(
- verify_webmention: Mock, app: Flask, client: FlaskClient
+ app: Flask,
+ client: FlaskClient,
+ views_module: ModuleType,
+ monkeypatch: pytest.MonkeyPatch,
) -> None:
- data = {
- "source": "https://source.example/post",
- "target": "https://dennisfink.me/blog/example/",
- }
+ mock_endpoint_form(views_module, monkeypatch, valid=True)
+ verify_webmention = Mock()
+ monkeypatch.setattr(views_module, "verify_webmention", verify_webmention)
- first_response = client.post("/endpoint", data=data)
- second_response = client.post("/endpoint", data=data)
+ first_response = client.post("/endpoint")
+ second_response = client.post("/endpoint")
assert first_response.status_code == 201
assert second_response.status_code == 201
@@ -155,8 +182,8 @@ def test_endpoint_is_idempotent(
webmention = webmentions[0]
- assert webmention.source == data["source"]
- assert webmention.target == data["target"]
+ assert webmention.source == SOURCE_URL
+ assert webmention.target == TARGET_URL
assert webmention.status == "received"
assert webmention.failure_reason is None
@@ -165,19 +192,21 @@ def test_endpoint_is_idempotent(
assert verify_webmention.call_args_list == [call(identifier), call(identifier)]
-@patch("webmentions_ssg.forms.validators.is_public_url", new=lambda url: True)
-@patch("webmentions_ssg.views.verify_webmention")
def test_resending_resets_failure_state(
- verify_webmention: Mock, app: Flask, client: FlaskClient
+ app: Flask,
+ client: FlaskClient,
+ views_module: ModuleType,
+ monkeypatch: pytest.MonkeyPatch,
) -> None:
- source = "https://source.example/post"
- target = "https://dennisfink.me/blog/example/"
+ mock_endpoint_form(views_module, monkeypatch, valid=True)
+ verify_webmention = Mock()
+ monkeypatch.setattr(views_module, "verify_webmention", verify_webmention)
with app.app_context():
existing = ReceivedWebmention(
uuid=uuid.uuid7(),
- source=source,
- target=target,
+ source=SOURCE_URL,
+ target=TARGET_URL,
status="failed",
failure_reason="Previous failure",
)
@@ -187,7 +216,7 @@ def test_resending_resets_failure_state(
identifier = existing.uuid
- response = client.post("/endpoint", data={"source": source, "target": target})
+ response = client.post("/endpoint")
assert response.status_code == 201
@@ -252,7 +281,5 @@ def test_sent_source_returns_404_for_unknown_source(
app: Flask, client: FlaskClient
) -> None:
log_in(app, client)
-
response = client.get(f"/sent/{uuid.uuid7()}")
-
assert response.status_code == 404