Skip to content

Commit

Permalink
SKError, StoreKitError, and Product.PurchaseError conform to `E…
Browse files Browse the repository at this point in the history
…rrorCodeConvertible` and added tests

Follow up to #1437.
Fixes [CF-323]
  • Loading branch information
NachoSoto committed Apr 12, 2022
1 parent 23f63c5 commit 59422da
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 10 deletions.
12 changes: 12 additions & 0 deletions RevenueCat.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@
5733B1AA27FFBCF900EC2045 /* BaseErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5733B1A927FFBCF900EC2045 /* BaseErrorTests.swift */; };
5738F46E278CAC520096D623 /* StoreTransactionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5738F46D278CAC520096D623 /* StoreTransactionTests.swift */; };
5738F489278CC2500096D623 /* MockTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = F591492726B9956C00D32E58 /* MockTransaction.swift */; };
573A10D52800A7C800F976E5 /* SKErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 573A10D42800A7C800F976E5 /* SKErrorTests.swift */; };
573A10D92800ADCD00F976E5 /* StoreKitErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 573A10D82800ADCD00F976E5 /* StoreKitErrorTests.swift */; };
573A10DB2800AF4700F976E5 /* PurchaseErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 573A10DA2800AF4700F976E5 /* PurchaseErrorTests.swift */; };
5746508C27586B2E0053AB09 /* Result+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5746508B27586B2E0053AB09 /* Result+Extensions.swift */; };
5746508E275949F20053AB09 /* DispatchTimeInterval+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5746508D275949F20053AB09 /* DispatchTimeInterval+Extensions.swift */; };
5751379527F4C4D80064AB2C /* Optional+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5751379427F4C4D80064AB2C /* Optional+Extensions.swift */; };
Expand Down Expand Up @@ -649,6 +652,9 @@
5733B1A727FFBCC800EC2045 /* BackendErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackendErrorTests.swift; sourceTree = "<group>"; };
5733B1A927FFBCF900EC2045 /* BaseErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseErrorTests.swift; sourceTree = "<group>"; };
5738F46D278CAC520096D623 /* StoreTransactionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreTransactionTests.swift; sourceTree = "<group>"; };
573A10D42800A7C800F976E5 /* SKErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SKErrorTests.swift; sourceTree = "<group>"; };
573A10D82800ADCD00F976E5 /* StoreKitErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreKitErrorTests.swift; sourceTree = "<group>"; };
573A10DA2800AF4700F976E5 /* PurchaseErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurchaseErrorTests.swift; sourceTree = "<group>"; };
5746508B27586B2E0053AB09 /* Result+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+Extensions.swift"; sourceTree = "<group>"; };
5746508D275949F20053AB09 /* DispatchTimeInterval+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DispatchTimeInterval+Extensions.swift"; sourceTree = "<group>"; };
5751379427F4C4D80064AB2C /* Optional+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extensions.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1670,6 +1676,9 @@
isa = PBXGroup;
children = (
F591492526B994B400D32E58 /* SKPaymentTransactionExtensionsTests.swift */,
573A10D42800A7C800F976E5 /* SKErrorTests.swift */,
573A10D82800ADCD00F976E5 /* StoreKitErrorTests.swift */,
573A10DA2800AF4700F976E5 /* PurchaseErrorTests.swift */,
);
path = StoreKitExtensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -2298,6 +2307,7 @@
2DDF41CC24F6F4C3005BC22D /* AppleReceiptBuilderTests.swift in Sources */,
351B51C026D450E800BD2BD7 /* PurchasesTests.swift in Sources */,
2DDF41CD24F6F4C3005BC22D /* ASN1ContainerBuilderTests.swift in Sources */,
573A10D52800A7C800F976E5 /* SKErrorTests.swift in Sources */,
351B513D26D4491E00BD2BD7 /* MockDeviceCache.swift in Sources */,
351B515C26D44B7900BD2BD7 /* MockIntroEligibilityCalculator.swift in Sources */,
35D83312262FBD4200E60AC5 /* MockETagManager.swift in Sources */,
Expand Down Expand Up @@ -2344,6 +2354,7 @@
5796A38127D6B78500653165 /* BaseBackendTest.swift in Sources */,
351B516226D44BEE00BD2BD7 /* CustomerInfoManagerTests.swift in Sources */,
351B51A326D450BC00BD2BD7 /* DictionaryExtensionsTests.swift in Sources */,
573A10D92800ADCD00F976E5 /* StoreKitErrorTests.swift in Sources */,
351B515826D44B3E00BD2BD7 /* MockOfferingsFactory.swift in Sources */,
351B51A526D450BC00BD2BD7 /* NSDate+RCExtensionsTests.swift in Sources */,
B390F5BA271DDC7400B64D65 /* PurchasesDeprecation.swift in Sources */,
Expand All @@ -2354,6 +2365,7 @@
351B517A26D44FF000BD2BD7 /* MockRequestFetcher.swift in Sources */,
351B514E26D44ACE00BD2BD7 /* SubscriberAttributesManagerTests.swift in Sources */,
2DDF41CE24F6F4C3005BC22D /* InAppPurchaseBuilderTests.swift in Sources */,
573A10DB2800AF4700F976E5 /* PurchaseErrorTests.swift in Sources */,
B300E4BF26D436F900B22262 /* LogIntent.swift in Sources */,
351B513F26D4496000BD2BD7 /* MockIdentityManager.swift in Sources */,
B319514926C19856002CA9AC /* NSData+RCExtensionsTests.swift in Sources */,
Expand Down
6 changes: 3 additions & 3 deletions Sources/Error Handling/ErrorUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ enum ErrorUtils {
) -> Error {
switch error {
case let skError as SKError:
return skError.toPurchasesError()
return skError.asPurchasesError

default:
return ErrorUtils.unknownError(
Expand All @@ -261,9 +261,9 @@ enum ErrorUtils {
) -> Error {
switch error {
case let storeKitError as StoreKitError:
return storeKitError.toPurchasesError()
return storeKitError.asPurchasesError
case let purchasesError as Product.PurchaseError:
return purchasesError.toPurchasesError()
return purchasesError.asPurchasesError
default:
return ErrorUtils.unknownError(
error: error,
Expand Down
5 changes: 2 additions & 3 deletions Sources/Error Handling/SKError+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
import Foundation
import StoreKit

extension SKError {
extension SKError: ErrorCodeConvertible {

// swiftlint:disable:next cyclomatic_complexity function_body_length
func toPurchasesError() -> Error {
var asPurchasesError: Error {
switch self.code {
case .cloudServiceNetworkConnectionFailed,
.cloudServiceRevoked,
Expand Down
8 changes: 4 additions & 4 deletions Sources/Error Handling/StoreKitError+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import StoreKit

/// - SeeAlso: SKError+Extensions
@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
extension StoreKitError {
extension StoreKitError: ErrorCodeConvertible {

func toPurchasesError() -> Error {
var asPurchasesError: Error {
switch self {
case .userCancelled:
return ErrorUtils.purchaseCancelledError(error: self)
Expand Down Expand Up @@ -50,9 +50,9 @@ extension StoreKitError {
}

@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
extension Product.PurchaseError {
extension Product.PurchaseError: ErrorCodeConvertible {

func toPurchasesError() -> Error {
var asPurchasesError: Error {
switch self {
case .invalidQuantity:
return ErrorUtils.storeProblemError(error: self)
Expand Down
68 changes: 68 additions & 0 deletions Tests/UnitTests/StoreKitExtensions/PurchaseErrorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// Copyright RevenueCat Inc. All Rights Reserved.
//
// Licensed under the MIT License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/MIT
//
// PurchaseErrorTests.swift
//
// Created by Nacho Soto on 4/8/22.

import Nimble
@testable import RevenueCat
import StoreKit
import XCTest

@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
class PurchaseErrorTests: BaseErrorTests {

override func setUpWithError() throws {
try super.setUpWithError()

try AvailabilityChecks.iOS15APIAvailableOrSkipTest()
}

func testInvalidQuantityError() {
let error: Product.PurchaseError = .invalidQuantity

verifyPurchasesError(error,
expectedCode: .storeProblemError,
underlyingError: error)
}

func testProductUnavailableError() {
let error: Product.PurchaseError = .productUnavailable

verifyPurchasesError(error,
expectedCode: .productNotAvailableForPurchaseError,
underlyingError: error)
}

func testPurchaseNotAllowedError() {
let error: Product.PurchaseError = .purchaseNotAllowed

verifyPurchasesError(error,
expectedCode: .purchaseNotAllowedError,
underlyingError: error)
}

func testIneligibleForOfferError() {
let error: Product.PurchaseError = .ineligibleForOffer

verifyPurchasesError(error,
expectedCode: .ineligibleError,
underlyingError: error)
}

func testInvalidOfferError() {
let error: Product.PurchaseError = .missingOfferParameters

verifyPurchasesError(error,
expectedCode: .invalidPromotionalOfferError,
underlyingError: error)
}

}
148 changes: 148 additions & 0 deletions Tests/UnitTests/StoreKitExtensions/SKErrorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
//
// Copyright RevenueCat Inc. All Rights Reserved.
//
// Licensed under the MIT License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/MIT
//
// SKErrorTests.swift
//
// Created by Nacho Soto on 4/8/22.

import Nimble
@testable import RevenueCat
import StoreKit
import XCTest

class SKErrorTests: BaseErrorTests {

func testStoreProblemError() {
let error: SKError = .init(.cloudServiceNetworkConnectionFailed)

verifyPurchasesError(error,
expectedCode: .storeProblemError,
underlyingError: error)
}

func testPurchaseNotAllowedError() {
let error: SKError = .init(.paymentNotAllowed)

verifyPurchasesError(error,
expectedCode: .purchaseNotAllowedError,
underlyingError: error)
}

func testPaymentCancelled() {
let error: SKError = .init(.paymentCancelled)

verifyPurchasesError(error,
expectedCode: .purchaseCancelledError,
underlyingError: error)
}

func testPaymentInvalid() {
let error: SKError = .init(.paymentInvalid)

verifyPurchasesError(error,
expectedCode: .purchaseInvalidError,
underlyingError: error)
}

func testProductNotAvailableError() {
let error: SKError = .init(.storeProductNotAvailable)

verifyPurchasesError(error,
expectedCode: .productNotAvailableForPurchaseError,
underlyingError: error)
}

@available(iOS 14.0, macOS 11.0, watchOS 6.2, *)
@available(tvOS, unavailable)
func testUnsupportedPlatformError() throws {
try AvailabilityChecks.iOS14APIAvailableOrSkipTest()

let error: SKError = .init(.unsupportedPlatform)

verifyPurchasesError(error,
expectedCode: .purchaseNotAllowedError,
underlyingError: error)
}

@available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 6.2, *)
func testIneligibleForOfferError() throws {
try AvailabilityChecks.iOS14APIAvailableOrSkipTest()

let error: SKError = .init(.ineligibleForOffer)

verifyPurchasesError(error,
expectedCode: .ineligibleError,
underlyingError: error)
}

@available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 6.2, *)
func testInvalidOfferError() throws {
try AvailabilityChecks.iOS14APIAvailableOrSkipTest()

let error: SKError = .init(.invalidOfferIdentifier)

verifyPurchasesError(error,
expectedCode: .invalidPromotionalOfferError,
underlyingError: error)
}

func testCurrentlySubscribedError() throws {
let error = try XCTUnwrap(
NSError(
domain: SKErrorDomain,
code: SKError.unknown.rawValue,
userInfo: [
NSUnderlyingErrorKey: NSError(
domain: "ASDServerErrorDomain",
code: 3532,
userInfo: [:]
)
]
) as? SKError
)

verifyPurchasesError(error,
expectedCode: .productAlreadyPurchasedError,
underlyingError: error)
}

func testPaymentSheetCancelledError() throws {
let error = try XCTUnwrap(
NSError(
domain: SKErrorDomain,
code: 907,
userInfo: [
NSUnderlyingErrorKey: NSError(
domain: "AMSErrorDomain",
code: 6,
userInfo: [:]
)
]
) as? SKError
)

verifyPurchasesError(error,
expectedCode: .purchaseCancelledError,
underlyingError: error)
}

func testUnknownError() throws {
let error = try XCTUnwrap(
NSError(
domain: SKErrorDomain,
code: 100000
) as? SKError
)

verifyPurchasesError(error,
expectedCode: .unknownError,
underlyingError: error)
}

}
Loading

0 comments on commit 59422da

Please sign in to comment.