| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- import pytest
- import factory
- from collections import namedtuple
- from wtforms import Form, fields
- from pydantic_form import PydanticForm
- from pydantic import BaseModel, ValidationError
- from pydantic.types import StrictStr
- from typing import List
- DataFactories = namedtuple(
- "DataFactories",
- ['valid', 'bad', 'missing', 'mixed']
- )
- ExpectedErrors = namedtuple(
- "ExpectedErrors",
- ['valid', 'bad', 'missing', 'mixed']
- )
- Scenario = namedtuple(
- "ScenarioClasses",
- ['form', 'schema', 'keys', 'data_factory', 'errors']
- )
- Keys = namedtuple(
- "Keys",
- ["class_", "instance"]
- )
- @pytest.fixture
- def scenario(request):
- return request.getfixturevalue(request.param)
- class MissingDataFactory(factory.Factory):
- class Meta:
- model = dict
- # Simplest case
- simple_keys = Keys(
- [('integer',), ('string',), ('float',)],
- [('integer',), ('string',), ('float',)]
- )
- class SimpleSchema(BaseModel):
- integer: int
- string: StrictStr
- float: float
- class SimpleWTForm(Form):
- _schema = SimpleSchema
- integer = fields.IntegerField()
- string = fields.StringField()
- float = fields.FloatField()
- class SimpleForm(SimpleWTForm, PydanticForm):
- _schema = SimpleSchema
- class SimpleDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pyint')
- string = factory.Faker('pystr')
- float = factory.Faker('pyfloat')
- class SimpleBadDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pystr')
- string = factory.Faker('pyint')
- float = factory.Faker('pystr')
- class SimpleMixedDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pyint')
- float = factory.Faker('pystr')
- simple_data_factories = DataFactories(
- SimpleDataFactory,
- SimpleBadDataFactory,
- MissingDataFactory,
- SimpleMixedDataFactory
- )
- simple_expected_errors = ExpectedErrors(
- {},
- {
- 'integer': 'type_error.integer',
- 'string': 'type_error.str',
- 'float': 'type_error.float'
- },
- {
- 'integer': 'value_error.missing',
- 'string': 'value_error.missing',
- 'float': 'value_error.missing',
- },
- {
- 'string': 'value_error.missing',
- 'float': 'type_error.float'
- }
- )
- @pytest.fixture
- def scenario_simple():
- return Scenario(
- SimpleForm,
- SimpleSchema,
- simple_keys,
- simple_data_factories,
- simple_expected_errors
- )
- # Simple list case
- simple_list_keys = Keys(
- [('integers',), ('strings',), ('floats',)],
- [
- ('integers', 0), ('integers', 1),
- ('strings', 0), ('strings', 1),
- ('floats', 0), ('floats', 1)
- ],
- )
- class SimpleListSchema(BaseModel):
- integers: List[int]
- strings: List[StrictStr]
- floats: List[float]
- class SimpleListWTForm(Form):
- _schema = SimpleSchema
- integers = fields.FieldList(fields.IntegerField(), min_entries=2)
- strings = fields.FieldList(fields.StringField(), min_entries=2)
- floats = fields.FieldList(fields.FloatField(), min_entries=2)
- class SimpleListForm(SimpleListWTForm, PydanticForm):
- _schema = SimpleListSchema
- class SimpleListDataFactory(factory.Factory):
- class Meta:
- model = dict
- integers = factory.List([factory.Faker('pyint'), factory.Faker('pyint')])
- strings = factory.List([factory.Faker('pystr'), factory.Faker('pystr')])
- floats = factory.List([factory.Faker('pyfloat'), factory.Faker('pyfloat')])
- class SimpleListBadDataFactory(factory.Factory):
- class Meta:
- model = dict
- integers = factory.List([factory.Faker('pystr'), factory.Faker('pystr')])
- strings = factory.List([factory.Faker('pyint'), factory.Faker('pyint')])
- floats = factory.List([factory.Faker('pystr'), factory.Faker('pystr')])
- class SimpleListMixedDataFactory(factory.Factory):
- class Meta:
- model = dict
- integers = factory.List([factory.Faker('pyint'), factory.Faker('pyint')])
- floats = factory.List([factory.Faker('pystr'), factory.Faker('pystr')])
- simple_list_data_factories = DataFactories(
- SimpleListDataFactory,
- SimpleListBadDataFactory,
- MissingDataFactory,
- SimpleListMixedDataFactory
- )
- simple_list_expected_errors = ExpectedErrors(
- {},
- {
- 'integers': ['type_error.integer', 'type_error.integer'],
- 'strings': ['type_error.str', 'type_error.str'],
- 'floats': ['type_error.float', 'type_error.float']
- },
- {
- 'integers': 'value_error.missing',
- 'strings': 'value_error.missing',
- 'floats': 'value_error.missing'
- },
- {
- 'strings': 'value_error.missing',
- 'floats': ['type_error.float', 'type_error.float']
- }
- )
- @pytest.fixture
- def scenario_simple_list():
- return Scenario(
- SimpleListForm,
- SimpleListSchema,
- simple_list_keys,
- simple_list_data_factories,
- simple_list_expected_errors
- )
- # Case with one level of nesting
- nested_keys = Keys(
- [('integer',), ('nested', 'integer'), ('nested', 'string'), ('nested', 'float',)],
- [('integer',), ('nested', 'integer'), ('nested', 'string'), ('nested', 'float',)]
- )
- class NestedSchema(BaseModel):
- integer: int
- nested: SimpleSchema
- class NestedWTForm(Form):
- _schema = NestedSchema
- integer = fields.IntegerField()
- nested = fields.FormField(SimpleForm)
- class NestedForm(NestedWTForm, PydanticForm):
- _schema = NestedSchema
- class NestedDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pyint')
- nested = factory.SubFactory(SimpleDataFactory)
- class NestedBadDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pystr')
- nested = factory.SubFactory(SimpleBadDataFactory)
- class NestedMixedDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pyint')
- nested = factory.SubFactory(SimpleMixedDataFactory)
- nested_data_factories = DataFactories(
- NestedDataFactory,
- NestedBadDataFactory,
- MissingDataFactory,
- NestedMixedDataFactory
- )
- nested_expected_errors = ExpectedErrors(
- {},
- {
- 'integer': 'type_error.integer',
- 'nested': simple_expected_errors.bad
- },
- {
- 'integer': 'value_error.missing',
- 'nested': 'value_error.missing',
- },
- {
- 'nested': simple_expected_errors.mixed
- },
- )
- @pytest.fixture
- def scenario_nested():
- return Scenario(
- NestedForm,
- NestedSchema,
- nested_keys,
- nested_data_factories,
- nested_expected_errors
- )
- # Case with one level of nesting inside a list
- nested_list_keys = Keys(
- [('integer',), ('nested_list', 'integer'), ('nested_list', 'string'), ('nested_list', 'float')],
- [
- ('integer',),
- ('nested_list', 0, 'integer'),
- ('nested_list', 1, 'integer'),
- ('nested_list', 0, 'string'),
- ('nested_list', 1, 'string'),
- ('nested_list', 0, 'float'),
- ('nested_list', 1, 'float')
- ]
- )
- class NestedListSchema(BaseModel):
- integer: int
- nested_list: List[SimpleSchema]
- class NestedListWTForm(Form):
- _schema = NestedListSchema
- integer = fields.IntegerField()
- nested_list = fields.FieldList(fields.FormField(SimpleForm), min_entries=2)
- class NestedListForm(NestedListWTForm, PydanticForm):
- _schema = NestedListSchema
- class NestedListDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pyint')
- nested_list = factory.List([
- factory.SubFactory(SimpleDataFactory),
- factory.SubFactory(SimpleDataFactory)
- ])
- class NestedListBadDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pystr')
- nested_list = factory.List([
- factory.SubFactory(SimpleBadDataFactory),
- factory.SubFactory(SimpleBadDataFactory)
- ])
- class NestedListMixedDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pyint')
- nested_list = factory.List([
- factory.SubFactory(SimpleMixedDataFactory),
- factory.SubFactory(SimpleMixedDataFactory)
- ])
- nested_list_data_factories = DataFactories(
- NestedListDataFactory,
- NestedListBadDataFactory,
- MissingDataFactory,
- NestedListMixedDataFactory
- )
- nested_list_expected_errors = ExpectedErrors(
- {},
- {
- 'integer': 'type_error.integer',
- 'nested_list': [
- {'integer': 'type_error.integer'},
- {'string': 'type_error.str'}
- ],
- },
- {
- 'integer': 'value_error.missing',
- 'nested_list': 'value_error.missing',
- },
- {
- 'nested_list': [
- simple_expected_errors.mixed
- ]
- },
- )
- @pytest.fixture
- def scenario_nested_list():
- return Scenario(
- NestedListForm,
- NestedListSchema,
- nested_list_keys,
- nested_list_data_factories,
- nested_list_expected_errors
- )
- # Case with two levels of nesting
- double_nested_keys = Keys([
- ('integer',),
- ('double_nested', 'integer'),
- ('double_nested', 'nested', 'integer'),
- ('double_nested', 'nested', 'string'),
- ('double_nested', 'nested', 'float')
- ],
- [
- ('integer',),
- ('double_nested', 'integer'),
- ('double_nested', 'nested', 'integer'),
- ('double_nested', 'nested', 'string'),
- ('double_nested', 'nested', 'float')
- ]
- )
- class DoubleNestedSchema(BaseModel):
- integer: int
- double_nested: NestedSchema
- class DoubleNestedWTForm(Form):
- _schema = DoubleNestedSchema
- integer = fields.IntegerField()
- double_nested = fields.FormField(NestedWTForm)
- class DoubleNestedForm(DoubleNestedWTForm, PydanticForm):
- _schema = DoubleNestedSchema
- double_nested = fields.FormField(NestedForm)
- class DoubleNestedDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pyint')
- double_nested = factory.SubFactory(NestedDataFactory)
- class DoubleNestedBadDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pystr')
- double_nested = factory.SubFactory(NestedBadDataFactory)
- class DoubleNestedMixedDataFactory(factory.Factory):
- class Meta:
- model = dict
- integer = factory.Faker('pyint')
- double_nested = factory.SubFactory(NestedMixedDataFactory)
- double_nested_data_factories = DataFactories(
- DoubleNestedDataFactory,
- DoubleNestedBadDataFactory,
- MissingDataFactory,
- DoubleNestedMixedDataFactory
- )
- double_nested_expected_errors = ExpectedErrors(
- {},
- {
- 'integer': 'type_error.integer',
- 'double_nested': {
- 'integer': 'type_error.integer',
- 'nested': simple_expected_errors.bad
- }
- },
- {
- 'integer': 'value_error.missing',
- 'double_nested': 'value_error.missing',
- },
- {
- 'double_nested': {
- 'nested': simple_expected_errors.mixed
- }
- },
- )
- @pytest.fixture
- def scenario_double_nested():
- return Scenario(
- DoubleNestedForm,
- DoubleNestedSchema,
- double_nested_keys,
- double_nested_data_factories,
- double_nested_expected_errors
- )
|