|
7 | 7 | from marshmallow import Schema, fields, validate |
8 | 8 | from packaging.version import Version |
9 | 9 |
|
| 10 | +from apispec.exceptions import APISpecError |
| 11 | + |
10 | 12 | from .schemas import CategorySchema, CustomIntegerField, CustomList, CustomStringField |
11 | 13 | from .utils import build_ref, get_schemas |
12 | 14 |
|
@@ -779,3 +781,105 @@ def test_field2property_examples(spec_fixture): |
779 | 781 | assert res == { |
780 | 782 | "examples": ["foo", "bar"], |
781 | 783 | } |
| 784 | + |
| 785 | + |
| 786 | +class TestField2PropertyTuple: |
| 787 | + @pytest.mark.parametrize("spec_fixture", ("2.0", "3.0.0"), indirect=True) |
| 788 | + def test_tuple_unsupported_openapi_versions(self, spec_fixture): |
| 789 | + field = fields.Tuple([fields.Integer(), fields.String()]) |
| 790 | + with pytest.raises( |
| 791 | + APISpecError, |
| 792 | + match="Tuple field is only supported in OpenAPI 3.1.0 and above.", |
| 793 | + ): |
| 794 | + spec_fixture.openapi.field2property(field) |
| 795 | + |
| 796 | + @pytest.mark.parametrize("spec_fixture", ("3.1.0",), indirect=True) |
| 797 | + def test_tuple_simple(self, spec_fixture): |
| 798 | + field = fields.Tuple([fields.Integer(), fields.String()]) |
| 799 | + res = spec_fixture.openapi.field2property(field) |
| 800 | + assert res == { |
| 801 | + "type": "array", |
| 802 | + "prefixItems": [{"type": "integer"}, {"type": "string"}], |
| 803 | + "items": False, |
| 804 | + } |
| 805 | + |
| 806 | + @pytest.mark.parametrize("spec_fixture", ("3.1.0",), indirect=True) |
| 807 | + def test_tuple_empty(self, spec_fixture): |
| 808 | + field = fields.Tuple([]) |
| 809 | + res = spec_fixture.openapi.field2property(field) |
| 810 | + assert res == { |
| 811 | + "type": "array", |
| 812 | + "prefixItems": [], |
| 813 | + "items": False, |
| 814 | + } |
| 815 | + |
| 816 | + @pytest.mark.parametrize("spec_fixture", ("3.1.0",), indirect=True) |
| 817 | + def test_tuple_nullable(self, spec_fixture): |
| 818 | + field = fields.Tuple([fields.Integer()], allow_none=True) |
| 819 | + res = spec_fixture.openapi.field2property(field) |
| 820 | + assert res == { |
| 821 | + "type": ["array", "null"], |
| 822 | + "prefixItems": [{"type": "integer"}], |
| 823 | + "items": False, |
| 824 | + } |
| 825 | + |
| 826 | + @pytest.mark.parametrize("spec_fixture", ("3.1.0",), indirect=True) |
| 827 | + def test_tuple_length_validator(self, spec_fixture): |
| 828 | + field = fields.Tuple( |
| 829 | + [fields.Integer(), fields.String()], |
| 830 | + validate=validate.Length(equal=2), |
| 831 | + ) |
| 832 | + res = spec_fixture.openapi.field2property(field) |
| 833 | + assert res == { |
| 834 | + "type": "array", |
| 835 | + "prefixItems": [{"type": "integer"}, {"type": "string"}], |
| 836 | + "items": False, |
| 837 | + "minItems": 2, |
| 838 | + "maxItems": 2, |
| 839 | + } |
| 840 | + |
| 841 | + @pytest.mark.parametrize("spec_fixture", ("3.1.0",), indirect=True) |
| 842 | + def test_tuple_dump_only_and_load_only(self, spec_fixture): |
| 843 | + dump_field = fields.Tuple([fields.Integer()], dump_only=True) |
| 844 | + assert spec_fixture.openapi.field2property(dump_field) == { |
| 845 | + "type": "array", |
| 846 | + "prefixItems": [{"type": "integer"}], |
| 847 | + "items": False, |
| 848 | + "readOnly": True, |
| 849 | + } |
| 850 | + |
| 851 | + load_field = fields.Tuple([fields.Integer()], load_only=True) |
| 852 | + assert spec_fixture.openapi.field2property(load_field) == { |
| 853 | + "type": "array", |
| 854 | + "prefixItems": [{"type": "integer"}], |
| 855 | + "items": False, |
| 856 | + "writeOnly": True, |
| 857 | + } |
| 858 | + |
| 859 | + @pytest.mark.parametrize("spec_fixture", ("3.1.0",), indirect=True) |
| 860 | + def test_tuple_metadata(self, spec_fixture): |
| 861 | + field = fields.Tuple( |
| 862 | + [fields.Integer()], |
| 863 | + metadata={"description": "Tuple of coordinates"}, |
| 864 | + ) |
| 865 | + assert spec_fixture.openapi.field2property(field) == { |
| 866 | + "type": "array", |
| 867 | + "prefixItems": [{"type": "integer"}], |
| 868 | + "items": False, |
| 869 | + "description": "Tuple of coordinates", |
| 870 | + } |
| 871 | + |
| 872 | + @pytest.mark.parametrize("spec_fixture", ("3.1.0",), indirect=True) |
| 873 | + def test_tuple_nested(self, spec_fixture): |
| 874 | + field = fields.Tuple([fields.Tuple([fields.Integer()])]) |
| 875 | + assert spec_fixture.openapi.field2property(field) == { |
| 876 | + "type": "array", |
| 877 | + "prefixItems": [ |
| 878 | + { |
| 879 | + "type": "array", |
| 880 | + "prefixItems": [{"type": "integer"}], |
| 881 | + "items": False, |
| 882 | + } |
| 883 | + ], |
| 884 | + "items": False, |
| 885 | + } |
0 commit comments