From 67bb6935638a26e9eb7310894755fc7c3c473a0d Mon Sep 17 00:00:00 2001 From: Amy Date: Wed, 20 Mar 2024 14:56:56 -0400 Subject: [PATCH] MBL-1123: Refactor PaymentSourceSelected to be an enum, instead of a struct --- Kickstarter.xcodeproj/project.pbxproj | 4 + .../ViewModels/PaymentSourceSelected.swift | 25 ++++++ .../PledgePaymentMethodsViewModel.swift | 10 +-- .../PledgePaymentMethodsViewModelTests.swift | 19 ++-- Library/ViewModels/PledgeViewModel.swift | 59 ++++--------- Library/ViewModels/PledgeViewModelTests.swift | 86 ++++--------------- 6 files changed, 73 insertions(+), 130 deletions(-) create mode 100644 Library/ViewModels/PaymentSourceSelected.swift diff --git a/Kickstarter.xcodeproj/project.pbxproj b/Kickstarter.xcodeproj/project.pbxproj index e6ef504dd2..932a1c3baa 100644 --- a/Kickstarter.xcodeproj/project.pbxproj +++ b/Kickstarter.xcodeproj/project.pbxproj @@ -1525,6 +1525,7 @@ E17611E22B73D9A400DF2F50 /* Data+PKCE.swift in Sources */ = {isa = PBXBuildFile; fileRef = E17611E12B73D9A400DF2F50 /* Data+PKCE.swift */; }; E17611E42B751E8100DF2F50 /* Paginator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E17611E32B751E8100DF2F50 /* Paginator.swift */; }; E17611E62B75242A00DF2F50 /* PaginatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E17611E52B75242A00DF2F50 /* PaginatorTests.swift */; }; + E1801FAA2BAB6D0900EBB533 /* PaymentSourceSelected.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1801FA82BAB6CD400EBB533 /* PaymentSourceSelected.swift */; }; E182E5BA2B8CDFDE0008DD69 /* AppEnvironmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7ED1F121E830FDC00BFFA01 /* AppEnvironmentTests.swift */; }; E182E5BC2B8D36FE0008DD69 /* AppEnvironmentTests+OAuthInKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = E182E5BB2B8D36FE0008DD69 /* AppEnvironmentTests+OAuthInKeychain.swift */; }; E1A1491E2ACDD76800F49709 /* FetchBackerProjectsQuery.graphql in Resources */ = {isa = PBXBuildFile; fileRef = E1A1491D2ACDD76700F49709 /* FetchBackerProjectsQuery.graphql */; }; @@ -3148,6 +3149,7 @@ E17611E12B73D9A400DF2F50 /* Data+PKCE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+PKCE.swift"; sourceTree = ""; }; E17611E32B751E8100DF2F50 /* Paginator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paginator.swift; sourceTree = ""; }; E17611E52B75242A00DF2F50 /* PaginatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginatorTests.swift; sourceTree = ""; }; + E1801FA82BAB6CD400EBB533 /* PaymentSourceSelected.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentSourceSelected.swift; sourceTree = ""; }; E182E5BB2B8D36FE0008DD69 /* AppEnvironmentTests+OAuthInKeychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppEnvironmentTests+OAuthInKeychain.swift"; sourceTree = ""; }; E1889D8D2B6065D6004FBE21 /* CombineTestObserverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineTestObserverTests.swift; sourceTree = ""; }; E1A1491D2ACDD76700F49709 /* FetchBackerProjectsQuery.graphql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FetchBackerProjectsQuery.graphql; sourceTree = ""; }; @@ -6529,6 +6531,7 @@ D710ADFA243FB94A00DC7199 /* PledgeViewCTAContainerViewModel.swift */, D710ADFC2441172100DC7199 /* PledgeViewCTAContainerViewModelTests.swift */, 37DEC1E62257C9F30051EF9B /* PledgeViewModel.swift */, + E1801FA82BAB6CD400EBB533 /* PaymentSourceSelected.swift */, 37DEC21F2257CA0A0051EF9B /* PledgeViewModelTests.swift */, 395A3BC82BA8D43F0091A379 /* PostCampaignCheckoutViewModel.swift */, 6044532D2BA0905600B8F485 /* PostCampaignPledgeRewardsSummaryViewModel.swift */, @@ -7698,6 +7701,7 @@ D7ADDFE722E0DAFA00157D83 /* RewardCellProjectBackingStateType.swift in Sources */, D79D61151FD0979D000F958B /* String+Base64.swift in Sources */, 7727494723FC66EA0065E9F2 /* CategorySelectionViewModel.swift in Sources */, + E1801FAA2BAB6D0900EBB533 /* PaymentSourceSelected.swift in Sources */, 77EFBAE32268D48A00DA5C3C /* RewardsCollectionViewModel.swift in Sources */, 3705CF0F222EE7670025D37E /* EnvironmentVariables.swift in Sources */, A73379601D0EDFEE00C91445 /* UIViewController-Preparation.swift in Sources */, diff --git a/Library/ViewModels/PaymentSourceSelected.swift b/Library/ViewModels/PaymentSourceSelected.swift new file mode 100644 index 0000000000..52e32d7203 --- /dev/null +++ b/Library/ViewModels/PaymentSourceSelected.swift @@ -0,0 +1,25 @@ +import Foundation +public enum PaymentSourceSelected: Equatable { + case paymentSourceId(String) + case setupIntentClientSecret(String) + + public var paymentSourceId: String? { + if case let .paymentSourceId(value) = self { + return value + } else { + return nil + } + } + + public var setupIntentClientSecret: String? { + if case let .setupIntentClientSecret(value) = self { + return value + } else { + return nil + } + } + + public var rawValue: String { + return self.paymentSourceId ?? self.setupIntentClientSecret! + } +} diff --git a/Library/ViewModels/PledgePaymentMethodsViewModel.swift b/Library/ViewModels/PledgePaymentMethodsViewModel.swift index 9b5ee8d0de..263c074a50 100644 --- a/Library/ViewModels/PledgePaymentMethodsViewModel.swift +++ b/Library/ViewModels/PledgePaymentMethodsViewModel.swift @@ -259,15 +259,9 @@ public final class PledgePaymentMethodsViewModel: PledgePaymentMethodsViewModelT switch (selectedPaymentMethodCardId, selectedPaymentSheetPaymentMethodCardId) { case let (.none, .some(selectedPaymentSheetPaymentMethodCardId)): - return PaymentSourceSelected( - paymentSourceId: selectedPaymentSheetPaymentMethodCardId, - isSetupIntentClientSecret: true - ) + return PaymentSourceSelected.setupIntentClientSecret(selectedPaymentSheetPaymentMethodCardId) case let (.some(selectedPaymentMethodCardId), .none): - return PaymentSourceSelected( - paymentSourceId: selectedPaymentMethodCardId, - isSetupIntentClientSecret: false - ) + return PaymentSourceSelected.paymentSourceId(selectedPaymentMethodCardId) default: return nil } diff --git a/Library/ViewModels/PledgePaymentMethodsViewModelTests.swift b/Library/ViewModels/PledgePaymentMethodsViewModelTests.swift index 3662c87084..1f90838101 100644 --- a/Library/ViewModels/PledgePaymentMethodsViewModelTests.swift +++ b/Library/ViewModels/PledgePaymentMethodsViewModelTests.swift @@ -740,7 +740,7 @@ final class PledgePaymentMethodsViewModelTests: TestCase { self.scheduler.run() self.notifyDelegateCreditCardSelected.assertValues( - [PaymentSourceSelected(paymentSourceId: UserCreditCards.amex.id, isSetupIntentClientSecret: false)], + [PaymentSourceSelected.paymentSourceId(UserCreditCards.amex.id)], "First card selected by default" ) @@ -752,11 +752,8 @@ final class PledgePaymentMethodsViewModelTests: TestCase { self.vm.inputs.didSelectRowAtIndexPath(discoverIndexPath) self.notifyDelegateCreditCardSelected.assertValues([ - PaymentSourceSelected(paymentSourceId: UserCreditCards.amex.id, isSetupIntentClientSecret: false), - PaymentSourceSelected( - paymentSourceId: UserCreditCards.discover.id, - isSetupIntentClientSecret: false - ) + PaymentSourceSelected.paymentSourceId(UserCreditCards.amex.id), + PaymentSourceSelected.paymentSourceId(UserCreditCards.discover.id) ]) } } @@ -774,7 +771,7 @@ final class PledgePaymentMethodsViewModelTests: TestCase { self.scheduler.run() self.notifyDelegateCreditCardSelected.assertValues( - [PaymentSourceSelected(paymentSourceId: UserCreditCards.visa.id, isSetupIntentClientSecret: false)], + [PaymentSourceSelected.paymentSourceId(UserCreditCards.visa.id)], "First card selected by default" ) @@ -793,11 +790,9 @@ final class PledgePaymentMethodsViewModelTests: TestCase { ) self.notifyDelegateCreditCardSelected.assertValues([ - PaymentSourceSelected(paymentSourceId: UserCreditCards.visa.id, isSetupIntentClientSecret: false), - PaymentSourceSelected( - paymentSourceId: "seti_1LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLZ", - isSetupIntentClientSecret: true - ) + PaymentSourceSelected.paymentSourceId(UserCreditCards.visa.id), + PaymentSourceSelected + .setupIntentClientSecret("seti_1LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLZ") ]) } } diff --git a/Library/ViewModels/PledgeViewModel.swift b/Library/ViewModels/PledgeViewModel.swift index d00066f04a..78ca49af7d 100644 --- a/Library/ViewModels/PledgeViewModel.swift +++ b/Library/ViewModels/PledgeViewModel.swift @@ -4,11 +4,6 @@ import PassKit import Prelude import ReactiveSwift -public struct PaymentSourceSelected: Equatable { - let paymentSourceId: String - let isSetupIntentClientSecret: Bool -} - public typealias StripeConfigurationData = (merchantIdentifier: String, publishableKey: String) public typealias CreateBackingData = ( project: Project, @@ -394,14 +389,8 @@ public class PledgeViewModel: PledgeViewModelType, PledgeViewModelInputs, Pledge ) } - /// The `selectedPaymentSourceId` will do as it did before taking the payment source id (A) or the setup intent client secret (B), one or the other for comparison against the existing backing payment source id. It does not care which of two payment sources the id refers to. - let selectedPaymentSourceId = Signal.merge( - initialData.mapConst(nil), - self.creditCardSelectedSignal.map { $0.paymentSourceId }.wrapInOptional() - ) - - /// The `selectedPaymentSourceIdOrSetupIntentClientSecret` will take the payment source id (A) or the setup intent client secret (B) and map only to `createBackingData` or `updateBackingData` - let selectedPaymentSourceIdOrSetupIntentClientSecret = Signal.merge( + /// The `selectedPaymentSource` will take the payment source id (A) or the setup intent client secret (B) and map only to `createBackingData` or `updateBackingData` + let selectedPaymentSource = Signal.merge( initialData.mapConst(nil), self.creditCardSelectedSignal.wrapInOptional() ) @@ -556,7 +545,7 @@ public class PledgeViewModel: PledgeViewModelType, PledgeViewModelInputs, Pledge pledgeTotal, selectedQuantities, selectedShippingRule, - selectedPaymentSourceIdOrSetupIntentClientSecret, + selectedPaymentSource, applePayParamsData, refTag ) @@ -566,19 +555,13 @@ public class PledgeViewModel: PledgeViewModelType, PledgeViewModelInputs, Pledge pledgeTotal, selectedQuantities, selectedShippingRule, - selectedPaymentSourceIdOrSetupIntentClientSecret, + selectedPaymentSource, applePayParams, refTag ) -> CreateBackingData in - var paymentSourceId: String? - var setupIntentClientSecret: String? - - if let isSetupIntentClientSecretAvailable = selectedPaymentSourceIdOrSetupIntentClientSecret { - paymentSourceId = isSetupIntentClientSecretAvailable - .isSetupIntentClientSecret ? nil : isSetupIntentClientSecretAvailable.paymentSourceId - setupIntentClientSecret = isSetupIntentClientSecretAvailable - .isSetupIntentClientSecret ? isSetupIntentClientSecretAvailable.paymentSourceId : nil - } + + var paymentSourceId = selectedPaymentSource?.paymentSourceId + var setupIntentClientSecret = selectedPaymentSource?.setupIntentClientSecret return ( project: project, @@ -639,7 +622,7 @@ public class PledgeViewModel: PledgeViewModelType, PledgeViewModelInputs, Pledge pledgeTotal, selectedQuantities, selectedShippingRule, - selectedPaymentSourceIdOrSetupIntentClientSecret, + selectedPaymentSource, applePayParamsData ) .map { ( @@ -648,18 +631,11 @@ public class PledgeViewModel: PledgeViewModelType, PledgeViewModelInputs, Pledge pledgeTotal, selectedQuantities, selectedShippingRule, - selectedPaymentSourceIdOrSetupIntentClientSecret, + selectedPaymentSource, applePayParams ) -> UpdateBackingData in - var paymentSourceId: String? - var setupIntentClientSecret: String? - - if let isSetupIntentClientSecretAvailable = selectedPaymentSourceIdOrSetupIntentClientSecret { - paymentSourceId = isSetupIntentClientSecretAvailable - .isSetupIntentClientSecret ? nil : isSetupIntentClientSecretAvailable.paymentSourceId - setupIntentClientSecret = isSetupIntentClientSecretAvailable - .isSetupIntentClientSecret ? isSetupIntentClientSecretAvailable.paymentSourceId : nil - } + var paymentSourceId = selectedPaymentSource?.paymentSourceId + var setupIntentClientSecret = selectedPaymentSource?.setupIntentClientSecret return ( backing: backing, @@ -774,7 +750,7 @@ public class PledgeViewModel: PledgeViewModelType, PledgeViewModelInputs, Pledge Signal.combineLatest( project, baseReward, - self.creditCardSelectedSignal.map { $0.paymentSourceId }, + self.creditCardSelectedSignal, context ) .map(paymentMethodValid) @@ -956,11 +932,12 @@ public class PledgeViewModel: PledgeViewModelType, PledgeViewModelInputs, Pledge let willRetryPaymentMethod = Signal.combineLatest( context, project, - selectedPaymentSourceId + selectedPaymentSource ) - .map { context, project, selectedPaymentSourceId -> Bool in + .map { context, project, selectedPaymentSource -> Bool in + context == .fixPaymentMethod - && project.personalization.backing?.paymentSource?.id == selectedPaymentSourceId + && project.personalization.backing?.paymentSource?.id == selectedPaymentSource?.rawValue } .skipRepeats() @@ -1335,7 +1312,7 @@ private func shippingRuleValid( private func paymentMethodValid( project: Project, reward: Reward, - paymentSourceId: String, + paymentSource: PaymentSourceSelected, context: PledgeViewContext ) -> Bool { guard @@ -1348,7 +1325,7 @@ private func paymentMethodValid( if project.personalization.backing?.status == .errored { return true - } else if backedPaymentSourceId != paymentSourceId { + } else if backedPaymentSourceId != paymentSource.rawValue { return true } diff --git a/Library/ViewModels/PledgeViewModelTests.swift b/Library/ViewModels/PledgeViewModelTests.swift index 787ba9f4ae..f5d068eb73 100644 --- a/Library/ViewModels/PledgeViewModelTests.swift +++ b/Library/ViewModels/PledgeViewModelTests.swift @@ -620,10 +620,7 @@ final class PledgeViewModelTests: TestCase { self.summarySectionSeparatorHidden.assertValues([true]) self.shippingLocationViewHidden.assertValues([true]) - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: backing.paymentSource?.id ?? "", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId(backing.paymentSource!.id!) self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -2204,10 +2201,7 @@ final class PledgeViewModelTests: TestCase { self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -2306,10 +2300,7 @@ final class PledgeViewModelTests: TestCase { self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -2391,10 +2382,7 @@ final class PledgeViewModelTests: TestCase { self.showErrorBannerWithMessage.assertDidNotEmitValue() self.processingViewIsHidden.assertDidNotEmitValue() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -2997,10 +2985,7 @@ final class PledgeViewModelTests: TestCase { "Amount and shipping rule unchanged" ) - var paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "12345", - isSetupIntentClientSecret: false - ) + var paymentSourceSelected = PaymentSourceSelected.paymentSourceId("12345") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -3009,10 +2994,7 @@ final class PledgeViewModelTests: TestCase { "Payment method changed" ) - paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: Backing.PaymentSource.template.id ?? "", - isSetupIntentClientSecret: false - ) + paymentSourceSelected = PaymentSourceSelected.paymentSourceId(Backing.PaymentSource.template.id ?? "") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -3976,10 +3958,7 @@ final class PledgeViewModelTests: TestCase { ) withEnvironment(apiService: mockService2) { - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -4086,10 +4065,7 @@ final class PledgeViewModelTests: TestCase { let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -4300,11 +4276,7 @@ final class PledgeViewModelTests: TestCase { let pledgeAmountData = (amount: 15.0, min: 5.0, max: 10_000.0, isValid: true) self.vm.inputs.pledgeAmountViewControllerDidUpdate(with: pledgeAmountData) - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) - + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) self.goToApplePayPaymentAuthorizationProject.assertDidNotEmitValue() @@ -4488,10 +4460,7 @@ final class PledgeViewModelTests: TestCase { self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -4612,10 +4581,7 @@ final class PledgeViewModelTests: TestCase { self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -4716,10 +4682,7 @@ final class PledgeViewModelTests: TestCase { self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -5525,10 +5488,7 @@ final class PledgeViewModelTests: TestCase { self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: true - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -5625,10 +5585,7 @@ final class PledgeViewModelTests: TestCase { self.goToThanksProject.assertDidNotEmitValue() self.showErrorBannerWithMessage.assertDidNotEmitValue() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: true - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -5957,10 +5914,7 @@ final class PledgeViewModelTests: TestCase { )) self.vm.inputs.shippingRuleSelected(.template) - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -6033,10 +5987,7 @@ final class PledgeViewModelTests: TestCase { )) self.vm.inputs.shippingRuleSelected(.template) - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "123", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("123") self.vm.inputs.creditCardSelected(with: paymentSourceSelected) @@ -6115,10 +6066,7 @@ final class PledgeViewModelTests: TestCase { self.vm.inputs.configure(with: data) self.vm.inputs.viewDidLoad() - let paymentSourceSelected = PaymentSourceSelected( - paymentSourceId: "12345", - isSetupIntentClientSecret: false - ) + let paymentSourceSelected = PaymentSourceSelected.paymentSourceId("12345") self.vm.inputs.creditCardSelected(with: paymentSourceSelected)