mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(ceo-approve): require substantive notes; panel collects them
ceo-approve was bound to QANotes (notes required), so the panel's
one-click approve (posts {}) 422'd. The wrong fix is to waive notes —
that empties the audit record for a production merge. Instead require
substantive notes (>=20 chars, mirroring pass-qa) and make the panel
COLLECT them: a new CeoApproveDialog (mirrors the reject dialog) gates
the 'Approve & Merge' action, and the dashboard approval-queue enforces
the same before POSTing. The CEO sign-off note is now always captured.
This commit is contained in:
@@ -2434,7 +2434,7 @@ async def test_ceo_approve_service_returns_none(ceo_client: dict) -> None:
|
||||
await ceo_client["db"].flush()
|
||||
response = await ceo_client["client"].post(
|
||||
f"/api/tasks/{task.id}/ceo-approve",
|
||||
json={"notes": "approved"},
|
||||
json={"notes": "Reviewed and approved for production release."},
|
||||
headers=_HDR,
|
||||
)
|
||||
assert response.status_code == HTTPStatus.BAD_REQUEST
|
||||
@@ -2452,12 +2452,31 @@ async def test_ceo_approve_success(ceo_client: dict) -> None:
|
||||
mock_factory.return_value = instance
|
||||
response = await ceo_client["client"].post(
|
||||
f"/api/tasks/{task.id}/ceo-approve",
|
||||
json={"notes": "approved"},
|
||||
json={"notes": "Verified against all acceptance criteria; approved."},
|
||||
headers=_HDR,
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ceo_approve_without_notes_rejected(ceo_client: dict) -> None:
|
||||
"""Audit: a CEO approval with no/thin notes leaves no record of WHY the
|
||||
work shipped, so the endpoint must reject it (>= 20 chars required). The
|
||||
panel collects the note before POSTing."""
|
||||
task = _seed_task_ceo(ceo_client)
|
||||
await ceo_client["db"].flush()
|
||||
for body in ({}, {"notes": ""}, {"notes": "lgtm"}):
|
||||
response = await ceo_client["client"].post(
|
||||
f"/api/tasks/{task.id}/ceo-approve",
|
||||
json=body,
|
||||
headers=_HDR,
|
||||
)
|
||||
assert response.status_code in (
|
||||
HTTPStatus.BAD_REQUEST,
|
||||
HTTPStatus.UNPROCESSABLE_ENTITY,
|
||||
), (body, response.status_code)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ceo_reject_task_not_found(ceo_client: dict) -> None:
|
||||
response = await ceo_client["client"].post(
|
||||
|
||||
Reference in New Issue
Block a user