feat(home-recommendation): AI 캐릭터 creatorId 응답을 추가한다
This commit is contained in:
@@ -286,6 +286,7 @@ class HomeRecommendationFacade(
|
||||
|
||||
private fun HomeAiCharacterRecommendationRecord.toItem() = HomeAiCharacterItem(
|
||||
characterId = characterId,
|
||||
creatorId = creatorId,
|
||||
name = name,
|
||||
description = description,
|
||||
profileImage = imageUrl(cloudFrontHost, profileImage),
|
||||
|
||||
@@ -71,6 +71,7 @@ data class HomeFirstAudioContentItem(
|
||||
|
||||
data class HomeAiCharacterItem(
|
||||
val characterId: Long,
|
||||
val creatorId: Long,
|
||||
val name: String,
|
||||
val description: String,
|
||||
val profileImage: String?,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package kr.co.vividnext.sodalive.v2.api.home
|
||||
|
||||
import kr.co.vividnext.sodalive.chat.character.ChatCharacter
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoom
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberAdapter
|
||||
import kr.co.vividnext.sodalive.member.MemberKind
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreference
|
||||
@@ -11,7 +13,9 @@ import kr.co.vividnext.sodalive.member.following.CreatorFollowing
|
||||
import kr.co.vividnext.sodalive.member.following.CreatorFollowingRepository
|
||||
import kr.co.vividnext.sodalive.support.EmbeddedRedisInitializer
|
||||
import kr.co.vividnext.sodalive.v2.api.home.application.HomeRecommendationFacade
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.RecommendationSnapshot
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryService
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendedSectionType
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
@@ -481,6 +485,29 @@ class HomeRecommendationControllerTest @Autowired constructor(
|
||||
.andExpect(jsonPath("$.data.size").value(20))
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("AI 캐릭터 추천은 홈 통합과 전체보기 응답에 characterId와 creatorId를 함께 노출한다")
|
||||
fun shouldExposeCreatorIdOnAiCharacterRecommendations() {
|
||||
val member = saveMember("ai-character-page-viewer", MemberRole.USER)
|
||||
val character = saveAiCharacter("ai-character-api")
|
||||
saveRecommendationSnapshot(character.id!!)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
mockMvc.perform(get("/api/v2/home/recommendations"))
|
||||
.andExpect(status().isOk)
|
||||
.andExpect(jsonPath("$.data.aiCharacters[0].characterId").value(character.id))
|
||||
.andExpect(jsonPath("$.data.aiCharacters[0].creatorId").value(character.creatorMember!!.id))
|
||||
|
||||
mockMvc.perform(
|
||||
get("/api/v2/home/recommendations/ai-characters")
|
||||
.with(user(MemberAdapter(member)))
|
||||
)
|
||||
.andExpect(status().isOk)
|
||||
.andExpect(jsonPath("$.data.items[0].characterId").value(character.id))
|
||||
.andExpect(jsonPath("$.data.items[0].creatorId").value(character.creatorMember!!.id))
|
||||
}
|
||||
|
||||
private fun saveMember(seed: String, role: MemberRole): Member {
|
||||
return memberRepository.saveAndFlush(
|
||||
Member(
|
||||
@@ -519,4 +546,37 @@ class HomeRecommendationControllerTest @Autowired constructor(
|
||||
entityManager.persist(room)
|
||||
return room
|
||||
}
|
||||
|
||||
private fun saveAiCharacter(name: String): ChatCharacter {
|
||||
val creatorMember = Member(
|
||||
email = null,
|
||||
password = "",
|
||||
nickname = name,
|
||||
role = MemberRole.CREATOR,
|
||||
memberKind = MemberKind.AI_CHARACTER
|
||||
)
|
||||
entityManager.persist(creatorMember)
|
||||
val character = ChatCharacter(
|
||||
characterUUID = "$name-uuid",
|
||||
name = name,
|
||||
description = "description",
|
||||
systemPrompt = "system",
|
||||
isActive = true
|
||||
)
|
||||
character.creatorMember = creatorMember
|
||||
entityManager.persist(character)
|
||||
return character
|
||||
}
|
||||
|
||||
private fun saveRecommendationSnapshot(characterId: Long) {
|
||||
entityManager.persist(
|
||||
RecommendationSnapshot(
|
||||
sectionType = RecommendedSectionType.AI_CHARACTER,
|
||||
targetId = characterId,
|
||||
score = 100.0,
|
||||
snapshotAt = LocalDateTime.of(2026, 6, 1, 23, 59, 59),
|
||||
randomTieBreaker = 0.1
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ class HomeRecommendationResponseTest {
|
||||
aiCharacters = listOf(
|
||||
HomeAiCharacterItem(
|
||||
characterId = 3L,
|
||||
creatorId = 13L,
|
||||
name = "character",
|
||||
description = "description",
|
||||
profileImage = "https://cdn.test/profile/character.png",
|
||||
@@ -38,6 +39,7 @@ class HomeRecommendationResponseTest {
|
||||
),
|
||||
HomeAiCharacterItem(
|
||||
characterId = 4L,
|
||||
creatorId = 14L,
|
||||
name = "character-without-image",
|
||||
description = "description",
|
||||
profileImage = null,
|
||||
@@ -86,6 +88,7 @@ class HomeRecommendationResponseTest {
|
||||
assertFalse(json["firstAudioContents"][0].has("pointAvailable"))
|
||||
assertFalse(json["firstAudioContents"][0].has("releaseDate"))
|
||||
assertEquals("https://cdn.test/profile/character.png", json["aiCharacters"][0]["profileImage"].asText())
|
||||
assertEquals(13L, json["aiCharacters"][0]["creatorId"].asLong())
|
||||
assertEquals(true, json["aiCharacters"][1]["profileImage"].isNull)
|
||||
assertEquals(5L, json["popularCommunityPosts"][0]["postId"].asLong())
|
||||
assertEquals("https://cdn.test/community/image.png", json["popularCommunityPosts"][0]["imageUrl"].asText())
|
||||
|
||||
Reference in New Issue
Block a user