chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
"""Tests for focus_nudge utility — should_nudge() logic and nudge_unity_focus() gating."""
|
||||
|
||||
import time
|
||||
from unittest.mock import patch, AsyncMock
|
||||
|
||||
import pytest
|
||||
|
||||
from utils.focus_nudge import (
|
||||
should_nudge,
|
||||
reset_nudge_backoff,
|
||||
nudge_unity_focus,
|
||||
_is_available,
|
||||
)
|
||||
|
||||
|
||||
class TestShouldNudge:
|
||||
"""Tests for should_nudge() decision logic."""
|
||||
|
||||
def test_returns_false_when_not_running(self):
|
||||
assert should_nudge(status="succeeded", editor_is_focused=False, last_update_unix_ms=0, current_time_ms=99999) is False
|
||||
|
||||
def test_returns_false_when_focused(self):
|
||||
assert should_nudge(status="running", editor_is_focused=True, last_update_unix_ms=0, current_time_ms=99999) is False
|
||||
|
||||
def test_returns_true_when_stalled_and_unfocused(self):
|
||||
now_ms = int(time.time() * 1000)
|
||||
stale_ms = now_ms - 5000 # 5s ago
|
||||
assert should_nudge(status="running", editor_is_focused=False, last_update_unix_ms=stale_ms, current_time_ms=now_ms) is True
|
||||
|
||||
def test_returns_false_when_recently_updated(self):
|
||||
now_ms = int(time.time() * 1000)
|
||||
recent_ms = now_ms - 1000 # 1s ago (within 3s threshold)
|
||||
assert should_nudge(status="running", editor_is_focused=False, last_update_unix_ms=recent_ms, current_time_ms=now_ms) is False
|
||||
|
||||
def test_returns_true_when_no_updates_yet(self):
|
||||
"""No last_update_unix_ms means tests might be stuck at start."""
|
||||
assert should_nudge(status="running", editor_is_focused=False, last_update_unix_ms=None) is True
|
||||
|
||||
def test_custom_stall_threshold(self):
|
||||
now_ms = int(time.time() * 1000)
|
||||
stale_ms = now_ms - 2000 # 2s ago
|
||||
# Default threshold (3s) — not stale yet
|
||||
assert should_nudge(status="running", editor_is_focused=False, last_update_unix_ms=stale_ms, current_time_ms=now_ms) is False
|
||||
# Custom threshold (1s) — stale
|
||||
assert should_nudge(status="running", editor_is_focused=False, last_update_unix_ms=stale_ms, current_time_ms=now_ms, stall_threshold_ms=1000) is True
|
||||
|
||||
def test_returns_false_for_failed_status(self):
|
||||
assert should_nudge(status="failed", editor_is_focused=False, last_update_unix_ms=0, current_time_ms=99999) is False
|
||||
|
||||
def test_returns_false_for_cancelled_status(self):
|
||||
assert should_nudge(status="cancelled", editor_is_focused=False, last_update_unix_ms=0, current_time_ms=99999) is False
|
||||
|
||||
|
||||
class TestResetNudgeBackoff:
|
||||
"""Tests for reset_nudge_backoff() state management."""
|
||||
|
||||
def test_resets_consecutive_nudges(self):
|
||||
import utils.focus_nudge as fn
|
||||
fn._consecutive_nudges = 5
|
||||
reset_nudge_backoff()
|
||||
assert fn._consecutive_nudges == 0
|
||||
|
||||
def test_updates_last_progress_time(self):
|
||||
import utils.focus_nudge as fn
|
||||
old_time = fn._last_progress_time
|
||||
reset_nudge_backoff()
|
||||
assert fn._last_progress_time >= old_time
|
||||
|
||||
|
||||
class TestNudgeUnityFocus:
|
||||
"""Tests for nudge_unity_focus() gating logic."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_skips_when_not_available(self):
|
||||
with patch("utils.focus_nudge._is_available", return_value=False):
|
||||
result = await nudge_unity_focus(force=True)
|
||||
assert result is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_skips_when_unity_already_focused(self):
|
||||
from utils.focus_nudge import _FrontmostAppInfo
|
||||
with patch("utils.focus_nudge._is_available", return_value=True), \
|
||||
patch("utils.focus_nudge._get_frontmost_app", return_value=_FrontmostAppInfo(name="Unity")):
|
||||
result = await nudge_unity_focus(force=True)
|
||||
assert result is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_skips_when_frontmost_app_unknown(self):
|
||||
with patch("utils.focus_nudge._is_available", return_value=True), \
|
||||
patch("utils.focus_nudge._get_frontmost_app", return_value=None):
|
||||
result = await nudge_unity_focus(force=True)
|
||||
assert result is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rate_limited_by_backoff(self):
|
||||
import utils.focus_nudge as fn
|
||||
from utils.focus_nudge import _FrontmostAppInfo
|
||||
# Simulate a very recent nudge
|
||||
fn._last_nudge_time = time.monotonic()
|
||||
fn._consecutive_nudges = 0
|
||||
with patch("utils.focus_nudge._is_available", return_value=True), \
|
||||
patch("utils.focus_nudge._get_frontmost_app", return_value=_FrontmostAppInfo(name="Terminal")):
|
||||
result = await nudge_unity_focus(force=False)
|
||||
assert result is False
|
||||
Reference in New Issue
Block a user