Files
hunjing/backend/tests/services/test_lorebook_service.py
2026-08-21 16:00:13 +08:00

113 lines
3.8 KiB
Python

"""世谱注入编排测试(DB 集成)。"""
from __future__ import annotations
import json
from app.db.session import AsyncSessionLocal
from app.models.character import Character
from app.models.lorebook import Lorebook, LorebookEntry
from app.services.lorebook import build_lorebook_injection
async def _make_character(session, owner_scope: str = "local-user") -> Character:
char = Character(name="tester", language="zh-CN", owner_scope=owner_scope)
session.add(char)
await session.flush()
return char
async def _add_entry(session, lorebook_id: str, keys: list[str], content: str, **kw) -> None:
session.add(
LorebookEntry(
lorebook_id=lorebook_id,
keys_json=json.dumps(keys),
content=content,
**kw,
)
)
await session.commit()
async def test_no_books_returns_none() -> None:
async with AsyncSessionLocal() as session:
before, after = await build_lorebook_injection(
session, "character_missing", "local-user", "任意文本"
)
assert before is None and after is None
async def test_keyword_match_injects_after_char() -> None:
async with AsyncSessionLocal() as session:
char = await _make_character(session)
book = Lorebook(character_id=char.id, owner_scope="local-user", scope="character")
session.add(book)
await session.flush()
await _add_entry(session, book.id, ["猫"], "她喜欢猫。", position="after_char")
before, after = await build_lorebook_injection(
session, char.id, "local-user", "今天看到一只猫"
)
assert before is None
assert after == "她喜欢猫。"
async def test_no_match_returns_none() -> None:
async with AsyncSessionLocal() as session:
char = await _make_character(session)
book = Lorebook(character_id=char.id, owner_scope="local-user")
session.add(book)
await session.flush()
await _add_entry(session, book.id, ["猫"], "她喜欢猫。")
before, after = await build_lorebook_injection(
session, char.id, "local-user", "无关文本"
)
assert before is None and after is None
async def test_before_position() -> None:
async with AsyncSessionLocal() as session:
char = await _make_character(session)
book = Lorebook(character_id=char.id, owner_scope="local-user")
session.add(book)
await session.flush()
await _add_entry(
session, book.id, ["魔法"], "世界观:存在魔法。", position="before_char"
)
before, after = await build_lorebook_injection(
session, char.id, "local-user", "使用魔法"
)
assert before == "世界观:存在魔法。"
assert after is None
async def test_global_scope_book_matched_for_any_character() -> None:
async with AsyncSessionLocal() as session:
char = await _make_character(session)
# global 书:character_id=None,所有人物共享
book = Lorebook(character_id=None, owner_scope="local-user", scope="global")
session.add(book)
await session.flush()
await _add_entry(session, book.id, ["龙"], "龙是传说生物。")
before, after = await build_lorebook_injection(
session, char.id, "local-user", "提到龙"
)
assert after == "龙是传说生物。"
async def test_disabled_entry_not_matched() -> None:
async with AsyncSessionLocal() as session:
char = await _make_character(session)
book = Lorebook(character_id=char.id, owner_scope="local-user")
session.add(book)
await session.flush()
await _add_entry(session, book.id, ["猫"], "x", enabled=False)
before, after = await build_lorebook_injection(
session, char.id, "local-user", "一只猫"
)
assert before is None and after is None