# -*- coding: utf-8 -*- """RpaVideoSession 与 cmd_run 测试。""" from __future__ import annotations import io import json import os import re import unittest from contextlib import redirect_stderr, redirect_stdout from unittest.mock import AsyncMock, MagicMock, patch from _support import IsolatedDataRoot, get_skill_root from jiangchang_skill_core import config class TestEnvExampleVideoDefaults(unittest.TestCase): def test_env_example_contains_required_keys(self) -> None: path = os.path.join(get_skill_root(), ".env.example") with open(path, encoding="utf-8") as f: text = f.read() for key in ( "OPENCLAW_TEST_TARGET=mock", "OPENCLAW_RECORD_VIDEO=1", "OPENCLAW_ARTIFACTS_ON_FAILURE=1", "OPENCLAW_BROWSER_HEADLESS=0", "OPENCLAW_PLAYWRIGHT_STEALTH=1", "AMAZON_SIM_REPORTS_URL=https://sandbox.jc2009.com", ): self.assertIn(key, text, msg=f"missing {key!r} in .env.example") class TestPrintVideoSummary(unittest.TestCase): def test_cli_prints_video_path_when_enabled(self) -> None: from service.task_run_support import _print_video_summary buf = io.StringIO() with redirect_stdout(buf), redirect_stderr(io.StringIO()): _print_video_summary( { "enabled": True, "path": r"D:\data\videos\download-settlement-report-amazon_demo.mp4", "record_log_path": r"D:\data\logs\ffmpeg-record.log", "warnings": [], } ) out = buf.getvalue() self.assertIn("录屏路径", out) self.assertIn("download-settlement-report-amazon_demo.mp4", out) self.assertIn("录屏日志", out) class TestCmdRunVideoSession(unittest.TestCase): def test_cmd_run_creates_video_session_with_chinese_titles(self) -> None: with IsolatedDataRoot(user_id="_video_run"): os.environ["OPENCLAW_RECORD_VIDEO"] = "1" os.environ["OPENCLAW_TEST_TARGET"] = "mock" config.reset_cache() from service import task_service from service.amazon_report_adapter.base import DownloadSettlementResult mock_result = DownloadSettlementResult( ok=True, job_id="MOCK-1", file_path="/tmp/settlement.xlsx", filename="settlement.xlsx", date_from="2025-12-01", date_to="2025-12-31", ) mock_video = MagicMock() mock_video.add_step = MagicMock() mock_video.summary.return_value = { "enabled": False, "path": None, "capture_path": None, "record_log_path": None, "warnings": [], "voiceover_path": None, "music_path": None, "audio_warnings": [], } created: list[dict] = [] class _CapturingFakeSession: def __init__(self, **kwargs): created.append(kwargs) async def __aenter__(self): return mock_video async def __aexit__(self, *args): return None mock_adapter = MagicMock() mock_adapter.name = "mock" mock_adapter.download_settlement.return_value = mock_result with patch.object(task_service, "RpaVideoSession", _CapturingFakeSession): with patch.object(task_service, "get_adapter", return_value=mock_adapter): buf = io.StringIO() with redirect_stdout(buf), redirect_stderr(io.StringIO()): rc = task_service.cmd_run( date_from="2025-12-01", date_to="2025-12-31", ) self.assertEqual(rc, 0) self.assertTrue(created, "RpaVideoSession should be constructed") kwargs = created[0] self.assertEqual(kwargs.get("title"), "开始下载 Amazon 结算报表") self.assertEqual(kwargs.get("closing_title"), "结算报表下载完成") self.assertTrue(re.search(r"[\u4e00-\u9fff]", kwargs.get("title", ""))) out = buf.getvalue() payload = json.loads(out.strip().splitlines()[-1]) self.assertTrue(payload.get("ok")) from db import task_logs_repository as tlr rows = tlr.list_task_logs(1) self.assertTrue(rows) self.assertEqual(rows[0][1], "download_settlement") if __name__ == "__main__": unittest.main()