initial
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
Form submission API tests.
|
||||
|
||||
Install dependencies:
|
||||
pip install pytest requests
|
||||
|
||||
Run:
|
||||
pytest tests/Forms/FormTests.py -v
|
||||
|
||||
The base URL is read from the WP_BASE_URL environment variable,
|
||||
defaulting to http://localhost/wordpress.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
BASE_URL = os.environ.get("WP_BASE_URL", "http://localhost/wordpress")
|
||||
FORM_ENDPOINT = f"{BASE_URL}/wp-json/reservations/v1/form/1"
|
||||
|
||||
|
||||
def post_form(data: dict) -> requests.Response:
|
||||
return requests.post(FORM_ENDPOINT, json=data)
|
||||
|
||||
|
||||
def find_error(errors: list, element: str) -> dict | None:
|
||||
return next((e for e in errors if e.get("element") == element), None)
|
||||
|
||||
|
||||
class TestFormResponseShape:
|
||||
def test_response_is_json(self):
|
||||
r = post_form({})
|
||||
assert r.headers["Content-Type"].startswith("application/json")
|
||||
|
||||
def test_response_has_success_field(self):
|
||||
r = post_form({})
|
||||
body = r.json()
|
||||
assert "success" in body
|
||||
|
||||
def test_failed_response_has_errors_list(self):
|
||||
r = post_form({})
|
||||
body = r.json()
|
||||
assert body["success"] is False
|
||||
assert isinstance(body["errors"], list)
|
||||
|
||||
def test_error_object_has_required_fields(self):
|
||||
r = post_form({})
|
||||
errors = r.json()["errors"]
|
||||
assert len(errors) > 0
|
||||
for error in errors:
|
||||
assert "element" in error
|
||||
assert "code" in error
|
||||
assert "message" in error
|
||||
|
||||
|
||||
class TestEmailValidation:
|
||||
def test_missing_email_returns_required_error(self):
|
||||
r = post_form({"name": "John"})
|
||||
errors = r.json()["errors"]
|
||||
email_error = find_error(errors, "email")
|
||||
assert email_error is not None
|
||||
assert email_error["code"] == "required"
|
||||
|
||||
def test_invalid_email_returns_invalid_email_error(self):
|
||||
r = post_form({"email": "not-an-email", "name": "John"})
|
||||
errors = r.json()["errors"]
|
||||
email_error = find_error(errors, "email")
|
||||
assert email_error is not None
|
||||
assert email_error["code"] == "invalid_email"
|
||||
|
||||
def test_empty_email_returns_required_error(self):
|
||||
r = post_form({"email": "", "name": "John"})
|
||||
errors = r.json()["errors"]
|
||||
email_error = find_error(errors, "email")
|
||||
assert email_error is not None
|
||||
assert email_error["code"] == "required"
|
||||
|
||||
def test_valid_email_produces_no_email_error(self):
|
||||
r = post_form({"email": "valid@example.com", "name": "John"})
|
||||
errors = r.json().get("errors", [])
|
||||
email_error = find_error(errors, "email")
|
||||
assert email_error is None
|
||||
|
||||
|
||||
class TestNameField:
|
||||
def test_missing_name_produces_no_name_error(self):
|
||||
r = post_form({"email": "valid@example.com"})
|
||||
errors = r.json().get("errors", [])
|
||||
name_error = find_error(errors, "name")
|
||||
assert name_error is None
|
||||
|
||||
def test_empty_name_produces_no_name_error(self):
|
||||
r = post_form({"email": "valid@example.com", "name": ""})
|
||||
errors = r.json().get("errors", [])
|
||||
name_error = find_error(errors, "name")
|
||||
assert name_error is None
|
||||
|
||||
class TestFormDefinition:
|
||||
def test_form_definition_returns_correct_fields(self):
|
||||
r = post_form({})
|
||||
body = r.json()
|
||||
assert "success" in body
|
||||
assert "definition" in body
|
||||
definition = body["definition"]
|
||||
assert isinstance(definition, dict)
|
||||
@@ -0,0 +1,2 @@
|
||||
pytest
|
||||
requests
|
||||
@@ -0,0 +1,81 @@
|
||||
"""
|
||||
Tests for the FormDefinition creation endpoint.
|
||||
|
||||
Endpoint: POST /wp-json/reservations/v1/form-definition
|
||||
Body: { "name": str, "definition": object }
|
||||
|
||||
Run:
|
||||
pytest tests/Forms/test_form_definition.py -v
|
||||
|
||||
Override the WordPress base URL:
|
||||
WP_BASE_URL=http://mysite.local pytest tests/Forms/test_form_definition.py -v
|
||||
"""
|
||||
|
||||
import os
|
||||
import requests
|
||||
|
||||
BASE_URL = os.environ.get("WP_BASE_URL", "http://localhost/wordpress")
|
||||
ENDPOINT = f"{BASE_URL}/wp-json/reservations/v1/form-definition"
|
||||
|
||||
VALID_DEFINITION = {
|
||||
"email_key": "email",
|
||||
"elements": [
|
||||
{"type": "text", "name": "name", "label": "Your name", "required": False},
|
||||
{"type": "text", "name": "email", "label": "Your email", "required": True},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def post_definition(payload: dict) -> requests.Response:
|
||||
return requests.post(ENDPOINT, json=payload)
|
||||
|
||||
|
||||
class TestFormDefinitionCreation:
|
||||
def test_can_create_form_definition(self):
|
||||
r = post_definition({"name": "Contact form", "definition": VALID_DEFINITION})
|
||||
assert r.status_code == 201
|
||||
body = r.json()
|
||||
assert "id" in body
|
||||
assert isinstance(body["id"], int)
|
||||
assert body["id"] > 0
|
||||
|
||||
def test_response_content_type_is_json(self):
|
||||
r = post_definition({"name": "Contact form", "definition": VALID_DEFINITION})
|
||||
assert r.headers["Content-Type"].startswith("application/json")
|
||||
|
||||
def test_each_creation_returns_a_new_id(self):
|
||||
r1 = post_definition({"name": "Form A", "definition": VALID_DEFINITION})
|
||||
r2 = post_definition({"name": "Form B", "definition": VALID_DEFINITION})
|
||||
assert r1.status_code == 201
|
||||
assert r2.status_code == 201
|
||||
assert r1.json()["id"] != r2.json()["id"]
|
||||
|
||||
|
||||
class TestFormDefinitionValidation:
|
||||
def test_missing_name_returns_400(self):
|
||||
r = post_definition({"definition": VALID_DEFINITION})
|
||||
assert r.status_code == 400
|
||||
|
||||
def test_empty_name_returns_400(self):
|
||||
r = post_definition({"name": "", "definition": VALID_DEFINITION})
|
||||
assert r.status_code == 400
|
||||
|
||||
def test_missing_definition_returns_400(self):
|
||||
r = post_definition({"name": "Contact form"})
|
||||
assert r.status_code == 400
|
||||
|
||||
def test_definition_must_be_object_not_string(self):
|
||||
r = post_definition({"name": "Contact form", "definition": "not-an-object"})
|
||||
assert r.status_code == 400
|
||||
|
||||
def test_missing_both_fields_returns_400(self):
|
||||
r = post_definition({})
|
||||
assert r.status_code == 400
|
||||
|
||||
def test_definition_with_no_elements_is_accepted(self):
|
||||
r = post_definition({"name": "Empty form", "definition": {}})
|
||||
assert r.status_code == 201
|
||||
|
||||
def test_definition_with_empty_elements_list_is_accepted(self):
|
||||
r = post_definition({"name": "Empty elements form", "definition": {"elements": []}})
|
||||
assert r.status_code == 201
|
||||
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
Tests for form submission.
|
||||
|
||||
A form definition is created once per session, then submissions are POSTed
|
||||
against that definition's ID.
|
||||
|
||||
Run:
|
||||
pytest Forms/test_form_submission.py -v
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
BASE_URL = os.environ.get("WP_BASE_URL", "http://localhost/wordpress")
|
||||
DEFINITION_ENDPOINT = f"{BASE_URL}/wp-json/reservations/v1/form-definition"
|
||||
FORM_ENDPOINT = f"{BASE_URL}/wp-json/reservations/v1/form"
|
||||
|
||||
FORM_DEFINITION = {
|
||||
"elements": [
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "email",
|
||||
"label": "Email",
|
||||
"required": True,
|
||||
"validation": "email",
|
||||
},
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "name",
|
||||
"label": "Name",
|
||||
"required": False,
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"name": "submit",
|
||||
"label": "Submit",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def form_id():
|
||||
r = requests.post(DEFINITION_ENDPOINT, json={"name": "Test submission form", "definition": FORM_DEFINITION})
|
||||
assert r.status_code == 201, f"Failed to create form definition: {r.text}"
|
||||
return r.json()["id"]
|
||||
|
||||
|
||||
def submit(form_id: int, data: dict) -> requests.Response:
|
||||
return requests.post(f"{FORM_ENDPOINT}/{form_id}", json=data)
|
||||
|
||||
|
||||
class TestFormSubmissionSuccess:
|
||||
def test_valid_submission_returns_200(self, form_id):
|
||||
r = submit(form_id, {"email": "user@example.com", "name": "Alice"})
|
||||
assert r.status_code == 200
|
||||
|
||||
def test_valid_submission_returns_success_true(self, form_id):
|
||||
r = submit(form_id, {"email": "user@example.com", "name": "Alice"})
|
||||
assert r.json()["success"] is True
|
||||
|
||||
def test_valid_submission_returns_submit_id(self, form_id):
|
||||
r = submit(form_id, {"email": "user@example.com", "name": "Alice"})
|
||||
body = r.json()
|
||||
assert "submit_id" in body
|
||||
assert isinstance(body["submit_id"], int)
|
||||
assert body["submit_id"] > 0
|
||||
|
||||
def test_valid_submission_has_values(self, form_id):
|
||||
r = submit(form_id, {"email": "user@example.com", "name": "Alice"})
|
||||
values = r.json()["values"]
|
||||
assert values["email"] == "user@example.com"
|
||||
assert values["name"] == "Alice"
|
||||
|
||||
def test_optional_name_can_be_omitted(self, form_id):
|
||||
r = submit(form_id, {"email": "user@example.com"})
|
||||
assert r.status_code == 200
|
||||
assert r.json()["success"] is True
|
||||
|
||||
|
||||
class TestFormSubmissionValidation:
|
||||
def test_missing_email_returns_400(self, form_id):
|
||||
r = submit(form_id, {"name": "Alice"})
|
||||
assert r.status_code == 400
|
||||
|
||||
def test_missing_email_returns_required_error(self, form_id):
|
||||
r = submit(form_id, {"name": "Alice"})
|
||||
errors = r.json()["errors"]
|
||||
email_error = next((e for e in errors if e["element"] == "email"), None)
|
||||
assert email_error is not None
|
||||
assert email_error["code"] == "required"
|
||||
|
||||
def test_invalid_email_returns_400(self, form_id):
|
||||
r = submit(form_id, {"email": "not-an-email", "name": "Alice"})
|
||||
assert r.status_code == 400
|
||||
|
||||
def test_invalid_email_returns_invalid_email_error(self, form_id):
|
||||
r = submit(form_id, {"email": "not-an-email", "name": "Alice"})
|
||||
errors = r.json()["errors"]
|
||||
email_error = next((e for e in errors if e["element"] == "email"), None)
|
||||
assert email_error is not None
|
||||
assert email_error["code"] == "invalid_email"
|
||||
|
||||
def test_empty_email_returns_required_error(self, form_id):
|
||||
r = submit(form_id, {"email": "", "name": "Alice"})
|
||||
errors = r.json()["errors"]
|
||||
email_error = next((e for e in errors if e["element"] == "email"), None)
|
||||
assert email_error is not None
|
||||
assert email_error["code"] == "required"
|
||||
|
||||
|
||||
class TestFormSubmissionNotFound:
|
||||
def test_unknown_form_id_returns_400(self):
|
||||
r = submit(999999, {"email": "user@example.com"})
|
||||
assert r.status_code == 400
|
||||
|
||||
def test_unknown_form_id_returns_not_found_error(self):
|
||||
r = submit(999999, {"email": "user@example.com"})
|
||||
errors = r.json()["errors"]
|
||||
assert any(e["code"] == "not_found" for e in errors)
|
||||
Reference in New Issue
Block a user