Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step4 - 페이먼츠(카드 수정) #61

Open
wants to merge 9 commits into
base: eshc123
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,17 @@
- 카드사 목록 아이템 구현
- 카드사 선택 시 해당 카드에 맞게 카드 미리보기 변경 구현

### STEP-3 Feedback
- 카드사 선택 테스트 코드 추가
- BottomSheet 자연스럽게 사라지기
- PaymentCard 프리뷰 보완
- BankTypeUiModel nullable 개선

## STEP-4
- 카드 수정 기능 구현
- 카드 목록에서 카드를 선택하면 카드 수정 화면
- 카드 수정 화면에서 변경사항이 발생하지 않으면 수정이 불가능하게 구현
- 카드가 수정되면 카드 목록 화면에 변경사항이 반영
- 카드 수정 시 상단 타이틀 UI


1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
id("kotlin-parcelize")
}

android {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package nextstep.payments.ui

import androidx.activity.ComponentActivity
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.lifecycle.SavedStateHandle
import nextstep.payments.data.model.BankType
import nextstep.payments.data.model.CreditCard
import nextstep.payments.screen.model.BankTypeUiModel
import nextstep.payments.screen.cardmanage.ManageCardRouteScreen
import nextstep.payments.screen.cardmanage.ManageCardViewModel
import nextstep.payments.screen.model.arg.CardArgType
import org.junit.Before
import org.junit.Rule
import org.junit.Test

internal class ManageCardRouteScreenTest {

@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
private lateinit var viewModel: ManageCardViewModel

@Before
fun setUp() {
viewModel = ManageCardViewModel(
savedStateHandle = SavedStateHandle()
)
}

@Test
fun 카드가_추가되면_화면_이동_로직이_실행된다() {
var isNavigated = false

//GIVEN
composeTestRule.setContent {
ManageCardRouteScreen(
navigateToCardList = {
isNavigated = true
},
viewModel = viewModel
)
}
viewModel.setBankType(BankTypeUiModel.BC)
viewModel.setCardNumber("1234123412341234")
viewModel.setExpiredDate("1228")
viewModel.setPassword("1234")

//WHEN
composeTestRule.onNodeWithTag("saveButton").performClick()

composeTestRule.waitForIdle()

//THEN
assert(isNavigated)
}

@Test
fun 새_카드_추가_화면_진입_시_카드사_선택_바텀_시트가_나타난다() {
//GIVEN
composeTestRule.setContent {
ManageCardRouteScreen(
navigateToCardList = { },
viewModel = viewModel
)
}

//THEN
composeTestRule.onNodeWithTag("BankSelectBottomSheet")
.assertIsDisplayed()
}

@Test
fun 카드사_선택을_하지_않고_뒤로_가기_시_카드_추가_화면에서_빠져나온다() {
//GIVEN
composeTestRule.setContent {
ManageCardRouteScreen(
modifier = Modifier.testTag("ManageCardRouteScreen"),
navigateToCardList = { },
viewModel = viewModel
)
}

//WHEN
composeTestRule.runOnUiThread {
composeTestRule.activity.onBackPressedDispatcher.onBackPressed()
}

composeTestRule.waitForIdle()

//THEN
composeTestRule.onNodeWithTag("ManageCardRouteScreen")
.assertDoesNotExist()
}

@Test
fun 카드사를_선택하면_바텀시트가_내려가고_카드사가_선택되어있다() {
//GIVEN
composeTestRule.setContent {
ManageCardRouteScreen(
modifier = Modifier.testTag("ManageCardRouteScreen"),
navigateToCardList = { },
viewModel = viewModel
)
}

//WHEN
composeTestRule.onNodeWithTag(BankTypeUiModel.BC.name).performClick()

composeTestRule.waitForIdle()

//THEN
composeTestRule.onNodeWithTag("BankSelectBottomSheet")
.assertIsNotDisplayed()
assert(viewModel.bankType.value == BankTypeUiModel.BC)
}

@Test
fun 카드_수정_화면에서_변경사항이_발생하지_않으면_저장_버튼을_클릭할_수_없다() {
//GIVEN
viewModel = ManageCardViewModel(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 테스트들이 ManageCardViewModel의 의존적이라고도 볼수 있을거같아요
Screen과 ViewModel을 분리해서 테스트하면 조금더 독립적인 테스트코드를 작성할수 있을거같아요 :)
( 이부분은 고민 만해주셔도 좋을거같아요!)

savedStateHandle = SavedStateHandle().apply {
set(CardArgType.MANAGE_CARD_TYPE_ARG,
CardArgType.EditCardArg(
CreditCard(
cardNumber = "1234123412341234",
expiredDate = "1122",
ownerName = "김컴포즈",
password = "1234",
bankType = BankType.BC
)
)
)
}
)
composeTestRule.setContent {
ManageCardRouteScreen(
modifier = Modifier.testTag("ManageCardRouteScreen"),
navigateToCardList = { },
viewModel = viewModel
)
}

//THEN
composeTestRule.onNodeWithTag("saveButton").assertIsNotEnabled()
}

@Test
fun 카드_수정_화면에서_변경사항이_발생하면_저장_버튼을_클릭할_수_있다() {
//GIVEN
viewModel = ManageCardViewModel(
savedStateHandle = SavedStateHandle().apply {
set(CardArgType.MANAGE_CARD_TYPE_ARG,
CardArgType.EditCardArg(
CreditCard(
cardNumber = "1234123412341234",
expiredDate = "1122",
ownerName = "김컴포즈",
password = "1234",
bankType = BankType.BC
)
)
)
}
)
composeTestRule.setContent {
ManageCardRouteScreen(
modifier = Modifier.testTag("ManageCardRouteScreen"),
navigateToCardList = { },
viewModel = viewModel
)
}

//WHEN
viewModel.setBankType(BankTypeUiModel.HYUNDAI)

composeTestRule.waitForIdle()

//THEN
composeTestRule.onNodeWithTag("saveButton").assertIsEnabled()
}
}

This file was deleted.

10 changes: 6 additions & 4 deletions app/src/androidTest/java/nextstep/payments/ui/PaymentCardTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ internal class PaymentCardTest {
month = "",
year = "",
bankTypeUiModel = BankTypeUiModel.BC
)
),
onClick = {}
)
}

//THEN
composeTestRule
.onNodeWithTag("cardNumberText")
.onNodeWithTag("cardNumberText",useUnmergedTree = true)
.assertTextContains("1234 - 1234 - **** - ****")
}

Expand All @@ -52,13 +53,14 @@ internal class PaymentCardTest {
month = "04",
year = "13",
bankTypeUiModel = BankTypeUiModel.BC
)
),
onClick = {}
)
}

//THEN
composeTestRule
.onNodeWithTag("expiredDateText")
.onNodeWithTag(testTag = "expiredDateText", useUnmergedTree = true)
.assertTextContains("04 / 13")
}

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
</intent-filter>
</activity>
<activity
android:name=".screen.newcard.NewCardActivity"
android:name=".screen.cardmanage.ManageCardActivity"
android:exported="true"
android:theme="@style/Theme.Payments">
</activity>
Expand Down
20 changes: 17 additions & 3 deletions app/src/main/java/nextstep/payments/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import nextstep.payments.screen.cardlist.CardListScreen
import nextstep.payments.screen.cardlist.CardListViewModel
import nextstep.payments.screen.newcard.NewCardActivity
import nextstep.payments.screen.cardmanage.ManageCardActivity
import nextstep.payments.screen.model.arg.CardArgType
import nextstep.payments.screen.model.toModel
import nextstep.payments.ui.theme.PaymentsTheme

class MainActivity : ComponentActivity() {
Expand All @@ -26,8 +28,20 @@ class MainActivity : ComponentActivity() {
PaymentsTheme {
CardListScreen(
viewModel = viewModel,
navigateToNewCard = {
launcher.launch(Intent(this, NewCardActivity::class.java))
navigateToAddCard = {
launcher.launch(
Intent(this, ManageCardActivity::class.java)
)
},
navigateToEditCard = { card ->
launcher.launch(
Intent(this, ManageCardActivity::class.java).apply {
putExtra(
CardArgType.MANAGE_CARD_TYPE_ARG,
CardArgType.EditCardArg(card.toModel())
)
}
)
}
)
}
Expand Down
Loading