fix: make advance_journey idempotent for same-state transitions
Browse filesClicking action buttons multiple times (or page reruns) no longer
throws ValueError when already at the target journey state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
app/services/state_manager.py
CHANGED
|
@@ -35,7 +35,8 @@ def get_current_journey_state() -> str:
|
|
| 35 |
def advance_journey(target_state: str) -> None:
|
| 36 |
"""Advance the journey to *target_state*.
|
| 37 |
|
| 38 |
-
|
|
|
|
| 39 |
"""
|
| 40 |
if target_state not in JOURNEY_STATES:
|
| 41 |
raise ValueError(f"Invalid journey state: {target_state}")
|
|
@@ -45,7 +46,7 @@ def advance_journey(target_state: str) -> None:
|
|
| 45 |
target_idx = JOURNEY_STATES.index(target_state)
|
| 46 |
|
| 47 |
if target_idx == current_idx:
|
| 48 |
-
|
| 49 |
if target_idx < current_idx:
|
| 50 |
raise ValueError(f"Cannot move backward from {current} to {target_state}")
|
| 51 |
|
|
@@ -80,3 +81,9 @@ def can_advance_to(target_state: str) -> bool:
|
|
| 80 |
return False
|
| 81 |
|
| 82 |
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
def advance_journey(target_state: str) -> None:
|
| 36 |
"""Advance the journey to *target_state*.
|
| 37 |
|
| 38 |
+
No-op if already at *target_state* (idempotent).
|
| 39 |
+
Raises ValueError if the target is invalid or backward.
|
| 40 |
"""
|
| 41 |
if target_state not in JOURNEY_STATES:
|
| 42 |
raise ValueError(f"Invalid journey state: {target_state}")
|
|
|
|
| 46 |
target_idx = JOURNEY_STATES.index(target_state)
|
| 47 |
|
| 48 |
if target_idx == current_idx:
|
| 49 |
+
return # idempotent — already at target state
|
| 50 |
if target_idx < current_idx:
|
| 51 |
raise ValueError(f"Cannot move backward from {current} to {target_state}")
|
| 52 |
|
|
|
|
| 81 |
return False
|
| 82 |
|
| 83 |
return True
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def reset_session_state() -> None:
|
| 87 |
+
"""Reset all session state to defaults for a new session."""
|
| 88 |
+
for key, default_value in _DEFAULTS.items():
|
| 89 |
+
st.session_state[key] = default_value
|
app/tests/test_state_manager.py
CHANGED
|
@@ -88,10 +88,10 @@ def test_advance_refuses_backward(mock_session_state):
|
|
| 88 |
assert mock_session_state["journey_state"] == "VALIDATE_TRIALS"
|
| 89 |
|
| 90 |
|
| 91 |
-
def
|
| 92 |
mock_session_state["journey_state"] = "PRESCREEN"
|
| 93 |
-
|
| 94 |
-
|
| 95 |
|
| 96 |
|
| 97 |
def test_advance_invalid_state(mock_session_state):
|
|
|
|
| 88 |
assert mock_session_state["journey_state"] == "VALIDATE_TRIALS"
|
| 89 |
|
| 90 |
|
| 91 |
+
def test_advance_same_state_is_idempotent(mock_session_state):
|
| 92 |
mock_session_state["journey_state"] = "PRESCREEN"
|
| 93 |
+
advance_journey("PRESCREEN") # should not raise
|
| 94 |
+
assert mock_session_state["journey_state"] == "PRESCREEN"
|
| 95 |
|
| 96 |
|
| 97 |
def test_advance_invalid_state(mock_session_state):
|