Skip to content

Commit

Permalink
[MBL-1328] Update Pledge Button Enabled Signals (#2022)
Browse files Browse the repository at this point in the history
* Use same signal for validate card input and deciding if pledge button is enabled

* Ensure selectedCard doesn't get filtered before pledge button is clicked

* add tests

---------

Co-authored-by: Ingerid Fosli <i.fosli@kickstarter.com>
  • Loading branch information
scottkicks and ifosli committed Apr 4, 2024
1 parent 39e2bf3 commit 4b90a3d
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 27 deletions.
73 changes: 47 additions & 26 deletions Library/ViewModels/PostCampaignCheckoutViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ public class PostCampaignCheckoutViewModel: PostCampaignCheckoutViewModelType,
.skipNil()

let context = initialData.map(\.context)
let project = initialData.map(\.project)
let checkoutId = initialData.map(\.checkoutId)
let baseReward = initialData.map(\.rewards).map(\.first)

Expand All @@ -110,28 +109,6 @@ public class PostCampaignCheckoutViewModel: PostCampaignCheckoutViewModelType,
.map { _ in AppEnvironment.current.currentUser }
.map(isNotNil)

let shouldEnablePledgeButton = self.creditCardSelectedProperty.signal.skipNil().mapConst(true)

let pledgeButtonEnabled = Signal.merge(
self.viewDidLoadProperty.signal.mapConst(false),
shouldEnablePledgeButton
)
.skipRepeats()

self.configurePledgeViewCTAContainerView = Signal.combineLatest(
isLoggedIn,
pledgeButtonEnabled,
context
)
.map { isLoggedIn, pledgeButtonEnabled, context in
PledgeViewCTAContainerViewData(
isLoggedIn: isLoggedIn,
isEnabled: pledgeButtonEnabled,
context: context,
willRetryPaymentMethod: false // Only retry in the `fixPaymentMethod` context.
)
}

self.paymentMethodsViewHidden = Signal.combineLatest(isLoggedIn, context)
.map { isLoggedIn, context in
!isLoggedIn || context.paymentMethodsViewHidden
Expand Down Expand Up @@ -219,9 +196,16 @@ public class PostCampaignCheckoutViewModel: PostCampaignCheckoutViewModelType,
let paymentIntentClientSecretForExistingCards = newPaymentIntentForExistingCards.values()
.map { $0.clientSecret }

let validateCheckoutExistingCardInput = Signal
.combineLatest(
checkoutId,
selectedCard,
paymentIntentClientSecretForExistingCards,
storedCardsValues
)

// Runs validation for pre-existing cards that were created with setup intents originally but require payment intents for late pledges.
let validateCheckoutExistingCard = Signal
.combineLatest(checkoutId, selectedCard, paymentIntentClientSecretForExistingCards, storedCardsValues)
let validateCheckoutExistingCard = validateCheckoutExistingCardInput
.takeWhen(self.submitButtonTappedProperty.signal)
.filter { _, selectedCard, _, _ in
selectedCard.isNewPaymentMethod == false
Expand Down Expand Up @@ -258,8 +242,10 @@ public class PostCampaignCheckoutViewModel: PostCampaignCheckoutViewModelType,

// MARK: - Validate New Cards

let validateCheckoutNewCardInput = Signal.combineLatest(checkoutId, selectedCard)

// Runs validation for new cards that were created with payment intents.
let validateCheckoutNewCard = Signal.combineLatest(checkoutId, selectedCard)
let validateCheckoutNewCard = validateCheckoutNewCardInput
.takeWhen(self.submitButtonTappedProperty.signal)
.filter { _, selectedCard in
selectedCard.isNewPaymentMethod == true
Expand Down Expand Up @@ -422,6 +408,41 @@ public class PostCampaignCheckoutViewModel: PostCampaignCheckoutViewModelType,

self.checkoutError = checkoutCompleteSignal.signal.errors()

// MARK: - UI related to checkout flow

let newCardActivatesPledgeButton = validateCheckoutNewCardInput
.filter { _, selectedCard in
selectedCard.isNewPaymentMethod == true
}
.mapConst(true)

let existingCardActivatesPledgeButton = validateCheckoutExistingCardInput
.filter { _, selectedCard, _, _ in
selectedCard.isNewPaymentMethod == false
}
.mapConst(true)

let pledgeButtonEnabled = Signal.merge(
self.viewDidLoadProperty.signal.mapConst(false),
newCardActivatesPledgeButton,
existingCardActivatesPledgeButton
)
.skipRepeats()

self.configurePledgeViewCTAContainerView = Signal.combineLatest(
isLoggedIn,
pledgeButtonEnabled,
context
)
.map { isLoggedIn, pledgeButtonEnabled, context in
PledgeViewCTAContainerViewData(
isLoggedIn: isLoggedIn,
isEnabled: pledgeButtonEnabled,
context: context,
willRetryPaymentMethod: false // Only retry in the `fixPaymentMethod` context.
)
}

self.processingViewIsHidden = Signal.merge(
// Processing view starts hidden, so show at the start of a pledge flow.
self.submitButtonTappedProperty.signal.mapConst(false),
Expand Down
30 changes: 29 additions & 1 deletion Library/ViewModels/PostCampaignCheckoutViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ final class PostCampaignCheckoutViewModelTests: TestCase {
}
}

func testPledgeViewCTA_LoggedIn_State() {
func testPledgeViewCTAEnabled_afterSelectingNewPaymentMethod_LoggedIn() {
let mockService = MockService(serverConfig: ServerConfig.staging)

withEnvironment(apiService: mockService, currentUser: .template) {
Expand Down Expand Up @@ -542,4 +542,32 @@ final class PostCampaignCheckoutViewModelTests: TestCase {
self.configurePledgeViewCTAContainerViewContext.assertValues([.latePledge, .latePledge])
}
}

func testPledgeViewCTADisabled_onViewDidLoad_LoggedIn() {
let mockService = MockService(serverConfig: ServerConfig.staging)

withEnvironment(apiService: mockService, currentUser: .template) {
let project = Project.cosmicSurgery
let reward = Reward.noReward |> Reward.lens.minimum .~ 5

let data = PostCampaignCheckoutData(
project: project,
rewards: [reward],
selectedQuantities: [:],
bonusAmount: 0,
total: 5,
shipping: nil,
refTag: nil,
context: .latePledge,
checkoutId: "0"
)

self.vm.inputs.configure(with: data)
self.vm.inputs.viewDidLoad()

self.configurePledgeViewCTAContainerViewIsLoggedIn.assertValues([true])
self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false])
self.configurePledgeViewCTAContainerViewContext.assertValues([.latePledge])
}
}
}

0 comments on commit 4b90a3d

Please sign in to comment.