"""人物服务测试:默认生日兜底(创建时未设 birthday → 用 created_at 兜底)。 纪念日表(time_anniversaries)随旧时间模型退役删除,本文件只验证 profile 兜底; 辰正(M8 重实现)落地后生日提醒改按 profile.birthday 计算。 """ import pytest from app.db.session import AsyncSessionLocal from app.models.character import Character from app.repositories.json_utils import loads_dict from app.schemas.character import CreateCharacterRequest from app.services.characters import create_character, create_character_from_template @pytest.mark.asyncio async def test_create_character_without_birthday_applies_default(): """未传 birthday → profile.birthday 取 created_at 的 ISO 日期。""" async with AsyncSessionLocal() as session: resp = await create_character(session, CreateCharacterRequest(name="lingxi")) character = await session.get(Character, resp.id) birthday_iso = character.created_at.strftime("%Y-%m-%d") assert resp.profile["birthday"] == birthday_iso @pytest.mark.asyncio async def test_create_character_with_birthday_keeps_user_value(): """用户传了 birthday(即便为自由文本)→ 保持用户值。""" async with AsyncSessionLocal() as session: resp = await create_character( session, CreateCharacterRequest(name="jingwu", profile={"birthday": "霜降之夜"}), ) assert resp.profile["birthday"] == "霜降之夜" @pytest.mark.asyncio async def test_create_character_with_blank_birthday_applies_default(): """birthday 为空白字符串视为未设 → 兜底。""" async with AsyncSessionLocal() as session: resp = await create_character( session, CreateCharacterRequest(name="yuelan", profile={"birthday": " "}), ) async with AsyncSessionLocal() as session: character = await session.get(Character, resp.id) assert resp.profile["birthday"] == character.created_at.strftime("%Y-%m-%d") def _template(key: str, profile_json: str) -> Character: return Character( name=key, display_name="模板", status="active", language="zh-CN", profile_json=profile_json, model_policy_json="{}", privacy_level="normal", owner_scope="system", is_system_template=True, source_template_id=None, template_key=key, ) @pytest.mark.asyncio async def test_create_character_from_template_without_birthday_uses_own_created_at(): """模板 profile 无 birthday → 子角色用自己的 created_at 兜底。""" async with AsyncSessionLocal() as session: template = _template("test_tpl", '{"background": "测试模板"}') session.add(template) await session.flush() character = await create_character_from_template(session, template, "local-user") profile = loads_dict(character.profile_json) assert profile["birthday"] == character.created_at.strftime("%Y-%m-%d") @pytest.mark.asyncio async def test_create_character_from_template_inherits_explicit_birthday(): """模板 profile 有显式 birthday → 子角色继承该值,不兜底。""" async with AsyncSessionLocal() as session: template = _template("test_tpl2", '{"birthday": "2020-01-01"}') session.add(template) await session.flush() character = await create_character_from_template(session, template, "local-user") profile = loads_dict(character.profile_json) assert profile["birthday"] == "2020-01-01"