test(creator): 커뮤니티 탭 레이아웃 검증을 추가한다
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
package kr.co.vividnext.sodalive.v2.creator.channel.community
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertSame
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import java.io.File
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [28], application = Application::class)
|
||||
class CreatorChannelCommunityFragmentLayoutTest {
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 fragment layout은 sort list empty error retry를 제공한다`() {
|
||||
val root = inflateView(R.layout.fragment_creator_channel_community)
|
||||
val layout = projectFile("app/src/main/res/layout/fragment_creator_channel_community.xml").readText()
|
||||
|
||||
val sortBar = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_community_sort_bar))
|
||||
val communityList = requireNotNull(root.findViewById<RecyclerView>(R.id.rv_creator_channel_community))
|
||||
val emptyContainer = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_community_empty))
|
||||
val emptyMessage = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_community_empty_message))
|
||||
val errorMessage = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_community_error_message))
|
||||
val retryButton = requireNotNull(root.findViewById<TextView>(R.id.btn_creator_channel_community_retry))
|
||||
|
||||
assertSame(root, sortBar.parent)
|
||||
assertSame(root, communityList.parent)
|
||||
assertSame(root, emptyContainer.parent)
|
||||
assertSame(emptyContainer, emptyMessage.parent)
|
||||
assertSame(root, errorMessage.parent)
|
||||
assertSame(root, retryButton.parent)
|
||||
assertEquals(false, communityList.clipToPadding)
|
||||
assertTrue(layout.contains("android:background=\"@color/black\""))
|
||||
assertTrue(layout.contains("android:text=\"@string/creator_channel_community_empty_message\""))
|
||||
assertTrue(layout.contains("android:text=\"@string/creator_channel_community_error_message\""))
|
||||
assertTrue(layout.contains("tools:listitem=\"@layout/item_creator_channel_community_list\""))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 sort bar는 전체 count 보기 방식 label icon을 제공한다`() {
|
||||
val root = inflateView(R.layout.fragment_creator_channel_community)
|
||||
val sortBar = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_community_sort_bar))
|
||||
|
||||
assertNotNull(sortBar.findViewById<TextView>(R.id.tv_creator_channel_community_total_label))
|
||||
assertNotNull(sortBar.findViewById<TextView>(R.id.tv_creator_channel_community_total_count))
|
||||
assertNotNull(sortBar.findViewById<View>(R.id.layout_creator_channel_community_view_mode_button))
|
||||
assertNotNull(sortBar.findViewById<TextView>(R.id.tv_creator_channel_community_view_mode_label))
|
||||
assertNotNull(sortBar.findViewById<ImageView>(R.id.iv_creator_channel_community_view_mode))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 list item layout은 프로필 본문 이미지 잠금 재생 반응 owner 영역을 제공한다`() {
|
||||
val item = inflateView(R.layout.item_creator_channel_community_list)
|
||||
val itemLayout = projectFile("app/src/main/res/layout/item_creator_channel_community_list.xml").readText()
|
||||
val imageContainer = requireNotNull(item.findViewById<View>(R.id.layout_creator_channel_community_list_image_container))
|
||||
val lockIcon = requireNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_community_list_lock))
|
||||
val lockedPrice = requireNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_locked_price))
|
||||
|
||||
assertNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_community_list_profile))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_nickname))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_time))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_notice))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_body))
|
||||
assertNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_community_list_image))
|
||||
assertNotNull(item.findViewById<View>(R.id.layout_creator_channel_community_list_locked_overlay))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_locked_price))
|
||||
assertNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_community_list_play))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_comment_count))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_like_count))
|
||||
assertNotNull(item.findViewById<View>(R.id.layout_creator_channel_community_list_top_actions))
|
||||
assertNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_community_list_owner_more))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_list_top_price))
|
||||
assertSame(imageContainer, (lockIcon.parent as View).parent)
|
||||
assertSame(imageContainer, (lockedPrice.parent as View).parent)
|
||||
assertSame(
|
||||
item.findViewById<View>(R.id.layout_creator_channel_community_list_top_actions),
|
||||
item.findViewById<TextView>(R.id.tv_creator_channel_community_list_top_price).parent
|
||||
)
|
||||
assertTrue(itemLayout.contains("android:id=\"@+id/layout_creator_channel_community_list_locked_overlay\""))
|
||||
assertTrue(itemLayout.contains("android:id=\"@+id/tv_creator_channel_community_list_locked_price\""))
|
||||
assertTrue(itemLayout.contains("android:background=\"@drawable/bg_creator_channel_community_price\""))
|
||||
assertTrue(itemLayout.contains("android:drawableStart=\"@drawable/ic_bar_cash\""))
|
||||
assertTrue(itemLayout.contains("android:id=\"@+id/iv_creator_channel_community_list_play\""))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 grid item layout은 이미지 본문 잠금 가격 공지와 정사각 root 계약을 제공한다`() {
|
||||
val item = inflateView(R.layout.item_creator_channel_community_grid)
|
||||
val itemLayout = projectFile("app/src/main/res/layout/item_creator_channel_community_grid.xml").readText()
|
||||
|
||||
assertNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_community_grid_image))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_grid_text_preview))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_grid_lock_price))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_community_grid_notice))
|
||||
assertTrue(itemLayout.contains("android:id=\"@+id/layout_creator_channel_community_grid_root\""))
|
||||
assertTrue(itemLayout.contains("app:layout_constraintDimensionRatio=\"1:1\"") || itemLayout.contains("Square"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 문자열은 한국어 영어 일본어와 기존 보기 방식 label에 존재한다`() {
|
||||
val ko = projectFile("app/src/main/res/values/strings.xml").readText()
|
||||
val en = projectFile("app/src/main/res/values-en/strings.xml").readText()
|
||||
val ja = projectFile("app/src/main/res/values-ja/strings.xml").readText()
|
||||
|
||||
listOf(ko, en, ja).forEach { strings ->
|
||||
assertTrue(strings.contains("name=\"creator_channel_community_empty_message\""))
|
||||
assertTrue(strings.contains("name=\"creator_channel_community_error_message\""))
|
||||
assertTrue(strings.contains("name=\"creator_channel_community_retry_button\""))
|
||||
assertTrue(strings.contains("name=\"creator_channel_community_notice\""))
|
||||
assertTrue(strings.contains("name=\"creator_channel_community_view_mode_list\""))
|
||||
assertTrue(strings.contains("name=\"creator_channel_community_view_mode_grid\""))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 fragment source는 pagination view mode owner padding stopContent 계약을 사용한다`() {
|
||||
val fragment = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/CreatorChannelCommunityFragment.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(fragment.contains("BaseFragment<FragmentCreatorChannelCommunityBinding>"))
|
||||
assertTrue(fragment.contains("private val viewModel: CreatorChannelCommunityViewModel by viewModel()"))
|
||||
assertTrue(fragment.contains("viewModel.communityStateLiveData.observe(viewLifecycleOwner)"))
|
||||
assertTrue(fragment.contains("viewModel.loadCommunity(creatorId, isOwner = host.isCreatorChannelOwner())"))
|
||||
assertTrue(fragment.contains("viewModel.loadMore()"))
|
||||
assertTrue(fragment.contains("viewModel.retryCommunity()"))
|
||||
assertTrue(fragment.contains("viewModel.toggleViewMode()"))
|
||||
assertTrue(fragment.contains("LinearLayoutManager"))
|
||||
assertTrue(
|
||||
fragment.contains("GridLayoutManager(requireContext(), 3") ||
|
||||
fragment.contains("GridLayoutManager(context, 3")
|
||||
)
|
||||
assertTrue(fragment.contains("viewModel.consumePaginationErrorMessage()"))
|
||||
assertTrue(fragment.contains("applyOwnerCtaPadding"))
|
||||
assertTrue(fragment.contains("pauseContent"))
|
||||
assertTrue(fragment.contains("stopContent"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 adapters source는 binding 상태 표시와 root click navigation 배제를 보장한다`() {
|
||||
val listAdapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/ui/CreatorChannelCommunityListAdapter.kt"
|
||||
).readText()
|
||||
val gridAdapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/ui/CreatorChannelCommunityGridAdapter.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(listAdapter.contains("ItemCreatorChannelCommunityListBinding"))
|
||||
assertTrue(gridAdapter.contains("ItemCreatorChannelCommunityGridBinding"))
|
||||
assertTrue(listAdapter.contains("submitItems"))
|
||||
assertTrue(gridAdapter.contains("submitItems"))
|
||||
assertTrue(listAdapter.contains("showComment") && listAdapter.contains("isVisible = item.showComment"))
|
||||
assertTrue(listAdapter.contains("isLocked"))
|
||||
assertTrue(gridAdapter.contains("isLocked"))
|
||||
assertTrue(listAdapter.contains("showPlayButton"))
|
||||
assertTrue(listAdapter.contains("showOwnerMore"))
|
||||
assertTrue(listAdapter.contains("isPlayingContent"))
|
||||
assertTrue(listAdapter.contains("R.drawable.ic_player_pause"))
|
||||
assertTrue(listAdapter.contains("R.drawable.ic_new_player_play"))
|
||||
assertTrue(listAdapter.contains("onOwnerMoreClick(item)"))
|
||||
assertTrue(listAdapter.contains("tvCreatorChannelCommunityListLockedPrice.isVisible = item.isLocked"))
|
||||
assertTrue(listAdapter.contains("tvCreatorChannelCommunityListTopPrice.isVisible = item.showOwnerTopPrice"))
|
||||
assertTrue(!listAdapter.contains("item.isLocked || item.showOwnerTopPrice"))
|
||||
assertTrue(!listAdapter.contains("root.setOnClickListener"))
|
||||
assertTrue(!gridAdapter.contains("root.setOnClickListener"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 media player source는 prepare 완료 전 pause stop 호출을 보호한다`() {
|
||||
val playerManager = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/all/player/" +
|
||||
"CreatorCommunityMediaPlayerManager.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(playerManager.contains("private var isPrepared: Boolean = false"))
|
||||
assertTrue(playerManager.contains("if (isPrepared)"))
|
||||
assertTrue(playerManager.contains("isPrepared = true"))
|
||||
assertTrue(playerManager.contains("isPrepared = false"))
|
||||
assertTrue(playerManager.contains("mediaPlayer?.pause()"))
|
||||
assertTrue(playerManager.contains("it.stop()"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 adapters source는 잠금 항목과 text preview에서 imageUrl load를 호출하지 않는다`() {
|
||||
val listAdapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/ui/CreatorChannelCommunityListAdapter.kt"
|
||||
).readText()
|
||||
val gridAdapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/ui/CreatorChannelCommunityGridAdapter.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(listAdapter.contains("val visibleImageUrl = item.imageUrl.takeUnless { item.isLocked }"))
|
||||
assertTrue(listAdapter.contains("ivCreatorChannelCommunityListImage.setImageDrawable(null)"))
|
||||
assertTrue(gridAdapter.contains("val visibleImageUrl = item.imageUrl.takeIf"))
|
||||
assertTrue(gridAdapter.contains("item.imageMode == CreatorChannelCommunityImageMode.Image"))
|
||||
assertTrue(gridAdapter.contains("ivCreatorChannelCommunityGridImage.setImageDrawable(null)"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `커뮤니티 grid adapter source는 margin을 제외한 3열 정사각 크기를 계산한다`() {
|
||||
val gridAdapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/ui/CreatorChannelCommunityGridAdapter.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(gridAdapter.contains("leftMargin + rightMargin"))
|
||||
assertTrue(gridAdapter.contains("availableWidth - totalHorizontalMargins"))
|
||||
assertTrue(gridAdapter.contains("coerceAtLeast(0)"))
|
||||
}
|
||||
|
||||
private fun inflateView(layoutResId: Int): View {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
return LayoutInflater.from(context).inflate(layoutResId, null, false)
|
||||
}
|
||||
|
||||
private fun projectFile(relativePath: String): File {
|
||||
val candidates = listOf(File(relativePath), File("../$relativePath"))
|
||||
return candidates.firstOrNull { it.exists() }
|
||||
?: error("Project file not found: $relativePath")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user