feat(creator): FanTalk 탭 화면 연결을 추가한다
This commit is contained in:
@@ -63,6 +63,7 @@ import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelAudioConte
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelLiveResponse
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelScheduleResponse
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelSeriesResponse
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.CreatorChannelFanTalkFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.live.CreatorChannelLiveFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelHeaderUiModel
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelScrollState
|
||||
@@ -83,7 +84,8 @@ class CreatorChannelActivity :
|
||||
CreatorChannelLiveFragment.Host,
|
||||
CreatorChannelAudioFragment.Host,
|
||||
CreatorChannelSeriesFragment.Host,
|
||||
CreatorChannelCommunityFragment.Host {
|
||||
CreatorChannelCommunityFragment.Host,
|
||||
CreatorChannelFanTalkFragment.Host {
|
||||
|
||||
private val liveViewModel: LiveViewModel by inject()
|
||||
private val myPageViewModel: MyPageViewModel by inject()
|
||||
@@ -430,6 +432,9 @@ class CreatorChannelActivity :
|
||||
CreatorChannelTab.Community.ordinal -> binding.viewPager.post {
|
||||
findCommunityFragment()?.onCreatorChannelCommunityTabSelected()
|
||||
}
|
||||
CreatorChannelTab.FanTalk.ordinal -> binding.viewPager.post {
|
||||
findFanTalkFragment()?.onCreatorChannelFanTalkTabSelected()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,6 +463,11 @@ class CreatorChannelActivity :
|
||||
findCommunityFragment()?.onCreatorChannelCommunityTabSelected()
|
||||
}
|
||||
}
|
||||
if (binding.viewPager.currentItem == CreatorChannelTab.FanTalk.ordinal) {
|
||||
binding.viewPager.post {
|
||||
findFanTalkFragment()?.onCreatorChannelFanTalkTabSelected()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatorChannelFollowProgressChanged(inProgress: Boolean) {
|
||||
@@ -532,6 +542,27 @@ class CreatorChannelActivity :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatorChannelFanTalkContentChanged() {
|
||||
updateViewPagerHeight {
|
||||
postCheckCreatorChannelCurrentTabNeedsMore()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatorChannelFanTalkDeleteClicked(fanTalkId: Long) {
|
||||
SodaDialog(
|
||||
activity = this,
|
||||
layoutInflater = layoutInflater,
|
||||
title = getString(R.string.screen_user_profile_cheer_delete_title),
|
||||
desc = getString(R.string.screen_user_profile_cheer_delete_desc),
|
||||
confirmButtonTitle = getString(R.string.confirm_delete_title),
|
||||
confirmButtonClick = {
|
||||
findFanTalkFragment()?.onCreatorChannelFanTalkDeleteConfirmed(fanTalkId)
|
||||
},
|
||||
cancelButtonTitle = getString(R.string.cancel),
|
||||
cancelButtonClick = {}
|
||||
).show(screenWidth)
|
||||
}
|
||||
|
||||
override fun onCreatorChannelCommunityOwnerMoreClicked(item: CreatorChannelCommunityPostUiModel) {
|
||||
CreatorCommunityPostMenuBottomSheetDialog(
|
||||
isFixed = item.isPinned,
|
||||
@@ -623,6 +654,10 @@ class CreatorChannelActivity :
|
||||
findCommunityFragment()?.onCreatorChannelCommunityRefreshRequested()
|
||||
}
|
||||
|
||||
private fun refreshCreatorChannelFanTalk() {
|
||||
findFanTalkFragment()?.onCreatorChannelFanTalkRefreshRequested()
|
||||
}
|
||||
|
||||
private fun setupOwnerFabInsets() {
|
||||
binding.viewPager.updatePadding(bottom = OWNER_FAB_CONTENT_BOTTOM_PADDING_DP.dpToPx().toInt())
|
||||
}
|
||||
@@ -817,12 +852,18 @@ class CreatorChannelActivity :
|
||||
return supportFragmentManager.findFragmentByTag(fragmentTag) as? CreatorChannelCommunityFragment
|
||||
}
|
||||
|
||||
private fun findFanTalkFragment(): CreatorChannelFanTalkFragment? {
|
||||
val fragmentTag = "f${CreatorChannelTab.FanTalk.ordinal}"
|
||||
return supportFragmentManager.findFragmentByTag(fragmentTag) as? CreatorChannelFanTalkFragment
|
||||
}
|
||||
|
||||
private fun notifyCurrentCreatorChannelTabScrolledToBottom() {
|
||||
when (binding.viewPager.currentItem) {
|
||||
CreatorChannelTab.Live.ordinal -> findLiveFragment()?.onCreatorChannelLiveScrolledToBottom()
|
||||
CreatorChannelTab.Audio.ordinal -> findAudioFragment()?.onCreatorChannelAudioScrolledToBottom()
|
||||
CreatorChannelTab.Series.ordinal -> findSeriesFragment()?.onCreatorChannelSeriesScrolledToBottom()
|
||||
CreatorChannelTab.Community.ordinal -> findCommunityFragment()?.onCreatorChannelCommunityScrolledToBottom()
|
||||
CreatorChannelTab.FanTalk.ordinal -> findFanTalkFragment()?.onCreatorChannelFanTalkScrolledToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,7 +871,8 @@ class CreatorChannelActivity :
|
||||
return position == CreatorChannelTab.Live.ordinal ||
|
||||
position == CreatorChannelTab.Audio.ordinal ||
|
||||
position == CreatorChannelTab.Series.ordinal ||
|
||||
position == CreatorChannelTab.Community.ordinal
|
||||
position == CreatorChannelTab.Community.ordinal ||
|
||||
position == CreatorChannelTab.FanTalk.ordinal
|
||||
}
|
||||
|
||||
private fun ensureLoginAndAdultAuth(isAdult: Boolean, onAuthed: () -> Unit) {
|
||||
@@ -928,6 +970,7 @@ class CreatorChannelActivity :
|
||||
CreatorChannelTab.Live.ordinal -> findLiveFragment()?.onCreatorChannelLiveViewportHeightChanged(minHeight)
|
||||
CreatorChannelTab.Audio.ordinal -> findAudioFragment()?.onCreatorChannelAudioViewportHeightChanged(minHeight)
|
||||
CreatorChannelTab.Series.ordinal -> findSeriesFragment()?.onCreatorChannelSeriesViewportHeightChanged(minHeight)
|
||||
CreatorChannelTab.FanTalk.ordinal -> findFanTalkFragment()?.onCreatorChannelFanTalkViewportHeightChanged(minHeight)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.audio.CreatorChannelAudioFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.CreatorChannelFanTalkFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.live.CreatorChannelLiveFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelTab
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.series.CreatorChannelSeriesFragment
|
||||
@@ -25,6 +26,7 @@ class CreatorChannelPagerAdapter(
|
||||
CreatorChannelTab.Audio -> CreatorChannelAudioFragment.newInstance(creatorId)
|
||||
CreatorChannelTab.Series -> CreatorChannelSeriesFragment.newInstance(creatorId)
|
||||
CreatorChannelTab.Community -> CreatorChannelCommunityFragment.newInstance(creatorId)
|
||||
CreatorChannelTab.FanTalk -> CreatorChannelFanTalkFragment.newInstance(creatorId)
|
||||
else -> CreatorChannelPlaceholderFragment.newInstance(tab)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ class CreatorChannelActivitySourceTest {
|
||||
assertFalse(source.contains("if (tab != CreatorChannelTab.Home) return"))
|
||||
assertTrue(pagerAdapter.contains("CreatorChannelTab.Audio -> CreatorChannelAudioFragment.newInstance(creatorId)"))
|
||||
assertTrue(pagerAdapter.contains("CreatorChannelTab.Series -> CreatorChannelSeriesFragment.newInstance(creatorId)"))
|
||||
assertFalse(source.contains("CreatorChannelTab.FanTalk ->"))
|
||||
assertTrue(pagerAdapter.contains("CreatorChannelTab.FanTalk -> CreatorChannelFanTalkFragment.newInstance(creatorId)"))
|
||||
assertFalse(source.contains("CreatorChannelTab.Donation ->"))
|
||||
}
|
||||
|
||||
@@ -487,6 +487,7 @@ class CreatorChannelActivitySourceTest {
|
||||
assertFalse(source.contains("onClickDelete = {},"))
|
||||
assertTrue(fragment.contains("fun onCreatorChannelCommunityRefreshRequested()"))
|
||||
assertTrue(
|
||||
|
||||
fragment.contains(
|
||||
"CreatorCommunityMediaPlayerManager(requireContext()) { listAdapter.notifyDataSetChanged() }"
|
||||
)
|
||||
@@ -495,6 +496,47 @@ class CreatorChannelActivitySourceTest {
|
||||
assertTrue(fragment.contains("mediaPlayerManager?.stopContent()"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `FanTalk tab source는 Fragment Host pagination height delete dialog를 Activity에 연결한다`() {
|
||||
val source = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt"
|
||||
).readText()
|
||||
val adapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelPagerAdapter.kt"
|
||||
).readText()
|
||||
val fragment = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkFragment.kt"
|
||||
).takeIf { it.exists() }?.readText().orEmpty()
|
||||
|
||||
assertTrue(adapter.contains("CreatorChannelFanTalkFragment.newInstance(creatorId)"))
|
||||
assertTrue(source.contains("CreatorChannelFanTalkFragment.Host"))
|
||||
assertTrue(
|
||||
source.contains(
|
||||
"import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.CreatorChannelFanTalkFragment"
|
||||
)
|
||||
)
|
||||
assertTrue(source.contains("private fun findFanTalkFragment(): CreatorChannelFanTalkFragment?"))
|
||||
assertTrue(source.contains("CreatorChannelTab.FanTalk.ordinal -> binding.viewPager.post"))
|
||||
assertTrue(source.contains("findFanTalkFragment()?.onCreatorChannelFanTalkTabSelected()"))
|
||||
assertTrue(source.contains("if (binding.viewPager.currentItem == CreatorChannelTab.FanTalk.ordinal)"))
|
||||
assertTrue(source.contains("findFanTalkFragment()?.onCreatorChannelFanTalkScrolledToBottom()"))
|
||||
assertTrue(source.contains("findFanTalkFragment()?.onCreatorChannelFanTalkViewportHeightChanged(minHeight)"))
|
||||
assertTrue(source.contains("position == CreatorChannelTab.FanTalk.ordinal"))
|
||||
assertTrue(source.contains("override fun onCreatorChannelFanTalkContentChanged()"))
|
||||
assertTrue(source.contains("override fun onCreatorChannelFanTalkDeleteClicked(fanTalkId: Long)"))
|
||||
assertTrue(source.contains("SodaDialog("))
|
||||
assertTrue(source.contains("R.string.screen_user_profile_cheer_delete_title"))
|
||||
assertTrue(source.contains("R.string.screen_user_profile_cheer_delete_desc"))
|
||||
assertTrue(source.contains("R.string.confirm_delete_title"))
|
||||
assertTrue(source.contains("R.string.cancel"))
|
||||
assertTrue(source.contains("findFanTalkFragment()?.onCreatorChannelFanTalkDeleteConfirmed(fanTalkId)"))
|
||||
assertTrue(source.contains("findFanTalkFragment()?.onCreatorChannelFanTalkRefreshRequested()"))
|
||||
assertTrue(fragment.contains("interface Host"))
|
||||
assertTrue(fragment.contains("fun isCreatorChannelOwner(): Boolean"))
|
||||
assertTrue(fragment.contains("fun onCreatorChannelFanTalkContentChanged()"))
|
||||
assertTrue(fragment.contains("fun onCreatorChannelFanTalkDeleteClicked(fanTalkId: Long)"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `section adapter source는 활동 지표를 행 단위 resource label로 표시한다`() {
|
||||
val adapter = projectFile(
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.Application
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.audio.CreatorChannelAudioFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.fantalk.CreatorChannelFanTalkFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.live.CreatorChannelLiveFragment
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelTab
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.series.CreatorChannelSeriesFragment
|
||||
@@ -20,7 +21,7 @@ import org.robolectric.annotation.Config
|
||||
class CreatorChannelPagerAdapterTest {
|
||||
|
||||
@Test
|
||||
fun `createFragment는 Home Live Audio Series Community를 실제 Fragment로 생성하고 나머지는 placeholder를 유지한다`() {
|
||||
fun `createFragment는 Home Live Audio Series Community FanTalk를 실제 Fragment로 생성하고 나머지는 placeholder를 유지한다`() {
|
||||
val activity = Robolectric.buildActivity(FragmentActivity::class.java).setup().get()
|
||||
val adapter = CreatorChannelPagerAdapter(activity, creatorId = 123L)
|
||||
|
||||
@@ -29,13 +30,15 @@ class CreatorChannelPagerAdapterTest {
|
||||
assertTrue(adapter.createFragment(CreatorChannelTab.Audio.ordinal) is CreatorChannelAudioFragment)
|
||||
assertTrue(adapter.createFragment(CreatorChannelTab.Series.ordinal) is CreatorChannelSeriesFragment)
|
||||
assertTrue(adapter.createFragment(CreatorChannelTab.Community.ordinal) is CreatorChannelCommunityFragment)
|
||||
assertTrue(adapter.createFragment(CreatorChannelTab.FanTalk.ordinal) is CreatorChannelFanTalkFragment)
|
||||
CreatorChannelTab.entries
|
||||
.filterNot {
|
||||
it == CreatorChannelTab.Home ||
|
||||
it == CreatorChannelTab.Live ||
|
||||
it == CreatorChannelTab.Audio ||
|
||||
it == CreatorChannelTab.Series ||
|
||||
it == CreatorChannelTab.Community
|
||||
it == CreatorChannelTab.Community ||
|
||||
it == CreatorChannelTab.FanTalk
|
||||
}
|
||||
.forEach { tab ->
|
||||
assertTrue(adapter.createFragment(tab.ordinal) is CreatorChannelPlaceholderFragment)
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
package kr.co.vividnext.sodalive.v2.creator.channel.fantalk
|
||||
|
||||
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.assertFalse
|
||||
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 CreatorChannelFanTalkFragmentLayoutTest {
|
||||
|
||||
@Test
|
||||
fun `팬톡 fragment layout은 count list empty error retry floating write를 제공하고 sort UI는 제외한다`() {
|
||||
val root = inflateView(R.layout.fragment_creator_channel_fantalk)
|
||||
val layout = projectFile("app/src/main/res/layout/fragment_creator_channel_fantalk.xml").readText()
|
||||
val countBar = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_count_bar))
|
||||
val fanTalkList = requireNotNull(root.findViewById<RecyclerView>(R.id.rv_creator_channel_fantalk))
|
||||
val emptyContainer = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_empty))
|
||||
val emptyMessage = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_fantalk_empty_message))
|
||||
val emptyButton = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_empty_write_button))
|
||||
val errorMessage = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_fantalk_error_message))
|
||||
val retryButton = requireNotNull(root.findViewById<TextView>(R.id.btn_creator_channel_fantalk_retry))
|
||||
val floatingWriteButton = requireNotNull(root.findViewById<View>(R.id.btn_creator_channel_fantalk_write))
|
||||
|
||||
assertSame(root, countBar.parent)
|
||||
assertSame(root, fanTalkList.parent)
|
||||
assertSame(root, emptyContainer.parent)
|
||||
assertSame(emptyContainer, emptyMessage.parent)
|
||||
assertSame(emptyContainer, emptyButton.parent)
|
||||
assertSame(root, errorMessage.parent)
|
||||
assertSame(root, retryButton.parent)
|
||||
assertSame(root, floatingWriteButton.parent)
|
||||
assertEquals(false, fanTalkList.clipToPadding)
|
||||
assertNotNull(countBar.findViewById<TextView>(R.id.tv_creator_channel_fantalk_total_label))
|
||||
assertNotNull(countBar.findViewById<TextView>(R.id.tv_creator_channel_fantalk_total_count))
|
||||
assertFalse(layout.contains("sort"))
|
||||
assertFalse(layout.contains("정렬"))
|
||||
assertFalse(layout.contains("iv_creator_channel_fantalk_sort"))
|
||||
assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_all_label\""))
|
||||
assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_empty_message\""))
|
||||
assertTrue(layout.contains("android:gravity=\"center\""))
|
||||
assertTrue(layout.contains("android:layout_height=\"0dp\""))
|
||||
assertTrue(layout.contains("app:layout_constraintBottom_toBottomOf=\"parent\""))
|
||||
assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_support_action\""))
|
||||
assertTrue(layout.contains("tools:listitem=\"@layout/item_creator_channel_fantalk\""))
|
||||
assertTrue(layout.contains("@drawable/ic_new_fantalk_plus"))
|
||||
assertLocaleString("values/strings.xml", "아직 응원이 없습니다.\\n처음으로 크리에이터를 응원해 보세요!")
|
||||
assertLocaleString("values-en/strings.xml", "No cheers yet.\\nBe the first to cheer for the creator!")
|
||||
assertLocaleString("values-ja/strings.xml", "まだ応援がありません。\\n最初にクリエイターを応援してみましょう!")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `팬톡 item layout은 원글 action과 reply container를 제공한다`() {
|
||||
val item = inflateView(R.layout.item_creator_channel_fantalk)
|
||||
val itemLayout = projectFile("app/src/main/res/layout/item_creator_channel_fantalk.xml").readText()
|
||||
val replyBackground = projectFile(
|
||||
"app/src/main/res/drawable/bg_creator_channel_fantalk_reply.xml"
|
||||
).readText()
|
||||
|
||||
assertNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_fantalk_profile))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_fantalk_nickname))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_fantalk_time))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_fantalk_content))
|
||||
assertNotNull(item.findViewById<TextView>(R.id.tv_creator_channel_fantalk_report))
|
||||
assertNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_fantalk_more))
|
||||
assertNotNull(item.findViewById<View>(R.id.view_creator_channel_fantalk_reply_connector))
|
||||
assertNotNull(item.findViewById<View>(R.id.layout_creator_channel_fantalk_reply))
|
||||
assertNotNull(item.findViewById<ImageView>(R.id.iv_creator_channel_fantalk_reply_profile))
|
||||
assertTrue(itemLayout.contains("@drawable/ic_new_more"))
|
||||
assertTrue(itemLayout.contains("android:text=\"@string/creator_channel_fantalk_report\""))
|
||||
assertTrue(itemLayout.contains("android:layout_width=\"42dp\""))
|
||||
assertTrue(itemLayout.contains("android:layout_height=\"42dp\""))
|
||||
assertTrue(itemLayout.contains("android:layout_width=\"20dp\""))
|
||||
assertTrue(itemLayout.contains("android:layout_height=\"20dp\""))
|
||||
assertTrue(itemLayout.contains("@+id/barrier_creator_channel_fantalk_action_start"))
|
||||
assertTrue(itemLayout.contains("app:barrierDirection=\"start\""))
|
||||
assertTrue(
|
||||
itemLayout.contains(
|
||||
"app:constraint_referenced_ids=\"tv_creator_channel_fantalk_report,iv_creator_channel_fantalk_more\""
|
||||
)
|
||||
)
|
||||
assertTrue(
|
||||
itemLayout.contains(
|
||||
"app:layout_constraintEnd_toStartOf=\"@id/barrier_creator_channel_fantalk_action_start\""
|
||||
)
|
||||
)
|
||||
assertTrue(itemLayout.contains("@drawable/bg_creator_channel_fantalk_reply"))
|
||||
assertTrue(replyBackground.contains("@color/gray_900"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `팬톡 more popup layout은 수정 삭제 TextView를 제공한다`() {
|
||||
val popup = inflateView(R.layout.view_creator_channel_fantalk_more_popup)
|
||||
val popupLayout = projectFile("app/src/main/res/layout/view_creator_channel_fantalk_more_popup.xml").readText()
|
||||
|
||||
assertNotNull(popup.findViewById<TextView>(R.id.tv_creator_channel_fantalk_more_edit))
|
||||
assertNotNull(popup.findViewById<TextView>(R.id.tv_creator_channel_fantalk_more_delete))
|
||||
assertTrue(popupLayout.contains("android:text=\"@string/creator_channel_fantalk_edit\""))
|
||||
assertTrue(popupLayout.contains("android:text=\"@string/creator_channel_fantalk_delete\""))
|
||||
assertTrue(popupLayout.contains("@drawable/bg_creator_channel_sort_popup"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `팬톡 adapter와 popup source는 Phase 4 바인딩 계약을 포함한다`() {
|
||||
val adapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/ui/CreatorChannelFanTalkAdapter.kt"
|
||||
).readText()
|
||||
val popup = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/ui/CreatorChannelFanTalkMorePopup.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(adapter.contains("ItemCreatorChannelFantalkBinding"))
|
||||
assertTrue(adapter.contains("fun submitItems(items: List<CreatorChannelFanTalkUiModel>)"))
|
||||
assertTrue(adapter.contains("notifyDataSetChanged()"))
|
||||
assertTrue(adapter.contains("CircleCropTransformation()"))
|
||||
assertTrue(adapter.contains("R.drawable.ic_placeholder_profile"))
|
||||
assertTrue(adapter.contains("CreatorChannelFanTalkRightAction.Report"))
|
||||
assertTrue(adapter.contains("CreatorChannelFanTalkRightAction.OwnerMore"))
|
||||
assertFalse(adapter.contains("root.setOnClickListener"))
|
||||
assertTrue(popup.contains("PopupWindow(anchor.context)"))
|
||||
assertTrue(popup.contains("tvCreatorChannelFantalkMoreEdit.isVisible = showEdit"))
|
||||
assertTrue(popup.contains("tvCreatorChannelFantalkMoreDelete.isVisible = showDelete"))
|
||||
assertTrue(popup.contains("onDeleteClick(fanTalkId)"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `팬톡 fragment source는 Phase 5 상태 신고 삭제 Host 계약을 포함한다`() {
|
||||
val fragment = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkFragment.kt"
|
||||
).readText()
|
||||
val adapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/ui/CreatorChannelFanTalkAdapter.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(fragment.contains("BaseFragment<FragmentCreatorChannelFantalkBinding>"))
|
||||
assertTrue(fragment.contains("private val viewModel: CreatorChannelFanTalkViewModel by viewModel()"))
|
||||
assertTrue(fragment.contains("layoutManager = LinearLayoutManager(requireContext())"))
|
||||
assertTrue(fragment.contains("onCreatorChannelFanTalkTabSelected()"))
|
||||
assertTrue(fragment.contains("viewModel.loadFanTalks(creatorId, isOwner = host.isCreatorChannelOwner())"))
|
||||
assertTrue(fragment.contains("onCreatorChannelFanTalkScrolledToBottom()"))
|
||||
assertTrue(fragment.contains("viewModel.loadMore()"))
|
||||
assertTrue(fragment.contains("onCreatorChannelFanTalkRefreshRequested()"))
|
||||
assertTrue(fragment.contains("viewModel.refreshFanTalks()"))
|
||||
assertTrue(fragment.contains("onCreatorChannelFanTalkViewportHeightChanged(minHeight: Int)"))
|
||||
assertTrue(fragment.contains("binding.root.minimumHeight = minHeight"))
|
||||
assertTrue(fragment.contains("onCreatorChannelFanTalkDeleteConfirmed(fanTalkId: Long)"))
|
||||
assertTrue(fragment.contains("viewModel.deleteFanTalk(fanTalkId)"))
|
||||
assertTrue(fragment.contains("CheersReportDialog(requireActivity(), layoutInflater)"))
|
||||
assertTrue(fragment.contains("R.string.screen_user_profile_fantalk_report_reason_required"))
|
||||
assertTrue(fragment.contains("viewModel.reportFanTalk(item.fanTalkId, reason)"))
|
||||
assertTrue(fragment.contains("CreatorChannelFanTalkMorePopup("))
|
||||
assertTrue(fragment.contains("onDeleteClick = host::onCreatorChannelFanTalkDeleteClicked"))
|
||||
assertTrue(fragment.contains("fun onCreatorChannelFanTalkContentChanged()"))
|
||||
assertTrue(fragment.contains("fun onCreatorChannelFanTalkDeleteClicked(fanTalkId: Long)"))
|
||||
assertTrue(adapter.contains("private val onReportClick: (CreatorChannelFanTalkUiModel) -> Unit"))
|
||||
assertTrue(adapter.contains("tvCreatorChannelFantalkReport.setOnClickListener { onReportClick(item) }"))
|
||||
}
|
||||
|
||||
private fun inflateView(layoutResId: Int): View {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
return LayoutInflater.from(context).inflate(layoutResId, null, false)
|
||||
}
|
||||
|
||||
private fun projectFile(path: String): File = File(projectRoot(), path)
|
||||
|
||||
private fun assertLocaleString(path: String, expectedValue: String) {
|
||||
val strings = projectFile("app/src/main/res/$path").readText()
|
||||
assertTrue(strings.contains("<string name=\"creator_channel_fantalk_empty_message\">$expectedValue</string>"))
|
||||
}
|
||||
|
||||
private fun projectRoot(): File {
|
||||
return generateSequence(File(System.getProperty("user.dir") ?: ".").absoluteFile) { it.parentFile }
|
||||
.first { File(it, "settings.gradle").exists() }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user