Skip to content

Commit 08600bf

Browse files
accept json string for reference calls
1 parent 9155ad1 commit 08600bf

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

src/models/flight.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import json
12
from typing import Optional, Self, ClassVar, Literal
23

3-
from pydantic import BaseModel, Field
4+
from pydantic import BaseModel, Field, field_validator
45
from src.models.interface import ApiBaseModel
56
from src.models.rocket import RocketModel
67
from src.models.environment import EnvironmentModel
@@ -112,3 +113,13 @@ class FlightWithReferencesRequest(BaseModel):
112113
environment_id: str
113114
rocket_id: str
114115
flight: FlightPartialModel
116+
117+
@field_validator('flight', mode='before')
118+
@classmethod
119+
def _coerce_flight(cls, value):
120+
if isinstance(value, str):
121+
try:
122+
value = json.loads(value)
123+
except json.JSONDecodeError as exc:
124+
raise ValueError('Invalid JSON for flight payload') from exc
125+
return value

src/models/rocket.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import json
12
from typing import Optional, Tuple, List, Union, Self, ClassVar, Literal
23

3-
from pydantic import BaseModel, Field
4+
from pydantic import BaseModel, Field, field_validator
45
from src.models.interface import ApiBaseModel
56
from src.models.motor import MotorModel
67
from src.models.sub.aerosurfaces import (
@@ -103,3 +104,13 @@ class RocketWithMotorReferenceRequest(BaseModel):
103104

104105
motor_id: str
105106
rocket: RocketPartialModel
107+
108+
@field_validator('rocket', mode='before')
109+
@classmethod
110+
def _coerce_rocket(cls, value):
111+
if isinstance(value, str):
112+
try:
113+
value = json.loads(value)
114+
except json.JSONDecodeError as exc:
115+
raise ValueError('Invalid JSON for rocket payload') from exc
116+
return value

tests/unit/test_routes/test_flights_route.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,21 @@ def test_create_flight_from_references(
104104
)
105105

106106

107+
def test_create_flight_from_references_with_string_payload(
108+
stub_flight_reference_payload, mock_controller_instance
109+
):
110+
payload = copy.deepcopy(stub_flight_reference_payload)
111+
payload['flight'] = json.dumps(payload['flight'])
112+
mock_controller_instance.create_flight_from_references = AsyncMock(
113+
return_value=FlightCreated(flight_id='123')
114+
)
115+
response = client.post('/flights/from-references', json=payload)
116+
assert response.status_code == 201
117+
mock_controller_instance.create_flight_from_references.assert_called_once_with(
118+
FlightWithReferencesRequest(**payload)
119+
)
120+
121+
107122
def test_create_flight_from_references_not_found(
108123
stub_flight_reference_payload, mock_controller_instance
109124
):
@@ -247,6 +262,21 @@ def test_update_flight_from_references(
247262
)
248263

249264

265+
def test_update_flight_from_references_with_string_payload(
266+
stub_flight_reference_payload, mock_controller_instance
267+
):
268+
payload = copy.deepcopy(stub_flight_reference_payload)
269+
payload['flight'] = json.dumps(payload['flight'])
270+
mock_controller_instance.update_flight_from_references = AsyncMock(
271+
return_value=None
272+
)
273+
response = client.put('/flights/123/from-references', json=payload)
274+
assert response.status_code == 204
275+
mock_controller_instance.update_flight_from_references.assert_called_once_with(
276+
'123', FlightWithReferencesRequest(**payload)
277+
)
278+
279+
250280
def test_update_flight_from_references_not_found(
251281
stub_flight_reference_payload, mock_controller_instance
252282
):

tests/unit/test_routes/test_rockets_route.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,21 @@ def test_create_rocket_from_motor_reference(
129129
)
130130

131131

132+
def test_create_rocket_from_motor_reference_with_string_payload(
133+
stub_rocket_reference_payload, mock_controller_instance
134+
):
135+
payload = copy.deepcopy(stub_rocket_reference_payload)
136+
payload['rocket'] = json.dumps(payload['rocket'])
137+
mock_controller_instance.create_rocket_from_motor_reference = AsyncMock(
138+
return_value=RocketCreated(rocket_id='123')
139+
)
140+
response = client.post('/rockets/from-motor-reference', json=payload)
141+
assert response.status_code == 201
142+
mock_controller_instance.create_rocket_from_motor_reference.assert_called_once_with(
143+
RocketWithMotorReferenceRequest(**payload)
144+
)
145+
146+
132147
def test_create_rocket_from_motor_reference_not_found(
133148
stub_rocket_reference_payload, mock_controller_instance
134149
):
@@ -447,6 +462,21 @@ def test_update_rocket_from_motor_reference(
447462
)
448463

449464

465+
def test_update_rocket_from_motor_reference_with_string_payload(
466+
stub_rocket_reference_payload, mock_controller_instance
467+
):
468+
payload = copy.deepcopy(stub_rocket_reference_payload)
469+
payload['rocket'] = json.dumps(payload['rocket'])
470+
mock_controller_instance.update_rocket_from_motor_reference = AsyncMock(
471+
return_value=None
472+
)
473+
response = client.put('/rockets/123/from-motor-reference', json=payload)
474+
assert response.status_code == 204
475+
mock_controller_instance.update_rocket_from_motor_reference.assert_called_once_with(
476+
'123', RocketWithMotorReferenceRequest(**payload)
477+
)
478+
479+
450480
def test_update_rocket_from_motor_reference_not_found(
451481
stub_rocket_reference_payload, mock_controller_instance
452482
):

0 commit comments

Comments
 (0)