diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt index 36c78e34..510e9167 100644 --- a/app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt @@ -23,18 +23,26 @@ import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationCreatorUiMo import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationGenreCreatorGroupUiModel import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationGenreCreatorSection import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationLiveUiModel +import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationPopularCommunityPostSection +import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationPopularCommunityPostUiModel +import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationPaidStatus +import kr.co.vividnext.sodalive.v2.main.home.model.visibleHomePopularCommunityPosts import kr.co.vividnext.sodalive.v2.main.home.model.visibleHomeGenreCreatorGroups +import kr.co.vividnext.sodalive.v2.main.home.data.HomePopularCommunityPostItem import kr.co.vividnext.sodalive.v2.main.home.ui.HomeAiCharacterAdapter import kr.co.vividnext.sodalive.v2.main.home.ui.HomeCheerCreatorAdapter import kr.co.vividnext.sodalive.v2.main.home.ui.HomeFirstAudioAdapter import kr.co.vividnext.sodalive.v2.main.home.ui.HomeFollowAllButtonBinder import kr.co.vividnext.sodalive.v2.main.home.ui.HomeGenreCreatorAdapter import kr.co.vividnext.sodalive.v2.main.home.ui.HomeLiveAdapter +import kr.co.vividnext.sodalive.v2.main.home.ui.HomePopularCommunityAdapter 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 kr.co.vividnext.sodalive.v2.widget.feed.FeedItem +import kr.co.vividnext.sodalive.v2.main.home.model.toUiModel import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull @@ -89,8 +97,7 @@ class HomeMainFragmentLayoutTest { R.id.rv_home_first_audio_contents, R.id.rv_home_ai_characters, R.id.rv_home_genre_creators, - R.id.rv_home_cheer_creators, - R.id.rv_home_popular_community_posts + R.id.rv_home_cheer_creators ) sectionIds.forEach { sectionId -> assertNotNull(root.findViewById(sectionId)) } @@ -101,6 +108,7 @@ class HomeMainFragmentLayoutTest { assertEquals(RecyclerView.HORIZONTAL, recyclerView.layoutManager?.canScrollHorizontally()?.toOrientation()) } assertNotNull(root.findViewById(R.id.rv_home_banners)) + assertNotNull(root.findViewById(R.id.rv_home_popular_community_posts)) assertNotNull(root.findViewById(R.id.ll_home_business_info)) } @@ -663,6 +671,74 @@ class HomeMainFragmentLayoutTest { assertEquals(View.GONE, popularCommunitySection.visibility) } + @Test + fun `home popular community section matches figma vertical list spacing`() { + val root = inflateView(R.layout.fragment_v2_main_home) + val communityList = root.findViewById(R.id.rv_home_popular_community_posts) + + assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, communityList.layoutParams.height) + assertEquals(14.dpToPx(), communityList.paddingStart) + assertEquals(14.dpToPx(), communityList.paddingEnd) + assertEquals(false, communityList.layoutManager?.canScrollHorizontally()) + } + + @Test + fun `home popular community adapter renders max ten posts`() { + val context = ApplicationProvider.getApplicationContext() + val parent = RecyclerView(context) + parent.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false) + val adapter = HomePopularCommunityAdapter(onClickItem = {}) + + adapter.submitSection(HomeRecommendationPopularCommunityPostSection((1L..11L).map(::popularCommunityPost))) + val viewHolder = adapter.onCreateViewHolder(parent, 0) + adapter.onBindViewHolder(viewHolder, 0) + + assertEquals(10, adapter.itemCount) + assertEquals( + "post-1", + (viewHolder.itemView as kr.co.vividnext.sodalive.v2.widget.feed.FeedCommunityView).boundItem()?.postId + ) + } + + @Test + fun `home popular community visible posts caps to ten`() { + val section = HomeRecommendationPopularCommunityPostSection((1L..11L).map(::popularCommunityPost)) + + assertEquals(10, section.visibleHomePopularCommunityPosts().size) + } + + @Test + fun `popular community mapper preserves audio url for detail data`() { + val item = popularCommunityData(audioUrl = "https://example.com/audio.m4a") + + assertEquals("https://example.com/audio.m4a", item.toUiModel().item.audioUrl) + } + + @Test + fun `home popular community adapter does not load original image for locked paid post`() { + val context = ApplicationProvider.getApplicationContext() + val parent = RecyclerView(context) + parent.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false) + val adapter = HomePopularCommunityAdapter(onClickItem = {}) + val post = popularCommunityPost(1L).copy( + item = popularCommunityPost(1L).item.copy( + imageUrl = "https://example.com/paid.png", + price = 30, + existOrdered = false + ), + paidStatus = HomeRecommendationPaidStatus.Paid(30) + ) + adapter.submitSection(HomeRecommendationPopularCommunityPostSection(listOf(post))) + val viewHolder = adapter.onCreateViewHolder(parent, 0) + val communityImage = viewHolder.itemView.findViewById(R.id.iv_feed_community_image) + communityImage.setImageResource(R.drawable.ic_launcher_background) + + adapter.onBindViewHolder(viewHolder, 0) + + assertEquals(null, communityImage.drawable) + assertEquals(View.VISIBLE, viewHolder.itemView.findViewById(R.id.ll_feed_community_paid_overlay).visibility) + } + @Test fun `home live section height follows its items`() { val root = inflateView(R.layout.fragment_v2_main_home) @@ -814,6 +890,46 @@ class HomeMainFragmentLayoutTest { ) } + private fun popularCommunityPost(id: Long): HomeRecommendationPopularCommunityPostUiModel { + return HomeRecommendationPopularCommunityPostUiModel( + item = FeedItem.Community( + feedId = "post-$id", + creatorId = "creator-$id", + creatorName = "크리에이터$id", + creatorImageUrl = "", + postId = "post-$id", + bodyText = "본문$id", + keywordText = "", + createdAtText = "2분 전", + commentCount = 5, + likeCount = 6, + imageUrl = null, + audioUrl = null, + price = 0, + existOrdered = false, + showKeyword = false + ), + paidStatus = HomeRecommendationPaidStatus.Free + ) + } + + private fun popularCommunityData(audioUrl: String?): HomePopularCommunityPostItem { + return HomePopularCommunityPostItem( + postId = 1L, + creatorId = 1L, + creatorNickname = "크리에이터", + creatorProfileImage = null, + imageUrl = null, + audioUrl = audioUrl, + content = "본문", + price = 0, + createdAt = "2분 전", + likeCount = 6L, + commentCount = 5L, + existOrdered = false + ) + } + private fun genreGroup( genre: String, creators: List