aboutsummaryrefslogtreecommitdiff
path: root/tests/forms/test_forms.py
blob: 6fe18491e3cb418f01b6bae4d8ef53be60832765 (plain) (blame)
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
# SPDX-FileCopyrightText: 2026 Dennis Fink <me+coding@dennisfink.me>
#
# SPDX-License-Identifier: BSD-3-Clause

from unittest.mock import Mock

import pytest
from flask import Flask
from werkzeug.datastructures import MultiDict

from webmentions_ssg.forms import AdminActionForm, EndpointForm, LoginForm

VALID_SOURCE = "https://source.example/post"
VALID_TARGET = "https://dennisfink.me/blog/example/"


@pytest.fixture(autouse=True)
def public_urls(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(
        "webmentions_ssg.forms.validators.is_public_url", Mock(return_value=True)
    )


@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_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",
        ),
    ],
)
def test_endpoint_form_rejects_invalid_field_syntax(
    app: Flask, form_data: dict[str, str], invalid_field: str, expected_error: str
) -> None:
    with app.test_request_context("/endpoint", method="POST"):
        form = EndpointForm(formdata=MultiDict(form_data), meta={"csrf": False})

        assert not form.validate()
        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 == {}


@pytest.mark.parametrize(
    ("form_data", "invalid_field"),
    [
        pytest.param({"password": "secret"}, "username", id="username-required"),
        pytest.param({"username": "admin"}, "password", id="password-required"),
    ],
)
def test_login_form_requires_credentials(
    app: Flask, form_data: dict[str, str], invalid_field: str
) -> None:
    with app.test_request_context("/login", method="POST"):
        form = LoginForm(formdata=MultiDict(form_data), meta={"csrf": False})

        assert not form.validate()
        assert "This field is required." in form.errors[invalid_field]


def test_login_form_accepts_credentials(app: Flask) -> None:
    with app.test_request_context("/login", method="POST"):
        form = LoginForm(
            formdata=MultiDict({"username": "admin", "password": "secret"}),
            meta={"csrf": False},
        )
        assert form.validate()


def test_admin_action_form_accepts_submission(app: Flask) -> None:
    with app.test_request_context(method="POST"):
        form = AdminActionForm(meta={"csrf": False})
        assert form.validate()