feat(creator-channel): 후원 탭 도메인 계약을 추가한다

This commit is contained in:
2026-06-22 17:59:01 +09:00
parent b2fae3e081
commit e516a7406f
5 changed files with 265 additions and 0 deletions
@@ -0,0 +1,125 @@
package kr.co.vividnext.sodalive.v2.creator.channel.donation.domain
import kr.co.vividnext.sodalive.member.DonationRankingPeriod
import kr.co.vividnext.sodalive.member.MemberRole
import kr.co.vividnext.sodalive.v2.creator.channel.donation.port.out.CreatorChannelDonationCreatorRecord
import kr.co.vividnext.sodalive.v2.creator.channel.donation.port.out.CreatorChannelDonationRankingRecord
import kr.co.vividnext.sodalive.v2.creator.channel.donation.port.out.CreatorChannelDonationRecord
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import java.time.LocalDateTime
class CreatorChannelDonationQueryPolicyTest {
private val policy = CreatorChannelDonationQueryPolicy()
@Test
@DisplayName("후원 탭 page 정책은 null 요청을 기본값으로 fallback하고 fetch limit을 계산한다")
fun shouldFallbackNullPageAndSizeForDonationTab() {
val page = policy.createPage(page = null, size = null)
assertEquals(0, page.page)
assertEquals(20, page.size)
assertEquals(0L, page.offset)
assertEquals(21, page.fetchLimit)
}
@Test
@DisplayName("후원 탭 page 정책은 최소/최대 범위로 fallback하고 fetch limit을 계산한다")
fun shouldFallbackPageAndSizeForDonationTab() {
val minimumPage = policy.createPage(page = -1, size = 10)
val maximumPage = policy.createPage(page = 2, size = 100)
assertEquals(0, minimumPage.page)
assertEquals(20, minimumPage.size)
assertEquals(0L, minimumPage.offset)
assertEquals(21, minimumPage.fetchLimit)
assertEquals(2, maximumPage.page)
assertEquals(50, maximumPage.size)
assertEquals(100L, maximumPage.offset)
assertEquals(51, maximumPage.fetchLimit)
}
@Test
@DisplayName("후원 탭 목록 정책은 요청 size만 남기고 다음 페이지 여부를 계산한다")
fun shouldLimitItemsAndCalculateHasNext() {
val page = policy.createPage(page = 0, size = 20)
val fetched = (1..21).toList()
val items = policy.limitItems(fetched, page)
assertEquals((1..20).toList(), items)
assertTrue(policy.hasNext(fetched, page))
assertFalse(policy.hasNext((1..20).toList(), page))
assertFalse(policy.hasNext(emptyList<Int>(), page))
}
@Test
@DisplayName("후원 탭 월 범위 정책은 현재 UTC 시각 기준 KST 월 시작과 다음 월 시작을 UTC로 계산한다")
fun shouldCalculateCurrentKstMonthRangeAsUtc() {
val range = policy.currentKstMonthRange(LocalDateTime.of(2026, 6, 22, 3, 0))
assertEquals(LocalDateTime.of(2026, 5, 31, 15, 0), range.startInclusiveUtc)
assertEquals(LocalDateTime.of(2026, 6, 30, 15, 0), range.endExclusiveUtc)
}
@Test
@DisplayName("후원 탭 domain model과 port record는 Phase 1 계약 필드를 유지한다")
fun shouldKeepDomainAndPortContract() {
val createdAt = LocalDateTime.of(2026, 6, 22, 10, 0)
val page = policy.createPage(page = 0, size = 20)
val ranking = CreatorChannelDonationRanking(
userId = 10L,
nickname = "fan",
profileImage = "https://cdn.test/fan.png",
donationCan = 100
)
val donation = CreatorChannelDonation(
nickname = "donor",
profileImageUrl = "https://cdn.test/donor.png",
can = 50,
message = "thanks",
createdAt = createdAt
)
val tab = CreatorChannelDonationTab(
donationCount = 1,
rankings = listOf(ranking),
donations = listOf(donation),
page = page,
hasNext = false
)
val creatorRecord = CreatorChannelDonationCreatorRecord(
creatorId = 1L,
role = MemberRole.CREATOR,
nickname = "creator",
isVisibleDonationRank = true,
donationRankingPeriod = DonationRankingPeriod.CUMULATIVE
)
val donationRecord = CreatorChannelDonationRecord(
nickname = "donor",
profileImagePath = null,
can = 50,
message = "thanks",
createdAt = createdAt
)
val rankingRecord = CreatorChannelDonationRankingRecord(
userId = 10L,
nickname = "fan",
profileImage = "https://cdn.test/fan.png",
donationCan = 100
)
assertEquals(1, tab.donationCount)
assertEquals(ranking, tab.rankings.first())
assertEquals(donation, tab.donations.first())
assertEquals(page, tab.page)
assertFalse(tab.hasNext)
assertEquals(MemberRole.CREATOR, creatorRecord.role)
assertEquals(DonationRankingPeriod.CUMULATIVE, creatorRecord.donationRankingPeriod)
assertNull(donationRecord.profileImagePath)
assertEquals(100, rankingRecord.donationCan)
}
}