package kr.co.vividnext.sodalive.member import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.member.login.LoginRequest import kr.co.vividnext.sodalive.support.EmbeddedRedisInitializer import kr.co.vividnext.sodalive.v2.home.following.adapter.out.persistence.HomeFollowingNewsInbox import kr.co.vividnext.sodalive.v2.home.following.adapter.out.persistence.HomeFollowingNewsInboxJpaRepository import kr.co.vividnext.sodalive.v2.home.following.domain.FollowingNewsType import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertThrows import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime import javax.persistence.EntityManager @SpringBootTest @Transactional @ContextConfiguration(initializers = [EmbeddedRedisInitializer::class]) class MemberServiceTest @Autowired constructor( private val service: MemberService, private val memberRepository: MemberRepository, private val homeFollowingNewsInboxJpaRepository: HomeFollowingNewsInboxJpaRepository, private val entityManager: EntityManager ) { @Test @DisplayName("AI 캐릭터용 Member는 일반 로그인할 수 없다") fun shouldRejectAiCharacterMemberLoginBeforeAuthentication() { val member = memberRepository.save( Member( email = "ai-character-login@test.com", password = "", nickname = "AI 캐릭터 로그인", role = MemberRole.CREATOR, memberKind = MemberKind.AI_CHARACTER ) ) entityManager.flush() entityManager.clear() val exception = assertThrows(SodaException::class.java) { service.login(LoginRequest(email = member.email!!, password = "password")) } assertEquals("common.error.bad_credentials", exception.messageKey) } @Test @DisplayName("언팔로우 성공 시 해당 회원과 크리에이터의 활성 최근 소식을 비활성화하고 재팔로우해도 복구하지 않는다") fun shouldDeactivateFollowingNewsInboxOnCreatorUnFollowAndKeepInactiveAfterRefollow() { val member = memberRepository.save(Member(email = "follower@test.com", password = "password", nickname = "follower")) val creator = memberRepository.save( Member( email = "creator@test.com", password = "password", nickname = "creator", role = MemberRole.CREATOR ) ) service.creatorFollow(creatorId = creator.id!!, isNotify = true, isActive = true, memberId = member.id!!) val inbox = homeFollowingNewsInboxJpaRepository.save( HomeFollowingNewsInbox( memberId = member.id!!, creatorId = creator.id!!, newsType = FollowingNewsType.COMMUNITY_POST, sourceKey = "COMMUNITY_POST:1", targetId = 1L, occurredAtUtc = LocalDateTime.of(2026, 6, 25, 1, 0), visibleFromAtUtc = LocalDateTime.of(2026, 6, 25, 1, 0), creatorNickname = "creator", creatorProfileImagePath = null, title = "title", body = "body", thumbnailImagePath = null, rank = null, isAdult = false ) ) entityManager.flush() entityManager.clear() service.creatorUnFollow(creatorId = creator.id!!, memberId = member.id!!) entityManager.flush() entityManager.clear() assertEquals(false, homeFollowingNewsInboxJpaRepository.findById(inbox.id!!).get().isActive) service.creatorFollow(creatorId = creator.id!!, isNotify = true, isActive = true, memberId = member.id!!) entityManager.flush() entityManager.clear() assertEquals(false, homeFollowingNewsInboxJpaRepository.findById(inbox.id!!).get().isActive) } }