|
1 |
| - |
2 |
| -from typing import Any |
3 | 1 | import pytest
|
4 | 2 | from end_to_end_tests.end_to_end_test_helpers import (
|
5 |
| - assert_bad_schema_warning, |
6 | 3 | assert_model_decode_encode,
|
7 |
| - inline_spec_should_cause_warnings, |
8 |
| - inline_spec_should_fail, |
9 | 4 | with_generated_code_import,
|
10 | 5 | with_generated_client_fixture,
|
11 | 6 | with_generated_code_imports,
|
@@ -133,52 +128,89 @@ def test_invalid_int(self, MyModel):
|
133 | 128 | MyModel.from_dict({"mustBeThirty": 29})
|
134 | 129 |
|
135 | 130 |
|
136 |
| -class TestEnumAndConstInvalidSchemas: |
137 |
| - @pytest.fixture(scope="class") |
138 |
| - def warnings(self): |
139 |
| - return inline_spec_should_cause_warnings( |
| 131 | +# The following tests of literal enums use basically the same specs as the tests above, but |
| 132 | +# the "literal_enums" option is enabled in the test configuration. |
| 133 | + |
| 134 | +@with_generated_client_fixture( |
140 | 135 | """
|
141 | 136 | components:
|
142 | 137 | schemas:
|
143 |
| - WithBadDefaultValue: |
144 |
| - enum: ["A"] |
145 |
| - default: "B" |
146 |
| - WithBadDefaultType: |
147 |
| - enum: ["A"] |
148 |
| - default: 123 |
149 |
| - WithMixedTypes: |
150 |
| - enum: ["A", 1] |
151 |
| - WithUnsupportedType: |
152 |
| - enum: [1.4, 1.5] |
153 |
| - DefaultNotMatchingConst: |
154 |
| - const: "aaa" |
155 |
| - default: "bbb" |
156 |
| -""" |
157 |
| - ) |
158 |
| - |
159 |
| - def test_enum_bad_default_value(self, warnings): |
160 |
| - assert_bad_schema_warning(warnings, "WithBadDefaultValue", "Value B is not valid") |
161 |
| - |
162 |
| - def test_enum_bad_default_type(self, warnings): |
163 |
| - assert_bad_schema_warning(warnings, "WithBadDefaultType", "Cannot convert 123 to enum") |
164 |
| - |
165 |
| - def test_enum_mixed_types(self, warnings): |
166 |
| - assert_bad_schema_warning(warnings, "WithMixedTypes", "Enum values must all be the same type") |
| 138 | + MyEnum: |
| 139 | + type: string |
| 140 | + enum: ["a", "A"] |
| 141 | + MyIntEnum: |
| 142 | + type: integer |
| 143 | + enum: [2, 3] |
| 144 | + MyEnumIncludingNull: |
| 145 | + type: ["string", "null"] |
| 146 | + enum: ["a", "b", null] |
| 147 | + MyNullOnlyEnum: |
| 148 | + enum: [null] |
| 149 | + MyModel: |
| 150 | + properties: |
| 151 | + enumProp: {"$ref": "#/components/schemas/MyEnum"} |
| 152 | + intEnumProp: {"$ref": "#/components/schemas/MyIntEnum"} |
| 153 | + nullableEnumProp: |
| 154 | + oneOf: |
| 155 | + - {"$ref": "#/components/schemas/MyEnum"} |
| 156 | + - type: "null" |
| 157 | + enumIncludingNullProp: {"$ref": "#/components/schemas/MyEnumIncludingNull"} |
| 158 | + nullOnlyEnumProp: {"$ref": "#/components/schemas/MyNullOnlyEnum"} |
| 159 | + inlineEnumProp: |
| 160 | + type: string |
| 161 | + enum: ["a", "b"] |
| 162 | +""", |
| 163 | + config=""" |
| 164 | +literal_enums: true |
| 165 | +""", |
| 166 | +) |
| 167 | +@with_generated_code_import(".models.MyModel") |
| 168 | +class TestLiteralEnums: |
| 169 | + def test_enum_prop(self, MyModel): |
| 170 | + assert_model_decode_encode(MyModel, {"enumProp": "a"}, MyModel(enum_prop="a")) |
| 171 | + assert_model_decode_encode(MyModel, {"enumProp": "A"}, MyModel(enum_prop="A")) |
| 172 | + assert_model_decode_encode(MyModel, {"intEnumProp": 2}, MyModel(int_enum_prop=2)) |
| 173 | + assert_model_decode_encode(MyModel, {"inlineEnumProp": "a"}, MyModel(inline_enum_prop="a")) |
| 174 | + |
| 175 | + def test_enum_prop_type(self, MyModel): |
| 176 | + assert MyModel.from_dict({"enumProp": "a"}).enum_prop.__class__ is str |
| 177 | + assert MyModel.from_dict({"intEnumProp": 2}).int_enum_prop.__class__ is int |
| 178 | + |
| 179 | + def test_nullable_enum_prop(self, MyModel): |
| 180 | + assert_model_decode_encode(MyModel, {"nullableEnumProp": "B"}, MyModel(nullable_enum_prop="B")) |
| 181 | + assert_model_decode_encode(MyModel, {"nullableEnumProp": None}, MyModel(nullable_enum_prop=None)) |
| 182 | + assert_model_decode_encode(MyModel, {"enumIncludingNullProp": "a"}, MyModel(enum_including_null_prop="a")) |
| 183 | + assert_model_decode_encode(MyModel, {"enumIncludingNullProp": None}, MyModel(enum_including_null_prop=None)) |
| 184 | + assert_model_decode_encode(MyModel, {"nullOnlyEnumProp": None}, MyModel(null_only_enum_prop=None)) |
167 | 185 |
|
168 |
| - def test_enum_unsupported_type(self, warnings): |
169 |
| - assert_bad_schema_warning(warnings, "WithUnsupportedType", "Unsupported enum type") |
| 186 | + def test_invalid_values(self, MyModel): |
| 187 | + with pytest.raises(TypeError): |
| 188 | + MyModel.from_dict({"enumProp": "c"}) |
| 189 | + with pytest.raises(TypeError): |
| 190 | + MyModel.from_dict({"enumProp": 2}) |
| 191 | + with pytest.raises(TypeError): |
| 192 | + MyModel.from_dict({"intEnumProp": 0}) |
| 193 | + with pytest.raises(TypeError): |
| 194 | + MyModel.from_dict({"intEnumProp": "a"}) |
170 | 195 |
|
171 |
| - def test_const_default_not_matching(self, warnings): |
172 |
| - assert_bad_schema_warning(warnings, "DefaultNotMatchingConst", "Invalid value for const") |
173 | 196 |
|
174 |
| - def test_enum_duplicate_values(self): |
175 |
| - # This one currently causes a full generator failure rather than a warning |
176 |
| - result = inline_spec_should_fail( |
| 197 | +@with_generated_client_fixture( |
177 | 198 | """
|
178 | 199 | components:
|
179 | 200 | schemas:
|
180 |
| - WithDuplicateValues: |
181 |
| - enum: ["x", "x"] |
182 |
| -""" |
183 |
| - ) |
184 |
| - assert "Duplicate key X in enum" in str(result.exception) |
| 201 | + MyEnum: |
| 202 | + type: string |
| 203 | + enum: ["a", "A"] |
| 204 | + MyModel: |
| 205 | + properties: |
| 206 | + enumProp: |
| 207 | + allOf: |
| 208 | + - $ref: "#/components/schemas/MyEnum" |
| 209 | + default: A |
| 210 | +""", |
| 211 | + config="literal_enums: true", |
| 212 | +) |
| 213 | +@with_generated_code_import(".models.MyModel") |
| 214 | +class TestLiteralEnumDefaults: |
| 215 | + def test_default_value(self, MyModel): |
| 216 | + assert MyModel().enum_prop == "A" |
0 commit comments