aboutsummaryrefslogtreecommitdiff
path: root/tests/test_forms.py
diff options
context:
space:
mode:
authorDennis Fink2026-08-09 14:15:29 +0200
committerDennis Fink2026-08-09 14:15:29 +0200
commite4a8194e6de25e8a48e2c61ce7f89a8159fd99d9 (patch)
tree234f63980aba8fe3c8d03e7bc8959598bce7e790 /tests/test_forms.py
parentf53c1136184d2afabfb1e5974e527229aa71939a (diff)
downloadwebmentions-ssg-e4a8194e6de25e8a48e2c61ce7f89a8159fd99d9.tar.gz
webmentions-ssg-e4a8194e6de25e8a48e2c61ce7f89a8159fd99d9.zip
Implement received Webmention handling
Add the Flask application setup, database models and migrations, authentication, and configuration for development and testing. Implement asynchronous Webmention verification with Huey, including HTML and plain-text source validation, retries, status tracking, and size limits. Add status, login, and paginated received-Webmention views together with comprehensive tests for forms, views, and receiver tasks.
Diffstat (limited to 'tests/test_forms.py')
-rw-r--r--tests/test_forms.py130
1 files changed, 130 insertions, 0 deletions
diff --git a/tests/test_forms.py b/tests/test_forms.py
new file mode 100644
index 0000000..9be6ca8
--- /dev/null
+++ b/tests/test_forms.py
@@ -0,0 +1,130 @@
+import pytest
+from flask import Flask
+from werkzeug.datastructures import MultiDict
+
+from webmentions_ssg.forms import EndpointForm
+
+VALID_SOURCE = "https://source.example/post"
+VALID_TARGET = "https://dennisfink.me/blog/example/"
+
+
+@pytest.mark.parametrize(
+ (
+ "form_data",
+ "invalid_field",
+ "expected_error",
+ ),
+ [
+ pytest.param(
+ {
+ "target": VALID_TARGET,
+ },
+ "source",
+ "This field is required.",
+ id="source-required",
+ ),
+ pytest.param(
+ {
+ "source": "not a URL",
+ "target": VALID_TARGET,
+ },
+ "source",
+ "Invalid URL.",
+ id="source-url",
+ ),
+ pytest.param(
+ {
+ "source": "ftp://source.example/post",
+ "target": VALID_TARGET,
+ },
+ "source",
+ "source must begin with http or https",
+ id="source-scheme",
+ ),
+ pytest.param(
+ {
+ "source": VALID_TARGET,
+ "target": VALID_TARGET,
+ },
+ "source",
+ None,
+ id="source-not-equal-to-target",
+ ),
+ pytest.param(
+ {
+ "source": VALID_SOURCE,
+ },
+ "target",
+ "This field is required.",
+ id="target-required",
+ ),
+ pytest.param(
+ {
+ "source": VALID_SOURCE,
+ "target": "not a URL",
+ },
+ "target",
+ "Invalid URL.",
+ id="target-url",
+ ),
+ pytest.param(
+ {
+ "source": VALID_SOURCE,
+ "target": "ftp://dennisfink.me/blog/example/",
+ },
+ "target",
+ "target must begin with http or https",
+ id="target-scheme",
+ ),
+ pytest.param(
+ {
+ "source": VALID_SOURCE,
+ "target": "https://example.com/post",
+ },
+ "target",
+ None,
+ id="target-allowed-hostname",
+ ),
+ ],
+)
+def test_endpoint_form_rejects_invalid_data(
+ app: Flask,
+ form_data: dict[str, str],
+ invalid_field: str,
+ expected_error: str | None,
+) -> None:
+ with app.test_request_context(
+ "/endpoint",
+ method="POST",
+ ):
+ form = EndpointForm(
+ formdata=MultiDict(form_data),
+ meta={"csrf": False},
+ )
+
+ assert not form.validate()
+ assert invalid_field in form.errors
+
+ if expected_error is not None:
+ assert expected_error in form.errors[invalid_field]
+
+
+def test_endpoint_form_accepts_valid_data(
+ app: Flask,
+) -> None:
+ with app.test_request_context(
+ "/endpoint",
+ method="POST",
+ ):
+ form = EndpointForm(
+ formdata=MultiDict(
+ {
+ "source": VALID_SOURCE,
+ "target": VALID_TARGET,
+ }
+ ),
+ meta={"csrf": False},
+ )
+
+ assert form.validate()
+ assert form.errors == {}