import pytest from accounts.migration_service import apply_visitor_migration, migration_summary from accounts.models import User, VisitorMigration from content.models import ContentInteraction, ContentItem from math_life.models import ( MathBTIAssessment, MathBTIResult, MathIdentity, Story, StoryRun, StoryVersion, ) from progression.models import Card, UserCard @pytest.mark.django_db def test_apply_visitor_migration_确认后事务化导入且可重复调用(): user = User.objects.create_user( username="visitor_user", password="StrongPass_2026", nickname="游客用户", ) definition = { "axes": [{"id": "style"}], "scoring": {"axes": ["style"], "cutoff": 0}, "questions": [ {"id": 1, "axis": "style", "options": [{"score": 0}, {"score": 1}]} ], } MathBTIAssessment.objects.create( version="test-1", title="测试 MathBTI", definition=definition, is_published=True, ) MathIdentity.objects.create( code="1", name="测试身份", clan="信仰者", mathematician="高斯", ) story = Story.objects.create(slug="visitor-story", title="游客人生") StoryVersion.objects.create( story=story, version=1, is_published=True, content={ "start_node": "start", "nodes": { "start": {"scene": "开始", "choices": []}, "saved": {"scene": "存档", "choices": []}, }, }, ) content = ContentItem.objects.create( slug="favorite-content", title="收藏内容", kind=ContentItem.Kind.KNOWLEDGE, is_published=True, ) legacy_card = Card.objects.create( slug="legacy-card", name="旧人物卡", mathematician="欧拉", description="游客阶段获得", ) payload = { "mathbti": {"version": "test-1", "answers": [1]}, "story_saves": [ { "story_slug": "visitor-story", "version": 1, "current_node": "saved", "state": {"energy": 3}, } ], "favorites": ["favorite-content"], "cards": ["legacy-card"], } VisitorMigration.objects.create( user=user, payload=payload, summary=migration_summary(payload), ) first = apply_visitor_migration(user) second = apply_visitor_migration(user) assert first.status == VisitorMigration.Status.APPLIED assert second.status == VisitorMigration.Status.APPLIED assert MathBTIResult.objects.filter(user=user).count() == 1 assert StoryRun.objects.get(user=user).current_node == "saved" assert ContentInteraction.objects.filter( user=user, content=content, action=ContentInteraction.Action.FAVORITE, ).count() == 1 assert UserCard.objects.filter(user=user, card=legacy_card).count() == 1