diff --git a/Kickstarter-iOS/Features/PledgeView/Controllers/NoShippingPledgeViewController.swift b/Kickstarter-iOS/Features/PledgeView/Controllers/NoShippingPledgeViewController.swift index 6597507d25..74d8bb9f89 100644 --- a/Kickstarter-iOS/Features/PledgeView/Controllers/NoShippingPledgeViewController.swift +++ b/Kickstarter-iOS/Features/PledgeView/Controllers/NoShippingPledgeViewController.swift @@ -41,11 +41,6 @@ final class NoShippingPledgeViewController: UIViewController, private var paymentSectionLabel: UILabel = { UILabel(frame: .zero) }() - private lazy var pledgeAmountViewController = { - PledgeAmountViewController.instantiate() - |> \.delegate .~ self - }() - internal var processingView: ProcessingView? = ProcessingView(frame: .zero) private lazy var pledgeDisclaimerView: PledgeDisclaimerView = { PledgeDisclaimerView(frame: .zero) @@ -305,12 +300,6 @@ final class NoShippingPledgeViewController: UIViewController, self?.pledgeRewardsSummaryViewController.configureWith(pledgeOverTimeData: data) } - self.viewModel.outputs.configurePledgeAmountViewWithData - .observeForUI() - .observeValues { [weak self] data in - self?.pledgeAmountViewController.configureWith(value: data) - } - self.viewModel.outputs.configurePledgeAmountSummaryViewControllerWithData .observeForUI() .observeValues { [weak self] data in @@ -337,12 +326,6 @@ final class NoShippingPledgeViewController: UIViewController, self?.pledgeCTAContainerView.configureWith(value: value) } - self.viewModel.outputs.notifyPledgeAmountViewControllerUnavailableAmountChanged - .observeForUI() - .observeValues { [weak self] amount in - self?.pledgeAmountViewController.unavailableAmountChanged(to: amount) - } - self.viewModel.outputs.configurePaymentMethodsViewControllerWithValue .observeForUI() .observeValues { [weak self] value in @@ -394,7 +377,6 @@ final class NoShippingPledgeViewController: UIViewController, self.localPickupLocationView.rac.hidden = self.viewModel.outputs.localPickupViewHidden self.paymentMethodsViewController.view.rac.hidden = self.viewModel.outputs.paymentMethodsViewHidden - self.pledgeAmountViewController.view.rac.hidden = self.viewModel.outputs.pledgeAmountViewHidden self.viewModel.outputs.title .observeForUI() @@ -429,12 +411,6 @@ final class NoShippingPledgeViewController: UIViewController, .observeValues { [weak self] errorMessage in self?.messageBannerViewController?.showBanner(with: .error, message: errorMessage) } - - self.viewModel.outputs.showApplePayAlert - .observeForControllerAction() - .observeValues { [weak self] title, message in - self?.presentApplePayInvalidAmountAlert(title: title, message: message) - } } private func goToPaymentAuthorization(_ paymentAuthorizationData: PaymentAuthorizationData) { @@ -461,10 +437,6 @@ final class NoShippingPledgeViewController: UIViewController, self.navigationController?.pushViewController(thanksVC, animated: true) } - private func presentApplePayInvalidAmountAlert(title: String, message: String) { - self.present(UIAlertController.alert(title, message: message), animated: true) - } - // MARK: - Actions @objc private func dismissKeyboard() { @@ -560,17 +532,6 @@ final class NoShippingPledgeViewController: UIViewController, } } -// MARK: - PledgeAmountViewControllerDelegate - -extension NoShippingPledgeViewController: PledgeAmountViewControllerDelegate { - func pledgeAmountViewController( - _: PledgeAmountViewController, - didUpdateWith data: PledgeAmountData - ) { - self.viewModel.inputs.pledgeAmountViewControllerDidUpdate(with: data) - } -} - // MARK: - STPAuthenticationContext extension NoShippingPledgeViewController: STPAuthenticationContext { diff --git a/Kickstarter-iOS/Features/PledgeView/Controllers/NoShippingPledgeViewControllerTests.swift b/Kickstarter-iOS/Features/PledgeView/Controllers/NoShippingPledgeViewControllerTests.swift index b06b7205e3..ea2765cc9c 100644 --- a/Kickstarter-iOS/Features/PledgeView/Controllers/NoShippingPledgeViewControllerTests.swift +++ b/Kickstarter-iOS/Features/PledgeView/Controllers/NoShippingPledgeViewControllerTests.swift @@ -267,6 +267,7 @@ final class NoShippingPledgeViewControllerTests: TestCase { let data = PledgeViewData( project: project, rewards: [nonReward], + bonusSupport: 1.0, selectedShippingRule: shippingRule, selectedQuantities: [nonReward.id: 1], selectedLocationId: ShippingRule.template.id, diff --git a/Library/ViewModels/NoShippingPledgeViewModel.swift b/Library/ViewModels/NoShippingPledgeViewModel.swift index eb2716f267..2aec48e6ba 100644 --- a/Library/ViewModels/NoShippingPledgeViewModel.swift +++ b/Library/ViewModels/NoShippingPledgeViewModel.swift @@ -23,7 +23,6 @@ public protocol NoShippingPledgeViewModelInputs { ) func paymentAuthorizationViewControllerDidFinish() func paymentPlanSelected(_ paymentPlan: PledgePaymentPlansType) - func pledgeAmountViewControllerDidUpdate(with data: PledgeAmountData) func pledgeDisclaimerViewDidTapLearnMore() func scaFlowCompleted(with result: StripePaymentHandlerActionStatusType, error: Error?) func stripeTokenCreated(token: String?, error: Error?) -> PKPaymentAuthorizationStatus @@ -38,7 +37,6 @@ public protocol NoShippingPledgeViewModelOutputs { var configureEstimatedShippingView: Signal<(String?, String?), Never> { get } var configureLocalPickupViewWithData: Signal { get } var configurePaymentMethodsViewControllerWithValue: Signal { get } - var configurePledgeAmountViewWithData: Signal { get } var configurePledgeAmountSummaryViewControllerWithData: Signal { get } var configurePledgeRewardsSummaryViewWithData: Signal< (PostCampaignRewardsSummaryViewData, Double?, PledgeSummaryViewData), @@ -53,13 +51,10 @@ public protocol NoShippingPledgeViewModelOutputs { var goToLoginSignup: Signal { get } var localPickupViewHidden: Signal { get } var notifyDelegateUpdatePledgeDidSucceedWithMessage: Signal { get } - var notifyPledgeAmountViewControllerUnavailableAmountChanged: Signal { get } var paymentMethodsViewHidden: Signal { get } - var pledgeAmountViewHidden: Signal { get } var pledgeAmountSummaryViewHidden: Signal { get } var popToRootViewController: Signal<(), Never> { get } var processingViewIsHidden: Signal { get } - var showApplePayAlert: Signal<(String, String), Never> { get } var showErrorBannerWithMessage: Signal { get } var showWebHelp: Signal { get } var title: Signal { get } @@ -95,7 +90,6 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin let backing = project.map { $0.personalization.backing }.skipNil() - self.pledgeAmountViewHidden = context.map { $0.pledgeAmountViewHidden } self.pledgeAmountSummaryViewHidden = context.map { $0.pledgeAmountSummaryViewHidden } self.descriptionSectionSeparatorHidden = Signal.combineLatest(context, baseReward) @@ -142,7 +136,7 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin ) // Initial pledge amount is zero if not backed and not set previously in the flow. - let initialAdditionalPledgeAmount = initialData.map { + let additionalPledgeAmount = initialData.map { if let bonusSupport = $0.bonusSupport { return bonusSupport } else if let backing = $0.project.personalization.backing { @@ -152,14 +146,6 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin } } - // TODO(MBL-1670): Delete the additional pledge amount, any validation, and the stepper class. - let additionalPledgeAmount = Signal.merge( - self.pledgeAmountDataSignal.map { $0.amount }, - initialAdditionalPledgeAmount - ) - - self.notifyPledgeAmountViewControllerUnavailableAmountChanged = allRewardsTotal - let projectAndReward = Signal.zip(project, baseReward) /** @@ -199,19 +185,6 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin self.localPickupViewHidden = baseReward.map(isRewardLocalPickup).negate() - self.configurePledgeAmountViewWithData = Signal.combineLatest( - projectAndReward, - initialAdditionalPledgeAmount - ) - .map(unpack) - .map { project, reward, additionalPledgeAmount in - ( - project, - reward, - additionalPledgeAmount - ) - } - self.configureLocalPickupViewWithData = projectAndReward .switchMap { projectAndReward -> SignalProducer in guard let locationName = projectAndReward.1.localPickup?.displayableName else { @@ -350,9 +323,6 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin self.paymentMethodsViewHidden = Signal.combineLatest(isLoggedIn, context) .map { !$0 || $1.paymentMethodsViewHidden } - let pledgeAmountIsValid: Signal = self.pledgeAmountDataSignal - .map { $0.isValid } - self.configureStripeIntegration = Signal.combineLatest( initialData, context @@ -416,14 +386,6 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin .filter { $0 == .changePaymentMethod } .ignoreValues() - let goToApplePayPaymentAuthorization = pledgeAmountIsValid - .takeWhen(self.applePayButtonTappedSignal) - .filter(isTrue) - - let showApplePayAlert = pledgeAmountIsValid - .takeWhen(self.applePayButtonTappedSignal) - .filter(isFalse) - let paymentAuthorizationData: Signal = Signal.combineLatest( project, baseReward, @@ -445,7 +407,7 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin } self.goToApplePayPaymentAuthorization = paymentAuthorizationData - .takeWhen(goToApplePayPaymentAuthorization) + .takeWhen(self.applePayButtonTappedSignal) let pkPaymentData = self.pkPaymentSignal .map { pkPayment -> PKPaymentData? in @@ -671,41 +633,6 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin // MARK: - Form Validation - let amountChangedAndValid = Signal.combineLatest( - project, - baseReward, - self.pledgeAmountDataSignal, - initialAdditionalPledgeAmount, - context - ) - .map(amountValid) - - self.showApplePayAlert = Signal.combineLatest( - project, - self.pledgeAmountDataSignal - ) - .takeWhen(showApplePayAlert) - .map { project, pledgeAmountData in (project, pledgeAmountData.min, pledgeAmountData.max) } - .map { project, min, max in - ( - Strings.Almost_there(), - Strings.Please_enter_a_pledge_amount_between_min_and_max( - min: Format - .currency( - min, - country: projectCountry(forCurrency: project.stats.currency) ?? project.country, - omitCurrencyCode: false - ), - max: Format - .currency( - max, - country: projectCountry(forCurrency: project.stats.currency) ?? project.country, - omitCurrencyCode: false - ) - ) - ) - } - let notChangingPaymentMethod = context.map { context in context.isUpdating && context != .changePaymentMethod } @@ -724,19 +651,20 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin ) let valuesChangedAndValid = Signal.combineLatest( - amountChangedAndValid, paymentMethodChangedAndValid, self.pledgeOverTimeUseCase.pledgeOverTimeIsLoading, context ) .map(allValuesChangedAndValid) + let didCreateOrUpdateBacking = createOrUpdateEvent.filter { $0.isTerminating } + let isEnabled = Signal.merge( self.viewDidLoadProperty.signal.mapConst(false) .take(until: valuesChangedAndValid.ignoreValues()), valuesChangedAndValid, self.submitButtonTappedSignal.mapConst(false), - createOrUpdateEvent.filter { $0.isTerminating }.mapConst(true) + valuesChangedAndValid.takeWhen(didCreateOrUpdateBacking) ) .skipRepeats() @@ -926,7 +854,7 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin rewards, selectedQuantities, refTag, - initialAdditionalPledgeAmount, + additionalPledgeAmount, pledgeTotal, context ) @@ -1065,11 +993,6 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin self.goToLoginSignupObserver.send(value: ()) } - private let (pledgeAmountDataSignal, pledgeAmountObserver) = Signal.pipe() - public func pledgeAmountViewControllerDidUpdate(with data: PledgeAmountData) { - self.pledgeAmountObserver.send(value: data) - } - private let (pledgeDisclaimerViewDidTapLearnMoreSignal, pledgeDisclaimerViewDidTapLearnMoreObserver) = Signal.pipe() public func pledgeDisclaimerViewDidTapLearnMore() { @@ -1119,7 +1042,6 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin public let configureEstimatedShippingView: Signal<(String?, String?), Never> public let configureLocalPickupViewWithData: Signal public let configurePaymentMethodsViewControllerWithValue: Signal - public let configurePledgeAmountViewWithData: Signal public let configurePledgeAmountSummaryViewControllerWithData: Signal public let configurePledgeRewardsSummaryViewWithData: Signal< (PostCampaignRewardsSummaryViewData, Double?, PledgeSummaryViewData), @@ -1134,14 +1056,11 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin public let goToLoginSignup: Signal public let localPickupViewHidden: Signal public let notifyDelegateUpdatePledgeDidSucceedWithMessage: Signal - public let notifyPledgeAmountViewControllerUnavailableAmountChanged: Signal public let paymentMethodsViewHidden: Signal - public let pledgeAmountViewHidden: Signal public let pledgeAmountSummaryViewHidden: Signal public let popToRootViewController: Signal<(), Never> public let processingViewIsHidden: Signal public let showErrorBannerWithMessage: Signal - public let showApplePayAlert: Signal<(String, String), Never> public let showWebHelp: Signal public let title: Signal @@ -1169,34 +1088,6 @@ private func requiresSCA(_ envelope: StripeSCARequiring) -> Bool { // MARK: - Validation Functions -private func amountValid( - project: Project, - reward: Reward, - pledgeAmountData: PledgeAmountData, - initialAdditionalPledgeAmount: Double, - context: PledgeViewContext -) -> Bool { - guard - project.personalization.backing != nil, - context.isUpdating, - userIsBacking(reward: reward, inProject: project) - else { - return pledgeAmountData.isValid - } - - /** - The amount is valid if it's changed or if the reward has add-ons. - This works because of the validation that would have occurred during add-ons selection, - that is, in `RewardAddOnSelectionViewController` we don't navigate further unless the selection changes. - */ - return [ - pledgeAmountData - .amount != initialAdditionalPledgeAmount || (reward.hasAddOns || featureNoShippingAtCheckout()), - pledgeAmountData.isValid - ] - .allSatisfy(isTrue) -} - private func shippingRuleValid( project: Project, reward: Reward, @@ -1242,16 +1133,15 @@ private func paymentMethodValid( } private func allValuesChangedAndValid( - amountValid: Bool, paymentSourceValid: Bool, pledgeOverTimeIsLoading: Bool, context: PledgeViewContext ) -> Bool { if context.isUpdating, context != .updateReward { - return amountValid || paymentSourceValid + return paymentSourceValid } - return amountValid && !pledgeOverTimeIsLoading + return !pledgeOverTimeIsLoading } // MARK: - Helper Functions diff --git a/Library/ViewModels/NoShippingPledgeViewModelTests.swift b/Library/ViewModels/NoShippingPledgeViewModelTests.swift index b32eb96862..e570640242 100644 --- a/Library/ViewModels/NoShippingPledgeViewModelTests.swift +++ b/Library/ViewModels/NoShippingPledgeViewModelTests.swift @@ -58,12 +58,9 @@ final class NoShippingPledgeViewModelTests: TestCase { private let notifyDelegateUpdatePledgeDidSucceedWithMessage = TestObserver() private let paymentMethodsViewHidden = TestObserver() - private let pledgeAmountViewHidden = TestObserver() private let pledgeAmountSummaryViewHidden = TestObserver() private let popToRootViewController = TestObserver<(), Never>() private let processingViewIsHidden = TestObserver() - private let showApplePayAlertMessage = TestObserver() - private let showApplePayAlertTitle = TestObserver() private let showErrorBannerWithMessage = TestObserver() private let showWebHelp = TestObserver() private let title = TestObserver() @@ -138,13 +135,10 @@ final class NoShippingPledgeViewModelTests: TestCase { .observe(self.notifyDelegateUpdatePledgeDidSucceedWithMessage.observer) self.vm.outputs.paymentMethodsViewHidden.observe(self.paymentMethodsViewHidden.observer) - self.vm.outputs.pledgeAmountViewHidden.observe(self.pledgeAmountViewHidden.observer) self.vm.outputs.pledgeAmountSummaryViewHidden.observe(self.pledgeAmountSummaryViewHidden.observer) self.vm.outputs.popToRootViewController.observe(self.popToRootViewController.observer) self.vm.outputs.processingViewIsHidden.observe(self.processingViewIsHidden.observer) - self.vm.outputs.showApplePayAlert.map(second).observe(self.showApplePayAlertMessage.observer) - self.vm.outputs.showApplePayAlert.map(first).observe(self.showApplePayAlertTitle.observer) self.vm.outputs.showWebHelp.observe(self.showWebHelp.observer) self.vm.outputs.showErrorBannerWithMessage.observe(self.showErrorBannerWithMessage.observer) @@ -218,7 +212,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configureStripeIntegrationPublishableKey.assertValues([Secrets.StripePublishableKey.staging]) self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) } } @@ -263,7 +256,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configureStripeIntegrationPublishableKey.assertValues([Secrets.StripePublishableKey.staging]) self.paymentMethodsViewHidden.assertValues([true]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) } } @@ -301,14 +293,20 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePaymentMethodsViewControllerWithContext.assertDidNotEmitValue() self.configurePledgeViewCTAContainerViewIsLoggedIn.assertValues([true]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues( + [true], + "CTA is automatically enabled when you are updating the pledge." + ) + XCTAssertTrue( + self.configurePledgeViewCTAContainerViewContext.lastValue!.applePayButtonHidden, + "ApplePay button is hidden when you are updating the pledge." + ) self.configurePledgeViewCTAContainerViewContext.assertValues([.updateReward]) self.configureStripeIntegrationMerchantId.assertDidNotEmitValue() self.configureStripeIntegrationPublishableKey.assertDidNotEmitValue() self.paymentMethodsViewHidden.assertValues([true]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) } } @@ -356,18 +354,23 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePaymentMethodsViewControllerWithContext.assertValues([.changePaymentMethod]) self.configurePledgeViewCTAContainerViewIsLoggedIn.assertValues([true]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until new payment method is selected" + ) self.configurePledgeViewCTAContainerViewContext.assertValues([.changePaymentMethod]) self.configureStripeIntegrationMerchantId.assertValues([Secrets.ApplePay.merchantIdentifier]) self.configureStripeIntegrationPublishableKey.assertValues([Secrets.StripePublishableKey.staging]) self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([true]) self.pledgeAmountSummaryViewHidden.assertValues([false]) - let pledgeAmountData: PledgeAmountData = (amount: 70, min: 10.00, max: 10_000, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) + self.vm.inputs.creditCardSelected(with: .savedCreditCard("12345", "pm_fake")) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "Selecting new payment method enables CTA" + ) } } @@ -405,6 +408,11 @@ final class NoShippingPledgeViewModelTests: TestCase { self.title.assertValues(["Fix payment method"]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until new payment method is selected" + ) + self.configurePledgeRewardsSummaryViewRewards.assertValues([[reward]]) self.configurePledgeRewardsSummaryViewProjectCurrencyCountry.assertValues([.us]) self.configurePledgeRewardsSummaryViewOmitCurrencyCode.assertValues([true]) @@ -421,17 +429,17 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePledgeViewCTAContainerViewWillRetryPaymentMethod.assertValues([false]) self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([true]) self.pledgeAmountSummaryViewHidden.assertValues([false]) let paymentSourceSelected = PaymentSourceSelected.savedCreditCard(backing.paymentSource!.id!, "pm_fake") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.configurePledgeViewCTAContainerViewWillRetryPaymentMethod.assertValues([false, true]) - - let pledgeAmountData: PledgeAmountData = (amount: 70, min: 10.00, max: 10_000, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) + self.configurePledgeViewCTAContainerViewWillRetryPaymentMethod.assertLastValue(true) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA is disabled until new payment method is selected" + ) } } @@ -482,12 +490,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configureStripeIntegrationPublishableKey.assertValues([Secrets.StripePublishableKey.staging]) self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([true]) self.pledgeAmountSummaryViewHidden.assertValues([false]) - - let pledgeAmountData: PledgeAmountData = (amount: 12.0, min: 1.0, max: 10_000, isValid: true) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) } } @@ -534,7 +537,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configureStripeIntegrationPublishableKey.assertValues([Secrets.StripePublishableKey.staging]) self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([true]) self.pledgeAmountSummaryViewHidden.assertValues([false]) self.configurePledgeRewardsSummaryViewRewards.assertLastValue([reward]) @@ -578,7 +580,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePledgeViewCTAContainerViewContext.assertValues([.pledge]) self.paymentMethodsViewHidden.assertValues([true]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) } } @@ -612,7 +613,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePledgeViewCTAContainerViewContext.assertValues([.pledge]) self.paymentMethodsViewHidden.assertValues([true]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) } } @@ -646,7 +646,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePledgeViewCTAContainerViewContext.assertValues([.pledge]) self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) } } @@ -680,7 +679,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePledgeViewCTAContainerViewContext.assertValues([.pledge]) self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) } } @@ -714,50 +712,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePledgeViewCTAContainerViewContext.assertValues([.pledge]) self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([false]) - self.pledgeAmountSummaryViewHidden.assertValues([true]) - } - } - - func testPledgeAmountUpdates() { - let project = Project.template - let reward = Reward.template - |> Reward.lens.shipping.enabled .~ true - - withEnvironment(currentUser: .template) { - let data = PledgeViewData( - project: project, - rewards: [reward], - selectedShippingRule: shippingRule, - selectedQuantities: [reward.id: 1], - selectedLocationId: nil, - refTag: .projectPage, - context: .pledge - ) - - self.vm.inputs.configure(with: data) - self.vm.inputs.viewDidLoad() - - self.configurePaymentMethodsViewControllerWithUser.assertValues([User.template]) - self.configurePaymentMethodsViewControllerWithProject.assertValues([project]) - self.configurePaymentMethodsViewControllerWithReward.assertValues([reward]) - self.configurePaymentMethodsViewControllerWithContext.assertValues([.pledge]) - - self.configurePledgeViewCTAContainerViewIsLoggedIn.assertValues([true]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - self.configurePledgeViewCTAContainerViewContext.assertValues([.pledge]) - - self.paymentMethodsViewHidden.assertValues([false]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) - - let data1 = (amount: 66.0, min: 10.0, max: 10_000.0, isValid: true) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: data1) - - let data2 = (amount: 93.0, min: 10.0, max: 10_000.0, isValid: true) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: data2) } } @@ -790,7 +745,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.configurePledgeViewCTAContainerViewContext.assertValues([.pledge]) self.paymentMethodsViewHidden.assertValues([true]) - self.pledgeAmountViewHidden.assertValues([false]) self.pledgeAmountSummaryViewHidden.assertValues([true]) withEnvironment(currentUser: user) { @@ -870,11 +824,11 @@ final class NoShippingPledgeViewModelTests: TestCase { let project = Project.template let reward = Reward.noReward |> Reward.lens.minimum .~ 1 - let pledgeAmountData = (amount: 5.0, min: 1.0, max: 10_000.0, isValid: true) let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 5.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: nil, @@ -885,8 +839,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationReward.assertDidNotEmitValue() @@ -912,11 +864,11 @@ final class NoShippingPledgeViewModelTests: TestCase { |> Reward.lens.minimum .~ 20 |> Reward.lens.shipping.enabled .~ true let shippingRule = ShippingRule.template - let pledgeAmountData = (amount: 25.0, min: 25.0, max: 10_000.0, isValid: true) let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 25, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: nil, @@ -935,8 +887,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.goToApplePayPaymentAuthorizationAllRewardsShippingTotal.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationMerchantId.assertDidNotEmitValue() - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.vm.inputs.applePayButtonTapped() self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() @@ -954,11 +904,11 @@ final class NoShippingPledgeViewModelTests: TestCase { |> Reward.lens.minimum .~ 20 |> Reward.lens.shipping.enabled .~ true let shippingRule = ShippingRule.template - let pledgeAmountData = (amount: 25.0, min: 25.0, max: 10_000.0, isValid: true) let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 25.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: nil, @@ -969,8 +919,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.vm.inputs.applePayButtonTapped() self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() @@ -1160,6 +1108,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 10.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: nil, @@ -1179,9 +1128,6 @@ final class NoShippingPledgeViewModelTests: TestCase { paymentData: (displayName: "Visa 123", network: "Visa", transactionIdentifier: "12345") ) - let pledgeAmountData = (amount: 10.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - XCTAssertEqual( PKPaymentAuthorizationStatus.success, self.vm.inputs.stripeTokenCreated(token: "stripe_token", error: nil) @@ -1251,6 +1197,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 10.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: nil, @@ -1270,9 +1217,6 @@ final class NoShippingPledgeViewModelTests: TestCase { paymentData: (displayName: "Visa 123", network: "Visa", transactionIdentifier: "12345") ) - let pledgeAmountData = (amount: 10.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - XCTAssertEqual( PKPaymentAuthorizationStatus.success, self.vm.inputs.stripeTokenCreated(token: "stripe_token", error: nil) @@ -1559,6 +1503,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward, addOn1, addOn2], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1, addOn1.id: 2, addOn2.id: 1], selectedLocationId: shippingRule.location.id, @@ -1578,20 +1523,14 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 15.0, min: 10.0, max: 10_000.0, isValid: true) - ) - self.processingViewIsHidden.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.vm.inputs.submitButtonTapped() self.processingViewIsHidden.assertValues([false]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -1599,7 +1538,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -1657,6 +1596,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 25.00, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1, addOnReward1.id: 2, addOnReward2.id: 1], selectedLocationId: nil, @@ -1676,20 +1616,14 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 10.0, max: 10_000.0, isValid: true) - ) - self.processingViewIsHidden.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.vm.inputs.submitButtonTapped() self.processingViewIsHidden.assertValues([false]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -1697,7 +1631,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -1759,19 +1693,13 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 10.0, max: 10_000.0, isValid: true) - ) - - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.vm.inputs.submitButtonTapped() self.processingViewIsHidden.assertValues([false]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -1779,7 +1707,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) @@ -1842,25 +1770,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - self.processingViewIsHidden.assertDidNotEmitValue() - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 25.0, max: 10_000.0, isValid: true) - ) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) - self.processingViewIsHidden.assertDidNotEmitValue() - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([true]) self.processingViewIsHidden.assertDidNotEmitValue() self.vm.inputs.submitButtonTapped() @@ -1869,13 +1779,13 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([true, false]) self.processingViewIsHidden.assertValues([false]) self.scheduler.run() self.processingViewIsHidden.assertValues([false, true]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([true, false, true]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertValues([ "Got it! Your changes have been saved." @@ -1924,25 +1834,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - self.processingViewIsHidden.assertDidNotEmitValue() - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 25.0, max: 10_000.0, isValid: true) - ) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) - self.processingViewIsHidden.assertDidNotEmitValue() - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([true]) self.processingViewIsHidden.assertDidNotEmitValue() self.vm.inputs.submitButtonTapped() @@ -1951,13 +1843,13 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([true, false]) self.processingViewIsHidden.assertValues([false]) self.scheduler.run() self.processingViewIsHidden.assertValues([false, true]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([true, false, true]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() @@ -1965,96 +1857,7 @@ final class NoShippingPledgeViewModelTests: TestCase { } } - func testUpdatingRewardSubmitButtonEnabled_ShippingEnabled() { - let reward = Reward.postcards - |> Reward.lens.shipping.enabled .~ true - - let project = Project.cosmicSurgery - |> Project.lens.state .~ .live - |> Project.lens.personalization.isBacking .~ true - |> Project.lens.personalization.backing .~ ( - .template - |> Backing.lens.paymentSource .~ Backing.PaymentSource.template - |> Backing.lens.status .~ .pledged - |> Backing.lens.reward .~ Reward.otherReward - |> Backing.lens.rewardId .~ Reward.otherReward.id - |> Backing.lens.shippingAmount .~ 10 - |> Backing.lens.amount .~ 700.0 - ) - - self.configurePledgeViewCTAContainerViewIsEnabled.assertDidNotEmitValue() - - let updateBackingEnvelope = UpdateBackingEnvelope( - updateBacking: .init( - checkout: .init( - id: "Q2hlY2tvdXQtMQ==", - state: .successful, - backing: .init( - clientSecret: "client-secret", - requiresAction: false - ) - ) - ) - ) - - let mockService = MockService( - updateBackingResult: .success(updateBackingEnvelope) - ) - - withEnvironment(apiService: mockService, currentUser: .template) { - let data = PledgeViewData( - project: project, - rewards: [reward], - selectedShippingRule: shippingRule, - selectedQuantities: [reward.id: 1], - selectedLocationId: nil, - refTag: nil, - context: .updateReward - ) - - self.vm.inputs.configure(with: data) - self.vm.inputs.viewDidLoad() - - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 690, min: 25.0, max: 10_000.0, isValid: true) - ) - - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true], "Amount unchanged") - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues( - [false, false, true], "Shipping rule and amount unchanged, button enabled due to different reward" - ) - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - - self.vm.inputs.submitButtonTapped() - - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - - self.scheduler.run() - - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertValues([ - "Got it! Your changes have been saved." - ]) - self.popToRootViewController.assertValueCount(1) - self.showErrorBannerWithMessage.assertDidNotEmitValue() - } - } - - func testChangingPaymentMethodSubmitButtonEnabled_ShippingEnabled() { + func testChangingPaymentMethod_SubmitButtonEnabled_OnlyWhenNewMethodIsSelected() { let reward = Reward.postcards |> Reward.lens.shipping.enabled .~ true |> Reward.lens.minimum .~ 10 @@ -2095,15 +1898,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 550, min: 25.0, max: 10_000.0, isValid: true) - ) - - self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( - false, - "CTA shouldn't be enabled until payment method is selected" - ) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(false, "No payment method selected") var paymentSourceSelected = PaymentSourceSelected.savedCreditCard("12345", "pm_fake") @@ -2118,7 +1913,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true, "Payment method unchanged") + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "Selected original payment method again" + ) } func testGoToApplePayPaymentAuthorization_HasAddOns() { @@ -2143,6 +1941,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward, addOnReward1, addOnReward2], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1, addOnReward1.id: 2, addOnReward2.id: 1], selectedLocationId: shippingRule.location.id, @@ -2153,9 +1952,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.vm.inputs.applePayButtonTapped() self.goToApplePayPaymentAuthorizationProject.assertValues([project]) @@ -2225,6 +2021,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: defaultShippingRule.location.id, @@ -2235,9 +2032,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationReward.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationAllRewardsTotal.assertDidNotEmitValue() @@ -2248,7 +2042,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.applePayButtonTapped() @@ -2263,7 +2057,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationDidAuthorizePayment( @@ -2280,7 +2074,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() XCTAssertEqual( @@ -2298,7 +2092,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationViewControllerDidFinish() @@ -2313,7 +2107,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -2330,7 +2124,7 @@ final class NoShippingPledgeViewModelTests: TestCase { ]) self.popToRootViewController.assertValueCount(1) self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() } } @@ -2381,6 +2175,7 @@ final class NoShippingPledgeViewModelTests: TestCase { |> Backing.lens.rewardId .~ reward.id |> Backing.lens.shippingAmount .~ 10 |> Backing.lens.amount .~ 700.0 + |> Backing.lens.bonusAmount .~ 15.0 ) let defaultShippingRule = ShippingRule( @@ -2394,6 +2189,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: defaultShippingRule.location.id, @@ -2404,9 +2200,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationReward.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationAllRewardsTotal.assertDidNotEmitValue() @@ -2417,7 +2210,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.applePayButtonTapped() @@ -2432,7 +2225,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() XCTAssertEqual( @@ -2450,7 +2243,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(false) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -2465,7 +2258,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(false) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationViewControllerDidFinish() @@ -2480,7 +2273,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(false) self.goToThanksProject.assertDidNotEmitValue() } } @@ -2517,6 +2310,7 @@ final class NoShippingPledgeViewModelTests: TestCase { |> Backing.lens.rewardId .~ reward.id |> Backing.lens.shippingAmount .~ 10 |> Backing.lens.amount .~ 700.0 + |> Backing.lens.bonusAmount .~ 15.0 ) let defaultShippingRule = ShippingRule( @@ -2530,6 +2324,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: defaultShippingRule.location.id, @@ -2540,9 +2335,6 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationReward.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationAllRewardsTotal.assertDidNotEmitValue() @@ -2552,7 +2344,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.applePayButtonTapped() @@ -2567,7 +2359,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationDidAuthorizePayment( @@ -2584,7 +2376,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() XCTAssertEqual( @@ -2602,7 +2394,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -2617,7 +2409,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationViewControllerDidFinish() @@ -2632,12 +2424,12 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) self.goToThanksProject.assertDidNotEmitValue() } } - func testApplePayBackingFails_ThenSucceeds_SignalsDoNotOverlap_UpdateContext() { + func testApplePayBackingFails_ThenSucceeds_SignalsDoNotOverlap_ChangePaymentMethodContext() { let mockService1 = MockService( updateBackingResult: .failure(.couldNotParseJSON) ) @@ -2682,19 +2474,17 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: defaultShippingRule.location.id, refTag: .projectPage, - context: .update + context: .changePaymentMethod ) self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationReward.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationAllRewardsTotal.assertDidNotEmitValue() @@ -2704,7 +2494,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.applePayButtonTapped() @@ -2719,7 +2512,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationDidAuthorizePayment( @@ -2736,7 +2532,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() XCTAssertEqual( @@ -2754,7 +2553,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -2769,7 +2571,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationViewControllerDidFinish() @@ -2784,7 +2589,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() } @@ -2834,7 +2642,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() XCTAssertEqual( @@ -2855,7 +2666,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -2873,7 +2687,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationViewControllerDidFinish() @@ -2893,12 +2710,15 @@ final class NoShippingPledgeViewModelTests: TestCase { ]) self.popToRootViewController.assertValueCount(1) self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() } } - func testApplePayBackingFails_ThenStoredCardSucceeds_SignalsDoNotOverlap_UpdateContext() { + func testApplePayBackingFails_ThenStoredCardSucceeds_SignalsDoNotOverlap_ChangePaymentMethodContext() { let mockService1 = MockService( updateBackingResult: .failure(.couldNotParseJSON) ) @@ -2917,6 +2737,7 @@ final class NoShippingPledgeViewModelTests: TestCase { |> Backing.lens.rewardId .~ reward.id |> Backing.lens.shippingAmount .~ 10 |> Backing.lens.amount .~ 700.0 + |> Backing.lens.bonusAmount .~ 15.0 ) self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() @@ -2943,19 +2764,17 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: defaultShippingRule.location.id, refTag: .projectPage, - context: .update + context: .changePaymentMethod ) self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationReward.assertDidNotEmitValue() self.goToApplePayPaymentAuthorizationAllRewardsTotal.assertDidNotEmitValue() @@ -2966,7 +2785,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.applePayButtonTapped() @@ -2981,7 +2803,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationDidAuthorizePayment( @@ -2998,7 +2823,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() XCTAssertEqual( @@ -3016,7 +2844,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -3031,7 +2862,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationViewControllerDidFinish() @@ -3046,7 +2880,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() } @@ -3082,7 +2919,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA enabled because payment method was selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.submitButtonTapped() @@ -3097,7 +2937,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA disabled because submit button was tapped" + ) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -3114,12 +2957,15 @@ final class NoShippingPledgeViewModelTests: TestCase { ]) self.popToRootViewController.assertValueCount(1) self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA enabled because update backing completed" + ) self.goToThanksProject.assertDidNotEmitValue() } } - func testStoredCardFails_ThenApplePaySucceeds_SignalsDoNotOverlap_UpdateContext() { + func testStoredCardFails_ThenApplePaySucceeds_SignalsDoNotOverlap_ChangePaymentMethodContext() { let mockService1 = MockService( updateBackingResult: .failure(.couldNotParseJSON) ) @@ -3138,6 +2984,7 @@ final class NoShippingPledgeViewModelTests: TestCase { |> Backing.lens.rewardId .~ reward.id |> Backing.lens.shippingAmount .~ 10 |> Backing.lens.amount .~ 700.0 + |> Backing.lens.bonusAmount .~ 15.0 ) self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() @@ -3165,19 +3012,17 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: defaultShippingRule.location.id, refTag: .projectPage, - context: .update + context: .changePaymentMethod ) self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - let paymentSourceSelected = PaymentSourceSelected.savedCreditCard("123", "pm_fake") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -3192,7 +3037,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.submitButtonTapped() @@ -3207,7 +3052,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(false) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -3222,7 +3067,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.goToThanksProject.assertDidNotEmitValue() } @@ -3256,7 +3101,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationDidAuthorizePayment( @@ -3273,7 +3118,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.goToThanksProject.assertDidNotEmitValue() XCTAssertEqual( @@ -3291,7 +3136,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -3306,7 +3151,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationViewControllerDidFinish() @@ -3323,12 +3168,12 @@ final class NoShippingPledgeViewModelTests: TestCase { ]) self.popToRootViewController.assertValueCount(1) self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.goToThanksProject.assertDidNotEmitValue() } } - func testStoredCardFails_ThenApplePayFails_SignalsDoNotOverlap_UpdateContext() { + func testStoredCardFails_ThenApplePayFails_SignalsDoNotOverlap_ChangePaymentMethodContext() { let mockService = MockService( updateBackingResult: .failure(.couldNotParseJSON) ) @@ -3347,6 +3192,7 @@ final class NoShippingPledgeViewModelTests: TestCase { |> Backing.lens.rewardId .~ reward.id |> Backing.lens.shippingAmount .~ 10 |> Backing.lens.amount .~ 700.0 + |> Backing.lens.bonusAmount .~ 15.0 ) self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() @@ -3374,18 +3220,21 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 15.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: defaultShippingRule.location.id, refTag: .projectPage, - context: .update + context: .changePaymentMethod ) self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled until payment method is selected" + ) let paymentSourceSelected = PaymentSourceSelected.savedCreditCard("123", "pm_fake") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -3400,7 +3249,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA is enabled once payment method is selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.submitButtonTapped() @@ -3415,7 +3267,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled after submit button tapped" + ) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -3430,7 +3285,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA is enabled again after update backing completes" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.applePayButtonTapped() @@ -3445,7 +3303,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA stays enabled because a payment method has been selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationDidAuthorizePayment( @@ -3462,7 +3323,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA stays enabled because a payment method has been selected" + ) self.goToThanksProject.assertDidNotEmitValue() XCTAssertEqual( @@ -3480,7 +3344,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA stays enabled because a payment method has been selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.scheduler.run() @@ -3495,7 +3362,10 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues(["Something went wrong."]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA stays enabled because a payment method has been selected" + ) self.goToThanksProject.assertDidNotEmitValue() self.vm.inputs.paymentAuthorizationViewControllerDidFinish() @@ -3513,7 +3383,10 @@ final class NoShippingPledgeViewModelTests: TestCase { "Something went wrong.", "Something went wrong." ]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA stays enabled because a payment method has been selected" + ) self.goToThanksProject.assertDidNotEmitValue() } } @@ -3553,6 +3426,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 15.00, selectedShippingRule: defaultShippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: defaultShippingRule.location.id, @@ -3573,16 +3447,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - self.goToThanksProject.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 15.0, min: 10.0, max: 10_000.0, isValid: true) - ) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3590,7 +3455,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3598,7 +3463,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3608,7 +3473,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3701,16 +3566,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - self.goToThanksProject.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 10.0, max: 10_000.0, isValid: true) - ) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() self.processingViewIsHidden.assertDidNotEmitValue() @@ -3719,7 +3575,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3727,7 +3583,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3737,7 +3593,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertValues( ["The operation couldn’t be completed. (KsApi.GraphError error 5.)"] @@ -3803,30 +3659,21 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - self.goToThanksProject.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 10.0, max: 10_000.0, isValid: true) - ) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() self.vm.inputs.submitButtonTapped() self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() self.scheduler.run() self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3835,7 +3682,7 @@ final class NoShippingPledgeViewModelTests: TestCase { ) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3854,7 +3701,7 @@ final class NoShippingPledgeViewModelTests: TestCase { } } - func testUpdateBacking_RequiresSCA_Success() { + func testChangePaymentMethod_RequiresSCA_Success() { let reward = Reward.postcards |> Reward.lens.shipping.enabled .~ true @@ -3896,33 +3743,24 @@ final class NoShippingPledgeViewModelTests: TestCase { selectedQuantities: [reward.id: 1], selectedLocationId: nil, refTag: .discovery, - context: .update + context: .changePaymentMethod ) self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() + self.vm.inputs.creditCardSelected(with: .savedCreditCard( + "12345", + "pm_fake" + )) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 25.0, max: 10_000.0, isValid: true) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA is enabled because payment method is selected" ) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) self.processingViewIsHidden.assertDidNotEmitValue() self.vm.inputs.submitButtonTapped() @@ -3931,14 +3769,20 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA is disabled because submit button was tapped" + ) self.processingViewIsHidden.assertValues([false]) self.scheduler.run() self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA is enabled because update backing completed" + ) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -3947,7 +3791,10 @@ final class NoShippingPledgeViewModelTests: TestCase { ) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA is enabled because update backing completed" + ) self.goToThanksProject.assertDidNotEmitValue() self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertValues([ "Got it! Your changes have been saved." @@ -3957,7 +3804,7 @@ final class NoShippingPledgeViewModelTests: TestCase { } } - func testUpdateBacking_RequiresSCA_Failed() { + func testChangePaymentMethod_RequiresSCA_Failed() { let reward = Reward.postcards |> Reward.lens.shipping.enabled .~ true @@ -3999,34 +3846,22 @@ final class NoShippingPledgeViewModelTests: TestCase { selectedQuantities: [reward.id: 1], selectedLocationId: nil, refTag: .discovery, - context: .update + context: .changePaymentMethod ) self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 25.0, max: 10_000.0, isValid: true) - ) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.vm.inputs.creditCardSelected(with: .savedCreditCard("12345", "pm_fake")) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) - self.processingViewIsHidden.assertDidNotEmitValue() + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA enabled because payment method is selected" + ) self.vm.inputs.submitButtonTapped() @@ -4034,14 +3869,20 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + false, + "CTA disabled because submit button tapped" + ) self.processingViewIsHidden.assertValues([false]) self.scheduler.run() self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA enabled because update backing completed" + ) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -4050,7 +3891,10 @@ final class NoShippingPledgeViewModelTests: TestCase { ) self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue( + true, + "CTA still enabled because update backing completed" + ) self.goToThanksProject.assertDidNotEmitValue() self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() @@ -4060,7 +3904,7 @@ final class NoShippingPledgeViewModelTests: TestCase { } } - func testUpdateBacking_RequiresSCA_Canceled() { + func testChangePaymentMethod_RequiresSCA_Canceled() { let reward = Reward.postcards |> Reward.lens.shipping.enabled .~ true @@ -4102,33 +3946,21 @@ final class NoShippingPledgeViewModelTests: TestCase { selectedQuantities: [reward.id: 1], selectedLocationId: nil, refTag: .discovery, - context: .update + context: .changePaymentMethod ) self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() + self.vm.inputs.creditCardSelected(with: .savedCreditCard( + "12345", + "pm_fake" + )) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 25.0, max: 10_000.0, isValid: true) - ) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) - - self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() - self.popToRootViewController.assertDidNotEmitValue() - self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.vm.inputs.submitButtonTapped() @@ -4136,12 +3968,12 @@ final class NoShippingPledgeViewModelTests: TestCase { self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(false) self.scheduler.run() self.beginSCAFlowWithClientSecret.assertValues(["client-secret"]) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) self.goToThanksProject.assertDidNotEmitValue() self.notifyDelegateUpdatePledgeDidSucceedWithMessage.assertDidNotEmitValue() self.popToRootViewController.assertDidNotEmitValue() @@ -4237,28 +4069,6 @@ final class NoShippingPledgeViewModelTests: TestCase { ]) } - func testPledgeAmountSummaryViewHidden_UpdateContext_RegularReward_IsNotHidden() { - self.pledgeAmountSummaryViewHidden.assertDidNotEmitValue() - - let project = Project.template - let reward = Reward.template - - let data = PledgeViewData( - project: project, - rewards: [reward], - selectedShippingRule: shippingRule, - selectedQuantities: [reward.id: 1], - selectedLocationId: nil, - refTag: .projectPage, - context: .update - ) - - self.vm.inputs.configure(with: data) - self.vm.inputs.viewDidLoad() - - self.pledgeAmountSummaryViewHidden.assertValues([false]) - } - func testCreateBacking_WithNewPaymentSheetCard_TappedPledgeButton_Success() { let createBacking = CreateBackingEnvelope.CreateBacking( checkout: Checkout( @@ -4285,6 +4095,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 25.00, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1, addOnReward1.id: 2, addOnReward2.id: 1], selectedLocationId: nil, @@ -4304,20 +4115,14 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 10.0, max: 10_000.0, isValid: true) - ) - self.processingViewIsHidden.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.vm.inputs.submitButtonTapped() self.processingViewIsHidden.assertValues([false]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -4325,7 +4130,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -4383,6 +4188,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 25.00, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1, addOnReward1.id: 1, addOnReward2.id: 1], selectedLocationId: nil, @@ -4402,7 +4208,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.processingViewIsHidden.assertDidNotEmitValue() @@ -4412,10 +4218,6 @@ final class NoShippingPledgeViewModelTests: TestCase { paymentData: (displayName: "Visa 123", network: "Visa", transactionIdentifier: "12345") ) - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 25.0, min: 10.0, max: 10_000.0, isValid: true) - ) - XCTAssertEqual( PKPaymentAuthorizationStatus.success, self.vm.inputs.stripeTokenCreated(token: "stripe_token", error: nil) @@ -4424,14 +4226,14 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.paymentAuthorizationViewControllerDidFinish() self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() self.scheduler.run() self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -4513,50 +4315,6 @@ final class NoShippingPledgeViewModelTests: TestCase { XCTAssertEqual(["Page Viewed", "CTA Clicked"], self.segmentTrackingClient.events) } - func testTrackingEvents_ContextIsUpdate() { - let project = Project.template - let reward = Reward.template - - let data = PledgeViewData( - project: project, - rewards: [reward], - selectedShippingRule: shippingRule, - selectedQuantities: [reward.id: 1], - selectedLocationId: nil, - refTag: nil, - context: .update - ) - - self.vm.inputs.configure(with: data) - self.vm.inputs.viewDidLoad() - - let segmentTrackingClientProps = self.segmentTrackingClient.properties.last - - XCTAssertEqual(["Page Viewed"], self.segmentTrackingClient.events) - XCTAssertEqual("update_pledge", segmentTrackingClientProps?["context_page"] as? String) - XCTAssertEqual("update_pledge", segmentTrackingClient.properties.last?["context_page"] as? String) - - // Checkout properties - - XCTAssertEqual("credit_card", segmentTrackingClientProps?["checkout_payment_type"] as? String) - XCTAssertEqual("My Reward", segmentTrackingClientProps?["checkout_reward_title"] as? String) - XCTAssertEqual(10.00, segmentTrackingClientProps?["checkout_reward_minimum_usd"] as? Decimal) - XCTAssertEqual("1", segmentTrackingClientProps?["checkout_reward_id"] as? String) - XCTAssertEqual(10.00, segmentTrackingClientProps?["checkout_amount_total_usd"] as? Decimal) - XCTAssertEqual(true, segmentTrackingClientProps?["checkout_reward_is_limited_quantity"] as? Bool) - XCTAssertEqual( - true, - segmentTrackingClientProps?["checkout_user_has_eligible_stored_apple_pay_card"] as? Bool - ) - - self.vm.inputs.submitButtonTapped() - - XCTAssertEqual( - ["Page Viewed", "CTA Clicked"], - self.segmentTrackingClient.events - ) - } - func testTrackingEvents_ContextIsUpdateReward() { let project = Project.template let reward = Reward.template @@ -4714,6 +4472,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward], + bonusSupport: 40.0, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1], selectedLocationId: nil, @@ -4726,13 +4485,6 @@ final class NoShippingPledgeViewModelTests: TestCase { XCTAssertEqual(["Page Viewed"], self.segmentTrackingClient.events) - self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: ( - amount: 40.0, - min: 10.0, - max: 100.0, - isValid: true - )) - let paymentSourceSelected = PaymentSourceSelected.savedCreditCard("123", "pm_fake") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -4960,9 +4712,6 @@ final class NoShippingPledgeViewModelTests: TestCase { let paymentSourceSelected = PaymentSourceSelected.savedCreditCard("123", "pm_fake") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 15.0, min: 10.0, max: 10_000.0, isValid: true) - ) // Should be true, since pledge over time loaded and everything else is correct self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) } @@ -4999,9 +4748,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let paymentSourceSelected = PaymentSourceSelected.savedCreditCard("123", "pm_fake") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 15.0, min: 10.0, max: 10_000.0, isValid: true) - ) + // Should be true, since pledge over time never loaded and everything else is correct self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(true) } @@ -5040,10 +4787,6 @@ final class NoShippingPledgeViewModelTests: TestCase { let paymentSourceSelected = PaymentSourceSelected.savedCreditCard("123", "pm_fake") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 15.0, min: 10.0, max: 10_000.0, isValid: true) - ) - // Should still be disabled, since pledge over time never loaded self.configurePledgeViewCTAContainerViewIsEnabled.assertLastValue(false) } @@ -5102,6 +4845,7 @@ final class NoShippingPledgeViewModelTests: TestCase { let data = PledgeViewData( project: project, rewards: [reward, addOn1, addOn2], + bonusSupport: 15.00, selectedShippingRule: shippingRule, selectedQuantities: [reward.id: 1, addOn1.id: 2, addOn2.id: 1], selectedLocationId: shippingRule.location.id, @@ -5121,14 +4865,8 @@ final class NoShippingPledgeViewModelTests: TestCase { self.vm.inputs.creditCardSelected(with: paymentSourceSelected) - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false]) - - self.vm.inputs.pledgeAmountViewControllerDidUpdate( - with: (amount: 15.0, min: 10.0, max: 10_000.0, isValid: true) - ) - self.processingViewIsHidden.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true]) self.vm.inputs.paymentPlanSelected(.pledgeOverTime) @@ -5136,7 +4874,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false]) self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() @@ -5144,7 +4882,7 @@ final class NoShippingPledgeViewModelTests: TestCase { self.processingViewIsHidden.assertValues([false, true]) self.beginSCAFlowWithClientSecret.assertDidNotEmitValue() - self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, false, true, false, true]) + self.configurePledgeViewCTAContainerViewIsEnabled.assertValues([false, true, false, true]) self.showErrorBannerWithMessage.assertDidNotEmitValue()