Test #465
+5
-1
@@ -7,6 +7,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService
|
||||
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationQueryRepository
|
||||
import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse
|
||||
import kr.co.vividnext.sodalive.event.EventService
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.rank.RankingService
|
||||
@@ -67,7 +68,10 @@ class AudioContentMainTabAlarmService(
|
||||
theme = alarmThemeList[0]
|
||||
)
|
||||
|
||||
val eventBannerList = eventService.getEventList(isAdult = isAdult)
|
||||
val eventBannerList = eventService.getEventList(
|
||||
isAdult = isAdult,
|
||||
lang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
|
||||
)
|
||||
val curationList = curationRepository.findByContentMainTabId(tabId = 4, isAdult = isAdult)
|
||||
.map {
|
||||
GetContentCurationResponse(
|
||||
|
||||
+5
-1
@@ -8,6 +8,7 @@ import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationQueryR
|
||||
import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTabRepository
|
||||
import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse
|
||||
import kr.co.vividnext.sodalive.event.EventService
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.rank.RankingService
|
||||
@@ -66,7 +67,10 @@ class AudioContentMainTabAsmrService(
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val eventBannerList = eventService.getEventList(isAdult = isAdult)
|
||||
val eventBannerList = eventService.getEventList(
|
||||
isAdult = isAdult,
|
||||
lang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
|
||||
)
|
||||
|
||||
val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult)
|
||||
.map {
|
||||
|
||||
+5
-1
@@ -9,6 +9,7 @@ import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationQueryR
|
||||
import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse
|
||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
||||
import kr.co.vividnext.sodalive.event.EventService
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.rank.RankingService
|
||||
@@ -86,7 +87,10 @@ class AudioContentMainTabContentService(
|
||||
)
|
||||
|
||||
// 이벤트 배너
|
||||
val eventBannerList = eventService.getEventList(isAdult = isAdult)
|
||||
val eventBannerList = eventService.getEventList(
|
||||
isAdult = isAdult,
|
||||
lang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
|
||||
)
|
||||
|
||||
val contentRankCreatorList = rankingService.fetchCreatorBySellContentCountRankTop20(
|
||||
memberId = member.id!!,
|
||||
|
||||
+5
-1
@@ -4,6 +4,7 @@ import kr.co.vividnext.sodalive.content.ContentType
|
||||
import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem
|
||||
import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService
|
||||
import kr.co.vividnext.sodalive.event.EventService
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.notice.ServiceNoticeService
|
||||
@@ -83,7 +84,10 @@ class AudioContentMainTabHomeService(
|
||||
)
|
||||
|
||||
// 이벤트 배너
|
||||
val eventBannerList = eventService.getEventList(isAdult = isAdult)
|
||||
val eventBannerList = eventService.getEventList(
|
||||
isAdult = isAdult,
|
||||
lang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
|
||||
)
|
||||
|
||||
val contentRankCreatorList = rankingService.fetchCreatorBySellContentCountRankTop20(
|
||||
memberId = member?.id,
|
||||
|
||||
+5
-1
@@ -8,6 +8,7 @@ import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationQueryR
|
||||
import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTabRepository
|
||||
import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse
|
||||
import kr.co.vividnext.sodalive.event.EventService
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.rank.RankingService
|
||||
@@ -66,7 +67,10 @@ class AudioContentMainTabLiveReplayService(
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val eventBannerList = eventService.getEventList(isAdult = isAdult)
|
||||
val eventBannerList = eventService.getEventList(
|
||||
isAdult = isAdult,
|
||||
lang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
|
||||
)
|
||||
|
||||
val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult)
|
||||
.map {
|
||||
|
||||
+5
-1
@@ -7,6 +7,7 @@ import kr.co.vividnext.sodalive.content.main.tab.RecommendSeriesRepository
|
||||
import kr.co.vividnext.sodalive.content.series.ContentSeriesService
|
||||
import kr.co.vividnext.sodalive.content.series.GetSeriesListResponse
|
||||
import kr.co.vividnext.sodalive.event.EventService
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.rank.RankingService
|
||||
@@ -123,7 +124,10 @@ class AudioContentMainTabSeriesService(
|
||||
}
|
||||
|
||||
// 이벤트 배너
|
||||
val eventBannerList = eventService.getEventList(isAdult = isAdult)
|
||||
val eventBannerList = eventService.getEventList(
|
||||
isAdult = isAdult,
|
||||
lang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
|
||||
)
|
||||
|
||||
// 큐레이션
|
||||
val curationList = curationRepository.findByContentMainTabId(tabId = 2, isAdult = isAdult)
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
package kr.co.vividnext.sodalive.event
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.jwt.TokenProvider
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreference
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceRepository
|
||||
import kr.co.vividnext.sodalive.member.token.MemberTokenRepository
|
||||
import kr.co.vividnext.sodalive.support.EmbeddedRedisInitializer
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.ValueSource
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate
|
||||
import org.springframework.http.HttpEntity
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
import org.springframework.test.annotation.DirtiesContext
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@SpringBootTest(
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = [
|
||||
"cloud.aws.cloud-front.host=https://cdn.test",
|
||||
"spring.datasource.url=jdbc:h2:mem:event-banner-language-http;" +
|
||||
"MODE=MySQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=VALUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
|
||||
]
|
||||
)
|
||||
@ContextConfiguration(initializers = [EmbeddedRedisInitializer::class])
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||
class EventBannerLanguageIntegrationTest @Autowired constructor(
|
||||
private val restTemplate: TestRestTemplate,
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val eventRepository: EventRepository,
|
||||
private val memberRepository: MemberRepository,
|
||||
private val preferenceRepository: MemberContentPreferenceRepository,
|
||||
private val tokenRepository: MemberTokenRepository,
|
||||
private val tokenProvider: TokenProvider,
|
||||
private val jdbcTemplate: JdbcTemplate
|
||||
) {
|
||||
private val eventIds = mutableMapOf<Pair<Lang, Boolean?>, Long>()
|
||||
private val tokens = mutableMapOf<Long, String>()
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
jdbcTemplate.execute(
|
||||
"CREATE ALIAS IF NOT EXISTS DATE_FORMAT FOR 'kr.co.vividnext.sodalive.support.H2MysqlDateFunctions.dateFormat'"
|
||||
)
|
||||
jdbcTemplate.execute(
|
||||
"CREATE ALIAS IF NOT EXISTS CONVERT_TZ FOR 'kr.co.vividnext.sodalive.support.H2MysqlDateFunctions.convertTz'"
|
||||
)
|
||||
Lang.values().forEach { lang ->
|
||||
listOf(null, false, true).forEach { adult ->
|
||||
val saved = eventRepository.saveAndFlush(
|
||||
Event(
|
||||
thumbnailImage = "$lang-$adult.png",
|
||||
detailImage = null,
|
||||
popupImage = null,
|
||||
link = "https://example.test/$lang",
|
||||
title = "$lang-$adult",
|
||||
lang = lang,
|
||||
isAdult = adult,
|
||||
startDate = LocalDateTime.now().minusDays(1),
|
||||
endDate = LocalDateTime.now().plusDays(1)
|
||||
)
|
||||
)
|
||||
eventIds[lang to adult] = requireNotNull(saved.id)
|
||||
}
|
||||
}
|
||||
listOf(900001L, 29721L, 16L).forEach { id ->
|
||||
val saved = memberRepository.saveAndFlush(
|
||||
Member(email = "banner-$id@test.com", password = "password", nickname = "banner-$id")
|
||||
)
|
||||
jdbcTemplate.update("update member set id = ? where id = ?", id, saved.id)
|
||||
val member = memberRepository.findById(id).orElseThrow()
|
||||
preferenceRepository.saveAndFlush(MemberContentPreference().apply { this.member = member })
|
||||
tokens[id] = tokenProvider.createToken(
|
||||
UsernamePasswordAuthenticationToken(member.email, "", listOf(SimpleGrantedAuthority("ROLE_USER"))),
|
||||
id
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun cleanUp() {
|
||||
tokenRepository.deleteAll()
|
||||
preferenceRepository.deleteAllInBatch()
|
||||
memberRepository.deleteAllById(tokens.keys)
|
||||
eventRepository.deleteAllInBatch()
|
||||
tokens.clear()
|
||||
eventIds.clear()
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = ["alarm", "replay", "series", "asmr", "content", "home"])
|
||||
@DisplayName("여섯 메인 탭은 실제 회원 국가·강제 매핑의 언어와 기존 성인 조건을 함께 적용한다")
|
||||
fun shouldFilterEachMainTabByCountryLanguageWithoutChangingAdultPolicy(tab: String) {
|
||||
val cases = listOf(
|
||||
Case("JP", 900001L, false, Lang.JA, false),
|
||||
Case("KR", 900001L, false, Lang.KO, false),
|
||||
Case("US", 900001L, false, Lang.KO, false),
|
||||
Case(null, 900001L, false, Lang.KO, false),
|
||||
Case("JP", 900001L, true, Lang.JA, true),
|
||||
Case("KR", 900001L, true, Lang.KO, false),
|
||||
Case("US", 900001L, true, Lang.KO, true),
|
||||
Case(null, 900001L, true, Lang.KO, false),
|
||||
Case("KR", 29721L, true, Lang.JA, true),
|
||||
Case("JP", 16L, true, Lang.KO, false)
|
||||
)
|
||||
cases.forEach { case ->
|
||||
jdbcTemplate.update(
|
||||
"update member_content_preference set is_adult_content_visible = ? where member_id = ?",
|
||||
case.storedAdult,
|
||||
case.memberId
|
||||
)
|
||||
assertEventIds(tab, case.country, tokens.getValue(case.memberId), case.lang, case.adult)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("익명 홈은 JP만 JA이며 국가 누락·KR·US는 KO 비성인 이벤트를 반환한다")
|
||||
fun shouldFilterAnonymousHomeWithoutEnablingAdultEvents() {
|
||||
listOf("JP" to Lang.JA, "KR" to Lang.KO, "US" to Lang.KO, null to Lang.KO).forEach { (country, lang) ->
|
||||
assertEventIds("home", country, null, lang, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertEventIds(tab: String, country: String?, token: String?, lang: Lang, adult: Boolean) {
|
||||
val path = "/v2/audio-content/main/$tab"
|
||||
val headers = HttpHeaders().apply {
|
||||
token?.let { setBearerAuth(it) }
|
||||
country?.let { set("CloudFront-Viewer-Country", it) }
|
||||
set(HttpHeaders.ACCEPT_LANGUAGE, "en")
|
||||
}
|
||||
val response = restTemplate.exchange(path, HttpMethod.GET, HttpEntity<Any>(headers), String::class.java)
|
||||
println("HTTP EVIDENCE GET $path country=$country lang=$lang adult=$adult ${response.statusCodeValue}: ${response.body}")
|
||||
assertEquals(HttpStatus.OK, response.statusCode, response.body)
|
||||
val body = objectMapper.readTree(response.body)
|
||||
assertEquals(true, body["success"].asBoolean(), response.body)
|
||||
val events = body["data"]["eventBannerList"]["eventList"]
|
||||
val expected = listOf(eventIds.getValue(lang to adult), eventIds.getValue(lang to null)).sortedDescending()
|
||||
assertEquals(expected, events.map { it["id"].asLong() }, "$path country=$country adult=$adult")
|
||||
events.forEach { event ->
|
||||
assertEquals(
|
||||
setOf("id", "thumbnailImageUrl", "detailImageUrl", "popupImageUrl", "link"),
|
||||
event.fieldNames().asSequence().toSet()
|
||||
)
|
||||
assertEquals(true, event["thumbnailImageUrl"].asText().startsWith("https://cdn.test/"))
|
||||
}
|
||||
}
|
||||
|
||||
private data class Case(
|
||||
val country: String?,
|
||||
val memberId: Long,
|
||||
val storedAdult: Boolean,
|
||||
val lang: Lang,
|
||||
val adult: Boolean
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user