"""commands/history.py 单元测试 — cmd_history + _format_date。 运行: python tests/unit/test_history.py """ from __future__ import annotations import argparse import os import sys import unittest from unittest.mock import MagicMock, patch sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "assets")) def _args(**kwargs): defaults = {"type": "class", "name": "ZCL_TEST"} defaults.update(kwargs) return argparse.Namespace(**defaults) # ═══════════════════════════════════════════ # _format_date # ═══════════════════════════════════════════ class TestFormatDate(unittest.TestCase): """_format_date 将 ISO 日期转为可读格式。""" def test_empty_returns_empty(self): from sapcli.commands.history import _format_date self.assertEqual(_format_date(""), "") def test_iso_datetime(self): from sapcli.commands.history import _format_date self.assertEqual(_format_date("2026-06-15T10:30:00"), "2026-06-15 10:30:00") def test_iso_with_z_suffix(self): from sapcli.commands.history import _format_date self.assertEqual(_format_date("2026-06-15T10:30:00Z"), "2026-06-15 10:30:00") def test_none_value(self): from sapcli.commands.history import _format_date self.assertEqual(_format_date(None), "") # ═══════════════════════════════════════════ # cmd_history # ═══════════════════════════════════════════ class TestCmdHistory(unittest.TestCase): """cmd_history 查询对象版本历史。""" def test_object_not_found_raises(self): from sapcli.commands.history import cmd_history from sapcli.exceptions import ObjectNotFoundError client = MagicMock() client.object_exists.return_value = False with self.assertRaises(ObjectNotFoundError) as ctx: cmd_history(_args(), client) self.assertIn("ZCL_TEST", str(ctx.exception)) def test_api_error_prints_failure_and_returns(self): """get_object_versions 抛异常时打印失败并返回。""" from sapcli.commands.history import cmd_history client = MagicMock() client.object_exists.return_value = True client.get_object_versions.side_effect = Exception("server down") with patch("builtins.print") as mock_print: cmd_history(_args(), client) printed = " ".join(str(c) for c, _ in mock_print.call_args_list) self.assertIn("失败", printed) def test_no_versions(self): """无版本历史时打印提示。""" from sapcli.commands.history import cmd_history client = MagicMock() client.object_exists.return_value = True client.get_object_versions.return_value = [] with patch("builtins.print") as mock_print: cmd_history(_args(), client) printed = " ".join(str(c) for c, _ in mock_print.call_args_list) self.assertIn("未找到版本历史", printed) def test_with_versions_prints_table(self): """有版本时打印版本表格。""" from sapcli.commands.history import cmd_history client = MagicMock() client.object_exists.return_value = True client.get_object_versions.return_value = [ { "version": "0001", "author": "ALICE", "date": "2026-06-15T10:30:00", "versionTitle": "initial import", }, { "version": "", "author": "BOB", "date": "", "versionTitle": "current", }, ] with patch("builtins.print") as mock_print: cmd_history(_args(), client) printed = " ".join(str(c) for c, _ in mock_print.call_args_list) self.assertIn("0001", printed) self.assertIn("ALICE", printed) self.assertIn("initial import", printed) # version 为空时回退到 "active" self.assertIn("active", printed) self.assertIn("2", printed) # 找到 2 个版本 def test_versions_missing_version_key(self): """版本记录缺 version 键时回退到 active。""" from sapcli.commands.history import cmd_history client = MagicMock() client.object_exists.return_value = True client.get_object_versions.return_value = [ {"author": "CAROL", "date": "2026-01-01T00:00:00", "versionTitle": "v1"}, ] with patch("builtins.print") as mock_print: cmd_history(_args(), client) printed = " ".join(str(c) for c, _ in mock_print.call_args_list) self.assertIn("active", printed) self.assertIn("CAROL", printed) if __name__ == "__main__": unittest.main(verbosity=2)