feat: add step cutoff and mid-session export support
- max_step_index slices decisions in all 4 export formats - Only set exported=True when session is completed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1184,3 +1184,138 @@ class TestSessions:
|
||||
content = response.text
|
||||
assert "## Resolution" not in content
|
||||
assert "Should not appear" not in content
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_export_max_step_index(
|
||||
self, client: AsyncClient, auth_headers: dict, test_tree: dict
|
||||
):
|
||||
"""Test max_step_index limits exported steps."""
|
||||
create_response = await client.post(
|
||||
"/api/v1/sessions",
|
||||
json={"tree_id": test_tree["id"]},
|
||||
headers=auth_headers
|
||||
)
|
||||
session_id = create_response.json()["id"]
|
||||
|
||||
decisions = [
|
||||
{"node_id": "n1", "question": "Step one?", "answer": "Yes", "timestamp": "2026-02-13T10:00:00Z", "attachments": []},
|
||||
{"node_id": "n2", "question": "Step two?", "answer": "No", "timestamp": "2026-02-13T10:01:00Z", "attachments": []},
|
||||
{"node_id": "n3", "question": "Step three?", "answer": "Maybe", "timestamp": "2026-02-13T10:02:00Z", "attachments": []},
|
||||
]
|
||||
await client.put(
|
||||
f"/api/v1/sessions/{session_id}",
|
||||
json={"decisions": decisions},
|
||||
headers=auth_headers
|
||||
)
|
||||
|
||||
response = await client.post(
|
||||
f"/api/v1/sessions/{session_id}/export",
|
||||
json={"format": "markdown", "max_step_index": 2},
|
||||
headers=auth_headers
|
||||
)
|
||||
content = response.text
|
||||
assert "Step one?" in content
|
||||
assert "Step two?" in content
|
||||
assert "Step three?" not in content
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_export_max_step_index_exceeds_count(
|
||||
self, client: AsyncClient, auth_headers: dict, test_tree: dict
|
||||
):
|
||||
"""Test max_step_index larger than decision count returns all steps."""
|
||||
create_response = await client.post(
|
||||
"/api/v1/sessions",
|
||||
json={"tree_id": test_tree["id"]},
|
||||
headers=auth_headers
|
||||
)
|
||||
session_id = create_response.json()["id"]
|
||||
|
||||
decisions = [
|
||||
{"node_id": "n1", "question": "Only step", "answer": "Done", "timestamp": "2026-02-13T10:00:00Z", "attachments": []},
|
||||
]
|
||||
await client.put(
|
||||
f"/api/v1/sessions/{session_id}",
|
||||
json={"decisions": decisions},
|
||||
headers=auth_headers
|
||||
)
|
||||
|
||||
response = await client.post(
|
||||
f"/api/v1/sessions/{session_id}/export",
|
||||
json={"format": "markdown", "max_step_index": 100},
|
||||
headers=auth_headers
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert "Only step" in response.text
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_export_max_step_index_zero_returns_422(
|
||||
self, client: AsyncClient, auth_headers: dict, test_tree: dict
|
||||
):
|
||||
"""Test max_step_index=0 returns validation error."""
|
||||
create_response = await client.post(
|
||||
"/api/v1/sessions",
|
||||
json={"tree_id": test_tree["id"]},
|
||||
headers=auth_headers
|
||||
)
|
||||
session_id = create_response.json()["id"]
|
||||
|
||||
response = await client.post(
|
||||
f"/api/v1/sessions/{session_id}/export",
|
||||
json={"format": "markdown", "max_step_index": 0},
|
||||
headers=auth_headers
|
||||
)
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_export_in_progress_session_does_not_mark_exported(
|
||||
self, client: AsyncClient, auth_headers: dict, test_tree: dict
|
||||
):
|
||||
"""Test that exporting an in-progress session does NOT set exported=True."""
|
||||
create_response = await client.post(
|
||||
"/api/v1/sessions",
|
||||
json={"tree_id": test_tree["id"]},
|
||||
headers=auth_headers
|
||||
)
|
||||
session_id = create_response.json()["id"]
|
||||
|
||||
await client.post(
|
||||
f"/api/v1/sessions/{session_id}/export",
|
||||
json={"format": "markdown"},
|
||||
headers=auth_headers
|
||||
)
|
||||
|
||||
response = await client.get(
|
||||
f"/api/v1/sessions/{session_id}",
|
||||
headers=auth_headers
|
||||
)
|
||||
assert response.json()["exported"] is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_export_completed_session_marks_exported(
|
||||
self, client: AsyncClient, auth_headers: dict, test_tree: dict
|
||||
):
|
||||
"""Test that exporting a completed session sets exported=True."""
|
||||
create_response = await client.post(
|
||||
"/api/v1/sessions",
|
||||
json={"tree_id": test_tree["id"]},
|
||||
headers=auth_headers
|
||||
)
|
||||
session_id = create_response.json()["id"]
|
||||
|
||||
await client.post(
|
||||
f"/api/v1/sessions/{session_id}/complete",
|
||||
json={"outcome": "resolved"},
|
||||
headers=auth_headers
|
||||
)
|
||||
|
||||
await client.post(
|
||||
f"/api/v1/sessions/{session_id}/export",
|
||||
json={"format": "markdown"},
|
||||
headers=auth_headers
|
||||
)
|
||||
|
||||
response = await client.get(
|
||||
f"/api/v1/sessions/{session_id}",
|
||||
headers=auth_headers
|
||||
)
|
||||
assert response.json()["exported"] is True
|
||||
|
||||
Reference in New Issue
Block a user