feat(widget): 오디오 콘텐츠 카드 배지를 정리한다

This commit is contained in:
2026-06-02 19:00:13 +09:00
parent bd475d1c87
commit b402025ca5
4 changed files with 185 additions and 28 deletions

View File

@@ -15,9 +15,13 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.test.core.app.ApplicationProvider
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationFirstAudioContentUiModel
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationLiveUiModel
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeFirstAudioAdapter
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeLiveAdapter
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeRecentDebutCreatorAdapter
import kr.co.vividnext.sodalive.v2.widget.AudioContentCardView
import kr.co.vividnext.sodalive.v2.widget.AudioContentTag
import kr.co.vividnext.sodalive.v2.widget.TextTabBarView
import kr.co.vividnext.sodalive.v2.widget.banner.BannerView
import org.junit.Assert.assertEquals
@@ -146,6 +150,131 @@ class HomeMainFragmentLayoutTest {
assertEquals(4.dpToPx(), layoutParams.marginEnd)
}
@Test
fun `first audio item matches figma card dimensions`() {
val firstAudio = inflateViewWithParent(R.layout.item_home_first_audio_content)
val thumbnailContainer = firstAudio.findViewById<View>(R.id.fl_home_first_audio_thumbnail_container)
val thumbnail = firstAudio.findViewById<ImageView>(R.id.iv_home_first_audio_thumbnail)
val creatorProfile = firstAudio.findViewById<ImageView>(R.id.iv_home_first_audio_creator_profile)
val creatorName = firstAudio.findViewById<TextView>(R.id.tv_home_first_audio_creator_nickname)
assertEquals(185.dpToPx(), firstAudio.layoutParams.width)
assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, firstAudio.layoutParams.height)
assertEquals(185.dpToPx(), thumbnail.layoutParams.width)
assertEquals(185.dpToPx(), thumbnail.layoutParams.height)
assertNotNull(thumbnailContainer)
assertEquals(42.dpToPx(), creatorProfile.layoutParams.width)
assertEquals(42.dpToPx(), creatorProfile.layoutParams.height)
assertEquals(14f, creatorName.textSize / creatorName.resources.displayMetrics.scaledDensity)
}
@Test
fun `home first audio section matches figma list spacing`() {
val root = inflateView(R.layout.fragment_v2_main_home)
val firstAudioList = root.findViewById<RecyclerView>(R.id.rv_home_first_audio_contents)
val context = ApplicationProvider.getApplicationContext<Context>()
val parent = RecyclerView(context)
parent.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
val viewHolder = HomeFirstAudioAdapter().onCreateViewHolder(parent, 0)
val layoutParams = viewHolder.itemView.layoutParams as ViewGroup.MarginLayoutParams
assertEquals(14.dpToPx(), firstAudioList.paddingStart)
assertEquals(14.dpToPx(), (firstAudioList.layoutParams as ViewGroup.MarginLayoutParams).topMargin)
assertEquals(4.dpToPx(), layoutParams.marginEnd)
}
@Test
fun `first audio adapter clips thumbnail container`() {
val context = ApplicationProvider.getApplicationContext<Context>()
val parent = RecyclerView(context)
parent.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
val viewHolder = HomeFirstAudioAdapter().onCreateViewHolder(parent, 0)
val thumbnailContainer = viewHolder.itemView.findViewById<View>(R.id.fl_home_first_audio_thumbnail_container)
assertEquals(true, thumbnailContainer.clipToOutline)
assertNotNull(thumbnailContainer.outlineProvider)
}
@Test
fun `first audio adapter binds tag visibility`() {
val context = ApplicationProvider.getApplicationContext<Context>()
val parent = RecyclerView(context)
parent.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
val adapter = HomeFirstAudioAdapter()
adapter.submitItems(listOf(firstAudioItem()))
val viewHolder = adapter.onCreateViewHolder(parent, 0)
adapter.onBindViewHolder(viewHolder, 0)
assertEquals(View.VISIBLE, viewHolder.itemView.findViewById<View>(R.id.ll_home_first_audio_tag_top).visibility)
assertEquals(View.VISIBLE, viewHolder.itemView.findViewById<View>(R.id.ll_home_first_audio_tag_bottom).visibility)
assertEquals(View.VISIBLE, viewHolder.itemView.findViewById<View>(R.id.ll_home_first_audio_tag_first).visibility)
assertEquals(View.VISIBLE, viewHolder.itemView.findViewById<View>(R.id.iv_home_first_audio_tag_point).visibility)
assertEquals(View.VISIBLE, viewHolder.itemView.findViewById<View>(R.id.tv_home_first_audio_tag_free).visibility)
}
@Test
fun `first audio adapter clears nullable images`() {
val context = ApplicationProvider.getApplicationContext<Context>()
val parent = RecyclerView(context)
parent.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
val adapter = HomeFirstAudioAdapter()
adapter.submitItems(listOf(firstAudioItem()))
val viewHolder = adapter.onCreateViewHolder(parent, 0)
val thumbnail = viewHolder.itemView.findViewById<ImageView>(R.id.iv_home_first_audio_thumbnail)
val creatorProfile = viewHolder.itemView.findViewById<ImageView>(R.id.iv_home_first_audio_creator_profile)
thumbnail.setImageResource(R.drawable.ic_launcher_background)
creatorProfile.setImageResource(R.drawable.ic_launcher_background)
adapter.onBindViewHolder(viewHolder, 0)
assertEquals(null, thumbnail.drawable)
assertEquals(null, creatorProfile.drawable)
}
@Test
fun `audio content card clips image area and overlay tags together`() {
val card = inflateView(R.layout.view_audio_content_card) as AudioContentCardView
val thumbnailContainer = card.findViewById<View>(R.id.fl_audio_content_thumbnail_container)
assertEquals(true, thumbnailContainer.clipToOutline)
assertNotNull(thumbnailContainer.outlineProvider)
}
@Test
fun `audio content card tag attributes match first audio item`() {
val card = inflateView(R.layout.view_audio_content_card) as AudioContentCardView
val firstAudio = inflateView(R.layout.item_home_first_audio_content)
card.setTags(setOf(AudioContentTag.Original, AudioContentTag.First, AudioContentTag.Point, AudioContentTag.Free))
val topTagContainer = card.findViewById<LinearLayout>(R.id.ll_audio_content_tag_top)
val bottomTagContainer = card.findViewById<LinearLayout>(R.id.ll_audio_content_tag_bottom)
val expectedFirstTag = firstAudio.findViewById<LinearLayout>(R.id.ll_home_first_audio_tag_first)
val expectedFreeTag = firstAudio.findViewById<TextView>(R.id.tv_home_first_audio_tag_free)
val originalTag = card.findViewById<ImageView>(R.id.iv_audio_content_tag_original)
val firstTag = card.findViewById<LinearLayout>(R.id.ll_audio_content_tag_first)
val firstIcon = firstTag.getChildAt(0) as ImageView
val firstText = firstTag.getChildAt(1) as TextView
val pointTag = card.findViewById<ImageView>(R.id.iv_audio_content_tag_point)
val freeTag = card.findViewById<TextView>(R.id.tv_audio_content_tag_free)
assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, topTagContainer.layoutParams.height)
assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, bottomTagContainer.layoutParams.height)
assertEquals(24.dpToPx(), originalTag.layoutParams.width)
assertEquals(24.dpToPx(), originalTag.layoutParams.height)
assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, firstTag.layoutParams.width)
assertEquals(expectedFirstTag.layoutParams.height, firstTag.layoutParams.height)
assertEquals(expectedFirstTag.paddingStart, firstTag.paddingStart)
assertEquals(expectedFirstTag.paddingTop, firstTag.paddingTop)
assertEquals(17.dpToPx(), firstIcon.layoutParams.width)
assertEquals(17.dpToPx(), firstIcon.layoutParams.height)
assertEquals(2.dpToPx(), (firstText.layoutParams as ViewGroup.MarginLayoutParams).marginStart)
assertEquals(true, firstText.includeFontPadding)
assertEquals(24.dpToPx(), pointTag.layoutParams.width)
assertEquals(24.dpToPx(), pointTag.layoutParams.height)
assertEquals(expectedFreeTag.layoutParams.height, freeTag.layoutParams.height)
assertEquals(expectedFreeTag.paddingStart, freeTag.paddingStart)
}
@Test
fun `popular community section is hidden until phase7 binding is implemented`() {
val root = inflateView(R.layout.fragment_v2_main_home)
@@ -289,4 +418,18 @@ class HomeMainFragmentLayoutTest {
beginDateTime = null
)
}
private fun firstAudioItem(): HomeRecommendationFirstAudioContentUiModel {
return HomeRecommendationFirstAudioContentUiModel(
contentId = 1L,
creatorId = 1L,
creatorNickname = "크리에이터 이름",
creatorProfileImage = null,
title = "콘텐츠 제목",
price = 0,
coverImage = null,
releaseDate = "",
tags = setOf(AudioContentTag.First, AudioContentTag.Point, AudioContentTag.Free)
)
}
}