from __future__ import annotations import io import unittest from types import SimpleNamespace from unittest.mock import patch class SystemInitializerCliTest(unittest.TestCase): def test_parse_fresh_arguments(self) -> None: from scripts.system_initialize import parse_args args = parse_args( [ "fresh", "--company-name", "百华", "--admin-name", "超级管理员", "--admin-phone", "13800000000", "--admin-password", "secret123", "--smart-operation-report", "off", "--delete-files", "--allow-any-database", ] ) self.assertEqual(args.mode, "fresh") self.assertEqual(args.company_name, "百华") self.assertEqual(args.admin_name, "超级管理员") self.assertEqual(args.admin_phone, "13800000000") self.assertEqual(args.admin_password, "secret123") self.assertEqual(args.smart_operation_report, "off") self.assertTrue(args.delete_files) self.assertTrue(args.allow_any_database) self.assertFalse(hasattr(args, "confirm_reset")) def test_parse_reset_arguments(self) -> None: from scripts.system_initialize import parse_args args = parse_args( [ "reset", "--company-name", "百华", "--admin-name", "超级管理员", "--admin-phone", "13800000000", "--admin-password", "secret123", "--confirm-reset", "--smart-operation-report", "off", ] ) self.assertEqual(args.mode, "reset") self.assertEqual(args.company_name, "百华") self.assertEqual(args.admin_phone, "13800000000") self.assertTrue(args.confirm_reset) self.assertEqual(args.smart_operation_report, "off") def test_main_fresh_creates_database_then_initializes_without_real_db(self) -> None: from scripts import system_initialize settings = SimpleNamespace( mysql_host="127.0.0.1", mysql_port=3306, mysql_database="erp_test", mysql_dsn="mysql+pymysql://root:secret@127.0.0.1:3306/erp_test", ) result = SimpleNamespace( backup_path=None, summary_path="/tmp/summary.json", seeded={"admin_username": "13800000000"}, ) with ( patch.object(system_initialize, "get_settings", return_value=settings), patch.object(system_initialize, "create_engine", return_value="engine") as create_engine_mock, patch.object(system_initialize, "create_database_if_missing", return_value="erp_test") as create_db_mock, patch.object(system_initialize, "fresh_initialize_database", return_value=result) as fresh_mock, patch.object(system_initialize, "reset_existing_database_with_backup") as reset_mock, patch("sys.stdout", new_callable=io.StringIO) as stdout, ): exit_code = system_initialize.main( [ "fresh", "--company-name", "百华", "--admin-name", "超级管理员", "--admin-phone", "13800000000", "--admin-password", "secret123", "--smart-operation-report", "on", ] ) self.assertEqual(exit_code, 0) create_db_mock.assert_called_once_with(settings) create_engine_mock.assert_called_once_with(settings.mysql_dsn, pool_pre_ping=True, future=True) fresh_mock.assert_called_once() reset_mock.assert_not_called() self.assertIn("mode=fresh", stdout.getvalue()) self.assertIn("database=127.0.0.1:3306/erp_test", stdout.getvalue()) self.assertIn("summary_path=/tmp/summary.json", stdout.getvalue()) self.assertIn("admin_username=13800000000", stdout.getvalue()) def test_main_reset_calls_backup_reset_without_swallowing_service_errors(self) -> None: from scripts import system_initialize settings = SimpleNamespace( mysql_host="127.0.0.1", mysql_port=3306, mysql_database="erp_test", mysql_dsn="mysql+pymysql://root:secret@127.0.0.1:3306/erp_test", ) with ( patch.object(system_initialize, "get_settings", return_value=settings), patch.object(system_initialize, "create_engine", return_value="engine"), patch.object( system_initialize, "reset_existing_database_with_backup", side_effect=ValueError("Refusing to reset database without --confirm-reset"), ), ): with self.assertRaisesRegex(ValueError, "confirm-reset"): system_initialize.main( [ "reset", "--company-name", "百华", "--admin-name", "超级管理员", "--admin-phone", "13800000000", "--admin-password", "secret123", ] ) if __name__ == "__main__": unittest.main()