Files
RuoYi-Vue3-FastAPI/ruoyi-fastapi-backend/tests/sql/test_plugin_schema.py
T
insistence 2a055ba648 feat: 新增插件系统 (#112)
* feat: 初始化插件系统

* refactor: 收口插件系统运行时重构

* perf: 优化插件系统类型提示

* fix&perf: 修复和优化插件系统

* fix: 修复gitignore规则误忽略插件文件的问题

* fix: 修复运行时插件根路径算错的问题

* fix: 加强插件发现和路由注册的防护措施

* revert: 回滚定时任务白名单

* fix: 移除未使用的应用路由注册探测

* revert: 恢复部分代码

* perf: 优化插件系统

* docs: 新增插件开发文档

* perf: 优化插件管理模块

* perf: 提升插件系统核心能力

* refactor: 重构生命周期 step runner

* fix: 修复lint错误

* test: 清理测试用例

* test: 调整测试目录名称

* fix: 修复前后端目录硬编码的问题

* fix: 修复插件系统安全性缺口

* refactor: 重新设计插件生命周期 Migration 事务与回滚

* perf: 优化插件系统边界问题

* refactor: 重构当前插件系统的依赖体系设计

* perf: 优化代码

* perf: 优化代码

* fix: 修复代码合并问题

* fix: 修复bug

* perf: 优化代码

* perf&fix: 优化代码和修复bug

* docs: 优化文档格式

* feat: 适配Vue2版本

* docs: 更新README文档

* fix: 修复ruff lint错误

* chore: 更新后端依赖文件
2026-07-28 20:35:18 +08:00

120 lines
4.9 KiB
Python

from pathlib import Path
BACKEND_ROOT = Path(__file__).resolve().parents[2]
SQL_FILES = (
(BACKEND_ROOT / 'sql' / 'ruoyi-fastapi.sql', "'"),
(BACKEND_ROOT / 'sql' / 'ruoyi-fastapi-pg.sql', ''),
)
def read_sql(sql_path: Path) -> str:
"""读取初始化 SQL 文件内容。"""
return sql_path.read_text(encoding='utf-8')
def test_builtin_sql_contains_plugin_schema_and_management_permissions() -> None:
"""校验内置 SQL 包含插件表结构与管理权限。"""
expected_menu_ids = ('120', '1069', '1070', '1071', '1072')
for sql_path, quote in SQL_FILES:
sql_content = read_sql(sql_path)
for expected_text in (
'插件管理',
'system/plugin/index',
'system:plugin:list',
'system:plugin:query',
'system:plugin:edit',
'create table sys_plugin',
'create table sys_plugin_menu',
'uk_sys_plugin_menu_key',
'create table sys_plugin_migration',
'migration_checksum',
'attempt_count',
'started_time',
'finished_time',
'ck_sys_plugin_enabled',
'ck_sys_plugin_status',
):
assert expected_text in sql_content
for menu_id in expected_menu_ids:
expected_insert = f'insert into sys_role_menu values ({quote}2{quote}, {quote}{menu_id}{quote});'
assert expected_insert in sql_content
def test_file_and_plugin_management_menu_ids_are_contiguous() -> None:
"""校验文件管理及插件管理菜单编号连续且父子关系正确。"""
file_permissions = (
'system:file:query',
'system:file:download',
'system:file:remove',
'system:file:edit',
'system:file:transfer',
'system:file:restore',
'system:file:purge',
'system:file:reconcile',
)
plugin_permissions = (
'system:plugin:query',
'system:plugin:edit',
'system:plugin:list',
'system:plugin:export',
)
for sql_path, quote in SQL_FILES:
sql_lines = read_sql(sql_path).splitlines()
file_menu_line = next(line for line in sql_lines if "'文件管理'" in line)
plugin_menu_line = next(line for line in sql_lines if "'插件管理'" in line)
assert f'values({quote}119{quote},' in file_menu_line
assert f'values({quote}120{quote},' in plugin_menu_line
for menu_id, permission in enumerate(file_permissions, start=1061):
permission_line = next(line for line in sql_lines if f"'{permission}'" in line and "'F'" in line)
assert f'values({quote}{menu_id}{quote},' in permission_line
assert f', {quote}119{quote},' in permission_line
for menu_id in (119, *range(1061, 1069)):
expected_insert = f'insert into sys_role_menu values ({quote}2{quote}, {quote}{menu_id}{quote});'
assert expected_insert in sql_lines
for menu_id, permission in enumerate(plugin_permissions, start=1069):
permission_line = next(line for line in sql_lines if f"'{permission}'" in line and "'F'" in line)
assert f'values({quote}{menu_id}{quote},' in permission_line
assert f', {quote}120{quote},' in permission_line
def test_builtin_sql_excludes_ai_plugin_content_and_preserves_file_management() -> None:
"""校验 AI 内容由插件管理,同时保留上游文件管理初始化内容。"""
for sql_path, _quote in SQL_FILES:
sql_content = read_sql(sql_path)
for excluded_text in (
'AI 管理',
'ai/model/index',
'ai/chat/index',
'plugin/ai/model/index',
'plugin/ai/chat/index',
'ai_provider_type',
'create table ai_models',
'create table ai_chat_config',
):
assert excluded_text not in sql_content
for expected_text in (
'文件管理',
'system/file/index',
'create table sys_file_info',
'create table sys_file_reconcile_issue',
):
assert expected_text in sql_content
assert '-- 20、文件信息表' in sql_content
assert '-- 27、文件存储对账异常表' in sql_content
assert '-- 28、插件信息表' in sql_content
assert '-- 32、插件批量操作审计日志表' in sql_content
assert sql_content.index('create table sys_file_info') < sql_content.index('create table sys_plugin')
def test_builtin_sql_uses_ordered_plugin_operation_dict_ids() -> None:
"""校验内置 SQL 中插件操作类型字典 ID 已顺序整理。"""
for sql_path, _quote in SQL_FILES:
sql_content = read_sql(sql_path)
assert "insert into sys_dict_type values(12, '插件操作类型', 'plugin_operation_type'" in sql_content
for dict_code in range(33, 48):
assert f'insert into sys_dict_data values({dict_code},' in sql_content