feat(creatorname): 레거시 조회와 검색에 언어별 이름을 적용한다

This commit is contained in:
2026-10-16 14:04:17 +09:00
parent 995b41e89d
commit eef2e2bf55
66 changed files with 3022 additions and 373 deletions
@@ -0,0 +1,108 @@
package kr.co.vividnext.sodalive.member
import kr.co.vividnext.sodalive.configs.QueryDslConfig
import org.junit.jupiter.api.Assertions.assertAll
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.context.annotation.Import
import org.springframework.jdbc.core.JdbcTemplate
import javax.persistence.EntityManager
@DataJpaTest(properties = ["spring.cache.type=none"])
@Import(QueryDslConfig::class)
class MemberRepositoryLocalizedNameTest @Autowired constructor(
private val repository: MemberRepository,
private val entityManager: EntityManager,
private val jdbcTemplate: JdbcTemplate
) {
@Test
@DisplayName("크리에이터 요청의 회원 검색은 USER 원본 매칭과 CREATOR 별칭을 함께 유지한다")
fun shouldRetainUserOriginalMatchesAndAddOnlyCreatorAliasesForCreatorRequester() {
val requester = saveMember("needle-requester", MemberRole.CREATOR)
val creator = saveMember("creator-original", MemberRole.CREATOR)
val user = saveMember("needle-user", MemberRole.USER)
val aiUser = saveMember("ai-user-original", MemberRole.USER).apply { memberKind = MemberKind.AI_CHARACTER }
val admin = saveMember("needle-admin", MemberRole.ADMIN)
val agent = saveMember("needle-agent", MemberRole.AGENT)
val bot = saveMember("needle-bot", MemberRole.BOT)
listOf(requester, creator, user, aiUser, admin, agent, bot).forEach { saveAlias(it, "needle-alias") }
entityManager.clear()
val matches = repository.findByNicknameAndOtherCondition("NeEdLe", requester)
assertEquals(setOf(creator.id, user.id), matches.map { it.id }.toSet())
assertEquals(2, matches.size)
assertEquals(listOf(creator.id), repository.findByNicknameAndOtherCondition("creator-original", requester).map { it.id })
}
@Test
@DisplayName("USER 요청의 회원 검색은 기존 USER·self·관리 역할 제외 조건을 별칭에도 적용한다")
fun shouldPreserveUserRequesterRoleAndSelfExclusionsForAliases() {
val requester = saveMember("needle-viewer", MemberRole.USER)
val creator = saveMember("creator-original", MemberRole.CREATOR)
val user = saveMember("needle-user", MemberRole.USER)
val admin = saveMember("needle-admin", MemberRole.ADMIN)
val agent = saveMember("needle-agent", MemberRole.AGENT)
val bot = saveMember("needle-bot", MemberRole.BOT)
listOf(requester, creator, user, admin, agent, bot).forEach { saveAlias(it, "needle-alias") }
entityManager.clear()
assertEquals(listOf(creator.id), repository.findByNicknameAndOtherCondition("needle", requester).map { it.id })
}
@Test
@DisplayName("비활성 JA와 다른 언어 이름은 회원 별칭 검색에서 제외하고 현재 원본은 유지한다")
fun shouldExcludeInactiveAndNonJaAliasesWhileRetainingCurrentOriginalNickname() {
val requester = saveMember("member-clear-viewer", MemberRole.CREATOR)
val creator = saveMember("before-rename", MemberRole.CREATOR)
saveAlias(creator, "RetainedAlias", isActive = false)
saveAlias(creator, "EnglishAlias", lang = "EN")
creator.nickname = "after-rename"
entityManager.flush()
entityManager.clear()
assertEquals(emptyList<Long>(), repository.findByNicknameAndOtherCondition("RetainedAlias", requester).map { it.id })
assertEquals(emptyList<Long>(), repository.findByNicknameAndOtherCondition("EnglishAlias", requester).map { it.id })
assertEquals(listOf(creator.id), repository.findByNicknameAndOtherCondition("after-rename", requester).map { it.id })
jdbcTemplate.update(
"update creator_localized_name set is_active = true where member_id = ? and lang = 'JA'",
creator.id!!
)
assertAll(
{
assertEquals(
listOf(creator.id),
repository.findByNicknameAndOtherCondition("RetainedAlias", requester).map { it.id }
)
},
{
assertEquals(
listOf(creator.id),
repository.findByNicknameAndOtherCondition("after-rename", requester).map { it.id }
)
}
)
}
private fun saveMember(nickname: String, role: MemberRole): Member {
return Member(email = "$nickname@test.com", password = "password", nickname = nickname, role = role).also {
entityManager.persist(it)
}
}
private fun saveAlias(member: Member, displayName: String, isActive: Boolean = true, lang: String = "JA") {
entityManager.flush()
jdbcTemplate.update(
"insert into creator_localized_name (member_id, lang, display_name, is_active, created_at, updated_at) " +
"values (?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)",
member.id!!,
lang,
displayName,
isActive
)
}
}
@@ -10,6 +10,7 @@ import kr.co.vividnext.sodalive.member.block.BlockMember
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
import kr.co.vividnext.sodalive.member.block.MemberBlockRequest
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
import kr.co.vividnext.sodalive.support.originalLocalizedNameService
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -62,6 +63,7 @@ class MemberServiceCacheEvictionTest {
authenticationManagerBuilder = mock(),
messageSource = SodaMessageSource(),
langContext = LangContext(),
localizedNameService = originalLocalizedNameService(),
countryContext = CountryContext(),
memberContentPreferenceService = mock<MemberContentPreferenceService>(),
objectMapper = ObjectMapper(),
@@ -13,6 +13,7 @@ import kr.co.vividnext.sodalive.member.stipulation.Stipulation
import kr.co.vividnext.sodalive.member.stipulation.StipulationAgreeRepository
import kr.co.vividnext.sodalive.member.stipulation.StipulationIds
import kr.co.vividnext.sodalive.member.stipulation.StipulationRepository
import kr.co.vividnext.sodalive.support.originalLocalizedNameService
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
@@ -71,6 +72,7 @@ class MemberServiceContentPreferenceTest {
authenticationManagerBuilder = mock(),
messageSource = SodaMessageSource(),
langContext = LangContext(),
localizedNameService = originalLocalizedNameService(),
countryContext = CountryContext(),
memberContentPreferenceService = memberContentPreferenceService,
objectMapper = ObjectMapper(),