refactor(creator-ranking): 어댑터 뷰 타입을 정리한다
This commit is contained in:
@@ -185,6 +185,9 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
|||||||
private fun setUpCreatorRankingAdapter() {
|
private fun setUpCreatorRankingAdapter() {
|
||||||
binding.rvHomeCreatorRankings.apply {
|
binding.rvHomeCreatorRankings.apply {
|
||||||
layoutManager = CreatorRankingAdapter.createGridLayoutManager(requireContext())
|
layoutManager = CreatorRankingAdapter.createGridLayoutManager(requireContext())
|
||||||
|
if (itemDecorationCount == 0) {
|
||||||
|
addItemDecoration(CreatorRankingAdapter.createItemDecoration(requireContext()))
|
||||||
|
}
|
||||||
adapter = creatorRankingAdapter
|
adapter = creatorRankingAdapter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.widget.creatorranking
|
package kr.co.vividnext.sodalive.v2.widget.creatorranking
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Rect
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
@@ -16,26 +18,22 @@ class CreatorRankingAdapter(
|
|||||||
|
|
||||||
private val items = mutableListOf<CreatorRankingItem>()
|
private val items = mutableListOf<CreatorRankingItem>()
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int = when (CreatorRankingPlacement.fromRank(items[position].rank).variant) {
|
override fun getItemViewType(position: Int): Int {
|
||||||
CreatorRankingCardVariant.Large -> VIEW_TYPE_LARGE
|
val placement = CreatorRankingPlacement.fromRank(items[position].rank)
|
||||||
CreatorRankingCardVariant.Compact -> VIEW_TYPE_COMPACT
|
return when (placement.viewType) {
|
||||||
CreatorRankingCardVariant.Horizontal -> VIEW_TYPE_HORIZONTAL
|
CreatorRankingViewType.TopTen -> VIEW_TYPE_TOP_TEN
|
||||||
|
CreatorRankingViewType.Lower -> VIEW_TYPE_LOWER
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
val inflater = LayoutInflater.from(parent.context)
|
val inflater = LayoutInflater.from(parent.context)
|
||||||
return when (viewType) {
|
return when (viewType) {
|
||||||
VIEW_TYPE_LARGE -> LargeViewHolder(
|
VIEW_TYPE_TOP_TEN -> TopTenViewHolder(
|
||||||
inflater.inflate(R.layout.view_creator_ranking_large_card, parent, false) as CreatorRankingLargeCardView,
|
inflater.inflate(R.layout.view_creator_ranking_top_card, parent, false) as CreatorRankingTopCardView
|
||||||
parent
|
|
||||||
)
|
)
|
||||||
VIEW_TYPE_COMPACT -> CompactViewHolder(
|
VIEW_TYPE_LOWER -> LowerViewHolder(
|
||||||
inflater.inflate(R.layout.view_creator_ranking_compact_card, parent, false) as CreatorRankingCompactCardView,
|
inflater.inflate(R.layout.view_creator_ranking_lower_row, parent, false) as CreatorRankingLowerRowView
|
||||||
parent
|
|
||||||
)
|
|
||||||
VIEW_TYPE_HORIZONTAL -> HorizontalViewHolder(
|
|
||||||
inflater.inflate(R.layout.view_creator_ranking_horizontal_card, parent, false) as CreatorRankingHorizontalCardView,
|
|
||||||
parent
|
|
||||||
)
|
)
|
||||||
else -> error("Unknown viewType: $viewType")
|
else -> error("Unknown viewType: $viewType")
|
||||||
}
|
}
|
||||||
@@ -44,9 +42,8 @@ class CreatorRankingAdapter(
|
|||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
val item = items[position]
|
val item = items[position]
|
||||||
when (holder) {
|
when (holder) {
|
||||||
is LargeViewHolder -> holder.bind(item)
|
is TopTenViewHolder -> holder.bind(item)
|
||||||
is CompactViewHolder -> holder.bind(item)
|
is LowerViewHolder -> holder.bind(item)
|
||||||
is HorizontalViewHolder -> holder.bind(item)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,66 +55,37 @@ class CreatorRankingAdapter(
|
|||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class LargeViewHolder(
|
private inner class TopTenViewHolder(
|
||||||
private val view: CreatorRankingLargeCardView,
|
private val view: CreatorRankingTopCardView
|
||||||
private val parent: ViewGroup
|
|
||||||
) : RecyclerView.ViewHolder(view) {
|
) : RecyclerView.ViewHolder(view) {
|
||||||
fun bind(item: CreatorRankingItem) {
|
fun bind(item: CreatorRankingItem) {
|
||||||
bindCommon(view, item, parent)
|
bindCommon(view, item)
|
||||||
view.bind(item)
|
view.bind(item)
|
||||||
view.setOnCreatorClick(onClickItem)
|
view.setOnCreatorClick(onClickItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class CompactViewHolder(
|
private inner class LowerViewHolder(
|
||||||
private val view: CreatorRankingCompactCardView,
|
private val view: CreatorRankingLowerRowView
|
||||||
private val parent: ViewGroup
|
|
||||||
) : RecyclerView.ViewHolder(view) {
|
) : RecyclerView.ViewHolder(view) {
|
||||||
fun bind(item: CreatorRankingItem) {
|
fun bind(item: CreatorRankingItem) {
|
||||||
bindCommon(view, item, parent)
|
bindCommon(view, item)
|
||||||
view.bind(item)
|
|
||||||
view.setOnCreatorClick(onClickItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class HorizontalViewHolder(
|
|
||||||
private val view: CreatorRankingHorizontalCardView,
|
|
||||||
private val parent: ViewGroup
|
|
||||||
) : RecyclerView.ViewHolder(view) {
|
|
||||||
fun bind(item: CreatorRankingItem) {
|
|
||||||
bindCommon(view, item, parent)
|
|
||||||
view.bind(item)
|
view.bind(item)
|
||||||
view.setOnCreatorClick(onClickItem)
|
view.setOnCreatorClick(onClickItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindCommon(
|
private fun bindCommon(
|
||||||
view: CreatorRankingLargeCardView,
|
view: CreatorRankingTopCardView,
|
||||||
item: CreatorRankingItem,
|
item: CreatorRankingItem
|
||||||
parent: ViewGroup
|
|
||||||
) {
|
) {
|
||||||
val size = calculateSize(item, parent)
|
|
||||||
view.setCardSize(size)
|
|
||||||
view.imageView().loadCreatorImage(item)
|
view.imageView().loadCreatorImage(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindCommon(
|
private fun bindCommon(
|
||||||
view: CreatorRankingCompactCardView,
|
view: CreatorRankingLowerRowView,
|
||||||
item: CreatorRankingItem,
|
item: CreatorRankingItem
|
||||||
parent: ViewGroup
|
|
||||||
) {
|
) {
|
||||||
val size = calculateSize(item, parent)
|
|
||||||
view.setCardSize(size)
|
|
||||||
view.imageView().loadCreatorImage(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun bindCommon(
|
|
||||||
view: CreatorRankingHorizontalCardView,
|
|
||||||
item: CreatorRankingItem,
|
|
||||||
parent: ViewGroup
|
|
||||||
) {
|
|
||||||
val size = calculateSize(item, parent)
|
|
||||||
view.setCardSize(size)
|
|
||||||
view.imageView().loadCreatorImage(item)
|
view.imageView().loadCreatorImage(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,21 +98,6 @@ class CreatorRankingAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateSize(
|
|
||||||
item: CreatorRankingItem,
|
|
||||||
parent: ViewGroup
|
|
||||||
): CreatorRankingCardSize {
|
|
||||||
val parentWidth = parent.width.takeIf { it > 0 } ?: parent.resources.displayMetrics.widthPixels
|
|
||||||
return CreatorRankingLayoutCalculator.calculate(
|
|
||||||
parentWidthPx = parentWidth,
|
|
||||||
parentHorizontalPaddingPx = parent.paddingLeft + parent.paddingRight,
|
|
||||||
horizontalGapPx = HORIZONTAL_GAP_DP.dpToPx(parent),
|
|
||||||
placement = CreatorRankingPlacement.fromRank(item.rank)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Int.dpToPx(parent: ViewGroup): Int = (this * parent.resources.displayMetrics.density).roundToInt()
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val GRID_SPAN_COUNT = 6
|
const val GRID_SPAN_COUNT = 6
|
||||||
|
|
||||||
@@ -152,6 +105,10 @@ class CreatorRankingAdapter(
|
|||||||
spanSizeLookup = createSpanSizeLookup()
|
spanSizeLookup = createSpanSizeLookup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createItemDecoration(context: Context): RecyclerView.ItemDecoration {
|
||||||
|
return CreatorRankingItemDecoration(HORIZONTAL_GAP_DP.dpToPx(context))
|
||||||
|
}
|
||||||
|
|
||||||
fun createSpanSizeLookup(): GridLayoutManager.SpanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
fun createSpanSizeLookup(): GridLayoutManager.SpanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||||
override fun getSpanSize(position: Int): Int = when (CreatorRankingPlacement.fromRank(position + 1).itemsPerRow) {
|
override fun getSpanSize(position: Int): Int = when (CreatorRankingPlacement.fromRank(position + 1).itemsPerRow) {
|
||||||
1 -> GRID_SPAN_COUNT
|
1 -> GRID_SPAN_COUNT
|
||||||
@@ -161,9 +118,50 @@ class CreatorRankingAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val VIEW_TYPE_LARGE = 1
|
private const val VIEW_TYPE_TOP_TEN = 1
|
||||||
private const val VIEW_TYPE_COMPACT = 2
|
private const val VIEW_TYPE_LOWER = 2
|
||||||
private const val VIEW_TYPE_HORIZONTAL = 3
|
private const val HORIZONTAL_GAP_DP = 8
|
||||||
private const val HORIZONTAL_GAP_DP = 4
|
|
||||||
|
private fun Int.dpToPx(context: Context): Int = (this * context.resources.displayMetrics.density).roundToInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CreatorRankingItemDecoration(
|
||||||
|
private val spacingPx: Int
|
||||||
|
) : RecyclerView.ItemDecoration() {
|
||||||
|
|
||||||
|
override fun getItemOffsets(
|
||||||
|
outRect: Rect,
|
||||||
|
view: View,
|
||||||
|
parent: RecyclerView,
|
||||||
|
state: RecyclerView.State
|
||||||
|
) {
|
||||||
|
val position = parent.getChildAdapterPosition(view)
|
||||||
|
val itemCount = parent.adapter?.itemCount ?: return
|
||||||
|
if (position == RecyclerView.NO_POSITION) return
|
||||||
|
|
||||||
|
outRect.set(offsetsForPosition(position, itemCount))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun offsetsForPosition(
|
||||||
|
adapterPosition: Int,
|
||||||
|
itemCount: Int
|
||||||
|
): Rect {
|
||||||
|
val placement = CreatorRankingPlacement.fromRank(adapterPosition + 1)
|
||||||
|
val indexInRow = adapterPosition.indexInRankingRow(placement.itemsPerRow)
|
||||||
|
return Rect().apply {
|
||||||
|
left = indexInRow * spacingPx / placement.itemsPerRow
|
||||||
|
right = spacingPx - (indexInRow + 1) * spacingPx / placement.itemsPerRow
|
||||||
|
if (adapterPosition < itemCount - 1) bottom = spacingPx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Int.indexInRankingRow(itemsPerRow: Int): Int {
|
||||||
|
return when (this) {
|
||||||
|
0 -> 0
|
||||||
|
in 1..6 -> (this - 1) % itemsPerRow
|
||||||
|
in 7..9 -> (this - 7) % itemsPerRow
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,5 +360,5 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/text_tab_bar_home"
|
app:layout_constraintTop_toBottomOf="@id/text_tab_bar_home"
|
||||||
tools:listitem="@layout/view_creator_ranking_horizontal_card" />
|
tools:listitem="@layout/view_creator_ranking_lower_row" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -585,24 +585,14 @@ class HomeMainFragmentLayoutTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `home ranking layout contains ranking list below text tab bar`() {
|
fun `home ranking layout declares ranking list without capsule tab source`() {
|
||||||
val root = inflateView(R.layout.fragment_v2_main_home)
|
val layoutSource = homeMainLayoutSource()
|
||||||
val rankingList = root.findViewById<RecyclerView>(R.id.rv_home_creator_rankings)
|
|
||||||
val layoutParams = rankingList.layoutParams as ConstraintLayout.LayoutParams
|
|
||||||
|
|
||||||
assertNotNull(rankingList)
|
assertTrue(layoutSource.contains("@+id/rv_home_creator_rankings"))
|
||||||
assertSame(root, rankingList.parent)
|
assertTrue(layoutSource.contains("@id/text_tab_bar_home"))
|
||||||
assertEquals(0, layoutParams.width)
|
assertFalse(layoutSource.contains("view_capsule_tab_bar"))
|
||||||
assertEquals(0, layoutParams.height)
|
assertFalse(layoutSource.contains("hsv_capsule_tab_bar"))
|
||||||
assertEquals(R.id.text_tab_bar_home, layoutParams.topToBottom)
|
assertFalse(layoutSource.contains("ll_capsule_tab_container"))
|
||||||
assertEquals(ConstraintLayout.LayoutParams.PARENT_ID, layoutParams.startToStart)
|
|
||||||
assertEquals(ConstraintLayout.LayoutParams.PARENT_ID, layoutParams.endToEnd)
|
|
||||||
assertEquals(ConstraintLayout.LayoutParams.PARENT_ID, layoutParams.bottomToBottom)
|
|
||||||
assertEquals(View.GONE, rankingList.visibility)
|
|
||||||
assertEquals(false, rankingList.clipToPadding)
|
|
||||||
assertEquals(14.dpToPx(), rankingList.paddingStart)
|
|
||||||
assertEquals(14.dpToPx(), rankingList.paddingTop)
|
|
||||||
assertEquals(28.dpToPx(), rankingList.paddingBottom)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1199,6 +1189,7 @@ class HomeMainFragmentLayoutTest {
|
|||||||
assertTrue(source.contains("CreatorRankingAdapter { openCreatorRankingProfile(it) }"))
|
assertTrue(source.contains("CreatorRankingAdapter { openCreatorRankingProfile(it) }"))
|
||||||
assertTrue(source.contains("binding.rvHomeCreatorRankings.apply"))
|
assertTrue(source.contains("binding.rvHomeCreatorRankings.apply"))
|
||||||
assertTrue(source.contains("layoutManager = CreatorRankingAdapter.createGridLayoutManager(requireContext())"))
|
assertTrue(source.contains("layoutManager = CreatorRankingAdapter.createGridLayoutManager(requireContext())"))
|
||||||
|
assertTrue(source.contains("addItemDecoration(CreatorRankingAdapter.createItemDecoration(requireContext()))"))
|
||||||
assertTrue(source.contains("adapter = creatorRankingAdapter"))
|
assertTrue(source.contains("adapter = creatorRankingAdapter"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,17 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.widget.creatorranking
|
package kr.co.vividnext.sodalive.v2.widget.creatorranking
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.test.core.app.ApplicationProvider
|
|
||||||
import kr.co.vividnext.sodalive.R
|
|
||||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.Increase
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.robolectric.RobolectricTestRunner
|
|
||||||
import org.robolectric.annotation.Config
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner::class)
|
|
||||||
@Config(sdk = [28], application = Application::class)
|
|
||||||
class CreatorRankingAdapterLayoutTest {
|
class CreatorRankingAdapterLayoutTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `span count supports full two and three column ranking rows`() {
|
fun `grid span count는 1 2 3 item row를 모두 표현한다`() {
|
||||||
assertEquals(6, CreatorRankingAdapter.GRID_SPAN_COUNT)
|
assertEquals(6, CreatorRankingAdapter.GRID_SPAN_COUNT)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `span lookup maps rank groups to expected row widths`() {
|
fun `span lookup은 rank 구간별 items per row를 span 크기로 변환한다`() {
|
||||||
val spanLookup = CreatorRankingAdapter.createSpanSizeLookup()
|
val spanLookup = CreatorRankingAdapter.createSpanSizeLookup()
|
||||||
|
|
||||||
assertEquals(6, spanLookup.getSpanSize(0))
|
assertEquals(6, spanLookup.getSpanSize(0))
|
||||||
@@ -42,200 +27,24 @@ class CreatorRankingAdapterLayoutTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `large card 순위 숫자는 Figma 고정 박스 안에서 중앙 정렬된다`() {
|
fun `item decoration은 rank 구간별 row index로 gap을 분배한다`() {
|
||||||
val view = inflateView<CreatorRankingLargeCardView>(R.layout.view_creator_ranking_large_card)
|
val spacing = 8
|
||||||
|
val decoration = CreatorRankingItemDecoration(spacing)
|
||||||
|
|
||||||
view.setCardSize(CreatorRankingCardSize(widthPx = 374, heightPx = 374))
|
val first = decoration.offsetsForPosition(adapterPosition = 0, itemCount = 12)
|
||||||
|
val second = decoration.offsetsForPosition(adapterPosition = 1, itemCount = 12)
|
||||||
|
val third = decoration.offsetsForPosition(adapterPosition = 2, itemCount = 12)
|
||||||
|
val eighth = decoration.offsetsForPosition(adapterPosition = 7, itemCount = 12)
|
||||||
|
val ninth = decoration.offsetsForPosition(adapterPosition = 8, itemCount = 12)
|
||||||
|
val tenth = decoration.offsetsForPosition(adapterPosition = 9, itemCount = 12)
|
||||||
|
val eleventh = decoration.offsetsForPosition(adapterPosition = 10, itemCount = 12)
|
||||||
|
|
||||||
assertRankTextBox(
|
assertEquals(spacing, first.bottom)
|
||||||
view = view.findViewById(R.id.tv_creator_ranking_rank),
|
assertEquals(spacing, second.right + third.left)
|
||||||
expectedWidth = 86,
|
assertEquals(spacing, second.bottom)
|
||||||
expectedHeight = 116,
|
assertEquals(spacing, eighth.right + ninth.left)
|
||||||
expectedLeft = 0,
|
assertEquals(spacing, ninth.right + tenth.left)
|
||||||
expectedTop = 0,
|
assertEquals(spacing, tenth.bottom)
|
||||||
expectedBottomPadding = 10
|
assertEquals(spacing, eleventh.bottom)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `compact medium card 순위 숫자는 Figma 고정 박스 안에서 중앙 정렬된다`() {
|
|
||||||
val view = inflateView<CreatorRankingCompactCardView>(R.layout.view_creator_ranking_compact_card)
|
|
||||||
|
|
||||||
view.setCardSize(CreatorRankingCardSize(widthPx = 185, heightPx = 185))
|
|
||||||
|
|
||||||
assertRankTextBox(
|
|
||||||
view = view.findViewById(R.id.tv_creator_ranking_rank),
|
|
||||||
expectedWidth = 56,
|
|
||||||
expectedHeight = 70,
|
|
||||||
expectedLeft = 0,
|
|
||||||
expectedTop = 0,
|
|
||||||
expectedBottomPadding = 6
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `compact small card 순위 숫자는 Figma 고정 박스 안에서 중앙 정렬된다`() {
|
|
||||||
val view = inflateView<CreatorRankingCompactCardView>(R.layout.view_creator_ranking_compact_card)
|
|
||||||
|
|
||||||
view.setCardSize(CreatorRankingCardSize(widthPx = 122, heightPx = 122))
|
|
||||||
|
|
||||||
assertRankTextBox(
|
|
||||||
view = view.findViewById(R.id.tv_creator_ranking_rank),
|
|
||||||
expectedWidth = 52,
|
|
||||||
expectedHeight = 50,
|
|
||||||
expectedLeft = 0,
|
|
||||||
expectedTop = 0,
|
|
||||||
expectedBottomPadding = 5
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `horizontal card 순위 그룹은 Figma 고정 박스 위치를 유지한다`() {
|
|
||||||
val view = inflateView<CreatorRankingHorizontalCardView>(R.layout.view_creator_ranking_horizontal_card)
|
|
||||||
|
|
||||||
view.setCardSize(CreatorRankingCardSize(widthPx = 374, heightPx = 100))
|
|
||||||
|
|
||||||
val rankGroup = view.findViewById<View>(R.id.ll_creator_ranking_rank_group)
|
|
||||||
val params = rankGroup.layoutParams as ViewGroup.MarginLayoutParams
|
|
||||||
assertEquals(49, params.width)
|
|
||||||
assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, params.height)
|
|
||||||
assertEquals(14, params.leftMargin)
|
|
||||||
assertEquals(12, params.topMargin)
|
|
||||||
|
|
||||||
assertRankTextBox(
|
|
||||||
view = view.findViewById(R.id.tv_creator_ranking_rank),
|
|
||||||
expectedWidth = 48,
|
|
||||||
expectedHeight = 52,
|
|
||||||
expectedLeft = 0,
|
|
||||||
expectedTop = 0,
|
|
||||||
expectedBottomPadding = 4
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `large card 순위 변화 표시는 Figma 위치를 유지한다`() {
|
|
||||||
val view = inflateView<CreatorRankingLargeCardView>(R.layout.view_creator_ranking_large_card)
|
|
||||||
|
|
||||||
view.setCardSize(CreatorRankingCardSize(widthPx = 374, heightPx = 374))
|
|
||||||
|
|
||||||
assertViewPosition(
|
|
||||||
view = view.findViewById(R.id.ll_creator_ranking_delta),
|
|
||||||
expectedLeft = 20,
|
|
||||||
expectedTop = 116
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `compact small card 순위 변화 표시는 Figma 위치를 유지한다`() {
|
|
||||||
val view = inflateView<CreatorRankingCompactCardView>(R.layout.view_creator_ranking_compact_card)
|
|
||||||
|
|
||||||
view.setCardSize(CreatorRankingCardSize(widthPx = 122, heightPx = 122))
|
|
||||||
|
|
||||||
assertViewPosition(
|
|
||||||
view = view.findViewById(R.id.ll_creator_ranking_delta),
|
|
||||||
expectedLeft = 10,
|
|
||||||
expectedTop = 50
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `large card는 순위 변동 숨김이면 delta를 숨긴다`() {
|
|
||||||
val view = inflateView<CreatorRankingLargeCardView>(R.layout.view_creator_ranking_large_card)
|
|
||||||
|
|
||||||
view.bind(sampleItem(showRankChange = false))
|
|
||||||
|
|
||||||
assertEquals(View.GONE, view.findViewById<View>(R.id.ll_creator_ranking_delta).visibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `large card는 순위 변동 표시이면 delta를 보여준다`() {
|
|
||||||
val view = inflateView<CreatorRankingLargeCardView>(R.layout.view_creator_ranking_large_card)
|
|
||||||
|
|
||||||
view.bind(sampleItem(showRankChange = true))
|
|
||||||
|
|
||||||
assertEquals(View.VISIBLE, view.findViewById<View>(R.id.ll_creator_ranking_delta).visibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `compact card는 순위 변동 숨김이면 delta를 숨긴다`() {
|
|
||||||
val view = inflateView<CreatorRankingCompactCardView>(R.layout.view_creator_ranking_compact_card)
|
|
||||||
|
|
||||||
view.bind(sampleItem(showRankChange = false))
|
|
||||||
|
|
||||||
assertEquals(View.GONE, view.findViewById<View>(R.id.ll_creator_ranking_delta).visibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `compact card는 순위 변동 표시이면 delta를 보여준다`() {
|
|
||||||
val view = inflateView<CreatorRankingCompactCardView>(R.layout.view_creator_ranking_compact_card)
|
|
||||||
|
|
||||||
view.bind(sampleItem(showRankChange = true))
|
|
||||||
|
|
||||||
assertEquals(View.VISIBLE, view.findViewById<View>(R.id.ll_creator_ranking_delta).visibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `horizontal card는 순위 변동 숨김이면 delta를 숨긴다`() {
|
|
||||||
val view = inflateView<CreatorRankingHorizontalCardView>(R.layout.view_creator_ranking_horizontal_card)
|
|
||||||
|
|
||||||
view.bind(sampleItem(rank = 11, showRankChange = false))
|
|
||||||
|
|
||||||
assertEquals(View.GONE, view.findViewById<View>(R.id.ll_creator_ranking_delta).visibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `horizontal card는 순위 변동 표시이면 delta를 보여준다`() {
|
|
||||||
val view = inflateView<CreatorRankingHorizontalCardView>(R.layout.view_creator_ranking_horizontal_card)
|
|
||||||
|
|
||||||
view.bind(sampleItem(rank = 11, showRankChange = true))
|
|
||||||
|
|
||||||
assertEquals(View.VISIBLE, view.findViewById<View>(R.id.ll_creator_ranking_delta).visibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun assertViewPosition(
|
|
||||||
view: View,
|
|
||||||
expectedLeft: Int,
|
|
||||||
expectedTop: Int
|
|
||||||
) {
|
|
||||||
val params = view.layoutParams as ViewGroup.MarginLayoutParams
|
|
||||||
assertEquals(expectedLeft, params.leftMargin)
|
|
||||||
assertEquals(expectedTop, params.topMargin)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun assertRankTextBox(
|
|
||||||
view: TextView,
|
|
||||||
expectedWidth: Int,
|
|
||||||
expectedHeight: Int,
|
|
||||||
expectedLeft: Int,
|
|
||||||
expectedTop: Int,
|
|
||||||
expectedBottomPadding: Int
|
|
||||||
) {
|
|
||||||
val params = view.layoutParams as ViewGroup.MarginLayoutParams
|
|
||||||
assertEquals(expectedWidth, params.width)
|
|
||||||
assertEquals(expectedHeight, params.height)
|
|
||||||
assertEquals(expectedLeft, params.leftMargin)
|
|
||||||
assertEquals(expectedTop, params.topMargin)
|
|
||||||
assertEquals(Gravity.CENTER, view.gravity)
|
|
||||||
assertEquals(false, view.includeFontPadding)
|
|
||||||
assertEquals(expectedBottomPadding, view.paddingBottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun <reified T : View> inflateView(layoutResId: Int): T {
|
|
||||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
|
||||||
return LayoutInflater.from(context).inflate(layoutResId, null, false) as T
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun sampleItem(
|
|
||||||
rank: Int = 1,
|
|
||||||
showRankChange: Boolean = true
|
|
||||||
) = CreatorRankingItem(
|
|
||||||
creatorId = 1L,
|
|
||||||
rank = rank,
|
|
||||||
rankChangeType = Increase,
|
|
||||||
rankChangeAmount = 4,
|
|
||||||
creatorName = "크리에이터 이름",
|
|
||||||
imageUrl = "https://example.com/image.png",
|
|
||||||
isBlocked = false,
|
|
||||||
showRankChange = showRankChange
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user