test(03-02): add failing tests for approval handler and progress monitor

- Add test_approval_handler.py with 8 tests for:
  - Approval request detection (AskUserQuestion, 需要确认)
  - Approval card creation with confirm/reject buttons
  - Callback handling (approved, rejected, error)
- Add test_progress_monitor.py with 7 tests for:
  - Progress extraction (percentage, fraction, phase)
  - Update throttling (60 second interval)
  - Progress card formatting

TDD RED phase - tests will fail until implementation is complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 16:01:08 +08:00
parent d86d4113a6
commit efd4892f2f
2 changed files with 309 additions and 0 deletions
+131
View File
@@ -0,0 +1,131 @@
"""
Tests for progress_monitor module - ProgressMonitor and ProgressInfo classes.
TDD Task 1: Test scaffold for progress detection and update logic.
"""
import pytest
from unittest.mock import Mock, MagicMock
import time
# These imports will fail initially (RED phase)
from gsd_openclaw.response_formatter import FeishuResponseFormatter
class TestProgressMonitorExtraction:
"""Test progress extraction from output."""
def test_extract_progress_returns_percentage(self):
"""extract_progress returns percentage for 'Progress: 75%'."""
from gsd_openclaw.progress_monitor import ProgressMonitor, ProgressInfo
formatter = Mock(spec=FeishuResponseFormatter)
monitor = ProgressMonitor(formatter)
output = "Working on task...\nProgress: 75%\nAlmost done"
result = monitor.extract_progress(output)
assert result is not None
assert result.type == "percentage"
assert result.value == 75
def test_extract_progress_returns_fraction(self):
"""extract_progress returns fraction for '[3/5 tasks]'."""
from gsd_openclaw.progress_monitor import ProgressMonitor, ProgressInfo
formatter = Mock(spec=FeishuResponseFormatter)
monitor = ProgressMonitor(formatter)
output = "Processing...\n[3/5 tasks] completed\nContinuing..."
result = monitor.extract_progress(output)
assert result is not None
assert result.type == "fraction"
assert result.current == 3
assert result.total == 5
def test_extract_progress_returns_phase(self):
"""extract_progress returns phase for 'Phase 2 complete'."""
from gsd_openclaw.progress_monitor import ProgressMonitor, ProgressInfo
formatter = Mock(spec=FeishuResponseFormatter)
monitor = ProgressMonitor(formatter)
output = "Starting work...\nPhase 2 complete\nMoving to next"
result = monitor.extract_progress(output)
assert result is not None
assert result.type == "phase"
assert result.value == 2
class TestProgressMonitorThrottling:
"""Test progress update throttling."""
def test_should_send_update_returns_false_immediately(self):
"""should_send_update returns False immediately after creation."""
from gsd_openclaw.progress_monitor import ProgressMonitor
formatter = Mock(spec=FeishuResponseFormatter)
monitor = ProgressMonitor(formatter, update_interval=60.0)
result = monitor.should_send_update()
assert result is False
def test_should_send_update_returns_true_after_interval(self):
"""should_send_update returns True after 60 seconds."""
from gsd_openclaw.progress_monitor import ProgressMonitor
formatter = Mock(spec=FeishuResponseFormatter)
monitor = ProgressMonitor(formatter, update_interval=60.0)
# Simulate time passing by modifying last_update_time
monitor.last_update_time = time.time() - 61.0
result = monitor.should_send_update()
assert result is True
class TestProgressMonitorCardCreation:
"""Test progress card creation."""
def test_create_progress_card_includes_percentage(self):
"""create_progress_card includes progress percentage in content."""
from gsd_openclaw.progress_monitor import ProgressMonitor, ProgressInfo
formatter = Mock(spec=FeishuResponseFormatter)
formatter.format_info = Mock(return_value={
"schema": "2.0",
"header": {"title": {"content": "正在执行..."}, "template": "blue"},
"elements": []
})
monitor = ProgressMonitor(formatter)
progress = ProgressInfo(type="percentage", value=75)
card = monitor.create_progress_card(progress, "Processing data...")
formatter.format_info.assert_called_once()
call_args = formatter.format_info.call_args
content = call_args[0][1]
assert "75%" in content
def test_create_progress_card_uses_executing_title(self):
"""create_progress_card uses title '正在执行...'."""
from gsd_openclaw.progress_monitor import ProgressMonitor, ProgressInfo
formatter = Mock(spec=FeishuResponseFormatter)
formatter.format_info = Mock(return_value={
"schema": "2.0",
"header": {"title": {"content": "正在执行..."}, "template": "blue"},
"elements": []
})
monitor = ProgressMonitor(formatter)
progress = ProgressInfo(type="percentage", value=50)
card = monitor.create_progress_card(progress, "Working...")
formatter.format_info.assert_called_once()
call_args = formatter.format_info.call_args
title = call_args[0][0]
assert title == "正在执行..."