diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBanner.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBanner.kt new file mode 100644 index 00000000..c60a081a --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBanner.kt @@ -0,0 +1,20 @@ +package kr.co.vividnext.sodalive.v2.subbanner.domain + +import java.time.LocalDateTime + +data class SubBanner( + val id: Long? = null, + val placement: SubBannerPlacement, + val imagePath: String, + val webUrl: String?, + val androidDeepLink: String?, + val iosDeepLink: String?, + val startDate: LocalDateTime?, + val endDate: LocalDateTime? +) { + init { + require(!webUrl.isNullOrBlank() || !androidDeepLink.isNullOrBlank() || !iosDeepLink.isNullOrBlank()) { + "At least one link must be nonblank" + } + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBannerPlacement.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBannerPlacement.kt new file mode 100644 index 00000000..c562ea1f --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBannerPlacement.kt @@ -0,0 +1,6 @@ +package kr.co.vividnext.sodalive.v2.subbanner.domain + +enum class SubBannerPlacement { + HOME_RECOMMENDATION, + CONTENT_RECOMMENDATION +} diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBannerTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBannerTest.kt new file mode 100644 index 00000000..e7905a8c --- /dev/null +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/subbanner/domain/SubBannerTest.kt @@ -0,0 +1,53 @@ +package kr.co.vividnext.sodalive.v2.subbanner.domain + +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 + +class SubBannerTest { + @Test + @DisplayName("세 링크 중 하나 이상이 있는 7개 조합은 허용하고 모두 null이면 거부한다") + fun shouldRejectAllEmptyLinksAndAllowSevenNonEmptyCombinations() { + for (mask in 1..7) { + val webUrl = if (mask and 1 != 0) "https://example.com/banner?next=%2Fhome" else null + val androidDeepLink = if (mask and 2 != 0) "sodalive://content/123?from=banner" else null + val iosDeepLink = if (mask and 4 != 0) "sodalive-ios://content/123#detail" else null + + val banner = banner(webUrl, androidDeepLink, iosDeepLink) + + assertEquals(webUrl, banner.webUrl) + assertEquals(androidDeepLink, banner.androidDeepLink) + assertEquals(iosDeepLink, banner.iosDeepLink) + } + + assertThrows(IllegalArgumentException::class.java) { banner(null, null, null) } + } + + @Test + @DisplayName("null과 빈 문자열 및 공백만으로 된 모든 조합을 거부한다") + fun shouldRejectAllBlankLinksAndAllowAnyNonblankLink() { + val emptyLinks = listOf(null, "", " ", "\t\n") + for (webUrl in emptyLinks) { + for (androidDeepLink in emptyLinks) { + for (iosDeepLink in emptyLinks) { + assertThrows(IllegalArgumentException::class.java) { banner(webUrl, androidDeepLink, iosDeepLink) } + } + } + } + + assertEquals("https://example.com", banner("https://example.com", " ", "").webUrl) + assertEquals("sodalive://home", banner(" ", "sodalive://home", "").androidDeepLink) + assertEquals("sodalive-ios://home", banner("", " ", "sodalive-ios://home").iosDeepLink) + } + + private fun banner(webUrl: String?, androidDeepLink: String?, iosDeepLink: String?): SubBanner = SubBanner( + placement = SubBannerPlacement.HOME_RECOMMENDATION, + imagePath = "sub-banner/image.png", + webUrl = webUrl, + androidDeepLink = androidDeepLink, + iosDeepLink = iosDeepLink, + startDate = null, + endDate = null + ) +}