import json from pathlib import Path from cli.runtime.plugin.service import CliPluginRuntimeService from .conftest import FakeRuntimeEnvironment, build_runtime def write_frontend_package(frontend_root: Path, dependencies: dict[str, str]) -> None: """写入测试用前端 package.json。""" frontend_root.mkdir(parents=True, exist_ok=True) (frontend_root / 'package.json').write_text( json.dumps({'dependencies': dependencies}), encoding='utf-8', ) class LazyPluginGateway: """ 测试用 CLI 插件网关,验证开发者能力可懒解析运行时依赖。 """ def __init__(self, backend_root: Path) -> None: """初始化测试用 CLI 插件网关。""" self.backend_root = backend_root self.runtime_environment_requested = False def get_core_runtime_environment(self) -> FakeRuntimeEnvironment: """获取测试运行时环境。""" self.runtime_environment_requested = True return FakeRuntimeEnvironment(self.backend_root) @staticmethod def build_exception_payload(message: str, exc: Exception) -> dict[str, object]: """构建测试异常负载。""" return {'ok': False, 'message': message, 'error': str(exc)} def test_plugin_runtime_create_plugin_lazily_resolves_runtime_environment(tmp_path: Path) -> None: """校验插件模板创建会通过 CLI 网关懒解析运行时环境。""" backend_root = tmp_path / 'backend' backend_root.mkdir() plugin_gateway = LazyPluginGateway(backend_root) runtime = CliPluginRuntimeService(plugin_gateway=plugin_gateway) payload = runtime.create_plugin('demo', dry_run=True) assert payload['ok'] is True assert plugin_gateway.runtime_environment_requested is True def test_plugin_runtime_create_plugin_dry_run_does_not_write_files(tmp_path: Path) -> None: """校验插件模板 dry-run 只返回写入计划,不写文件。""" project_root = tmp_path / 'project' backend_root = project_root / 'ruoyi-fastapi-backend' backend_root.mkdir(parents=True) payload = build_runtime(backend_root).create_plugin('demo', dry_run=True) assert payload['ok'] is True assert payload['dryRun'] is True assert payload['template'] == 'full-stack' assert payload['backend'] is True assert payload['frontend'] is True assert payload['frontendVersion'] == 'vue3' assert payload['test'] is True assert payload['backendTest'] is True assert payload['frontendTest'] is True assert str(backend_root / 'tests' / 'plugins' / 'demo') in payload['targetDirs'] assert str(project_root / 'ruoyi-fastapi-frontend' / 'tests' / 'plugins' / 'demo') in payload['targetDirs'] assert payload['files'] assert not (backend_root / 'plugins' / 'demo' / 'plugin.yaml').exists() assert not (backend_root / 'tests' / 'plugins' / 'demo' / 'test_ping.py').exists() assert not (project_root / 'ruoyi-fastapi-frontend' / 'tests' / 'plugins' / 'demo' / 'pluginView.test.js').exists() def test_plugin_runtime_create_plugin_rejects_unsafe_plugin_id(tmp_path: Path) -> None: """校验插件模板创建会拒绝不安全的插件ID。""" project_root = tmp_path / 'project' backend_root = project_root / 'ruoyi-fastapi-backend' backend_root.mkdir(parents=True) payload = build_runtime(backend_root).create_plugin('../../evil', dry_run=True) assert payload['ok'] is False assert '插件ID必须' in str(payload['error']) assert not (project_root / 'evil').exists() def test_plugin_runtime_create_plugin_uses_runtime_frontend_dir(tmp_path: Path) -> None: """校验插件模板创建使用运行时环境提供的前端目录。""" project_root = tmp_path / 'project' backend_root = project_root / 'api-server' frontend_root = project_root / 'web-client' backend_root.mkdir(parents=True) payload = build_runtime(backend_root, frontend_root=frontend_root).create_plugin('demo') assert payload['ok'] is True assert (backend_root / 'plugins' / 'demo' / 'plugin.yaml').is_file() assert (frontend_root / 'plugins' / 'demo' / 'views' / 'index.vue').is_file() assert (frontend_root / 'tests' / 'plugins' / 'demo' / 'pluginView.test.js').is_file() def test_plugin_runtime_create_plugin_auto_detects_vue2_frontend(tmp_path: Path) -> None: """校验脚手架会从 package.json 自动识别 Vue 2 并生成对应语法。""" project_root = tmp_path / 'project' backend_root = project_root / 'api-server' frontend_root = project_root / 'web-client' backend_root.mkdir(parents=True) write_frontend_package(frontend_root, {'vue': '^2.7.16', 'element-ui': '^2.15.14'}) payload = build_runtime(backend_root, frontend_root=frontend_root).create_plugin('demo', template='crud-page') view_content = (frontend_root / 'plugins' / 'demo' / 'views' / 'index.vue').read_text(encoding='utf-8') test_content = (frontend_root / 'tests' / 'plugins' / 'demo' / 'pluginView.test.js').read_text(encoding='utf-8') assert payload['ok'] is True assert payload['frontendVersion'] == 'vue2' assert '