Skip to content

Instantly share code, notes, and snippets.

@frosty
Created May 4, 2016 15:14
Show Gist options
  • Select an option

  • Save frosty/cce75783ce3756bc4729950e7a004757 to your computer and use it in GitHub Desktop.

Select an option

Save frosty/cce75783ce3756bc4729950e7a004757 to your computer and use it in GitHub Desktop.
diff --git a/WordPress/Classes/Services/Store.swift b/WordPress/Classes/Services/Store.swift
index daa668b..e8112f6 100644
--- a/WordPress/Classes/Services/Store.swift
+++ b/WordPress/Classes/Services/Store.swift
@@ -30,6 +30,10 @@ struct StoreKitCoordinator {
typealias PendingPayment = (planID: PlanID, productID: String, siteID: Int)
+enum StoreCoordinatorError: ErrorType {
+ case PaymentAlreadyInProgress
+}
+
/// StoreCoordinator coordinates purchasing of products, processing of transactions, and
/// verification of purchases between the App Store (StoreKit) and WordPress.com.
///
@@ -45,7 +49,7 @@ typealias PendingPayment = (planID: PlanID, productID: String, siteID: Int)
class StoreCoordinator<S: Store> {
private let store: S
- var pendingPayment: PendingPayment? {
+ private var pendingPayment: PendingPayment? {
set {
let defaults = NSUserDefaults.standardUserDefaults()
@@ -74,16 +78,16 @@ class StoreCoordinator<S: Store> {
init(store: S) {
self.store = store
+ self.pendingPayment = nil
}
/// Initiates a purchase for the specified plan if a purchase isn't already in progress.
- func purchasePlan(plan: Plan, product: S.ProductType, forSite siteID: Int) {
+ func purchasePlan(plan: Plan, product: S.ProductType, forSite siteID: Int) throws {
precondition(plan.productIdentifier == product.productIdentifier)
// We _should_ never have a pending payment at this point, so we'll fail in that case.
guard pendingPayment == nil else {
- postTransactionFailedNotification([StoreKitCoordinator.NotificationProductIdentifierKey: product.productIdentifier])
- return
+ throw StoreCoordinatorError.PaymentAlreadyInProgress
}
pendingPayment = (plan.id, product.productIdentifier, siteID)
diff --git a/WordPress/Classes/ViewRelated/Plans/PlanDetailViewController.swift b/WordPress/Classes/ViewRelated/Plans/PlanDetailViewController.swift
index a32306a..04577da 100644
--- a/WordPress/Classes/ViewRelated/Plans/PlanDetailViewController.swift
+++ b/WordPress/Classes/ViewRelated/Plans/PlanDetailViewController.swift
@@ -269,7 +269,11 @@ class PlanDetailViewController: UIViewController {
store.getProductsWithIdentifiers(
Set([identifier]),
success: { [viewModel] products in
- StoreKitCoordinator.instance.purchasePlan(viewModel.plan, product: products[0], forSite: viewModel.siteID)
+ do {
+ try StoreKitCoordinator.instance.purchasePlan(viewModel.plan, product: products[0], forSite: viewModel.siteID)
+ } catch StoreError.PaymentAlreadyInProgress {
+ self.purchaseButton?.selected = false
+ } catch {}
},
failure: { error in
DDLogSwift.logError("Error fetching Store products: \(error)")
diff --git a/WordPress/WordPressTest/StoreCoordinatorTests.swift b/WordPress/WordPressTest/StoreCoordinatorTests.swift
index 516d246..f16309a 100644
--- a/WordPress/WordPressTest/StoreCoordinatorTests.swift
+++ b/WordPress/WordPressTest/StoreCoordinatorTests.swift
@@ -56,33 +56,24 @@ class StoreCoordinatorTests: XCTestCase {
XCTAssertEqual(availability, PurchaseAvailability.available)
}
- func testPendingPaymentStoredWhenAllValuesPresent() {
- let payment: PendingPayment = (5, testProduct, 1000)
+ func testCannotPurchaseWhenPurchaseAlreadyPending() {
+ let payment: PendingPayment = (premium.id, testProduct, testSite)
let coordinator = storeCoordinator(paymentsEnabled: true, pending: payment)
-
- XCTAssertEqual(coordinator.pendingPayment?.planID, payment.planID)
- XCTAssertEqual(coordinator.pendingPayment?.productID, payment.productID)
- XCTAssertEqual(coordinator.pendingPayment?.siteID, payment.siteID)
- }
-
- func testPendingPaymentHandlesNil() {
- let payment: PendingPayment? = nil
- let coordinator = storeCoordinator(paymentsEnabled: true, pending: payment)
-
- XCTAssertNil(coordinator.pendingPayment)
+ let product = productForPlan(TestPlans.business.plan)
+
+ // And now attempt a second purchase
+ XCTAssertThrowsError(try coordinator.purchasePlan(business, product: product, forSite: testSite))
}
- func testExistingPendingPaymentIsClearedWhenSetToNil() {
- let payment: PendingPayment = (5, testProduct, 1000)
- let coordinator = storeCoordinator(paymentsEnabled: true, pending: payment)
-
- XCTAssertEqual(coordinator.pendingPayment?.planID, payment.planID)
- XCTAssertEqual(coordinator.pendingPayment?.productID, payment.productID)
- XCTAssertEqual(coordinator.pendingPayment?.siteID, payment.siteID)
-
- coordinator.pendingPayment = nil
-
- XCTAssertNil(coordinator.pendingPayment)
+ func testCanMakePaymentWhenNoPaymentIsPending() {
+ let coordinator = storeCoordinator(paymentsEnabled: true, pending: nil)
+ let product = productForPlan(TestPlans.business.plan)
+
+ do {
+ try coordinator.purchasePlan(business, product: product, forSite: otherSite)
+ } catch {
+ XCTFail("Expected call not to throw")
+ }
}
// ========================= END OF TESTS =============================== //
@@ -99,10 +90,25 @@ class StoreCoordinatorTests: XCTestCase {
private func storeCoordinator(paymentsEnabled paymentsEnabled: Bool, pending: PendingPayment?) -> StoreCoordinator<MockStore> {
var store = MockStore.succeeding()
store.canMakePayments = paymentsEnabled
+
let coordinator = StoreCoordinator(store: store)
- coordinator.pendingPayment = pending
+
+ if let pending = pending,
+ let plan = TestPlans.allPlans.filter({ $0.id == pending.planID }).first {
+ let product = productForPlan(plan)
+ try! coordinator.purchasePlan(plan, product: product, forSite: pending.siteID)
+ }
+
return coordinator
}
+
+ private func productForPlan(plan: Plan) -> MockProduct {
+ return MockProduct(localizedDescription: plan.tagline,
+ localizedTitle: plan.title,
+ price: 299.99,
+ priceLocale: NSLocale.currentLocale(),
+ productIdentifier: plan.productIdentifier!)
+ }
private func pending(plan plan: Plan, productID: String, siteID: Int, state: PendingState) -> PendingPayment? {
switch state {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment