generated from coulomb/repo-seed
48 lines
1.8 KiB
Python
48 lines
1.8 KiB
Python
import pytest
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_idempotent_progress_post_replays_original_response(client):
|
|
payload = {"event_type": "note", "summary": "first idempotent write", "author": "codex"}
|
|
headers = {"Idempotency-Key": "test-progress-key", "X-StateHub-Source-Agent": "pytest"}
|
|
|
|
first = await client.post("/progress/", json=payload, headers=headers)
|
|
assert first.status_code in {200, 201}
|
|
first_body = first.json()
|
|
|
|
second = await client.post("/progress/", json=dict(reversed(list(payload.items()))), headers=headers)
|
|
assert second.status_code == first.status_code
|
|
assert second.headers["x-statehub-idempotency-replay"] == "true"
|
|
assert second.json() == first_body
|
|
|
|
listed = await client.get("/progress/")
|
|
assert len([row for row in listed.json() if row["summary"] == payload["summary"]]) == 1
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_idempotency_key_reuse_with_different_request_conflicts(client):
|
|
headers = {"Idempotency-Key": "same-key-different-body"}
|
|
first = await client.post(
|
|
"/progress/",
|
|
json={"event_type": "note", "summary": "original"},
|
|
headers=headers,
|
|
)
|
|
assert first.status_code in {200, 201}
|
|
|
|
second = await client.post(
|
|
"/progress/",
|
|
json={"event_type": "note", "summary": "changed"},
|
|
headers=headers,
|
|
)
|
|
assert second.status_code == 409
|
|
assert "different request" in second.json()["error"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_idempotency_header_on_unsupported_route_is_ignored(client):
|
|
first = await client.get("/state/health", headers={"Idempotency-Key": "ignored-on-read"})
|
|
second = await client.get("/state/health", headers={"Idempotency-Key": "ignored-on-read"})
|
|
assert first.status_code == 200
|
|
assert second.status_code == 200
|
|
assert "x-statehub-idempotency-replay" not in second.headers
|