mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-21 16:23:34 +08:00
feat(v3): move notification templates into DB migration and support music notifications
This commit is contained in:
154
tests/test_notification_template_render.py
Normal file
154
tests/test_notification_template_render.py
Normal file
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
通知模板渲染回归测试。
|
||||
|
||||
V3 起通知模板不再硬编码在程序中,默认模板由数据库升级迁移写入
|
||||
``SystemConfigKey.NotificationTemplates``。本测试验证:
|
||||
|
||||
1. V3 迁移会把默认模板一次性写入数据库配置,并覆盖用户旧设置;
|
||||
2. 带双引号条件的 Jinja 模板(如 ``{% if type == "音乐" %}``)可正常渲染,
|
||||
避免 JSON 序列化转义引号导致音乐下载/入库通知内容为空的历史问题;
|
||||
3. 模板完全由数据库配置驱动,配置缺失时不渲染、消息保持原样。
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
import importlib.util
|
||||
|
||||
import pytest
|
||||
|
||||
from app.db.systemconfig_oper import SystemConfigOper
|
||||
from app.helper.message import MessageTemplateHelper, TemplateHelper
|
||||
from app.schemas.message import Notification
|
||||
from app.schemas.types import ContentType, SystemConfigKey
|
||||
|
||||
MUSIC_ORGANIZE_TEMPLATE = """
|
||||
{
|
||||
'title': '{{ title_year }}{% if track_number %} #{{ track_number }}{% endif %}'
|
||||
'{% if season_episode %} {{ season_episode }}{% endif %} 已入库',
|
||||
'text': '类型:{{ type }}{% if category %},类别:{{ category }}{% endif %}'
|
||||
'{% if type == "音乐" and artist %}\\n艺术家:{{ artist }}{% endif %}'
|
||||
'{% if type == "音乐" and album %}\\n专辑:{{ album }}{% endif %}'
|
||||
'{% if type == "音乐" and audio_specs %}\\n音质:{{ audio_specs }}{% endif %}'
|
||||
'{% if resource_term %},质量:{{ resource_term }}{% endif %}'
|
||||
',共{{ file_count }}个文件,大小:{{ total_size }}'
|
||||
}"""
|
||||
|
||||
MUSIC_CONTEXT = {
|
||||
"type": "音乐",
|
||||
"title_year": "晴天 (2003)",
|
||||
"track_number": 3,
|
||||
"artist": "周杰伦",
|
||||
"album": "叶惠美",
|
||||
"audio_specs": "FLAC · 24-bit · 96 kHz",
|
||||
"resource_term": "无损",
|
||||
"file_count": 12,
|
||||
"total_size": "1.2 GB",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def notification_templates() -> SystemConfigOper:
|
||||
"""备份并还原通知模板配置,避免测试污染其它用例。"""
|
||||
config_oper = SystemConfigOper()
|
||||
original = config_oper.get(SystemConfigKey.NotificationTemplates)
|
||||
yield config_oper
|
||||
config_oper.set(SystemConfigKey.NotificationTemplates, original)
|
||||
|
||||
|
||||
def test_literal_template_with_quoted_condition_renders_music() -> None:
|
||||
"""
|
||||
带 ``{% if type == "音乐" %}`` 双引号条件的模板应能正常渲染,
|
||||
音乐字段(艺术家/专辑/音质)必须出现在渲染结果中。
|
||||
"""
|
||||
rendered = TemplateHelper().render(
|
||||
template_content=MUSIC_ORGANIZE_TEMPLATE, **MUSIC_CONTEXT
|
||||
)
|
||||
|
||||
assert isinstance(rendered, dict)
|
||||
assert rendered["title"] == "晴天 (2003) #3 已入库"
|
||||
assert "艺术家:周杰伦" in rendered["text"]
|
||||
assert "专辑:叶惠美" in rendered["text"]
|
||||
assert "音质:FLAC · 24-bit · 96 kHz" in rendered["text"]
|
||||
|
||||
|
||||
def test_literal_template_skips_music_fields_for_video() -> None:
|
||||
"""
|
||||
影视场景下模板中的音乐专属字段不应出现,影视字段正常渲染。
|
||||
"""
|
||||
rendered = TemplateHelper().render(
|
||||
template_content=MUSIC_ORGANIZE_TEMPLATE,
|
||||
type="电视剧",
|
||||
title_year="测试剧集 (2025)",
|
||||
season_episode="S01E05",
|
||||
category="国产剧",
|
||||
resource_term="1080p",
|
||||
file_count=1,
|
||||
total_size="5 GB",
|
||||
)
|
||||
|
||||
assert isinstance(rendered, dict)
|
||||
assert rendered["title"] == "测试剧集 (2025) S01E05 已入库"
|
||||
assert "艺术家" not in rendered["text"]
|
||||
assert "专辑" not in rendered["text"]
|
||||
assert "类别:国产剧" in rendered["text"]
|
||||
|
||||
|
||||
def test_message_renders_from_db_config(notification_templates: SystemConfigOper) -> None:
|
||||
"""
|
||||
MessageTemplateHelper 应使用数据库配置的模板渲染消息,
|
||||
而不再依赖程序内硬编码模板。
|
||||
"""
|
||||
notification_templates.set(
|
||||
SystemConfigKey.NotificationTemplates,
|
||||
{"organizeSuccess": MUSIC_ORGANIZE_TEMPLATE},
|
||||
)
|
||||
message = Notification(ctype=ContentType.OrganizeSuccess)
|
||||
|
||||
MessageTemplateHelper.render(message, **MUSIC_CONTEXT)
|
||||
|
||||
assert message.title == "晴天 (2003) #3 已入库"
|
||||
assert "艺术家:周杰伦" in message.text
|
||||
|
||||
|
||||
def test_message_without_template_config_stays_unchanged(
|
||||
notification_templates: SystemConfigOper,
|
||||
) -> None:
|
||||
"""
|
||||
数据库中没有模板配置时消息应保持原样,不应渲染也不应报错。
|
||||
"""
|
||||
notification_templates.set(SystemConfigKey.NotificationTemplates, None)
|
||||
message = Notification(ctype=ContentType.OrganizeSuccess)
|
||||
|
||||
MessageTemplateHelper.render(message, **MUSIC_CONTEXT)
|
||||
|
||||
assert message.title is None
|
||||
assert message.text is None
|
||||
|
||||
|
||||
def test_v3_migration_overwrites_templates_once(
|
||||
notification_templates: SystemConfigOper,
|
||||
) -> None:
|
||||
"""
|
||||
V3 大版本迁移应无条件覆盖用户旧通知模板配置,并写入全部 4 类模板。
|
||||
"""
|
||||
migration_path = (
|
||||
Path(__file__).resolve().parent.parent
|
||||
/ "database" / "versions" / "4dadad1d161a_3_0_0.py"
|
||||
)
|
||||
spec = importlib.util.spec_from_file_location("v3_migration", migration_path)
|
||||
migration = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(migration)
|
||||
|
||||
notification_templates.set(
|
||||
SystemConfigKey.NotificationTemplates, {"organizeSuccess": "用户自定义模板"}
|
||||
)
|
||||
migration.upgrade()
|
||||
|
||||
templates = notification_templates.get(SystemConfigKey.NotificationTemplates)
|
||||
assert set(templates.keys()) == {
|
||||
"organizeSuccess", "downloadAdded", "subscribeAdded", "subscribeComplete",
|
||||
}
|
||||
assert templates["organizeSuccess"] != "用户自定义模板"
|
||||
assert "音乐" in templates["organizeSuccess"]
|
||||
assert "音乐" in templates["downloadAdded"]
|
||||
Reference in New Issue
Block a user