diff options
| author | natsuoto <[email protected]> | 2026-07-15 16:56:09 +0530 |
|---|---|---|
| committer | natsuoto <[email protected]> | 2026-07-15 16:56:09 +0530 |
| commit | 93371d459ad47a46310f729950ec383372cd2706 (patch) | |
| tree | a669070a6a3225cc7a2e27ffc1a6e3d3807bee10 /tests | |
| parent | 433d41bf5887e61cc570a874e244e226c25b8a41 (diff) | |
| download | edify-93371d459ad47a46310f729950ec383372cd2706.tar.xz edify-93371d459ad47a46310f729950ec383372cd2706.zip | |
feat(integrations): edify[pydantic], edify[fastapi], edify[django] with deferred imports + Sphinx autodoc section + per-extra CI install verification
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/integrations/django.test.py | 60 | ||||
| -rw-r--r-- | tests/integrations/fastapi.test.py | 75 | ||||
| -rw-r--r-- | tests/integrations/pydantic.test.py | 67 |
3 files changed, 202 insertions, 0 deletions
diff --git a/tests/integrations/django.test.py b/tests/integrations/django.test.py new file mode 100644 index 0000000..11aa835 --- /dev/null +++ b/tests/integrations/django.test.py @@ -0,0 +1,60 @@ +"""Tests for :mod:`edify.integrations.django`.""" + +import sys + +import pytest + +from edify import Pattern +from edify.errors.integration import MissingIntegrationDependencyError +from edify.integrations.django import pattern_validator + +_DIGITS_PATTERN = Pattern().start_of_input().one_or_more().digit().end_of_input() + + +def test_pattern_validator_returns_a_regex_validator_pinned_to_the_pattern_source(): + from django.core.validators import RegexValidator + + validator = pattern_validator(_DIGITS_PATTERN) + assert isinstance(validator, RegexValidator) + assert validator.regex.pattern == _DIGITS_PATTERN.to_regex_string() + + +def test_pattern_validator_accepts_matching_input_without_raising(): + validator = pattern_validator(_DIGITS_PATTERN) + validator("42") + + +def test_pattern_validator_raises_django_validation_error_on_non_matching_input(): + from django.core.exceptions import ValidationError + + validator = pattern_validator(_DIGITS_PATTERN) + with pytest.raises(ValidationError): + validator("abc") + + +def test_pattern_validator_carries_the_default_error_message_reproducing_the_regex(): + validator = pattern_validator(_DIGITS_PATTERN) + assert _DIGITS_PATTERN.to_regex_string() in validator.message + + +def test_pattern_validator_accepts_an_override_message_and_code(): + validator = pattern_validator(_DIGITS_PATTERN, message="digits only", code="bad_digits") + assert validator.message == "digits only" + assert validator.code == "bad_digits" + + +def test_pattern_validator_raises_missing_integration_when_django_absent(monkeypatch): + monkeypatch.setitem(sys.modules, "django", None) + monkeypatch.setitem(sys.modules, "django.core", None) + monkeypatch.setitem(sys.modules, "django.core.validators", None) + with pytest.raises(MissingIntegrationDependencyError, match="django"): + pattern_validator(_DIGITS_PATTERN) + + +def test_missing_integration_error_carries_the_actionable_install_hint(monkeypatch): + monkeypatch.setitem(sys.modules, "django", None) + monkeypatch.setitem(sys.modules, "django.core", None) + monkeypatch.setitem(sys.modules, "django.core.validators", None) + with pytest.raises(MissingIntegrationDependencyError) as excinfo: + pattern_validator(_DIGITS_PATTERN) + assert "pip install edify[django]" in str(excinfo.value) diff --git a/tests/integrations/fastapi.test.py b/tests/integrations/fastapi.test.py new file mode 100644 index 0000000..636d78b --- /dev/null +++ b/tests/integrations/fastapi.test.py @@ -0,0 +1,75 @@ +"""Tests for :mod:`edify.integrations.fastapi`.""" + +import sys + +import pytest + +from edify import Pattern +from edify.errors.integration import MissingIntegrationDependencyError +from edify.integrations.fastapi import pattern_path, pattern_query + +_UUID_PATTERN = ( + Pattern() + .start_of_input() + .exactly(8) + .any_of() + .range("0", "9") + .range("a", "f") + .end() + .end_of_input() +) + + +def test_pattern_query_returns_a_fastapi_query_pinned_to_the_pattern_regex(): + query_default = pattern_query(_UUID_PATTERN) + fastapi_module = _fastapi() + assert type(query_default).__name__ == "Query" or isinstance( + query_default, fastapi_module.params.Query + ) + + +def test_pattern_query_forwards_extra_kwargs_to_fastapi_query(): + query_with_description = pattern_query(_UUID_PATTERN, description="prefix") + assert query_with_description.description == "prefix" + + +def test_pattern_query_default_differs_from_an_explicit_default(): + without_default = pattern_query(_UUID_PATTERN) + with_default = pattern_query(_UUID_PATTERN, default="deadbeef") + assert without_default.default != with_default.default + + +def test_pattern_query_respects_an_explicit_default_kwarg(): + query_with_default = pattern_query(_UUID_PATTERN, default="deadbeef") + assert query_with_default.default == "deadbeef" + + +def test_pattern_path_returns_a_fastapi_path_pinned_to_the_pattern_regex(): + path_default = pattern_path(_UUID_PATTERN) + fastapi_module = _fastapi() + assert isinstance(path_default, fastapi_module.params.Path) + + +def test_pattern_query_raises_missing_integration_when_fastapi_absent(monkeypatch): + monkeypatch.setitem(sys.modules, "fastapi", None) + with pytest.raises(MissingIntegrationDependencyError, match="fastapi"): + pattern_query(_UUID_PATTERN) + + +def test_pattern_path_raises_missing_integration_when_fastapi_absent(monkeypatch): + monkeypatch.setitem(sys.modules, "fastapi", None) + with pytest.raises(MissingIntegrationDependencyError, match="fastapi"): + pattern_path(_UUID_PATTERN) + + +def test_missing_integration_error_carries_the_actionable_install_hint(monkeypatch): + monkeypatch.setitem(sys.modules, "fastapi", None) + with pytest.raises(MissingIntegrationDependencyError) as excinfo: + pattern_query(_UUID_PATTERN) + assert "pip install edify[fastapi]" in str(excinfo.value) + + +def _fastapi(): + import fastapi + + return fastapi diff --git a/tests/integrations/pydantic.test.py b/tests/integrations/pydantic.test.py new file mode 100644 index 0000000..da0ff2a --- /dev/null +++ b/tests/integrations/pydantic.test.py @@ -0,0 +1,67 @@ +"""Tests for :mod:`edify.integrations.pydantic`.""" + +import sys + +import pytest + +from edify import Pattern +from edify.errors.integration import MissingIntegrationDependencyError +from edify.integrations.pydantic import pattern_field, pattern_validator + +_DIGITS_PATTERN = Pattern().start_of_input().one_or_more().digit().end_of_input() + + +def test_pattern_validator_accepts_a_matching_string_and_returns_it_unchanged(): + validate = pattern_validator(_DIGITS_PATTERN) + assert validate("42") == "42" + + +def test_pattern_validator_raises_value_error_on_non_matching_input(): + validate = pattern_validator(_DIGITS_PATTERN) + with pytest.raises(ValueError, match="does not match"): + validate("abc") + + +def test_pattern_field_returns_an_annotated_str_type_for_pydantic_models(): + from typing import get_args, get_type_hints + + from pydantic import AfterValidator, BaseModel + + class Payload(BaseModel): + value: pattern_field(_DIGITS_PATTERN) + + resolved = get_type_hints(Payload, include_extras=True)["value"] + metadata = get_args(resolved)[1:] + assert any(isinstance(item, AfterValidator) for item in metadata) + + +def test_pattern_field_is_accepted_by_pydantic_model_validation(): + from pydantic import BaseModel, ValidationError + + class Payload(BaseModel): + value: pattern_field(_DIGITS_PATTERN) + + assert Payload(value="42").value == "42" + with pytest.raises(ValidationError): + Payload(value="abc") + + +def test_pattern_validator_raises_missing_integration_when_pydantic_absent(monkeypatch): + monkeypatch.setitem(sys.modules, "pydantic", None) + with pytest.raises(MissingIntegrationDependencyError, match="pydantic"): + pattern_validator(_DIGITS_PATTERN) + + +def test_pattern_field_raises_missing_integration_when_pydantic_absent(monkeypatch): + monkeypatch.setitem(sys.modules, "pydantic", None) + with pytest.raises(MissingIntegrationDependencyError, match="pydantic"): + pattern_field(_DIGITS_PATTERN) + + +def test_missing_integration_error_carries_the_actionable_install_hint(monkeypatch): + monkeypatch.setitem(sys.modules, "pydantic", None) + with pytest.raises(MissingIntegrationDependencyError) as excinfo: + pattern_validator(_DIGITS_PATTERN) + text = str(excinfo.value) + assert "pip install edify[pydantic]" in text + assert "= note:" in text |
