Files
cursor-flasher/tests/test_state.py
cottongin c0477d2f40 fix: prevent false positives from stale approval buttons in chat history
State machine no longer transitions directly from IDLE to WAITING_FOR_USER
on approval signals. Must see AGENT_WORKING first — this prevents stale
buttons like "Run this time only" persisting in chat history from
triggering the flash when no agent task is active.

Also removed "Continue" and "Resume" from approval keywords (too generic,
appear in normal chat text).

Made-with: Cursor
2026-03-10 03:17:34 -04:00

83 lines
3.3 KiB
Python

import pytest
from cursor_flasher.state import FlasherState, StateMachine
class TestStateMachine:
def test_initial_state_is_idle(self):
sm = StateMachine()
assert sm.state == FlasherState.IDLE
def test_idle_to_agent_working(self):
sm = StateMachine()
changed = sm.update(agent_working=True, approval_needed=False)
assert sm.state == FlasherState.AGENT_WORKING
assert changed is True
def test_agent_working_to_waiting(self):
sm = StateMachine()
sm.update(agent_working=True, approval_needed=False)
changed = sm.update(agent_working=False, approval_needed=False)
assert sm.state == FlasherState.WAITING_FOR_USER
assert changed is True
def test_approval_needed_triggers_waiting(self):
sm = StateMachine()
sm.update(agent_working=True, approval_needed=False)
changed = sm.update(agent_working=False, approval_needed=True)
assert sm.state == FlasherState.WAITING_FOR_USER
assert changed is True
def test_idle_does_not_jump_to_waiting(self):
sm = StateMachine()
changed = sm.update(agent_working=False, approval_needed=False)
assert sm.state == FlasherState.IDLE
assert changed is False
def test_waiting_to_user_interacting(self):
sm = StateMachine()
sm.update(agent_working=True, approval_needed=False)
sm.update(agent_working=False, approval_needed=False)
assert sm.state == FlasherState.WAITING_FOR_USER
changed = sm.dismiss()
assert sm.state == FlasherState.IDLE
assert changed is True
def test_waiting_to_agent_working(self):
sm = StateMachine()
sm.update(agent_working=True, approval_needed=False)
sm.update(agent_working=False, approval_needed=False)
changed = sm.update(agent_working=True, approval_needed=False)
assert sm.state == FlasherState.AGENT_WORKING
assert changed is True
def test_no_change_returns_false(self):
sm = StateMachine()
sm.update(agent_working=True, approval_needed=False)
changed = sm.update(agent_working=True, approval_needed=False)
assert changed is False
def test_cooldown_prevents_immediate_retrigger(self):
sm = StateMachine(cooldown=5.0)
sm.update(agent_working=True, approval_needed=False)
sm.update(agent_working=False, approval_needed=False)
assert sm.state == FlasherState.WAITING_FOR_USER
sm.dismiss()
sm.update(agent_working=True, approval_needed=False)
changed = sm.update(agent_working=False, approval_needed=False)
assert sm.cooldown == 5.0
def test_stale_approval_from_idle_ignored(self):
"""Approval buttons in IDLE state (stale chat history) must not trigger flash."""
sm = StateMachine()
changed = sm.update(agent_working=False, approval_needed=True)
assert sm.state == FlasherState.IDLE
assert changed is False
def test_approval_after_working_triggers(self):
"""Approval buttons after seeing agent work should trigger flash."""
sm = StateMachine()
sm.update(agent_working=True, approval_needed=False)
changed = sm.update(agent_working=False, approval_needed=True)
assert sm.state == FlasherState.WAITING_FOR_USER
assert changed is True