Skip to content

Commit

Permalink
[NT-209, NT-156] Pledge Button Interaction (Create Backing) (#855)
Browse files Browse the repository at this point in the history
* Create Backing

* Create Backing Tests

* Formatting

* Fix formatting issues

* Use paymentType instead of string
  • Loading branch information
Isabel Barrera authored Sep 27, 2019
1 parent 08995ab commit 57ddae9
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ protocol PledgePaymentMethodsViewControllerDelegate: AnyObject {
_ viewController: PledgePaymentMethodsViewController,
didSelectCreditCard paymentSourceId: String
)

func pledgePaymentMethodsViewControllerDidTapPledgeButton(
_ viewController: PledgePaymentMethodsViewController
)
}

final class PledgePaymentMethodsViewController: UIViewController {
Expand Down Expand Up @@ -64,6 +68,12 @@ final class PledgePaymentMethodsViewController: UIViewController {
action: #selector(PledgePaymentMethodsViewController.applePayButtonTapped),
for: .touchUpInside
)

self.pledgeButton.addTarget(
self,
action: #selector(PledgePaymentMethodsViewController.pledgeButtonTapped),
for: .touchUpInside
)
}

private func setupConstraints() {
Expand Down Expand Up @@ -137,6 +147,14 @@ final class PledgePaymentMethodsViewController: UIViewController {
self.delegate?.pledgePaymentMethodsViewController(self, didSelectCreditCard: paymentSourceId)
}

self.viewModel.outputs.notifyDelegatePledgeButtonTapped
.observeForUI()
.observeValues { [weak self] in
guard let self = self else { return }

self.delegate?.pledgePaymentMethodsViewControllerDidTapPledgeButton(self)
}

self.viewModel.outputs.updateSelectedCreditCard
.observeForUI()
.observeValues { [weak self] card in
Expand Down Expand Up @@ -165,6 +183,10 @@ final class PledgePaymentMethodsViewController: UIViewController {
self.viewModel.inputs.applePayButtonTapped()
}

@objc private func pledgeButtonTapped() {
self.viewModel.inputs.pledgeButtonTapped()
}

func updatePledgeButton(_ enabled: Bool) {
self.viewModel.inputs.updatePledgeButtonEnabled(isEnabled: enabled)
}
Expand Down
4 changes: 4 additions & 0 deletions Kickstarter-iOS/Views/Controllers/PledgeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ extension PledgeViewController: PledgePaymentMethodsViewControllerDelegate {
) {
self.viewModel.inputs.creditCardSelected(with: paymentSourceId)
}

func pledgePaymentMethodsViewControllerDidTapPledgeButton(_: PledgePaymentMethodsViewController) {
self.viewModel.inputs.pledgeButtonTapped()
}
}

// MARK: - Styles
Expand Down
10 changes: 9 additions & 1 deletion Kickstarter.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@
77A3C53D219CCF1300824FC1 /* SettingsAccountDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A3C53C219CCF1300824FC1 /* SettingsAccountDataSourceTests.swift */; };
77A7B64321026CAE008D12C1 /* SettingsNotificationCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77A7B64221026CAE008D12C1 /* SettingsNotificationCell.xib */; };
77A7B67B21026F4F008D12C1 /* SettingsNotificationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A7B67A21026F4E008D12C1 /* SettingsNotificationCell.swift */; };
77AA2B3B233C0A1B008BBCB8 /* CreateBackingInput+Constructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77AA2B39233C09F5008BBCB8 /* CreateBackingInput+Constructor.swift */; };
77AA2B3D233D10D3008BBCB8 /* CreateBackingConstructorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77AA2B3C233D10D3008BBCB8 /* CreateBackingConstructorTests.swift */; };
77BC00F02326F0CC00808E75 /* PKPaymentRequestHelpersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77BC00EF2326F0CC00808E75 /* PKPaymentRequestHelpersTests.swift */; };
77BC00F2232BE49E00808E75 /* CreateApplePayBackingInput+Constructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77BC00F1232BE49E00808E75 /* CreateApplePayBackingInput+Constructor.swift */; };
77BC00F4232BE52C00808E75 /* CreateApplePayBackingInputConstructorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77BC00F3232BE52C00808E75 /* CreateApplePayBackingInputConstructorTests.swift */; };
Expand Down Expand Up @@ -1601,6 +1603,8 @@
77A3C53C219CCF1300824FC1 /* SettingsAccountDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAccountDataSourceTests.swift; sourceTree = "<group>"; };
77A7B64221026CAE008D12C1 /* SettingsNotificationCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsNotificationCell.xib; sourceTree = "<group>"; };
77A7B67A21026F4E008D12C1 /* SettingsNotificationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsNotificationCell.swift; sourceTree = "<group>"; };
77AA2B39233C09F5008BBCB8 /* CreateBackingInput+Constructor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CreateBackingInput+Constructor.swift"; sourceTree = "<group>"; };
77AA2B3C233D10D3008BBCB8 /* CreateBackingConstructorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateBackingConstructorTests.swift; sourceTree = "<group>"; };
77BC00EF2326F0CC00808E75 /* PKPaymentRequestHelpersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PKPaymentRequestHelpersTests.swift; sourceTree = "<group>"; };
77BC00F1232BE49E00808E75 /* CreateApplePayBackingInput+Constructor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CreateApplePayBackingInput+Constructor.swift"; sourceTree = "<group>"; };
77BC00F3232BE52C00808E75 /* CreateApplePayBackingInputConstructorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateApplePayBackingInputConstructorTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3060,6 +3064,7 @@
A7C725771C85D36D005A016B /* Library */ = {
isa = PBXGroup;
children = (
8A142EBC23354BFD00FB43AB /* AddNewCardIntent.swift */,
A709697D1D143D1300DB39D3 /* AlertError.swift */,
A7C725781C85D36D005A016B /* AppEnvironment.swift */,
A7ED1F121E830FDC00BFFA01 /* AppEnvironmentTests.swift */,
Expand All @@ -3073,6 +3078,8 @@
A7D121081D15B08200F364FD /* CountBadgeView.swift */,
77BC00F1232BE49E00808E75 /* CreateApplePayBackingInput+Constructor.swift */,
77BC00F3232BE52C00808E75 /* CreateApplePayBackingInputConstructorTests.swift */,
77AA2B39233C09F5008BBCB8 /* CreateBackingInput+Constructor.swift */,
77AA2B3C233D10D3008BBCB8 /* CreateBackingConstructorTests.swift */,
D6534D3922E7878D00E9D279 /* CreditCard+Utils.swift */,
D612A21822F0ED5A007F7FD9 /* CreditCard+UtilsTests.swift */,
D798A6AD21656D970053D097 /* Currency.swift */,
Expand Down Expand Up @@ -3217,7 +3224,6 @@
A73378F91D0AE33B00C91445 /* Styles */,
A7ED1F421E831BA200BFFA01 /* TestHelpers */,
A7F4418D1D005A9400FE6FC5 /* ViewModels */,
8A142EBC23354BFD00FB43AB /* AddNewCardIntent.swift */,
);
path = Library;
sourceTree = "<group>";
Expand Down Expand Up @@ -4757,6 +4763,7 @@
77C93C1A22C13DED005D3195 /* PledgeContinueViewModel.swift in Sources */,
A76126BB1C90C94000EDCCB9 /* UITableView-Extensions.swift in Sources */,
9D9F58191D13243900CE81DE /* ProjectActivitiesViewModel.swift in Sources */,
77AA2B3B233C0A1B008BBCB8 /* CreateBackingInput+Constructor.swift in Sources */,
A72C3A8E1D00F6A80075227E /* SelectableRow.swift in Sources */,
3706408222A8A66E00889CBD /* PledgeAmountViewModel.swift in Sources */,
A7F441C11D005A9400FE6FC5 /* DiscoveryViewModel.swift in Sources */,
Expand Down Expand Up @@ -4809,6 +4816,7 @@
A7ED1FD71E831C5C00BFFA01 /* SearchEmptyStateCellViewModelTests.swift in Sources */,
A7ED1F491E831BA200BFFA01 /* DispatchTimeInterval-Extensions.swift in Sources */,
A7ED1FBB1E831C5C00BFFA01 /* CommentsViewModelTests.swift in Sources */,
77AA2B3D233D10D3008BBCB8 /* CreateBackingConstructorTests.swift in Sources */,
A7ED1FD91E831C5C00BFFA01 /* ProjectActivitiesViewModelTests.swift in Sources */,
A7ED1FDB1E831C5C00BFFA01 /* DashboardViewModelTests.swift in Sources */,
3706408822A8A6F200889CBD /* PledgeShippingLocationViewModelTests.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions KsApi/models/PaymentType.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation

// This type should be removed once the createBacking mutation is updated to automatically set this type
public enum PaymentType: String, Encodable {
case creditCard = "CREDIT_CARD"
}
15 changes: 10 additions & 5 deletions KsApi/mutations/inputs/CreateBackingInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,32 @@ public struct CreateBackingInput: GraphMutationInput {
let amount: String
let locationId: String?
let paymentSourceId: String
let paymentType: String
let projectId: String
let rewardId: String?
let refParam: String?

public init(
amount: String,
locationId: String?,
paymentSourceId: String,
paymentType: String,
projectId: String,
rewardId: String?
rewardId: String?,
refParam: String?
) {
self.amount = amount
self.locationId = locationId
self.paymentSourceId = paymentSourceId
self.paymentType = paymentType
self.projectId = projectId
self.rewardId = rewardId
self.refParam = refParam
}

public func toInputDictionary() -> [String: Any] {
var inputDictionary = [
"amount": amount,
"paymentSourceId": paymentSourceId,
"paymentType": paymentType,
// swiftlint:disable:next line_length
"paymentType": PaymentType.creditCard.rawValue, // this is temporary and will be removed once the mutation has been updated
"projectId": projectId
]

Expand All @@ -40,6 +41,10 @@ public struct CreateBackingInput: GraphMutationInput {
inputDictionary["rewardId"] = rewardId
}

if let refParam = self.refParam {
inputDictionary["refParam"] = refParam
}

return inputDictionary
}
}
14 changes: 8 additions & 6 deletions KsApi/mutations/inputs/CreateBackingInputTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,40 @@ final class CreateBackingInputTests: XCTestCase {
amount: "200.00",
locationId: "NY",
paymentSourceId: "paymentSourceId",
paymentType: "card",
projectId: "projectId",
rewardId: "rewardId"
rewardId: "rewardId",
refParam: "activity"
)

let input = createBackingInput.toInputDictionary()

XCTAssertEqual(input["amount"] as? String, "200.00")
XCTAssertEqual(input["locationId"] as? String, "NY")
XCTAssertEqual(input["paymentSourceId"] as? String, "paymentSourceId")
XCTAssertEqual(input["paymentType"] as? String, "card")
XCTAssertEqual(input["paymentType"] as? String, "CREDIT_CARD")
XCTAssertEqual(input["projectId"] as? String, "projectId")
XCTAssertEqual(input["rewardId"] as? String, "rewardId")
XCTAssertEqual(input["refParam"] as? String, "activity")
}

func testCreateBackingInputDictionary_TestNilLocationAndReward() {
let createBackingInput = CreateBackingInput(
amount: "200.00",
locationId: nil,
paymentSourceId: "paymentSourceId",
paymentType: "card",
projectId: "projectId",
rewardId: nil
rewardId: nil,
refParam: nil
)

let input = createBackingInput.toInputDictionary()

XCTAssertEqual(input["amount"] as? String, "200.00")
XCTAssertNil(input["locationId"])
XCTAssertEqual(input["paymentSourceId"] as? String, "paymentSourceId")
XCTAssertEqual(input["paymentType"] as? String, "card")
XCTAssertEqual(input["paymentType"] as? String, "CREDIT_CARD")
XCTAssertEqual(input["projectId"] as? String, "projectId")
XCTAssertNil(input["rewardId"])
XCTAssertNil(input["refParam"])
}
}
52 changes: 52 additions & 0 deletions Library/CreateBackingConstructorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Foundation
@testable import KsApi
@testable import Library
import Prelude
import XCTest

final class CreateBackingInputConstructorTests: XCTestCase {
func testCreateBackingInput_NoShipping() {
let project = Project.template
let reward = Reward.noReward

let input = CreateBackingInput.input(
from: project,
reward: reward,
pledgeAmount: 10,
selectedShippingRule: nil,
refTag: RefTag.projectPage,
paymentSourceId: "123"
)

XCTAssertEqual(input.amount, "10.00")
XCTAssertNil(input.locationId)
XCTAssertEqual(input.projectId, project.graphID)
XCTAssertNil(input.rewardId)
XCTAssertEqual(input.refParam, "project_page")
XCTAssertEqual(input.paymentSourceId, "123")
}

func testCreateBackingInput_WithShipping_RefTagNil() {
let project = Project.template
let reward = Reward.template
let shippingRule = ShippingRule.template
|> ShippingRule.lens.location .. Location.lens.id .~ 1
|> ShippingRule.lens.cost .~ 5

let input = CreateBackingInput.input(
from: project,
reward: reward,
pledgeAmount: 10,
selectedShippingRule: shippingRule,
refTag: nil,
paymentSourceId: "123"
)

XCTAssertEqual(input.amount, "15.00")
XCTAssertEqual(input.locationId, "1")
XCTAssertEqual(input.projectId, project.graphID)
XCTAssertEqual(input.rewardId, reward.graphID)
XCTAssertEqual(input.paymentSourceId, "123")
XCTAssertNil(input.refParam)
}
}
36 changes: 36 additions & 0 deletions Library/CreateBackingInput+Constructor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Foundation
import KsApi

extension CreateBackingInput {
internal static func input(
from project: Project,
reward: Reward,
pledgeAmount: Double,
selectedShippingRule: ShippingRule?,
refTag: RefTag?,
paymentSourceId: String
) -> CreateBackingInput {
let pledgeAmountDecimal = Decimal(pledgeAmount)
var shippingAmountDecimal: Decimal = Decimal()
var shippingLocationId: String?

if let shippingRule = selectedShippingRule, shippingRule.cost > 0 {
shippingAmountDecimal = Decimal(shippingRule.cost)
shippingLocationId = String(shippingRule.location.id)
}

let pledgeTotal = NSDecimalNumber(decimal: pledgeAmountDecimal + shippingAmountDecimal)
let formattedPledgeTotal = Format.decimalCurrency(for: pledgeTotal.doubleValue)

let rewardId = reward == Reward.noReward ? nil : reward.graphID

return CreateBackingInput(
amount: formattedPledgeTotal,
locationId: shippingLocationId,
paymentSourceId: paymentSourceId,
projectId: project.graphID,
rewardId: rewardId,
refParam: refTag?.description
)
}
}
9 changes: 9 additions & 0 deletions Library/ViewModels/PledgePaymentMethodsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public protocol PledgePaymentMethodsViewModelInputs {
func applePayButtonTapped()
func configureWith(_ value: PledgePaymentMethodsValue)
func creditCardSelected(paymentSourceId: String)
func pledgeButtonTapped()
func updatePledgeButtonEnabled(isEnabled: Bool)
func addNewCardViewControllerDidAdd(newCard card: GraphUserCreditCard.CreditCard)
func viewDidLoad()
Expand All @@ -20,6 +21,7 @@ public protocol PledgePaymentMethodsViewModelOutputs {
var notifyDelegateApplePayButtonTapped: Signal<Void, Never> { get }
var notifyDelegateCreditCardSelected: Signal<String, Never> { get }
var notifyDelegateLoadPaymentMethodsError: Signal<String, Never> { get }
var notifyDelegatePledgeButtonTapped: Signal<Void, Never> { get }
var pledgeButtonEnabled: Signal<Bool, Never> { get }
var reloadPaymentMethods: Signal<[GraphUserCreditCard.CreditCard], Never> { get }
var updateSelectedCreditCard: Signal<GraphUserCreditCard.CreditCard, Never> { get }
Expand Down Expand Up @@ -68,6 +70,7 @@ public final class PledgePaymentMethodsViewModel: PledgePaymentMethodsViewModelT
.scan([]) { current, new in new + current }

self.notifyDelegateApplePayButtonTapped = self.applePayButtonTappedProperty.signal
self.notifyDelegatePledgeButtonTapped = self.pledgeButtonTappedSignal

self.notifyDelegateLoadPaymentMethodsError = storedCardsEvent
.errors()
Expand Down Expand Up @@ -97,6 +100,11 @@ public final class PledgePaymentMethodsViewModel: PledgePaymentMethodsViewModelT
self.creditCardSelectedObserver.send(value: paymentSourceId)
}

private let (pledgeButtonTappedSignal, pledgeButtonTappedObserver) = Signal<Void, Never>.pipe()
public func pledgeButtonTapped() {
self.pledgeButtonTappedObserver.send(value: ())
}

private let (pledgeButtonEnabledSignal, pledgeButtonEnabledObserver) = Signal<Bool, Never>.pipe()
public func updatePledgeButtonEnabled(isEnabled: Bool) {
self.pledgeButtonEnabledObserver.send(value: isEnabled)
Expand All @@ -119,6 +127,7 @@ public final class PledgePaymentMethodsViewModel: PledgePaymentMethodsViewModelT
public let applePayButtonHidden: Signal<Bool, Never>
public let notifyDelegateCreditCardSelected: Signal<String, Never>
public let notifyDelegateLoadPaymentMethodsError: Signal<String, Never>
public let notifyDelegatePledgeButtonTapped: Signal<Void, Never>
public let pledgeButtonEnabled: Signal<Bool, Never>
public let reloadPaymentMethods: Signal<[GraphUserCreditCard.CreditCard], Never>
public let updateSelectedCreditCard: Signal<GraphUserCreditCard.CreditCard, Never>
Expand Down
17 changes: 17 additions & 0 deletions Library/ViewModels/PledgePaymentMethodsViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ final class PledgePaymentMethodsViewModelTests: TestCase {
private let notifyDelegateApplePayButtonTapped = TestObserver<Void, Never>()
private let notifyDelegateCreditCardSelected = TestObserver<String, Never>()
private let notifyDelegateLoadPaymentMethodsError = TestObserver<String, Never>()
private let notifyDelegatePledgeButtonTapped = TestObserver<Void, Never>()
private let pledgeButtonEnabled = TestObserver<Bool, Never>()
private let reloadPaymentMethods = TestObserver<[GraphUserCreditCard.CreditCard], Never>()
private let updateSelectedCreditCard = TestObserver<GraphUserCreditCard.CreditCard, Never>()
Expand All @@ -25,6 +26,7 @@ final class PledgePaymentMethodsViewModelTests: TestCase {
.observe(self.notifyDelegateCreditCardSelected.observer)
self.vm.outputs.notifyDelegateLoadPaymentMethodsError
.observe(self.notifyDelegateLoadPaymentMethodsError.observer)
self.vm.outputs.notifyDelegatePledgeButtonTapped.observe(self.notifyDelegatePledgeButtonTapped.observer)
self.vm.outputs.pledgeButtonEnabled.observe(self.pledgeButtonEnabled.observer)
self.vm.outputs.reloadPaymentMethods.observe(self.reloadPaymentMethods.observer)
self.vm.outputs.updateSelectedCreditCard.observe(self.updateSelectedCreditCard.observer)
Expand Down Expand Up @@ -255,4 +257,19 @@ final class PledgePaymentMethodsViewModelTests: TestCase {

self.pledgeButtonEnabled.assertValues([false, true, false])
}

func testPledgeButtonTapped() {
self.vm.inputs.configureWith((User.template, Project.template, true))
self.vm.inputs.viewDidLoad()

self.notifyDelegatePledgeButtonTapped.assertDidNotEmitValue()

self.vm.inputs.pledgeButtonTapped()

self.notifyDelegatePledgeButtonTapped.assertValueCount(1)

self.vm.inputs.pledgeButtonTapped()

self.notifyDelegatePledgeButtonTapped.assertValueCount(2)
}
}
Loading

0 comments on commit 57ddae9

Please sign in to comment.