diff options
Diffstat (limited to 'tests/test_views.py')
| -rw-r--r-- | tests/test_views.py | 117 |
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 |
