Created
May 4, 2016 15:14
-
-
Save frosty/cce75783ce3756bc4729950e7a004757 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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