feat(client): initialize procurement tool skeleton
This commit is contained in:
@@ -0,0 +1 @@
|
||||
"""采购工具的离线单元测试。"""
|
||||
@@ -0,0 +1,24 @@
|
||||
"""验证桌面入口的纯参数处理,不启动 PySide6。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
|
||||
CLIENT_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(CLIENT_ROOT / "src"))
|
||||
|
||||
from cmbuyer_client.app import select_application_argv
|
||||
|
||||
|
||||
class ApplicationArgumentsTests(unittest.TestCase):
|
||||
def test_empty_argument_list_is_not_replaced_with_process_arguments(self) -> None:
|
||||
with mock.patch("cmbuyer_client.app.sys.argv", ["process-name", "--process-option"]):
|
||||
self.assertEqual([], select_application_argv([]))
|
||||
|
||||
def test_none_uses_process_arguments(self) -> None:
|
||||
with mock.patch("cmbuyer_client.app.sys.argv", ["process-name", "--process-option"]):
|
||||
self.assertEqual(["process-name", "--process-option"], select_application_argv(None))
|
||||
@@ -0,0 +1,49 @@
|
||||
"""验证日志脱敏边界,不需要 PySide6 或真机。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
CLIENT_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(CLIENT_ROOT / "src"))
|
||||
|
||||
from cmbuyer_client.logging_policy import configure_application_logger, redact_text
|
||||
from cmbuyer_client.runtime import RuntimePaths
|
||||
|
||||
|
||||
class LoggingPolicyTests(unittest.TestCase):
|
||||
def test_redact_text_hides_required_sensitive_values(self) -> None:
|
||||
message = (
|
||||
"token=secret-value authorization: Bearer-value "
|
||||
"address='浙江省杭州市' phone=13800138000 payment=card-value"
|
||||
)
|
||||
|
||||
redacted = redact_text(message)
|
||||
|
||||
for raw_value in ("secret-value", "Bearer-value", "浙江省杭州市", "13800138000", "card-value"):
|
||||
self.assertNotIn(raw_value, redacted)
|
||||
self.assertIn("token=[已隐藏]", redacted)
|
||||
|
||||
def test_file_handler_writes_only_redacted_text(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
paths = RuntimePaths.from_root(Path(directory))
|
||||
logger = configure_application_logger(paths)
|
||||
try:
|
||||
logger.info("token=not-for-log phone=13900139000 payment=not-for-log")
|
||||
|
||||
for handler in logger.handlers:
|
||||
handler.flush()
|
||||
content = (paths.logs / "client.log").read_text(encoding="utf-8")
|
||||
finally:
|
||||
# Windows 不允许在 FileHandler 持有文件时删除临时目录。
|
||||
for handler in tuple(logger.handlers):
|
||||
logger.removeHandler(handler)
|
||||
handler.close()
|
||||
|
||||
self.assertNotIn("not-for-log", content)
|
||||
self.assertNotIn("13900139000", content)
|
||||
self.assertIn("[已隐藏]", content)
|
||||
@@ -0,0 +1,25 @@
|
||||
"""验证本地运行目录策略,不需要连接设备。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
CLIENT_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(CLIENT_ROOT / "src"))
|
||||
|
||||
from cmbuyer_client.runtime import RuntimePaths
|
||||
|
||||
|
||||
class RuntimePathsTests(unittest.TestCase):
|
||||
def test_ensure_exists_creates_only_runtime_directories(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
paths = RuntimePaths.from_root(Path(directory) / "runtime")
|
||||
|
||||
paths.ensure_exists()
|
||||
|
||||
self.assertTrue(paths.logs.is_dir())
|
||||
self.assertTrue(paths.artifacts.is_dir())
|
||||
@@ -0,0 +1,29 @@
|
||||
"""验证 wheel 元数据检查脚本,不构建 wheel 或安装运行时依赖。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
import zipfile
|
||||
|
||||
|
||||
CLIENT_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(CLIENT_ROOT / "scripts"))
|
||||
|
||||
from verify_wheel_metadata import dependencies_from_requirements, verify_wheel_metadata
|
||||
|
||||
|
||||
class WheelMetadataTests(unittest.TestCase):
|
||||
def test_metadata_checker_accepts_dependencies_from_the_single_requirements_file(self) -> None:
|
||||
expected_dependencies = dependencies_from_requirements(CLIENT_ROOT / "requirements.txt")
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
wheel_file = Path(directory) / "cmbuyer_client-0.1.0-py3-none-any.whl"
|
||||
metadata = "Metadata-Version: 2.3\n" + "".join(
|
||||
f"Requires-Dist: {dependency}\n" for dependency in sorted(expected_dependencies)
|
||||
)
|
||||
with zipfile.ZipFile(wheel_file, "w") as wheel:
|
||||
wheel.writestr("cmbuyer_client-0.1.0.dist-info/METADATA", metadata)
|
||||
|
||||
self.assertEqual(set(), verify_wheel_metadata(wheel_file, CLIENT_ROOT / "requirements.txt"))
|
||||
Reference in New Issue
Block a user