mirror of
https://github.com/Sea-Haven-Industries/meal-order-manager.git
synced 2026-09-30 04:13:12 +00:00
fix(api): document 4xx and reject invalid form-status weeks (DEV-289)
Health, form-status, and roster document 400. form-status now maps current and returns 400 for a week that is not current or YYYY-WNN. Redocly treats 302 as a success response, matching the portal. Co-authored-by: Adam Moussa <amoussa1229@users.noreply.github.com>
This commit is contained in:
parent
198269db5b
commit
fbd9444a36
5 changed files with 72 additions and 8 deletions
|
|
@ -1,7 +1,29 @@
|
|||
# Same Redocly recommended ruleset as internal-portal (DEV-223 / DEV-289).
|
||||
# Login-style redirects succeed with 302. Recommended only counts 2XX.
|
||||
extends:
|
||||
- recommended
|
||||
|
||||
rules:
|
||||
operation-2xx-response: off
|
||||
rule/operation-2xx-or-3xx-response:
|
||||
subject:
|
||||
type: Responses
|
||||
message: Operation must define a 2XX or 3XX response.
|
||||
severity: warn
|
||||
assertions:
|
||||
requireAny:
|
||||
- "200"
|
||||
- "201"
|
||||
- "202"
|
||||
- "204"
|
||||
- "301"
|
||||
- "302"
|
||||
- "303"
|
||||
- "307"
|
||||
- "308"
|
||||
- "2XX"
|
||||
- "3XX"
|
||||
|
||||
apis:
|
||||
meals@v1:
|
||||
root: openapi.yaml
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Health"
|
||||
"400":
|
||||
$ref: "#/components/responses/StringError"
|
||||
|
||||
/api/menu/{week}:
|
||||
get:
|
||||
|
|
@ -82,6 +84,8 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/FormStatus"
|
||||
"400":
|
||||
$ref: "#/components/responses/StringError"
|
||||
|
||||
/api/submit-order:
|
||||
post:
|
||||
|
|
@ -260,6 +264,8 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/FormRoster"
|
||||
"400":
|
||||
$ref: "#/components/responses/StringError"
|
||||
|
||||
/api/publish/settings:
|
||||
get:
|
||||
|
|
|
|||
|
|
@ -279,15 +279,20 @@ def lambda_handler(event, context):
|
|||
return response(405, {"error": "Method not allowed"})
|
||||
|
||||
|
||||
def handle_menu(event):
|
||||
"""Return the published menu in the portal's public MenuPayload shape."""
|
||||
def _week_from_path(event):
|
||||
requested_week = (event.get("pathParameters") or {}).get("week", "")
|
||||
if requested_week == "current":
|
||||
week = current_week()
|
||||
elif re.fullmatch(r"\d{4}-W\d{2}", requested_week):
|
||||
week = requested_week
|
||||
else:
|
||||
return response(400, {"error": "week path param must be current or YYYY-WNN"})
|
||||
return current_week(), None
|
||||
if re.fullmatch(r"\d{4}-W\d{2}", requested_week):
|
||||
return requested_week, None
|
||||
return None, response(400, {"error": "week path param must be current or YYYY-WNN"})
|
||||
|
||||
|
||||
def handle_menu(event):
|
||||
"""Return the published menu in the portal's public MenuPayload shape."""
|
||||
week, error = _week_from_path(event)
|
||||
if error is not None:
|
||||
return error
|
||||
|
||||
menu = get_menu(week)
|
||||
if menu is None:
|
||||
|
|
@ -623,7 +628,9 @@ def handle_my_orders(event):
|
|||
|
||||
|
||||
def handle_form_status(event):
|
||||
week = event.get("pathParameters", {}).get("week", current_week())
|
||||
week, error = _week_from_path(event)
|
||||
if error is not None:
|
||||
return error
|
||||
status = get_form_status(week)
|
||||
result = {"week": week, "status": status}
|
||||
if status == "closed":
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ def test_openapi_uses_redocly_recommended():
|
|||
ci = (ROOT / ".github" / "workflows" / "ci.yml").read_text()
|
||||
assert "extends:" in redocly
|
||||
assert "- recommended" in redocly
|
||||
assert "operation-2xx-response: off" in redocly
|
||||
assert "rule/operation-2xx-or-3xx-response" in redocly
|
||||
assert "root: openapi.yaml" in redocly
|
||||
assert '"openapi:lint"' in package
|
||||
assert '"@redocly/cli": "2.52.1"' in package
|
||||
|
|
|
|||
|
|
@ -1446,6 +1446,33 @@ def test_form_status_open(mock_week, mock_status):
|
|||
assert "reopen_at" not in body, "reopen_at should NOT be present when form is open"
|
||||
|
||||
|
||||
@patch("submit_order_handler.get_form_status", return_value="open")
|
||||
@patch("submit_order_handler.current_week", return_value="2026-W20")
|
||||
def test_form_status_current_maps_to_current_week(mock_week, mock_status):
|
||||
from submit_order_handler import lambda_handler
|
||||
|
||||
event = _make_event(
|
||||
method="GET", path="/form-status/current", path_parameters={"week": "current"}
|
||||
)
|
||||
status, body = _parse_response(lambda_handler(event, None))
|
||||
assert status == 200, f"Expected 200, got {status}: {body}"
|
||||
assert body["week"] == "2026-W20"
|
||||
mock_status.assert_called_once_with("2026-W20")
|
||||
|
||||
|
||||
@patch("submit_order_handler.get_form_status")
|
||||
def test_form_status_rejects_invalid_week(mock_status):
|
||||
from submit_order_handler import lambda_handler
|
||||
|
||||
event = _make_event(
|
||||
method="GET", path="/form-status/nope", path_parameters={"week": "nope"}
|
||||
)
|
||||
status, body = _parse_response(lambda_handler(event, None))
|
||||
assert status == 400, f"Expected 400, got {status}: {body}"
|
||||
assert "week path param" in body["error"]
|
||||
mock_status.assert_not_called()
|
||||
|
||||
|
||||
@patch("submit_order_handler.get_form_status", return_value="closed")
|
||||
@patch("submit_order_handler.current_week", return_value="2026-W20")
|
||||
def test_form_status_closed_reopen_at(mock_week, mock_status):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue