Test #467
+4
@@ -1,5 +1,6 @@
|
||||
package kr.co.vividnext.sodalive.v2.api.creator.channel.home.dto
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import kr.co.vividnext.sodalive.v2.api.creator.channel.common.dto.CreatorChannelAudioContentResponse
|
||||
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
||||
@@ -109,6 +110,8 @@ data class CreatorChannelLiveResponse(
|
||||
}
|
||||
|
||||
data class CreatorChannelDonationResponse(
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
val donationId: Long?,
|
||||
val nickname: String,
|
||||
val profileImageUrl: String,
|
||||
val can: Int,
|
||||
@@ -120,6 +123,7 @@ data class CreatorChannelDonationResponse(
|
||||
companion object {
|
||||
fun from(donation: CreatorChannelDonation): CreatorChannelDonationResponse {
|
||||
return CreatorChannelDonationResponse(
|
||||
donationId = donation.donationId,
|
||||
nickname = donation.nickname,
|
||||
profileImageUrl = donation.profileImageUrl,
|
||||
can = donation.can,
|
||||
|
||||
+2
@@ -195,6 +195,7 @@ class DefaultCreatorChannelHomeQueryRepository(
|
||||
.select(
|
||||
Projections.constructor(
|
||||
CreatorChannelDonationRecord::class.java,
|
||||
channelDonationMessage.id,
|
||||
channelDonationMessage.member.id,
|
||||
donorName.displayName,
|
||||
channelDonationMessage.member.profileImage,
|
||||
@@ -210,6 +211,7 @@ class DefaultCreatorChannelHomeQueryRepository(
|
||||
.leftJoin(donorName.name).on(donorName.condition)
|
||||
.where(
|
||||
channelDonationMessage.creator.id.eq(creatorId),
|
||||
channelDonationMessage.isHidden.isFalse,
|
||||
channelDonationMessage.createdAt.goe(start),
|
||||
channelDonationMessage.createdAt.lt(end)
|
||||
)
|
||||
|
||||
+4
-2
@@ -103,7 +103,7 @@ class CreatorChannelHomeQueryService(
|
||||
)?.toDomain(),
|
||||
latestAudioContent = latestAudioContent,
|
||||
channelDonations = queryPort.findChannelDonations(creatorId, viewerId, now, lang = lang)
|
||||
.map { it.toDomain(creatorId, viewerId, lang) },
|
||||
.map { it.toDomain(creatorId, viewer, lang) },
|
||||
notices = communityQueryService.findHomeCommunityPosts(
|
||||
creatorId = creatorId,
|
||||
viewerId = viewerId,
|
||||
@@ -197,9 +197,11 @@ class CreatorChannelHomeQueryService(
|
||||
isRented = isRented
|
||||
)
|
||||
|
||||
private fun CreatorChannelDonationRecord.toDomain(creatorId: Long, viewerId: Long, lang: Lang): CreatorChannelDonation {
|
||||
private fun CreatorChannelDonationRecord.toDomain(creatorId: Long, viewer: Member, lang: Lang): CreatorChannelDonation {
|
||||
val viewerId = viewer.id!!
|
||||
val isMasked = isSecret && viewerId != creatorId && viewerId != memberId
|
||||
return CreatorChannelDonation(
|
||||
donationId = donationId.takeIf { viewer.role == MemberRole.CREATOR && viewerId == creatorId },
|
||||
memberId = memberId,
|
||||
nickname = when {
|
||||
isMasked -> messageSource.getMessage("explorer.channel_donation.anonymous.nickname", lang).orEmpty()
|
||||
|
||||
+1
@@ -43,6 +43,7 @@ data class CreatorChannelLive(
|
||||
)
|
||||
|
||||
data class CreatorChannelDonation(
|
||||
val donationId: Long?,
|
||||
val memberId: Long,
|
||||
val nickname: String,
|
||||
val profileImageUrl: String,
|
||||
|
||||
+1
@@ -114,6 +114,7 @@ data class CreatorChannelAudioContentRecord(
|
||||
)
|
||||
|
||||
data class CreatorChannelDonationRecord(
|
||||
val donationId: Long,
|
||||
val memberId: Long,
|
||||
val nickname: String,
|
||||
val profileImagePath: String?,
|
||||
|
||||
+6
-1
@@ -35,6 +35,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.boot.test.mock.mockito.MockBean
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user
|
||||
import org.springframework.test.annotation.DirtiesContext
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
|
||||
@@ -54,6 +55,7 @@ import javax.persistence.EntityManager
|
||||
)
|
||||
@AutoConfigureMockMvc
|
||||
@ContextConfiguration(initializers = [EmbeddedRedisInitializer::class])
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||
class CreatorChannelHomeEndToEndTest @Autowired constructor(
|
||||
private val mockMvc: MockMvc,
|
||||
private val entityManager: EntityManager,
|
||||
@@ -178,9 +180,12 @@ class CreatorChannelHomeEndToEndTest @Autowired constructor(
|
||||
item["createdAtUtc"].asText()
|
||||
)
|
||||
assertEquals(
|
||||
setOf("nickname", "profileImageUrl", "can", "message", "createdAtUtc", "isSecret"),
|
||||
setOf("nickname", "profileImageUrl", "can", "message", "createdAtUtc", "isSecret") +
|
||||
if (viewerRole == "creator") setOf("donationId") else emptySet(),
|
||||
item.fieldNames().asSequence().toSet()
|
||||
)
|
||||
if (viewerRole == "creator") assertEquals(stored.id, item["donationId"]?.asLong())
|
||||
assertFalse(item.has("memberId"))
|
||||
val masked = stored.isSecret && fixture.viewer.id != fixture.creatorId && fixture.viewer.id != stored.member?.id
|
||||
if (masked) {
|
||||
assertEquals(anonymousNickname, item["nickname"].asText())
|
||||
|
||||
+1
@@ -254,6 +254,7 @@ class CreatorChannelHomeControllerTest @Autowired constructor(
|
||||
),
|
||||
channelDonations = listOf(
|
||||
CreatorChannelDonation(
|
||||
donationId = null,
|
||||
memberId = 20L,
|
||||
nickname = "fan",
|
||||
profileImageUrl = "fan.png",
|
||||
|
||||
+1
@@ -186,6 +186,7 @@ class CreatorChannelHomeFacadeTest {
|
||||
),
|
||||
channelDonations = listOf(
|
||||
CreatorChannelDonation(
|
||||
donationId = null,
|
||||
memberId = 20L,
|
||||
nickname = "fan",
|
||||
profileImageUrl = "fan.png",
|
||||
|
||||
+52
-1
@@ -821,6 +821,55 @@ class DefaultCreatorChannelHomeQueryRepositoryTest @Autowired constructor(
|
||||
assertEquals(listOf(true, true, false, true, false, true, false, true), records.map { it.isSecret })
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("홈은 최신 숨김 공개·비밀 후보를 제외한 뒤 동시각 ID순으로 visible 8건을 보충한다")
|
||||
fun shouldRefillHomeWithLatestEightVisibleDonationsAfterHiddenRowsAreExcluded() {
|
||||
val now = LocalDateTime.of(2026, 6, 12, 12, 0)
|
||||
val creator = saveMember("hidden-home-creator", MemberRole.CREATOR)
|
||||
val donor = saveMember("hidden-home-donor", MemberRole.USER)
|
||||
val viewers = listOf(
|
||||
creator,
|
||||
donor,
|
||||
saveMember("hidden-home-outsider", MemberRole.USER),
|
||||
saveMember("hidden-home-other-creator", MemberRole.CREATOR),
|
||||
saveMember("hidden-home-admin", MemberRole.ADMIN)
|
||||
)
|
||||
val rows = (1..12).map { index ->
|
||||
saveDonation(
|
||||
creator,
|
||||
donor,
|
||||
index,
|
||||
now.plusMinutes((index / 2).toLong()),
|
||||
isSecret = index % 2 == 1,
|
||||
isHidden = index >= 10
|
||||
)
|
||||
}
|
||||
flushAndClear()
|
||||
|
||||
viewers.forEach { viewer ->
|
||||
val records = repository.findChannelDonations(creator.id!!, viewer.id!!, now, limit = 8, lang = Lang.KO)
|
||||
assertEquals((9 downTo 2).toList(), records.map { it.can })
|
||||
assertEquals(rows.take(9).drop(1).reversed().map { it.id }, records.map { it.donationId })
|
||||
assertEquals(listOf(true, false, true, false, true, false, true, false), records.map { it.isSecret })
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("모든 후원이 숨김이면 홈 후원은 빈 목록이다")
|
||||
fun shouldReturnEmptyHomeDonationsWhenAllRowsAreHidden() {
|
||||
val now = LocalDateTime.of(2026, 6, 12, 12, 0)
|
||||
val creator = saveMember("all-hidden-home-creator", MemberRole.CREATOR)
|
||||
val donor = saveMember("all-hidden-home-donor", MemberRole.USER)
|
||||
listOf(false, true).forEach { secret ->
|
||||
saveDonation(creator, donor, 100, now, isSecret = secret, isHidden = true)
|
||||
}
|
||||
flushAndClear()
|
||||
|
||||
listOf(creator, donor).forEach { viewer ->
|
||||
assertTrue(repository.findChannelDonations(creator.id!!, viewer.id!!, now, limit = 8, lang = Lang.KO).isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("채널 후원 메시지는 추가 메시지만 반환하고 없으면 빈 문자열을 반환한다")
|
||||
fun shouldReturnOnlyAdditionalChannelDonationMessage() {
|
||||
@@ -1376,9 +1425,11 @@ class DefaultCreatorChannelHomeQueryRepositoryTest @Autowired constructor(
|
||||
can: Int,
|
||||
createdAt: LocalDateTime,
|
||||
isSecret: Boolean = false,
|
||||
additionalMessage: String? = "thanks"
|
||||
additionalMessage: String? = "thanks",
|
||||
isHidden: Boolean = false
|
||||
): ChannelDonationMessage {
|
||||
val donation = ChannelDonationMessage(can = can, isSecret = isSecret, additionalMessage = additionalMessage)
|
||||
donation.isHidden = isHidden
|
||||
donation.creator = creator
|
||||
donation.member = donor
|
||||
entityManager.persist(donation)
|
||||
|
||||
+6
@@ -204,6 +204,9 @@ class CreatorChannelHomeQueryServiceTest {
|
||||
"20, USER, true",
|
||||
"10, USER, true",
|
||||
"30, CREATOR, true",
|
||||
"1, USER, true",
|
||||
"1, ADMIN, true",
|
||||
"40, ADMIN, true",
|
||||
"1, CREATOR, false",
|
||||
"20, USER, false",
|
||||
"10, USER, false",
|
||||
@@ -237,6 +240,7 @@ class CreatorChannelHomeQueryServiceTest {
|
||||
assertEquals(isSecret, donation.isSecret)
|
||||
assertEquals(30, donation.can)
|
||||
assertEquals(LocalDateTime.of(2026, 6, 13, 8, 0), donation.createdAt)
|
||||
assertEquals(if (role == MemberRole.CREATOR && viewerId == 1L) 101L else null, donation.donationId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,6 +459,7 @@ class CreatorChannelHomeQueryServiceTest {
|
||||
),
|
||||
channelDonations = listOf(
|
||||
CreatorChannelDonation(
|
||||
donationId = null,
|
||||
memberId = 20L,
|
||||
nickname = "fan",
|
||||
profileImageUrl = "fan.png",
|
||||
@@ -690,6 +695,7 @@ private class FakeCreatorChannelHomeQueryPort(private val donorId: Long = 20L) :
|
||||
lang: Lang
|
||||
): List<CreatorChannelDonationRecord> = listOf(
|
||||
CreatorChannelDonationRecord(
|
||||
donationId = 101L,
|
||||
memberId = donorId,
|
||||
nickname = channelDonationNickname,
|
||||
profileImagePath = channelDonationProfilePath,
|
||||
|
||||
Reference in New Issue
Block a user