From 84867aa9643fa5a61b3b3605b8b3097f18610c3f Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 20 Jan 2023 18:03:19 +0400 Subject: [PATCH 01/44] Update `README.md` --- README.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a05c5cf6b..9108fe9cb 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,66 @@

Liscence Platform -Swift4.2 +Swift5.5 + CI +

## Description -Flare is a framework written in Swift that makes it easy for you to work with in-app purchases and subscriptions. \ No newline at end of file +Flare is a framework written in Swift that makes it easy for you to work with in-app purchases and subscriptions. + +- [Features](#features) +- [Documentaton](#documentation) +- [Requirements](#requirements) +- [Installation](#installation) +- [Communication](#communication) +- [Contributing](#contributing) +- [Author](#author) +- [License](#license) + +## Features +- [x] Support Consumable & Non-Consumable Purchases +- [x] Support Subscription Purchase +- [x] Refresh Receipt +- [x] Complete Unit Test Coverage + +## Documentation +Check out [flare documentation](https://github.com/space-code/flare/blob/main/Documentation/Usage.md). + +## Requirements +- iOS 13.0+ / macOS 10.15+ / tvOS 11.0+ / watchOS 7.0+ +- Xcode 14.0 +- Swift 5.5 + +## Installation +### Swift Package Manager + +The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but `flare` does support its use on supported platforms. + +Once you have your Swift package set up, adding `flare` as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`. + +```swift +dependencies: [ + .package(url: "https://github.com/space-code/flare.git", .upToNextMajor(from: "1.0.0")) +] +``` + +## Communication +- If you **found a bug**, open an issue. +- If you **have a feature request**, open an issue. +- If you **want to contribute**, submit a pull request. + +## Contributing +Bootstrapping development environment + +``` +make bootstrap +``` + +Please feel free to help out with this project! If you see something that could be made better or want a new feature, open up an issue or send a Pull Request! + +## Author +Nikita Vasilev, nv3212@gmail.com + +## License +flare is available under the MIT license. See the LICENSE file for more info. \ No newline at end of file From 937bcd4f6825d507a694eded2c3597e121d5600a Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 20 Jan 2023 18:03:40 +0400 Subject: [PATCH 02/44] Add `CHANGELOG.md` --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..c64915145 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Change Log +All notable changes to this project will be documented in this file. + +#### 1.x Releases +- `1.0.x` Releases - [1.0.0](#100) + +## [1.0.0](https://github.com/space-code/flare/releases/tag/1.0.0) +Released on 2023-01-20. + +#### Added +- Initial release of Flare. + - Added by [Nikita Vasilev](https://github.com/nik3212). \ No newline at end of file From f13742bd9eef0d960d8a8afd8aa332838760ab13 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 20 Jan 2023 18:14:19 +0400 Subject: [PATCH 03/44] Update `Makefile` --- Makefile | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1bd068d6c..856d64b45 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,19 @@ +all: bootstrap + +bootstrap: hook + mint bootstrap + hook: ln -sf ../../hooks/pre-commit .git/hooks/pre-commit chmod +x .git/hooks/pre-commit -.PHONY: hook \ No newline at end of file +mint: + mint bootstrap + +lint: + mint run swiftlint + +fmt: + mint run swiftformat Sources Tests + +.PHONY: all bootstrap hook mint lint fmt \ No newline at end of file From c427834396105904e6bf81ea24f95d424fd43067 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sat, 9 Sep 2023 09:38:07 +0400 Subject: [PATCH 04/44] Implement `async` requests --- .../xcshareddata/xcschemes/Flare.xcscheme | 92 +++++++++ .../PaymentTransaction.swift | 2 +- Sources/Flare/Classes/Models/IAPError.swift | 27 +++ .../Providers/IAPProvider/IAPProvider.swift | 39 ++++ .../Providers/IAPProvider/IIAPProvider.swift | 22 +- .../IReceiptRefreshProvider.swift | 5 + .../ReceiptRefreshProvider.swift | 13 ++ Sources/Flare/Flare.swift | 13 ++ Sources/Flare/IFlare.swift | 19 ++ Tests/FlareTests/Classes/FlareTests.swift | 192 ++++++++++++++++-- .../Classes/Mocks/IAPProviderMock.swift | 53 +++++ .../Mocks/ReceiptRefreshProviderMock.swift | 12 ++ 12 files changed, 472 insertions(+), 17 deletions(-) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme new file mode 100644 index 000000000..d81d19a4c --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/Flare/Classes/Helpers/PaymentTransaction/PaymentTransaction.swift b/Sources/Flare/Classes/Helpers/PaymentTransaction/PaymentTransaction.swift index 72735c854..ff71880d3 100644 --- a/Sources/Flare/Classes/Helpers/PaymentTransaction/PaymentTransaction.swift +++ b/Sources/Flare/Classes/Helpers/PaymentTransaction/PaymentTransaction.swift @@ -5,7 +5,7 @@ import StoreKit -public struct PaymentTransaction { +public struct PaymentTransaction: Equatable { // MARK: Lifecycle init(_ skTransaction: SKPaymentTransaction) { diff --git a/Sources/Flare/Classes/Models/IAPError.swift b/Sources/Flare/Classes/Models/IAPError.swift index e69668023..e15615ab8 100644 --- a/Sources/Flare/Classes/Models/IAPError.swift +++ b/Sources/Flare/Classes/Models/IAPError.swift @@ -49,3 +49,30 @@ extension IAPError { } } } + +extension IAPError: Equatable { + public static func == (lhs: IAPError, rhs: IAPError) -> Bool { + switch (lhs, rhs) { + case (.emptyProducts, .emptyProducts): + return true + case let (.invalid(lhs), .invalid(rhs)): + return lhs == rhs + case (.paymentNotAllowed, .paymentNotAllowed): + return true + case (.paymentCancelled, .paymentCancelled): + return true + case (.storeProductNotAvailable, .storeProductNotAvailable): + return true + case (.storeTrouble, .storeTrouble): + return true + case let (.with(lhs), .with(rhs)): + return (lhs as NSError) == (rhs as NSError) + case (.receiptNotFound, .receiptNotFound): + return true + case (.unknown, .unknown): + return true + default: + return false + } + } +} diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index 8782266c2..e8398cc0b 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -41,6 +41,19 @@ final class IAPProvider: IIAPProvider { ) } + func fetch(productsIDs: Set) async throws -> [SKProduct] { + try await withCheckedThrowingContinuation { continuation in + self.fetch(productsIds: productsIDs) { result in + switch result { + case let .success(products): + continuation.resume(returning: products) + case let .failure(error): + continuation.resume(throwing: error) + } + } + } + } + func purchase(productId: String, completion: @escaping Closure>) { productProvider.fetch(productIds: [productId], requestId: UUID().uuidString) { result in switch result { @@ -66,6 +79,19 @@ final class IAPProvider: IIAPProvider { } } + func purchase(productId: String) async throws -> PaymentTransaction { + try await withCheckedThrowingContinuation { continuation in + purchase(productId: productId) { result in + switch result { + case let .success(transaction): + continuation.resume(returning: transaction) + case let .failure(error): + continuation.resume(throwing: error) + } + } + } + } + func refreshReceipt(completion: @escaping Closure>) { receiptRefreshProvider.refresh(requestId: UUID().uuidString) { [weak self] result in guard let self = self else { @@ -85,6 +111,19 @@ final class IAPProvider: IIAPProvider { } } + func refreshReceipt() async throws -> String { + try await withCheckedThrowingContinuation { continuation in + refreshReceipt { result in + switch result { + case let .success(receipt): + continuation.resume(returning: receipt) + case let .failure(error): + continuation.resume(throwing: error) + } + } + } + } + func finish(transaction: PaymentTransaction) { paymentProvider.finish(transaction: transaction) } diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift index db5c627fe..3d96b0c58 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift @@ -15,19 +15,37 @@ public protocol IIAPProvider { /// - productsIds: The list of product identifiers for the products you wish to retrieve descriptions of. /// - completion: A products handler. func fetch(productsIds: Set, completion: @escaping Closure>) - + + /// Retrieve localized information from the App Store about a specified list of products. + /// + /// - Parameter productsIDs: The list of product identifiers for the products you wish to retrieve descriptions of. + /// + /// - Returns: Products. + func fetch(productsIDs: Set) async throws -> [SKProduct] + /// Perform purchase a product with given id. /// /// - Parameters: /// - productId: A product identifier. /// - completion: A block object to be executed when the purchase operation ends. func purchase(productId: String, completion: @escaping Closure>) + + /// <#Description#> + /// + /// - Parameter productId: <#productId description#> + /// + /// - Returns: <#description#> + func purchase(productId: String) async throws -> PaymentTransaction /// A request to refresh the receipt, which represents the user’s transactions with your app. /// /// - Parameter completion: A block object to be executed when the refresh operation ends. func refreshReceipt(completion: @escaping Closure>) - + + /// <#Description#> + /// - Returns: <#description#> + func refreshReceipt() async throws -> String + /// Remove a finished (i.e. failed or completed) transaction from the queue. Attempting to finish a purchasing transaction will throw an exception. /// /// - Parameter transaction: An object in the payment queue. diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift index c7b4811d9..d2d3826b3 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift @@ -15,4 +15,9 @@ public protocol IReceiptRefreshProvider { /// - requestId: A request identifier. /// - handler: A receipt refresh handler. func refresh(requestId: String, handler: @escaping ReceiptRefreshHandler) + + /// <#Description#> + /// + /// - Parameter requestId: <#requestId description#> + func refresh(requestId: String) async throws } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift index 2ed574331..c703375bd 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift @@ -62,6 +62,19 @@ extension ReceiptRefreshProvider: IReceiptRefreshProvider { let request = makeRequest(id: requestId) fetch(request: request, handler: handler) } + + func refresh(requestId: String) async throws { + try await withCheckedThrowingContinuation { continuation in + refresh(requestId: requestId) { result in + switch result { + case .success: + continuation.resume(with: .success(())) + case let .failure(error): + continuation.resume(with: .failure(error)) + } + } + } + } } // MARK: SKRequestDelegate diff --git a/Sources/Flare/Flare.swift b/Sources/Flare/Flare.swift index c560800f9..6f804bc29 100644 --- a/Sources/Flare/Flare.swift +++ b/Sources/Flare/Flare.swift @@ -30,6 +30,10 @@ extension Flare: IFlare { iapProvider.fetch(productsIds: ids, completion: completion) } + public func fetch(ids: Set) async throws -> [SKProduct] { + try await iapProvider.fetch(productsIDs: ids) + } + public func buy(id: String, completion: @escaping Closure>) { guard iapProvider.canMakePayments else { completion(.failure(.paymentNotAllowed)) @@ -46,6 +50,11 @@ extension Flare: IFlare { } } + public func buy(id: String) async throws -> PaymentTransaction { + guard iapProvider.canMakePayments else { throw IAPError.paymentNotAllowed } + return try await iapProvider.purchase(productId: id) + } + public func receipt(completion: @escaping Closure>) { iapProvider.refreshReceipt { result in switch result { @@ -57,6 +66,10 @@ extension Flare: IFlare { } } + public func receipt() async throws -> String { + try await iapProvider.refreshReceipt() + } + public func finish(transaction: PaymentTransaction) { iapProvider.finish(transaction: transaction) } diff --git a/Sources/Flare/IFlare.swift b/Sources/Flare/IFlare.swift index 881fec7e9..a568daab9 100644 --- a/Sources/Flare/IFlare.swift +++ b/Sources/Flare/IFlare.swift @@ -14,6 +14,13 @@ public protocol IFlare { /// - completion: A products handler. func fetch(ids: Set, completion: @escaping Closure>) + /// Retrieve localized information from the App Store about a specified list of products. + /// + /// - Parameter ids: The list of product identifiers for the products you wish to retrieve descriptions of. + /// + /// - Returns: Products. + func fetch(ids: Set) async throws -> [SKProduct] + /// Perform purchase a product with given id. /// /// - Parameters: @@ -21,10 +28,22 @@ public protocol IFlare { /// - completion: A block object to be executed when the purchase operation ends. func buy(id: String, completion: @escaping Closure>) + /// <#Description#> + /// + /// - Parameter id: <#id description#> + /// + /// - Returns: <#description#> + func buy(id: String) async throws -> PaymentTransaction + /// A request to refresh the receipt, which represents the user’s transactions with your app. /// /// - Parameter completion: A block object to be executed when the refresh operation ends. func receipt(completion: @escaping Closure>) + + /// <#Description#> + /// + /// - Returns: <#description#> + func receipt() async throws -> String /// Remove a finished (i.e. failed or completed) transaction from the queue. /// Attempting to finish a purchasing transaction will throw an exception. diff --git a/Tests/FlareTests/Classes/FlareTests.swift b/Tests/FlareTests/Classes/FlareTests.swift index 323e977ab..b842a4b51 100644 --- a/Tests/FlareTests/Classes/FlareTests.swift +++ b/Tests/FlareTests/Classes/FlareTests.swift @@ -29,55 +29,219 @@ class FlareTests: XCTestCase { // MARK: - Tests - func testThatPurchaseManagerFetchProducts() { + func test_thatPurchaseManagerFetchesProducts() { + // when + flare.fetch(ids: .ids, completion: { _ in }) + + // then + XCTAssertTrue(iapProviderMock.invokedFetch) + } + + func test_thatPurchaseManagerFetchesProductsAsync() async throws { // given - let ids = Set(arrayLiteral: "1", "2", "3") + let productMocks = [ProductMock(), ProductMock(), ProductMock()] + iapProviderMock.fetchAsyncResult = productMocks // when - flare.fetch(ids: ids, completion: { _ in }) + let products = try await flare.fetch(ids: .ids) // then - XCTAssertTrue(iapProviderMock.invokedFetch) + XCTAssertEqual(products, productMocks) } - func testThatPurchaseManagerBuyProductWhenCanMakePayments() { + func test_thatPurchaseManagerBuysProduct_whenCanMakePayments() { // given - let productId = "product_identifier" iapProviderMock.stubbedCanMakePayments = true // when - flare.buy(id: productId, completion: { _ in }) + flare.buy(id: .productID, completion: { _ in }) // then XCTAssertTrue(iapProviderMock.invokedPurchase) - XCTAssertEqual(iapProviderMock.invokedPurchaseParameters?.productId, productId) + XCTAssertEqual(iapProviderMock.invokedPurchaseParameters?.productId, .productID) } - func testThatPurchaseManagerDontBuyProductWhenCannotMakePayments() { + func test_thatPurchaseManagerDoesNotBuyProduct_whenCannotMakePayments() { // given - let productId = "product_identifier" iapProviderMock.stubbedCanMakePayments = false // when - flare.buy(id: productId, completion: { _ in }) + flare.buy(id: .productID, completion: { _ in }) // then XCTAssertFalse(iapProviderMock.invokedPurchase) } - func testThatPurchaseManagerFetchReceipt() { + func test_thatPurchaseManagersBuysProduct_whenCanMakePaymentsSuccess() { + // given + let paymentTransaction = PaymentTransaction(PaymentTransactionMock()) + iapProviderMock.stubbedCanMakePayments = true + + // when + var transaction: PaymentTransaction? + flare.buy(id: .productID, completion: { result in + if case let .success(result) = result { + transaction = result + } + }) + iapProviderMock.invokedPurchaseParameters?.completion(.success(paymentTransaction)) + + // then + XCTAssertTrue(iapProviderMock.invokedPurchase) + XCTAssertEqual(transaction, paymentTransaction) + } + + func test_thatPurchaseManagersBuysProduct_whenCanMakePaymentsFailed() { + // given + let errorMock = IAPError.paymentNotAllowed + iapProviderMock.stubbedCanMakePayments = true + + // when + var error: IAPError? + flare.buy(id: .productID, completion: { result in + if case let .failure(result) = result { + error = result + } + }) + iapProviderMock.invokedPurchaseParameters?.completion(.failure(errorMock)) + + // then + XCTAssertTrue(iapProviderMock.invokedPurchase) + XCTAssertEqual(error, errorMock) + } + + func test_thatPurchaseManagerDoesNotBuyProductAsync_whenCannotMakePayments() async { + // given + iapProviderMock.stubbedCanMakePayments = false + iapProviderMock.stubbedAsyncPurchase = PaymentTransaction(PaymentTransactionMock()) + + // when + var iapError: IAPError? + do { + let _ = try await flare.buy(id: .productID) + } catch { + iapError = error as? IAPError + } + + // then + XCTAssertFalse(iapProviderMock.invokedAsyncPurchase) + XCTAssertEqual(iapError, .paymentNotAllowed) + } + + func test_thatPurchaseManagerBuysProduct_whenCannotMakePayments() async { + // given + let transactionMock = PaymentTransaction(PaymentTransactionMock()) + + iapProviderMock.stubbedCanMakePayments = true + iapProviderMock.stubbedAsyncPurchase = transactionMock + // when - flare.receipt(completion: { _ in }) + var transaction: PaymentTransaction? + var iapError: IAPError? + do { + transaction = try await flare.buy(id: .productID) + } catch { + iapError = error as? IAPError + } + + // then + XCTAssertTrue(iapProviderMock.invokedAsyncPurchase) + XCTAssertNil(iapError) + XCTAssertEqual(transaction, transactionMock) + } + + func test_thatPurchaseManagerFetchReceipt_whenRequestCompleted() { + // when + var receipt: String? + flare.receipt(completion: { result in + if case let .success(result) = result { + receipt = result + } + }) + iapProviderMock.invokedRefreshReceiptParameters?.0(.success(.receipt)) + + // then + XCTAssertTrue(iapProviderMock.invokedRefreshReceipt) + XCTAssertEqual(receipt, .receipt) + } + + func test_thatPurchaseManagerFetchReceipt_whenRequestFailed() { + // when + var error: IAPError? + flare.receipt(completion: { result in + if case let .failure(result) = result { + error = result + } + }) + iapProviderMock.invokedRefreshReceiptParameters?.0(.failure(.paymentNotAllowed)) // then XCTAssertTrue(iapProviderMock.invokedRefreshReceipt) + XCTAssertEqual(error, .paymentNotAllowed) } - func testThatPurchaseManagerRemoveTransactionObserver() { + func test_thatPurchaseManagerRemovesTransactionObserver() { // when flare.removeTransactionObserver() // then XCTAssertTrue(iapProviderMock.invokedRemoveTransactionObserver) } + + func test_thatPurchaseManagerFetchReceiptAsync_whenRequestCompleted() async throws { + // given + iapProviderMock.stubbedRefreshReceiptAsyncResult = .success(.receipt) + + // when + let receipt = try await flare.receipt() + + // then + XCTAssertEqual(receipt, .receipt) + } + + func test_thatPurchaseManagerFetchesReceiptAsync_whenRequestFailed() async throws { + // given + iapProviderMock.stubbedRefreshReceiptAsyncResult = .failure(.paymentNotAllowed) + + // when + var iapError: IAPError? + do { + let _ = try await flare.receipt() + } catch { + iapError = error as? IAPError + } + + // then + XCTAssertEqual(iapError, .paymentNotAllowed) + } + + func test_thatPurchaseManagerFinishesTransaction() { + // given + let transaction = PaymentTransaction(PaymentTransactionMock()) + + // when + flare.finish(transaction: transaction) + + // then + XCTAssertTrue(iapProviderMock.invokedFinishTransaction) + } + + func test_thatPurchaseManagerAddsTransactionObserver() { + // when + flare.addTransactionObserver(fallbackHandler: { _ in }) + + // then + XCTAssertTrue(iapProviderMock.invokedAddTransactionObserver) + } +} + +// MARK: - Constants + +private extension Set where Element == String { + static let ids = Set(arrayLiteral: "1", "2", "3") +} + +private extension String { + static let productID = "product_ID" + static let receipt = "receipt" } diff --git a/Tests/FlareTests/Classes/Mocks/IAPProviderMock.swift b/Tests/FlareTests/Classes/Mocks/IAPProviderMock.swift index 5b1ff51de..070670715 100644 --- a/Tests/FlareTests/Classes/Mocks/IAPProviderMock.swift +++ b/Tests/FlareTests/Classes/Mocks/IAPProviderMock.swift @@ -45,12 +45,17 @@ final class IAPProviderMock: IIAPProvider { var invokedRefreshReceiptCount = 0 var invokedRefreshReceiptParameters: (Closure>, Void)? var invokedRefreshReceiptParametersList = [(Closure>, Void)]() + var stubbedRefreshReceiptResult: Result? func refreshReceipt(completion: @escaping Closure>) { invokedRefreshReceipt = true invokedRefreshReceiptCount += 1 invokedRefreshReceiptParameters = (completion, ()) invokedRefreshReceiptParametersList.append((completion, ())) + + if let result = stubbedRefreshReceiptResult { + completion(result) + } } var invokedFinishTransaction = false @@ -84,4 +89,52 @@ final class IAPProviderMock: IIAPProvider { invokedRemoveTransactionObserver = true invokedRemoveTransactionObserverCount += 1 } + + var invokedFetchAsync = false + var invokedFetchAsyncCount = 0 + var invokedFetchAsyncParameters: (productIDs: Set, Void)? + var invokedFetchAsyncParametersList = [(productIDs: Set, Void)]() + var fetchAsyncResult: [SKProduct] = [] + + func fetch(productsIDs: Set) async throws -> [SKProduct] { + invokedFetchAsync = true + invokedFetchAsyncCount += 1 + invokedFetchAsyncParameters = (productsIDs, ()) + invokedFetchAsyncParametersList.append((productsIDs, ())) + return fetchAsyncResult + } + + var invokedAsyncPurchase = false + var invokedAsyncPurchaseCount = 0 + var invokedAsyncPurchaseParameters: (productID: String, Void)? + var invokedAsyncPurchaseParametersList = [(productID: String, Void)?]() + var stubbedAsyncPurchase: PaymentTransaction! + + func purchase(productId: String) async throws -> PaymentTransaction { + invokedAsyncPurchase = true + invokedAsyncPurchaseCount += 1 + invokedAsyncPurchaseParameters = (productId, ()) + invokedAsyncPurchaseParametersList.append((productId, ())) + return stubbedAsyncPurchase + } + + var invokedAsyncRefreshReceipt = false + var invokedAsyncRefreshReceiptCounter = 0 + var stubbedRefreshReceiptAsyncResult: Result! + + func refreshReceipt() async throws -> String { + invokedAsyncRefreshReceipt = true + invokedAsyncRefreshReceiptCounter += 1 + + let result = stubbedRefreshReceiptAsyncResult + + switch result { + case let .success(receipt): + return receipt + case let .failure(error): + throw error + default: + fatalError("An unknown type") + } + } } diff --git a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift b/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift index 886e9aedc..2685cd703 100644 --- a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift +++ b/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift @@ -27,4 +27,16 @@ final class ReceiptRefreshProviderMock: IReceiptRefreshProvider { invokedRefreshParameters = (requestId, handler) invokedRefreshParametersList.append((requestId, handler)) } + + var invokedAsyncRefresh = false + var invokedAsyncRefreshCount = 0 + var invokedAsyncRefreshParameters: (requestID: String, Void)? + var invokedAsyncRefreshParametersList = [(requestID: String, Void)]() + + func refresh(requestId: String) async throws { + invokedAsyncRefresh = true + invokedAsyncRefreshCount += 1 + invokedAsyncRefreshParameters = (requestId, ()) + invokedAsyncRefreshParametersList.append((requestId, ())) + } } From 205a9c95e763f5b488549e19fc4ba600492af8f3 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sat, 9 Sep 2023 09:41:01 +0400 Subject: [PATCH 05/44] Revise the documentation for the methods. --- Sources/Flare/Classes/Common/Types.swift | 2 ++ .../Providers/IAPProvider/IIAPProvider.swift | 32 +++++++++++-------- .../PaymentProvider/IPaymentProvider.swift | 3 +- .../PaymentProvider/PaymentProvider.swift | 10 +++--- .../IReceiptRefreshProvider.swift | 8 ++--- Sources/Flare/IFlare.swift | 12 +++---- hooks/pre-commit | 0 7 files changed, 38 insertions(+), 29 deletions(-) mode change 100644 => 100755 hooks/pre-commit diff --git a/Sources/Flare/Classes/Common/Types.swift b/Sources/Flare/Classes/Common/Types.swift index 6d71b8f40..c5ba333ce 100644 --- a/Sources/Flare/Classes/Common/Types.swift +++ b/Sources/Flare/Classes/Common/Types.swift @@ -3,6 +3,8 @@ // Copyright © 2023 Space Code. All rights reserved. // +// swiftlint:disable line_length + import Foundation public typealias Closure = (T) -> Void diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift index 3d96b0c58..140f70dc5 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift @@ -15,45 +15,49 @@ public protocol IIAPProvider { /// - productsIds: The list of product identifiers for the products you wish to retrieve descriptions of. /// - completion: A products handler. func fetch(productsIds: Set, completion: @escaping Closure>) - + /// Retrieve localized information from the App Store about a specified list of products. /// /// - Parameter productsIDs: The list of product identifiers for the products you wish to retrieve descriptions of. /// /// - Returns: Products. func fetch(productsIDs: Set) async throws -> [SKProduct] - + /// Perform purchase a product with given id. /// /// - Parameters: /// - productId: A product identifier. /// - completion: A block object to be executed when the purchase operation ends. func purchase(productId: String, completion: @escaping Closure>) - - /// <#Description#> + + /// Perform purchase a product with given id. + /// + /// - Parameter productId: A product identifier. /// - /// - Parameter productId: <#productId description#> - /// - /// - Returns: <#description#> + /// - Returns: A payment transaction. func purchase(productId: String) async throws -> PaymentTransaction /// A request to refresh the receipt, which represents the user’s transactions with your app. /// /// - Parameter completion: A block object to be executed when the refresh operation ends. func refreshReceipt(completion: @escaping Closure>) - - /// <#Description#> - /// - Returns: <#description#> + + /// A request to refresh the receipt, which represents the user’s transactions with your app. + /// + /// - Returns: A refreshed receipt. func refreshReceipt() async throws -> String - - /// Remove a finished (i.e. failed or completed) transaction from the queue. Attempting to finish a purchasing transaction will throw an exception. + + /// Remove a finished (i.e. failed or completed) transaction from the queue. + /// Attempting to finish a purchasing transaction will throw an exception. /// /// - Parameter transaction: An object in the payment queue. func finish(transaction: PaymentTransaction) - /// The transactions array will only be synchronized with the server while the queue has observers. This may require that the user authenticate. + /// The transactions array will only be synchronized with the server while the queue has observers. + /// This may require that the user authenticate. func addTransactionObserver(fallbackHandler: Closure>?) - /// The transactions array will only be synchronized with the server while the queue has observers. This may require that the user authenticate + /// The transactions array will only be synchronized with the server while the queue has observers. + /// This may require that the user authenticate func removeTransactionObserver() } diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift index df5a248e5..519d96616 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift @@ -20,7 +20,8 @@ public protocol IPaymentProvider: AnyObject { /// This may require that the user authenticate. func removeTransactionObserver() - /// Will add completed transactions for the current user back to the queue to be re-completed. User will be asked to authenticate. + /// Will add completed transactions for the current user back to the queue to be re-completed. + /// User will be asked to authenticate. /// /// - Parameter handler: A restore handler. func restoreCompletedTransactions(handler: @escaping RestoreHandler) diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift index db2bb80eb..10b5f84ea 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift @@ -104,7 +104,9 @@ extension PaymentProvider: SKPaymentTransactionObserver { return } - if let handlers = self.paymentHandlers.removeValue(forKey: transaction.payment.productIdentifier), !handlers.isEmpty { + if let handlers = self.paymentHandlers.removeValue( + forKey: transaction.payment.productIdentifier + ), !handlers.isEmpty { self.dispatchQueueFactory.main().async { handlers.forEach { $0(queue, .success(transaction)) } } @@ -139,9 +141,9 @@ extension PaymentProvider: SKPaymentTransactionObserver { } #if os(iOS) || os(tvOS) || os(macOS) - func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool { - shouldAddStorePaymentHandler?(queue, payment, product) ?? false - } + func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool { + shouldAddStorePaymentHandler?(queue, payment, product) ?? false + } #endif func finish(transaction: PaymentTransaction) { diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift index d2d3826b3..738a08bbb 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift @@ -15,9 +15,9 @@ public protocol IReceiptRefreshProvider { /// - requestId: A request identifier. /// - handler: A receipt refresh handler. func refresh(requestId: String, handler: @escaping ReceiptRefreshHandler) - - /// <#Description#> - /// - /// - Parameter requestId: <#requestId description#> + + /// A request to refresh the receipt, which represents the user’s transactions with your app. + /// + /// - Parameter requestId: A request identifier. func refresh(requestId: String) async throws } diff --git a/Sources/Flare/IFlare.swift b/Sources/Flare/IFlare.swift index a568daab9..9f009d4c0 100644 --- a/Sources/Flare/IFlare.swift +++ b/Sources/Flare/IFlare.swift @@ -28,21 +28,21 @@ public protocol IFlare { /// - completion: A block object to be executed when the purchase operation ends. func buy(id: String, completion: @escaping Closure>) - /// <#Description#> + /// Perform purchase a product with given id. /// - /// - Parameter id: <#id description#> + /// - Parameter id: A product identifier. /// - /// - Returns: <#description#> + /// - Returns: A payment transaction. func buy(id: String) async throws -> PaymentTransaction /// A request to refresh the receipt, which represents the user’s transactions with your app. /// /// - Parameter completion: A block object to be executed when the refresh operation ends. func receipt(completion: @escaping Closure>) - - /// <#Description#> + + /// A request to refresh the receipt, which represents the user’s transactions with your app. /// - /// - Returns: <#description#> + /// - Returns: A receipt. func receipt() async throws -> String /// Remove a finished (i.e. failed or completed) transaction from the queue. diff --git a/hooks/pre-commit b/hooks/pre-commit old mode 100644 new mode 100755 From 423d0c80fdc83630b3ed9cdf86c974f7c1f61bc0 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sat, 9 Sep 2023 09:47:25 +0400 Subject: [PATCH 06/44] Update `pre-commit` hooks - Integrate `SwiftLint` for validating modified lines. --- hooks/pre-commit | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/hooks/pre-commit b/hooks/pre-commit index 89b3319d8..956fdcb6a 100755 --- a/hooks/pre-commit +++ b/hooks/pre-commit @@ -8,4 +8,31 @@ git diff --diff-filter=d --staged --name-only | grep -e '\.swift$' | while read fi done -swiftlint \ No newline at end of file +LINT=$(which mint) +if [[ -e "${LINT}" ]]; then + # Export files in SCRIPT_INPUT_FILE_$count to lint against later + count=0 + while IFS= read -r file_path; do + export SCRIPT_INPUT_FILE_$count="$file_path" + count=$((count + 1)) + done < <(git diff --name-only --cached --diff-filter=d | grep ".swift$") + export SCRIPT_INPUT_FILE_COUNT=$count + + if [ "$count" -eq 0 ]; then + echo "No files to lint!" + exit 0 + fi + + echo "Found $count lintable files! Linting now.." + mint run swiftlint --use-script-input-files --strict --config .swiftlint.yml + RESULT=$? # swiftline exit value is number of errors + + if [ $RESULT -eq 0 ]; then + echo "🎉 Well done. No violation." + fi + exit $RESULT +else + echo "⚠️ WARNING: SwiftLint not found" + echo "⚠️ You might want to edit .git/hooks/pre-commit to locate your swiftlint" + exit 0 +fi \ No newline at end of file From 2e612152eda6362b06013bee55c9999e910e1239 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sat, 9 Sep 2023 09:56:07 +0400 Subject: [PATCH 07/44] Resolve `SwiftLint` warnings --- .swiftlint.yml | 7 ++++--- Sources/Flare/Classes/Common/Types.swift | 2 -- .../Providers/PaymentProvider/PaymentProvider.swift | 5 +---- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index c25e9471f..b5956417d 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -13,12 +13,10 @@ disabled_rules: opt_in_rules: # some rules are only opt-in - anyobject_protocol - array_init - - attributes - closure_body_length - closure_end_indentation - closure_spacing - collection_alignment - - conditional_returns_on_newline - contains_over_filter_count - contains_over_filter_is_empty - contains_over_first_not_nil @@ -131,4 +129,7 @@ nesting: type_name: max_length: warning: 40 - error: 50 \ No newline at end of file + error: 50 + +file_name: + excluded: ["Types.swift"] \ No newline at end of file diff --git a/Sources/Flare/Classes/Common/Types.swift b/Sources/Flare/Classes/Common/Types.swift index c5ba333ce..6d71b8f40 100644 --- a/Sources/Flare/Classes/Common/Types.swift +++ b/Sources/Flare/Classes/Common/Types.swift @@ -3,8 +3,6 @@ // Copyright © 2023 Space Code. All rights reserved. // -// swiftlint:disable line_length - import Foundation public typealias Closure = (T) -> Void diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift index 10b5f84ea..4679e52d8 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift @@ -98,11 +98,8 @@ extension PaymentProvider: SKPaymentTransactionObserver { @unknown default: continue } - privateQueue.async { [weak self] in - guard let self = self else { - return - } + guard let self = self else { return } if let handlers = self.paymentHandlers.removeValue( forKey: transaction.payment.productIdentifier From df8e080eb1c643073aad352a2fd3fe282ab761fd Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sat, 9 Sep 2023 15:20:31 +0400 Subject: [PATCH 08/44] Implement `ReceiptRefreshProvider` tests --- .../Bundle+IAppStoreReceiptProvider.swift | 8 ++ .../Extensions/FileManager+IFileManager.swift | 8 ++ .../SKRequest+IReceiptRefreshRequest.swift | 10 ++ .../Helpers/FileManager/IFileManager.swift | 10 ++ .../IAppStoreReceiptProvider.swift | 10 ++ .../Factories/IReceiptRefreshRequest.swift | 12 ++ .../ReceiptRefreshRequestFactory.swift | 25 ++++ .../ReceiptRefreshProvider.swift | 27 ++-- .../Mocks/AppStoreReceiptProviderMock.swift | 19 +++ .../Classes/Mocks/FileManagerMock.swift | 23 ++++ .../Mocks/ReceiptRefreshRequestFactory.swift | 24 ++++ .../Mocks/ReceiptRefreshRequestMock.swift | 41 ++++++ .../ReceiptRefreshProviderTests.swift | 128 ++++++++++++++++-- 13 files changed, 325 insertions(+), 20 deletions(-) create mode 100644 Sources/Flare/Classes/Extensions/Bundle+IAppStoreReceiptProvider.swift create mode 100644 Sources/Flare/Classes/Extensions/FileManager+IFileManager.swift create mode 100644 Sources/Flare/Classes/Extensions/SKRequest+IReceiptRefreshRequest.swift create mode 100644 Sources/Flare/Classes/Helpers/FileManager/IFileManager.swift create mode 100644 Sources/Flare/Classes/Providers/AppStoreReceiptProvider/IAppStoreReceiptProvider.swift create mode 100644 Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/IReceiptRefreshRequest.swift create mode 100644 Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory.swift create mode 100644 Tests/FlareTests/Classes/Mocks/AppStoreReceiptProviderMock.swift create mode 100644 Tests/FlareTests/Classes/Mocks/FileManagerMock.swift create mode 100644 Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestFactory.swift create mode 100644 Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestMock.swift diff --git a/Sources/Flare/Classes/Extensions/Bundle+IAppStoreReceiptProvider.swift b/Sources/Flare/Classes/Extensions/Bundle+IAppStoreReceiptProvider.swift new file mode 100644 index 000000000..f762c9d2b --- /dev/null +++ b/Sources/Flare/Classes/Extensions/Bundle+IAppStoreReceiptProvider.swift @@ -0,0 +1,8 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +extension Bundle: IAppStoreReceiptProvider {} diff --git a/Sources/Flare/Classes/Extensions/FileManager+IFileManager.swift b/Sources/Flare/Classes/Extensions/FileManager+IFileManager.swift new file mode 100644 index 000000000..43c2f32c2 --- /dev/null +++ b/Sources/Flare/Classes/Extensions/FileManager+IFileManager.swift @@ -0,0 +1,8 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +extension FileManager: IFileManager {} diff --git a/Sources/Flare/Classes/Extensions/SKRequest+IReceiptRefreshRequest.swift b/Sources/Flare/Classes/Extensions/SKRequest+IReceiptRefreshRequest.swift new file mode 100644 index 000000000..deea382c5 --- /dev/null +++ b/Sources/Flare/Classes/Extensions/SKRequest+IReceiptRefreshRequest.swift @@ -0,0 +1,10 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import StoreKit + +// MARK: - SKRequest + IReceiptRefreshRequest + +extension SKRequest: IReceiptRefreshRequest {} diff --git a/Sources/Flare/Classes/Helpers/FileManager/IFileManager.swift b/Sources/Flare/Classes/Helpers/FileManager/IFileManager.swift new file mode 100644 index 000000000..f53e1ca11 --- /dev/null +++ b/Sources/Flare/Classes/Helpers/FileManager/IFileManager.swift @@ -0,0 +1,10 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +protocol IFileManager { + func fileExists(atPath path: String) -> Bool +} diff --git a/Sources/Flare/Classes/Providers/AppStoreReceiptProvider/IAppStoreReceiptProvider.swift b/Sources/Flare/Classes/Providers/AppStoreReceiptProvider/IAppStoreReceiptProvider.swift new file mode 100644 index 000000000..a462151a8 --- /dev/null +++ b/Sources/Flare/Classes/Providers/AppStoreReceiptProvider/IAppStoreReceiptProvider.swift @@ -0,0 +1,10 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +protocol IAppStoreReceiptProvider { + var appStoreReceiptURL: URL? { get } +} diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/IReceiptRefreshRequest.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/IReceiptRefreshRequest.swift new file mode 100644 index 000000000..ee7708bf7 --- /dev/null +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/IReceiptRefreshRequest.swift @@ -0,0 +1,12 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +protocol IReceiptRefreshRequest { + var id: String { get set } + + func start() +} diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory.swift new file mode 100644 index 000000000..0180c5d90 --- /dev/null +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory.swift @@ -0,0 +1,25 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import class StoreKit.SKReceiptRefreshRequest +import protocol StoreKit.SKRequestDelegate + +// MARK: - IReceiptRefreshRequestFactory + +protocol IReceiptRefreshRequestFactory { + func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest +} + +// MARK: - ReceiptRefreshRequestFactory + +final class ReceiptRefreshRequestFactory: IReceiptRefreshRequestFactory { + func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest { + let request = SKReceiptRefreshRequest() + request.id = id + request.delegate = delegate + return request + } +} diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift index c703375bd..2f7e55bf1 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift @@ -13,21 +13,33 @@ final class ReceiptRefreshProvider: NSObject { // MARK: Properties private let dispatchQueueFactory: IDispatchQueueFactory + private let fileManager: IFileManager + private let appStoreReceiptProvider: IAppStoreReceiptProvider + private let receiptRefreshRequestFactory: IReceiptRefreshRequestFactory + private var handlers: [String: ReceiptRefreshHandler] = [:] private lazy var dispatchQueue: IDispatchQueue = dispatchQueueFactory.privateQueue(label: String(describing: self)) // MARK: Initialization - init(dispatchQueueFactory: IDispatchQueueFactory = DispatchQueueFactory()) { + init( + dispatchQueueFactory: IDispatchQueueFactory = DispatchQueueFactory(), + fileManager: IFileManager = FileManager.default, + appStoreReceiptProvider: IAppStoreReceiptProvider = Bundle.main, + receiptRefreshRequestFactory: IReceiptRefreshRequestFactory = ReceiptRefreshRequestFactory() + ) { self.dispatchQueueFactory = dispatchQueueFactory + self.fileManager = fileManager + self.appStoreReceiptProvider = appStoreReceiptProvider + self.receiptRefreshRequestFactory = receiptRefreshRequestFactory } // MARK: Internal var receipt: String? { - if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, - FileManager.default.fileExists(atPath: appStoreReceiptURL.path) + if let appStoreReceiptURL = appStoreReceiptProvider.appStoreReceiptURL, + fileManager.fileExists(atPath: appStoreReceiptURL.path) { let receiptData = try? Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped) let receiptString = receiptData?.base64EncodedString(options: []) @@ -38,14 +50,11 @@ final class ReceiptRefreshProvider: NSObject { // MARK: Private - private func makeRequest(id: String) -> SKReceiptRefreshRequest { - let request = SKReceiptRefreshRequest() - request.id = id - request.delegate = self - return request + private func makeRequest(id: String) -> IReceiptRefreshRequest { + receiptRefreshRequestFactory.make(id: id, delegate: self) } - private func fetch(request: SKRequest, handler: @escaping ReceiptRefreshHandler) { + private func fetch(request: IReceiptRefreshRequest, handler: @escaping ReceiptRefreshHandler) { dispatchQueue.async { self.handlers[request.id] = handler self.dispatchQueueFactory.main().async { diff --git a/Tests/FlareTests/Classes/Mocks/AppStoreReceiptProviderMock.swift b/Tests/FlareTests/Classes/Mocks/AppStoreReceiptProviderMock.swift new file mode 100644 index 000000000..f5d1ea48f --- /dev/null +++ b/Tests/FlareTests/Classes/Mocks/AppStoreReceiptProviderMock.swift @@ -0,0 +1,19 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class AppStoreReceiptProviderMock: IAppStoreReceiptProvider { + var invokedAppStoreReceiptURLGetter = false + var invokedAppStoreReceiptURLGetterCount = 0 + var stubbedAppStoreReceiptURL: URL! + + var appStoreReceiptURL: URL? { + invokedAppStoreReceiptURLGetter = true + invokedAppStoreReceiptURLGetterCount += 1 + return stubbedAppStoreReceiptURL + } +} diff --git a/Tests/FlareTests/Classes/Mocks/FileManagerMock.swift b/Tests/FlareTests/Classes/Mocks/FileManagerMock.swift new file mode 100644 index 000000000..f80a2b988 --- /dev/null +++ b/Tests/FlareTests/Classes/Mocks/FileManagerMock.swift @@ -0,0 +1,23 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class FileManagerMock: IFileManager { + var invokedFileExists = false + var invokedFileExistsCount = 0 + var invokedFileExistsParameters: (path: String, Void)? + var invokedFileExistsParametersList = [(path: String, Void)]() + var stubbedFileExistsResult: Bool! = false + + func fileExists(atPath path: String) -> Bool { + invokedFileExists = true + invokedFileExistsCount += 1 + invokedFileExistsParameters = (path, ()) + invokedFileExistsParametersList.append((path, ())) + return stubbedFileExistsResult + } +} diff --git a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestFactory.swift b/Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestFactory.swift new file mode 100644 index 000000000..98ba935fb --- /dev/null +++ b/Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestFactory.swift @@ -0,0 +1,24 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation +import protocol StoreKit.SKRequestDelegate + +final class ReceiptRefreshRequestFactoryMock: IReceiptRefreshRequestFactory { + var invokedMake = false + var invokedMakeCount = 0 + var invokedMakeParameters: (id: String, delegate: SKRequestDelegate?)? + var invokedMakeParametersList = [(id: String, delegate: SKRequestDelegate?)]() + var stubbedMakeResult: IReceiptRefreshRequest! + + func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest { + invokedMake = true + invokedMakeCount += 1 + invokedMakeParameters = (id, delegate) + invokedMakeParametersList.append((id, delegate)) + return stubbedMakeResult + } +} diff --git a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestMock.swift b/Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestMock.swift new file mode 100644 index 000000000..9ffbfc7c4 --- /dev/null +++ b/Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestMock.swift @@ -0,0 +1,41 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class ReceiptRefreshRequestMock: IReceiptRefreshRequest { + var invokedIdSetter = false + var invokedIdSetterCount = 0 + var invokedId: String? + var invokedIdList = [String]() + var invokedIdGetter = false + var invokedIdGetterCount = 0 + var stubbedId: String! = "" + + var id: String { + set { + invokedIdSetter = true + invokedIdSetterCount += 1 + invokedId = newValue + invokedIdList.append(newValue) + } + get { + invokedIdGetter = true + invokedIdGetterCount += 1 + return stubbedId + } + } + + var invokedStart = false + var invokedStartCount = 0 + var stubbedStartAction: (() -> Void)? + + func start() { + invokedStart = true + invokedStartCount += 1 + stubbedStartAction?() + } +} diff --git a/Tests/FlareTests/Classes/Providers/ReceiptRefreshProviderTests.swift b/Tests/FlareTests/Classes/Providers/ReceiptRefreshProviderTests.swift index 112fd8261..c2636edc8 100644 --- a/Tests/FlareTests/Classes/Providers/ReceiptRefreshProviderTests.swift +++ b/Tests/FlareTests/Classes/Providers/ReceiptRefreshProviderTests.swift @@ -4,13 +4,10 @@ // @testable import Flare +import StoreKit import TestConcurrency import XCTest -private extension String { - static let requestId = "request_identifier" -} - // MARK: - ReceiptRefreshProviderTests class ReceiptRefreshProviderTests: XCTestCase { @@ -19,34 +16,50 @@ class ReceiptRefreshProviderTests: XCTestCase { private var testDispatchQueue: TestDispatchQueue! private var dispatchQueueFactory: TestDispatchQueueFactory! private var receiptRefreshProvider: ReceiptRefreshProvider! + private var appStoreReceiptProviderMock: AppStoreReceiptProviderMock! + private var fileManagerMock: FileManagerMock! + private var receiptRefreshRequestFactoryMock: ReceiptRefreshRequestFactoryMock! // MARK: - XCTestCase override func setUp() { super.setUp() testDispatchQueue = TestDispatchQueue() + appStoreReceiptProviderMock = AppStoreReceiptProviderMock() dispatchQueueFactory = TestDispatchQueueFactory(testQueue: testDispatchQueue) - receiptRefreshProvider = ReceiptRefreshProvider(dispatchQueueFactory: dispatchQueueFactory) + fileManagerMock = FileManagerMock() + receiptRefreshRequestFactoryMock = ReceiptRefreshRequestFactoryMock() + receiptRefreshProvider = ReceiptRefreshProvider( + dispatchQueueFactory: dispatchQueueFactory, + fileManager: fileManagerMock, + appStoreReceiptProvider: appStoreReceiptProviderMock, + receiptRefreshRequestFactory: receiptRefreshRequestFactoryMock + ) } override func tearDown() { testDispatchQueue = nil dispatchQueueFactory = nil receiptRefreshProvider = nil + appStoreReceiptProviderMock = nil + fileManagerMock = nil + receiptRefreshRequestFactoryMock = nil super.tearDown() } // MARK: - Tests - func testThatReceiptRefreshProviderHandleRequestError() { + func test_thatReceiptRefreshProviderHandlesRequestError() { // given + receiptRefreshRequestFactoryMock.stubbedMakeResult = ReceiptRefreshRequestMock() + var result: Result? - let request = PurchaseManagerTestHelper.makeRequest(with: .requestId) + let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let handler: ReceiptRefreshHandler = { result = $0 } let error = IAPError.paymentCancelled // when - receiptRefreshProvider.refresh(requestId: .requestId, handler: handler) + receiptRefreshProvider.refresh(requestId: .requestID, handler: handler) receiptRefreshProvider.request(request, didFailWithError: error) // then @@ -55,14 +68,16 @@ class ReceiptRefreshProviderTests: XCTestCase { } } - func testThatReceiptRefreshProviderFinishRequest() { + func test_thatReceiptRefreshProviderFinishesRequest() { // given + receiptRefreshRequestFactoryMock.stubbedMakeResult = ReceiptRefreshRequestMock() + var result: Result? - let request = PurchaseManagerTestHelper.makeRequest(with: .requestId) + let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let handler: ReceiptRefreshHandler = { result = $0 } // when - receiptRefreshProvider.refresh(requestId: .requestId, handler: handler) + receiptRefreshProvider.refresh(requestId: .requestID, handler: handler) receiptRefreshProvider.requestDidFinish(request) // then @@ -70,4 +85,95 @@ class ReceiptRefreshProviderTests: XCTestCase { XCTFail() } } + + func test_thatReceiptRefreshProviderLoadsAppStoreReceipt_whenReceiptExists() { + // given + appStoreReceiptProviderMock.stubbedAppStoreReceiptURL = .mockURL + fileManagerMock.stubbedFileExistsResult = true + + // when + let receipt = receiptRefreshProvider.receipt + + // then + XCTAssertNotNil(receipt) + } + + func test_thatReceiptRefreshProviderDoesNotLoadAppStoreReceipt_whenReceiptDoesNotExist() { + // given + appStoreReceiptProviderMock.stubbedAppStoreReceiptURL = nil + fileManagerMock.stubbedFileExistsResult = false + + // when + let receipt = receiptRefreshProvider.receipt + + // then + XCTAssertNil(receipt) + } + + func test_thatReceiptRefreshProviderRefreshesReceipt_whenRequestDidFailWithError() async { + // given + let request = ReceiptRefreshRequestMock() + receiptRefreshRequestFactoryMock.stubbedMakeResult = request + + request.stubbedStartAction = { + self.receiptRefreshProvider.request( + self.makeSKRequest(id: request.id), + didFailWithError: IAPError.paymentNotAllowed + ) + } + + // when + var iapError: IAPError? + + do { + try await receiptRefreshProvider.refresh(requestId: .requestID) + } catch { + iapError = error as? IAPError + } + + // then + XCTAssertEqual(iapError, IAPError(error: IAPError.paymentNotAllowed)) + } + + func test_thatReceiptRefreshProviderRefreshesReceipt_whenRequestDid() async { + // given + let request = ReceiptRefreshRequestMock() + request.stubbedId = .requestID + + receiptRefreshRequestFactoryMock.stubbedMakeResult = request + + request.stubbedStartAction = { + self.receiptRefreshProvider.requestDidFinish(self.makeSKRequest(id: .requestID)) + } + + // when + var iapError: IAPError? + + do { + try await receiptRefreshProvider.refresh(requestId: .requestID) + } catch { + iapError = error as? IAPError + } + + // then + XCTAssertNil(iapError) + } + + // MARK: Private + + private func makeSKRequest(id: String) -> SKRequest { + let skRequest = SKRequest() + skRequest.id = id + return skRequest + } +} + +// MARK: - Constants + +private extension URL { + static let mockURL = URL(string: "https://google.com") +} + +private extension String { + static let requestID = "request_id" } From 6fc48082fdbbffb6ec03a91459578fd0661682be Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Tue, 12 Sep 2023 17:04:58 +0400 Subject: [PATCH 09/44] Increase project's test-coverage --- .../xcshareddata/xcschemes/Flare.xcscheme | 12 +- Documentation/Usage.md | 2 +- .../Providers/IAPProvider/IAPProvider.swift | 6 +- .../ReceiptRefreshFactoryTests.swift | 42 +++ .../Classes/Mocks/PaymentProviderMock.swift | 10 + .../Mocks/PaymentTransactionMock.swift | 10 + .../Classes/Mocks/ProductMock.swift | 2 +- .../Classes/Mocks/ProductProviderMock.swift | 6 + .../Mocks/ReceiptRefreshProviderMock.swift | 5 + .../Models/PaymentTransactionTests.swift | 144 +++++++++ .../Classes/Providers/IAPProviderTests.swift | 280 ++++++++++++++++-- .../Providers/PaymentProviderTests.swift | 101 +++++-- 12 files changed, 568 insertions(+), 52 deletions(-) create mode 100644 Tests/FlareTests/Classes/Factories/ReceiptRefreshFactoryTests.swift create mode 100644 Tests/FlareTests/Classes/Models/PaymentTransactionTests.swift diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme index d81d19a4c..46bcfc41a 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme @@ -41,7 +41,17 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES" - codeCoverageEnabled = "YES"> + codeCoverageEnabled = "YES" + onlyGenerateCoverageForSpecifiedTargets = "YES"> + + + + diff --git a/Documentation/Usage.md b/Documentation/Usage.md index af7a0955b..eadc098e2 100644 --- a/Documentation/Usage.md +++ b/Documentation/Usage.md @@ -111,4 +111,4 @@ public enum IAPError: Swift.Error { } ``` -If you need a `SKError` you can just look at the `plainError` property in the `IAPError`. \ No newline at end of file +If you need a `SKError` you can just look at the `plainError` property in the `IAPError`. diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index e8398cc0b..1d27a4475 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -94,13 +94,9 @@ final class IAPProvider: IIAPProvider { func refreshReceipt(completion: @escaping Closure>) { receiptRefreshProvider.refresh(requestId: UUID().uuidString) { [weak self] result in - guard let self = self else { - return - } - switch result { case .success: - if let receipt = self.receiptRefreshProvider.receipt { + if let receipt = self?.receiptRefreshProvider.receipt { completion(.success(receipt)) } else { completion(.failure(.receiptNotFound)) diff --git a/Tests/FlareTests/Classes/Factories/ReceiptRefreshFactoryTests.swift b/Tests/FlareTests/Classes/Factories/ReceiptRefreshFactoryTests.swift new file mode 100644 index 000000000..785c1cd25 --- /dev/null +++ b/Tests/FlareTests/Classes/Factories/ReceiptRefreshFactoryTests.swift @@ -0,0 +1,42 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation +import XCTest + +// MARK: - IReceiptRefreshRequestFactoryTests + +final class IReceiptRefreshRequestFactoryTests: XCTestCase { + // MARK: Properties + + private var factory: ReceiptRefreshRequestFactory! + + // MARK: Initialization + + override func setUp() { + super.setUp() + factory = ReceiptRefreshRequestFactory() + } + + override func tearDown() { + factory = nil + super.tearDown() + } + + func test_thatFactoryMakesReceipt() { + // when + let receipt = factory.make(id: .productID, delegate: nil) + + // then + XCTAssertEqual(receipt.id, .productID) + } +} + +// MARK: - Constants + +private extension String { + static let productID = "product_id" +} diff --git a/Tests/FlareTests/Classes/Mocks/PaymentProviderMock.swift b/Tests/FlareTests/Classes/Mocks/PaymentProviderMock.swift index 8e2558e35..5025e5170 100644 --- a/Tests/FlareTests/Classes/Mocks/PaymentProviderMock.swift +++ b/Tests/FlareTests/Classes/Mocks/PaymentProviderMock.swift @@ -59,12 +59,17 @@ final class PaymentProviderMock: IPaymentProvider { var invokedAddCount = 0 var invokedAddParameters: (payment: SKPayment, handler: PaymentHandler)? var invokedAddParametersList = [(payment: SKPayment, handler: PaymentHandler)]() + var stubbedAddResult: (queue: PaymentQueue, result: Result)? func add(payment: SKPayment, handler: @escaping PaymentHandler) { invokedAdd = true invokedAddCount += 1 invokedAddParameters = (payment, handler) invokedAddParametersList.append((payment, handler)) + + if let result = stubbedAddResult { + handler(result.0, result.1) + } } var invokedAddPaymentHandler = false @@ -95,12 +100,17 @@ final class PaymentProviderMock: IPaymentProvider { var invokedFallbackHandlerCount = 0 var invokedFallbackHandlerParameters: (PaymentHandler, Void)? var invokedFallbackHandlerParametersList = [(PaymentHandler, Void)]() + var stubbedFallbackHandlerResult: (queue: PaymentQueue, result: Result)? func set(fallbackHandler: @escaping PaymentHandler) { invokedFallbackHandler = true invokedFallbackHandlerCount += 1 invokedFallbackHandlerParameters = (fallbackHandler, ()) invokedFallbackHandlerParametersList.append((fallbackHandler, ())) + + if let result = stubbedFallbackHandlerResult { + fallbackHandler(result.queue, result.result) + } } var invokedFinishTransaction = false diff --git a/Tests/FlareTests/Classes/Mocks/PaymentTransactionMock.swift b/Tests/FlareTests/Classes/Mocks/PaymentTransactionMock.swift index 26838815d..efae4bd7d 100644 --- a/Tests/FlareTests/Classes/Mocks/PaymentTransactionMock.swift +++ b/Tests/FlareTests/Classes/Mocks/PaymentTransactionMock.swift @@ -33,4 +33,14 @@ final class PaymentTransactionMock: SKPaymentTransaction { invokedPaymentCount += 1 return stubbedPayment } + + var stubbedOriginal: SKPaymentTransaction? + override var original: SKPaymentTransaction? { + stubbedOriginal + } + + var stubbedError: Error? + override var error: Error? { + stubbedError + } } diff --git a/Tests/FlareTests/Classes/Mocks/ProductMock.swift b/Tests/FlareTests/Classes/Mocks/ProductMock.swift index 797690d58..d5a3f0b6f 100644 --- a/Tests/FlareTests/Classes/Mocks/ProductMock.swift +++ b/Tests/FlareTests/Classes/Mocks/ProductMock.swift @@ -8,7 +8,7 @@ import StoreKit final class ProductMock: SKProduct { var invokedProductIdentifier = false var invokedProductIdentifierCount = 0 - var stubbedProductIdentifier: String! + var stubbedProductIdentifier: String = "" override var productIdentifier: String { invokedProductIdentifier = true diff --git a/Tests/FlareTests/Classes/Mocks/ProductProviderMock.swift b/Tests/FlareTests/Classes/Mocks/ProductProviderMock.swift index 48e5ee4b5..c3b2ccc7c 100644 --- a/Tests/FlareTests/Classes/Mocks/ProductProviderMock.swift +++ b/Tests/FlareTests/Classes/Mocks/ProductProviderMock.swift @@ -4,17 +4,23 @@ // @testable import Flare +import class StoreKit.SKProduct final class ProductProviderMock: IProductProvider { var invokedFetch = false var invokedFetchCount = 0 var invokedFetchParameters: (productIds: Set, requestId: String, completion: ProductsHandler)? var invokedFetchParamtersList = [(productIds: Set, requestId: String, completion: ProductsHandler)]() + var stubbedFetchResult: Result<[SKProduct], IAPError>? func fetch(productIds: Set, requestId: String, completion: @escaping ProductsHandler) { invokedFetch = true invokedFetchCount += 1 invokedFetchParameters = (productIds, requestId, completion) invokedFetchParamtersList.append((productIds, requestId, completion)) + + if let result = stubbedFetchResult { + completion(result) + } } } diff --git a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift b/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift index 2685cd703..d90321e02 100644 --- a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift +++ b/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift @@ -20,12 +20,17 @@ final class ReceiptRefreshProviderMock: IReceiptRefreshProvider { var invokedRefreshCount = 0 var invokedRefreshParameters: (requestId: String, handler: ReceiptRefreshHandler)? var invokedRefreshParametersList = [(requestId: String, handler: ReceiptRefreshHandler)]() + var stubbedRefreshResult: Result? func refresh(requestId: String, handler: @escaping ReceiptRefreshHandler) { invokedRefresh = true invokedRefreshCount += 1 invokedRefreshParameters = (requestId, handler) invokedRefreshParametersList.append((requestId, handler)) + + if let result = stubbedRefreshResult { + handler(result) + } } var invokedAsyncRefresh = false diff --git a/Tests/FlareTests/Classes/Models/PaymentTransactionTests.swift b/Tests/FlareTests/Classes/Models/PaymentTransactionTests.swift new file mode 100644 index 000000000..b5345c068 --- /dev/null +++ b/Tests/FlareTests/Classes/Models/PaymentTransactionTests.swift @@ -0,0 +1,144 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import struct StoreKit.SKError +import class StoreKit.SKPaymentTransaction +import enum StoreKit.SKPaymentTransactionState +import XCTest + +final class PaymentTransactionTests: XCTestCase { + func test_thatTransactionHasTransactionIdentifierEqualsToSKPaymentTransactionIdentifier() { + // given + let skPaymentTransaction = SKPaymentTransaction() + let paymentTransaction = PaymentTransaction(skPaymentTransaction) + + // when + let identifier = paymentTransaction.transactionIdentifier + + // then + XCTAssertEqual(identifier, skPaymentTransaction.transactionIdentifier) + } + + func test_thatTransactionHasOriginalTransactionIdentifierEqualsToSKPaymentOriginalTransactionIdentifier() { + // given + let skPaymentTransaction = SKPaymentTransaction() + let paymentTransaction = PaymentTransaction(skPaymentTransaction) + + // when + let identifier = paymentTransaction.originalTransactionIdentifier + + // then + XCTAssertEqual(identifier, skPaymentTransaction.original?.transactionIdentifier) + } + + func test_thatTransactionHasProductIdentifierEqualsToSKPaymentProductIdentifier() { + // given + let skPaymentTransaction = SKPaymentTransaction() + let paymentTransaction = PaymentTransaction(skPaymentTransaction) + + // when + let identifier = paymentTransaction.productIdentifier + + // then + XCTAssertEqual(identifier, skPaymentTransaction.payment.productIdentifier) + } + + func test_thatTransactionHasTransactionStateEqualsToDeffered() { + test_transactionState(stubbedState: .deferred, expectedState: .deferred) + } + + func test_thatTransactionHasTransactionStateEqualsToFailed() { + test_transactionState(stubbedState: .failed, expectedState: .failed) + } + + func test_thatTransactionHasTransactionStateEqualsToPurchased() { + test_transactionState(stubbedState: .purchased, expectedState: .purchased) + } + + func test_thatTransactionHasTransactionStateEqualsToPurchasing() { + test_transactionState(stubbedState: .purchasing, expectedState: .purchasing) + } + + func test_thatTransactionHasTransactionStateEqualsToRestored() { + test_transactionState(stubbedState: .restored, expectedState: .restored) + } + + func test_thatTransactionHasOriginalTransactionEqualsToSKPaymentTransaction() { + // given + let originalTransactionMock = PaymentTransactionMock() + let skPaymentTransaction = PaymentTransactionMock() + skPaymentTransaction.stubbedOriginal = originalTransactionMock + + let paymentTransaction = PaymentTransaction(skPaymentTransaction) + + // when + let originalTransaction = paymentTransaction.original + + // then + XCTAssertTrue(originalTransaction?.skTransaction === originalTransactionMock) + } + + func test_thatTransactionHasErrorEqualsToSKPaymentTransactionError() { + // given + let skPaymentTransaction = PaymentTransactionMock() + skPaymentTransaction.stubbedError = IAPError.unknown + let paymentTransaction = PaymentTransaction(skPaymentTransaction) + + // when + let error = paymentTransaction.error + + // then + XCTAssertEqual(error as? NSError, IAPError.unknown as NSError) + } + + func test_thatTransactionWrappsErrorIntoIAPError_whenErrorIsSKError() { + // given + let errorMock = SKError(SKError.clientInvalid) + let skPaymentTransaction = PaymentTransactionMock() + skPaymentTransaction.stubbedError = errorMock + let paymentTransaction = PaymentTransaction(skPaymentTransaction) + + // when + let error = paymentTransaction.error as? IAPError + + // then + if let error = error, case let IAPError.with(error) = error { + XCTAssertEqual(error as? SKError, errorMock) + } else { + XCTFail("Errors must be equal.") + } + } + + func test_thatTransactionMarksAsCancelled_whenOriginalPaymentTransactionIsCancelled() { + // given + let skPaymentTransaction = PaymentTransactionMock() + skPaymentTransaction.stubbedError = SKError(SKError.Code.paymentCancelled) + + let paymentTransaction = PaymentTransaction(skPaymentTransaction) + + // when + let isCancelled = paymentTransaction.isCancelled + + // then + XCTAssertTrue(isCancelled) + } + + // MARK: Private + + private func test_transactionState(stubbedState: SKPaymentTransactionState, expectedState: PaymentTransaction.State) { + // given + let skPaymentTransaction = PaymentTransactionMock() + skPaymentTransaction.stubbedTransactionState = stubbedState + + let paymentTransaction = PaymentTransaction(skPaymentTransaction) + + // when + let state = paymentTransaction.state + + // then + XCTAssertEqual(state, expectedState) + } +} diff --git a/Tests/FlareTests/Classes/Providers/IAPProviderTests.swift b/Tests/FlareTests/Classes/Providers/IAPProviderTests.swift index e18083bf5..cca833f6f 100644 --- a/Tests/FlareTests/Classes/Providers/IAPProviderTests.swift +++ b/Tests/FlareTests/Classes/Providers/IAPProviderTests.swift @@ -7,14 +7,6 @@ import StoreKit import XCTest -private extension String { - static let productId = "product_identifier" -} - -private extension Set where Element == String { - static let productIds: Set = .init(arrayLiteral: "1", "2", "3") -} - // MARK: - IAPProviderTests class IAPProviderTests: XCTestCase { @@ -53,7 +45,7 @@ class IAPProviderTests: XCTestCase { // MARK: - Tests - func testThatIAPProviderCanMakePayments() { + func test_thatIAPProviderCanMakePayments() { // given paymentQueueMock.stubbedCanMakePayments = true @@ -61,29 +53,25 @@ class IAPProviderTests: XCTestCase { XCTAssertTrue(iapProvider.canMakePayments) } - func testThatIAPProviderFetchProducts() throws { - // given - + func test_thatIAPProviderFetchesProducts() throws { // when - iapProvider.fetch(productsIds: .productIds, completion: { _ in }) + iapProvider.fetch(productsIds: .productIDs, completion: { _ in }) // then let parameters = try XCTUnwrap(productProviderMock.invokedFetchParameters) - XCTAssertEqual(parameters.productIds, .productIds) + XCTAssertEqual(parameters.productIds, .productIDs) XCTAssertTrue(!parameters.requestId.isEmpty) } - func testThatIAPProviderPurchaseProduct() throws { - // given - + func test_thatIAPProviderPurchasesProduct() throws { // when - iapProvider.purchase(productId: .productId, completion: { _ in }) + iapProvider.purchase(productId: .productID, completion: { _ in }) // then XCTAssertTrue(productProviderMock.invokedFetch) } - func testThatIAPProviderRefreshReceipt() { + func test_thatIAPProviderRefreshesReceipt() { // when iapProvider.refreshReceipt(completion: { _ in }) @@ -91,7 +79,7 @@ class IAPProviderTests: XCTestCase { XCTAssertTrue(receiptRefreshProviderMock.invokedRefresh) } - func testThatIAPProviderFinishTransaction() { + func test_thatIAPProviderFinishesTransaction() { // given let transaction = PurchaseManagerTestHelper.makePaymentTransaction(state: .purchased) @@ -102,7 +90,7 @@ class IAPProviderTests: XCTestCase { XCTAssertTrue(paymentProviderMock.invokedFinishTransaction) } - func testThatIAPProviderAddTransactionObserver() { + func test_thatIAPProviderAddsTransactionObserver() { // when iapProvider.addTransactionObserver(fallbackHandler: { _ in }) @@ -111,11 +99,259 @@ class IAPProviderTests: XCTestCase { XCTAssertTrue(paymentProviderMock.invokedAddTransactionObserver) } - func testThatIAPProviderRemoveTransactionObserver() { + func test_thatIAPProviderRemovesTransactionObserver() { // when iapProvider.removeTransactionObserver() // then XCTAssertTrue(paymentProviderMock.invokedRemoveTransactionObserver) } + + func test_thatIAPProviderFetchesProducts_whenProducts() async throws { + // given + let productsMock = [SKProduct(), SKProduct(), SKProduct()] + productProviderMock.stubbedFetchResult = .success(productsMock) + + // when + let products = try await iapProvider.fetch(productsIDs: .productIDs) + + // then + XCTAssertEqual(productsMock, products) + } + + func test_thatIAPProviderThrowsNoProductsError_whenProductsProductProviderReturnsError() async { + // given + productProviderMock.stubbedFetchResult = .failure(IAPError.unknown) + + // when + var errorResult: Error? + do { + _ = try await iapProvider.fetch(productsIDs: .productIDs) + } catch { + errorResult = error + } + + // then + XCTAssertEqual(errorResult as? NSError, IAPError.unknown as NSError) + } + + func test_thatIAPProviderThrowsStoreProductNotAvailableError_whenProductProviderDoesNotHaveProducts() { + // given + productProviderMock.stubbedFetchResult = .success([]) + + // when + var error: Error? + iapProvider.purchase(productId: .productID) { result in + if case let .failure(result) = result { + error = result + } + } + + // then + XCTAssertEqual(error as? NSError, IAPError.storeProductNotAvailable as NSError) + } + + func test_thatIAPProviderReturnsPaymentTransaction_whenProductsExist() { + // given + let paymentTransactionMock = PaymentTransactionMock() + productProviderMock.stubbedFetchResult = .success([ProductMock()]) + paymentProviderMock.stubbedAddResult = (paymentQueueMock, .success(paymentTransactionMock)) + + // when + var transactionResult: PaymentTransaction? + iapProvider.purchase(productId: .productID) { result in + if case let .success(transaction) = result { + transactionResult = transaction + } + } + + // then + XCTAssertEqual(transactionResult?.skTransaction, paymentTransactionMock) + } + + func test_thatIAPProviderReturnsError_whenAddingPaymentFailed() { + // given + productProviderMock.stubbedFetchResult = .success([ProductMock()]) + paymentProviderMock.stubbedAddResult = (paymentQueueMock, .failure(.unknown)) + + // when + var errorResult: Error? + iapProvider.purchase(productId: .productID) { result in + if case let .failure(error) = result { + errorResult = error + } + } + + // then + XCTAssertEqual(errorResult as? NSError, IAPError.unknown as NSError) + } + + func test_thatIAPProviderReturnsError_whenFetchRequestFailed() { + // given + productProviderMock.stubbedFetchResult = .failure(.storeProductNotAvailable) + + // when + var errorResult: Error? + iapProvider.purchase(productId: .productID) { result in + if case let .failure(error) = result { + errorResult = error + } + } + + // then + XCTAssertEqual(errorResult as? NSError, IAPError.storeProductNotAvailable as NSError) + } + + func test_thatIAPProviderThrowsStoreProductNotAvailableError_whenProductsDoNotExist() async throws { + // given + productProviderMock.stubbedFetchResult = .success([]) + + // when + var errorResult: Error? + do { + _ = try await iapProvider.purchase(productId: .productID) + } catch { + errorResult = error + } + + // then + XCTAssertEqual(errorResult as? NSError, IAPError.storeProductNotAvailable as NSError) + } + + func test_thatIAPProviderPurchasesForAProduct_whenProductsExist() async throws { + // given + let transactionMock = SKPaymentTransaction() + productProviderMock.stubbedFetchResult = .success([ProductMock()]) + paymentProviderMock.stubbedAddResult = (paymentQueueMock, .success(transactionMock)) + + // when + let transactionResult = try await iapProvider.purchase(productId: .productID) + + // then + XCTAssertEqual(transactionMock, transactionResult.skTransaction) + } + + func test_thatIAPProviderRefreshesReceipt_when() { + // given + receiptRefreshProviderMock.stubbedReceipt = .receipt + receiptRefreshProviderMock.stubbedRefreshResult = .success(()) + + // when + var receiptResult: String? + iapProvider.refreshReceipt { result in + if case let .success(receipt) = result { + receiptResult = receipt + } + } + + // then + XCTAssertEqual(receiptResult, .receipt) + } + + func test_thatIAPProviderDoesNotRefreshReceipt_whenRequestFailed() { + // given + receiptRefreshProviderMock.stubbedReceipt = nil + receiptRefreshProviderMock.stubbedRefreshResult = .failure(.receiptNotFound) + + // when + var errorResult: Error? + iapProvider.refreshReceipt { result in + if case let .failure(error) = result { + errorResult = error + } + } + + // then + XCTAssertEqual(errorResult as? NSError, IAPError.receiptNotFound as NSError) + } + + func test_thatIAPProviderReturnsReceiptNotFoundError_whenReceiptIsNil() { + // given + receiptRefreshProviderMock.stubbedReceipt = nil + receiptRefreshProviderMock.stubbedRefreshResult = .success(()) + + // when + var errorResult: Error? + iapProvider.refreshReceipt { result in + if case let .failure(error) = result { + errorResult = error + } + } + + // then + XCTAssertEqual(errorResult as? NSError, IAPError.receiptNotFound as NSError) + } + + func test_thatIAPProviderRefreshesReceipt_whenReceiptIsNotNil() async throws { + // given + receiptRefreshProviderMock.stubbedReceipt = .receipt + receiptRefreshProviderMock.stubbedRefreshResult = .success(()) + + // when + let receipt = try await iapProvider.refreshReceipt() + + // then + XCTAssertEqual(receipt, .receipt) + } + + func test_thatIAPProviderDoesNotRefreshReceipt_whenReceiptIsNil() async throws { + // given + receiptRefreshProviderMock.stubbedReceipt = nil + receiptRefreshProviderMock.stubbedRefreshResult = .success(()) + + // when + var errorResult: Error? + do { + _ = try await iapProvider.refreshReceipt() + } catch { + errorResult = error + } + + // then + XCTAssertEqual(errorResult as? NSError, IAPError.receiptNotFound as NSError) + } + + func test_thatIAPProviderReturnsTransaction() { + // given + let transactionMock = SKPaymentTransaction() + paymentProviderMock.stubbedFallbackHandlerResult = (paymentQueueMock, .success(transactionMock)) + + // when + var transactionResult: PaymentTransaction? + iapProvider.addTransactionObserver { result in + if case let .success(transaction) = result { + transactionResult = transaction + } + } + + // then + XCTAssertEqual(transactionResult?.skTransaction, transactionMock) + } + + func test_thatIAPProviderReturnsError() { + // given + paymentProviderMock.stubbedFallbackHandlerResult = (paymentQueueMock, .failure(.unknown)) + + // when + var errorResult: Error? + iapProvider.addTransactionObserver { result in + if case let .failure(error) = result { + errorResult = error + } + } + + // then + XCTAssertEqual(errorResult as? NSError, IAPError.unknown as NSError) + } +} + +// MARK: - Constants + +private extension String { + static let receipt = "receipt" + static let productID = "product_identifier" +} + +private extension Set where Element == String { + static let productIDs: Set = .init(arrayLiteral: "1", "2", "3") } diff --git a/Tests/FlareTests/Classes/Providers/PaymentProviderTests.swift b/Tests/FlareTests/Classes/Providers/PaymentProviderTests.swift index 0b3337632..d8781cc83 100644 --- a/Tests/FlareTests/Classes/Providers/PaymentProviderTests.swift +++ b/Tests/FlareTests/Classes/Providers/PaymentProviderTests.swift @@ -172,42 +172,99 @@ class PaymentProviderTests: XCTestCase { } #if os(iOS) || os(tvOS) || os(macOS) - func testThatPaymentProviderAddAppStoreHandler() { + func testThatPaymentProviderAddAppStoreHandler() { + // given + let payment = SKPayment() + let product = SKProduct() + + var invokedQueue: PaymentQueue? + var invokedPayment: SKPayment? + var invokedProduct: SKProduct? + + let shouldAddStorePaymentHandler: ShouldAddStorePaymentHandler = { queue, payment, product in + invokedQueue = queue + invokedPayment = payment + invokedProduct = product + return true + } + + // when + paymentProvider.set(shouldAddStorePaymentHandler: shouldAddStorePaymentHandler) + let result = paymentProvider.paymentQueue(paymentQueueMock, shouldAddStorePayment: payment, for: product) + + // then + XCTAssertTrue(paymentQueueMock === invokedQueue) + XCTAssertEqual(product, invokedProduct) + XCTAssertEqual(payment, invokedPayment) + XCTAssertTrue(result) + } + #endif + + func testThatPaymentQueueFinishTransaction() { // given - let payment = SKPayment() - let product = SKProduct() + let transaction = PurchaseManagerTestHelper.makePaymentTransaction(state: .purchased) + + // when + paymentProvider.finish(transaction: PaymentTransaction(transaction)) - var invokedQueue: PaymentQueue? - var invokedPayment: SKPayment? - var invokedProduct: SKProduct? + // then + XCTAssertEqual(paymentQueueMock.invokedFinishTransactionParametersList.first?.0, transaction) + } + + func test_thatPaymentQueueRestoresCompletedTransactions() { + // when + paymentProvider.restoreCompletedTransactions(handler: { _, _ in }) + + // then + XCTAssertTrue(paymentQueueMock.invokedRestoreCompletedTransactions) + } - let shouldAddStorePaymentHandler: ShouldAddStorePaymentHandler = { queue, payment, product in - invokedQueue = queue - invokedPayment = payment - invokedProduct = product - return true + func test_thatPaymentQueueRestoresCompletedTransactions_whenTransactionFinished() { + // when + var queueResult: SKPaymentQueue? + var errorResult: Error? + let restoreHandler: RestoreHandler = { queue, error in + queueResult = queue + errorResult = error } + paymentProvider.restoreCompletedTransactions(handler: restoreHandler) + paymentProvider.paymentQueueRestoreCompletedTransactionsFinished(paymentQueueMock) + + // then + XCTAssertEqual(queueResult, paymentQueueMock) + XCTAssertNil(errorResult) + } + + func test_thatPaymentQueueDoesNotRestoreCompletedTransactions_whenRequestFailDueToTransactionError() { + // given + let errorMock = IAPError.paymentNotAllowed + // when - paymentProvider.set(shouldAddStorePaymentHandler: shouldAddStorePaymentHandler) - let result = paymentProvider.paymentQueue(paymentQueueMock, shouldAddStorePayment: payment, for: product) + var queueResult: SKPaymentQueue? + var errorResult: Error? + let restoreHandler: RestoreHandler = { queue, error in + queueResult = queue + errorResult = error + } + + paymentProvider.restoreCompletedTransactions(handler: restoreHandler) + paymentProvider.paymentQueue(paymentQueueMock, restoreCompletedTransactionsFailedWithError: errorMock) // then - XCTAssertTrue(paymentQueueMock === invokedQueue) - XCTAssertEqual(product, invokedProduct) - XCTAssertEqual(payment, invokedPayment) - XCTAssertTrue(result) + XCTAssertEqual(queueResult, paymentQueueMock) + XCTAssertEqual(errorResult as? NSError, IAPError(error: errorMock) as NSError) } - #endif - func testThatPaymentQueueFinishTransaction() { + func test_thatPaymentQueueHandlesTransactions_whenPendingTransactionsExist() { // given - let transaction = PurchaseManagerTestHelper.makePaymentTransaction(state: .purchased) + let transactionMocks = [SKPaymentTransaction(), SKPaymentTransaction(), SKPaymentTransaction()] + paymentQueueMock.stubbedTransactions = transactionMocks // when - paymentProvider.finish(transaction: PaymentTransaction(transaction)) + let transactions = paymentProvider.transactions // then - XCTAssertEqual(paymentQueueMock.invokedFinishTransactionParametersList.first?.0, transaction) + XCTAssertEqual(transactions, transactionMocks.map(PaymentTransaction.init)) } } From f04bff68cbe8c7bb9ddd276cbf8261874f13dc9e Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Tue, 12 Sep 2023 18:35:46 +0400 Subject: [PATCH 10/44] Update comments --- .../Helpers/PaymentQueue/PaymentQueue.swift | 3 ++ Sources/Flare/Classes/Models/IAPError.swift | 13 +++++ .../IAppStoreReceiptProvider.swift | 2 + .../Providers/IAPProvider/IIAPProvider.swift | 53 ++++++++++++------- .../PaymentProvider/IPaymentProvider.swift | 41 ++++++++------ .../ProductProvider/IProductProvider.swift | 8 +-- .../Factories/IReceiptRefreshRequest.swift | 3 ++ .../IReceiptRefreshRequestFactory.swift | 19 +++++++ .../ReceiptRefreshRequestFactory.swift | 8 --- .../IReceiptRefreshProvider.swift | 13 +++-- Sources/Flare/IFlare.swift | 51 ++++++++++++------ 11 files changed, 145 insertions(+), 69 deletions(-) create mode 100644 Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/IReceiptRefreshRequestFactory.swift rename Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/{ => ReceiptRefreshRequestFactory}/ReceiptRefreshRequestFactory.swift (69%) diff --git a/Sources/Flare/Classes/Helpers/PaymentQueue/PaymentQueue.swift b/Sources/Flare/Classes/Helpers/PaymentQueue/PaymentQueue.swift index fc181c0b4..6bcfe38e6 100644 --- a/Sources/Flare/Classes/Helpers/PaymentQueue/PaymentQueue.swift +++ b/Sources/Flare/Classes/Helpers/PaymentQueue/PaymentQueue.swift @@ -9,12 +9,14 @@ import StoreKit public protocol PaymentQueue: AnyObject { /// `False` if this device is not able or allowed to make payments var canMakePayments: Bool { get } + /// Payment transactions. var transactions: [SKPaymentTransaction] { get } /// The transactions array will only be synchronized with the server while the queue has observers. /// This may require that the user authenticate. func add(_ observer: SKPaymentTransactionObserver) + /// The transactions array will only be synchronized with the server while the queue has observers. /// This may require that the user authenticate. func remove(_ observer: SKPaymentTransactionObserver) @@ -22,6 +24,7 @@ public protocol PaymentQueue: AnyObject { /// Add a payment to the server queue. The payment is copied to add an SKPaymentTransaction to the transactions array. /// The same payment can be added multiple times to create multiple transactions. func add(_ payment: SKPayment) + /// Will add completed transactions for the current user back to the queue to be re-completed. /// User will be asked to authenticate. Observers will receive 0 or more -paymentQueue:updatedTransactions:, /// followed by either -paymentQueueRestoreCompletedTransactionsFinished: on success or diff --git a/Sources/Flare/Classes/Models/IAPError.swift b/Sources/Flare/Classes/Models/IAPError.swift index e15615ab8..65fae3136 100644 --- a/Sources/Flare/Classes/Models/IAPError.swift +++ b/Sources/Flare/Classes/Models/IAPError.swift @@ -7,15 +7,26 @@ import StoreKit // MARK: - IAPError +/// `IAPError` is the error type returned by Flare. +/// It encompasses a few different types of errors, each with their own associated reasons. public enum IAPError: Swift.Error { + /// The empty array of products were fetched. case emptyProducts + /// The attempt to fetch products with invalid identifiers. case invalid(productIds: [String]) + /// The attempt to purchase a product when payments are not allowed. case paymentNotAllowed + /// The payment was cancelled. case paymentCancelled + /// The attempt to fetch a product that doesn't available. case storeProductNotAvailable + /// The `SKPayment` returned unknown error. case storeTrouble + /// The operation failed with an underlying error. case with(error: Swift.Error) + /// The App Store receipt wasn't found. case receiptNotFound + /// The unknown error occurred. case unknown } @@ -50,6 +61,8 @@ extension IAPError { } } +// MARK: Equatable + extension IAPError: Equatable { public static func == (lhs: IAPError, rhs: IAPError) -> Bool { switch (lhs, rhs) { diff --git a/Sources/Flare/Classes/Providers/AppStoreReceiptProvider/IAppStoreReceiptProvider.swift b/Sources/Flare/Classes/Providers/AppStoreReceiptProvider/IAppStoreReceiptProvider.swift index a462151a8..f13e50f3c 100644 --- a/Sources/Flare/Classes/Providers/AppStoreReceiptProvider/IAppStoreReceiptProvider.swift +++ b/Sources/Flare/Classes/Providers/AppStoreReceiptProvider/IAppStoreReceiptProvider.swift @@ -5,6 +5,8 @@ import Foundation +/// Type that retrieves the App Store receipt URL. protocol IAppStoreReceiptProvider { + /// The App Store receipt URL for the app. var appStoreReceiptURL: URL? { get } } diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift index 140f70dc5..f2d813f92 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift @@ -5,59 +5,76 @@ import StoreKit +/// Type that provides in-app purchase functionality. public protocol IIAPProvider { /// False if this device is not able or allowed to make payments var canMakePayments: Bool { get } - /// Retrieve localized information from the App Store about a specified list of products. + /// Retrieves localized information from the App Store about a specified list of products. /// /// - Parameters: - /// - productsIds: The list of product identifiers for the products you wish to retrieve descriptions of. - /// - completion: A products handler. + /// - ids: The list of product identifiers for which you wish to retrieve descriptions. + /// - completion: The completion containing the response of retrieving products. func fetch(productsIds: Set, completion: @escaping Closure>) - /// Retrieve localized information from the App Store about a specified list of products. + /// Retrieves localized information from the App Store about a specified list of products. /// - /// - Parameter productsIDs: The list of product identifiers for the products you wish to retrieve descriptions of. + /// - Parameter ids: The list of product identifiers for which you wish to retrieve descriptions. /// - /// - Returns: Products. + /// - Throws: `IAPError(error:)` if the request did fail with error. + /// + /// - Returns: An array of products. func fetch(productsIDs: Set) async throws -> [SKProduct] - /// Perform purchase a product with given id. + /// Performs a purchase of a product with a given ID. + /// + /// - Note: The method automatically checks if the user can buy a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. /// /// - Parameters: - /// - productId: A product identifier. - /// - completion: A block object to be executed when the purchase operation ends. + /// - id: The product identifier. + /// - completion: The closure to be executed once the purchase is complete. func purchase(productId: String, completion: @escaping Closure>) - /// Perform purchase a product with given id. + /// Purchases a product with a given ID. + /// + /// - Note: The method automatically checks if the user can buy a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameter id: The product identifier. /// - /// - Parameter productId: A product identifier. + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. func purchase(productId: String) async throws -> PaymentTransaction - /// A request to refresh the receipt, which represents the user’s transactions with your app. + /// Refreshes the receipt, representing the user's transactions with your app. /// - /// - Parameter completion: A block object to be executed when the refresh operation ends. + /// - Parameter completion: The closure to be executed when the refresh operation ends. func refreshReceipt(completion: @escaping Closure>) - /// A request to refresh the receipt, which represents the user’s transactions with your app. + /// Refreshes the receipt, representing the user's transactions with your app. /// - /// - Returns: A refreshed receipt. + /// `IAPError(error:)` if the request did fail with error. + /// + /// - Returns: A receipt. func refreshReceipt() async throws -> String - /// Remove a finished (i.e. failed or completed) transaction from the queue. + /// Removes a finished (i.e. failed or completed) transaction from the queue. /// Attempting to finish a purchasing transaction will throw an exception. /// /// - Parameter transaction: An object in the payment queue. func finish(transaction: PaymentTransaction) /// The transactions array will only be synchronized with the server while the queue has observers. - /// This may require that the user authenticate. + /// + /// - Note: This may require that the user authenticate. func addTransactionObserver(fallbackHandler: Closure>?) /// The transactions array will only be synchronized with the server while the queue has observers. - /// This may require that the user authenticate + /// + /// - Note: This may require that the user authenticate. func removeTransactionObserver() } diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift index 519d96616..468260459 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift @@ -5,52 +5,59 @@ import StoreKit -/// Payment provider. +/// Type that provides payment functionality. public protocol IPaymentProvider: AnyObject { /// False if this device is not able or allowed to make payments var canMakePayments: Bool { get } - /// Payment transactions. + /// The active payment transactinos. var transactions: [PaymentTransaction] { get } + /// Adds transaction observer to a payment queue. /// The transactions array will only be synchronized with the server while the queue has observers. - /// This may require that the user authenticate. + /// + /// - Note: This may require that the user authenticate. func addTransactionObserver() + + /// Removes transaction observer from a payment queue. /// The transactions array will only be synchronized with the server while the queue has observers. - /// This may require that the user authenticate. + /// + /// - Note: This may require that the user authenticate. func removeTransactionObserver() - /// Will add completed transactions for the current user back to the queue to be re-completed. - /// User will be asked to authenticate. + /// Restores completed transactions for the current user back to the queue for re-completion. + /// + /// - Note: A user will be asked to authenticate. /// /// - Parameter handler: A restore handler. func restoreCompletedTransactions(handler: @escaping RestoreHandler) - /// Add a payment to the server queue. + /// Adds a payment to the payment queue. /// /// - Parameters: - /// - payment: A payment object identifies a product and the quantity of those items the user would like to purchase. - /// - handler: A payment handler. + /// - payment: The payment object identifies a product and specifies the quantity of + /// those items the user would like to purchase. + /// - handler: The closure to be executed once the purchase is complete. func add(payment: SKPayment, handler: @escaping PaymentHandler) - /// Add handler to the payment with specific id. + /// Adds a handler to the payment queue with a specific ID. /// /// - Parameters: - /// - withProductIdentifier: Product identifier. - /// - handler: A payment handler. + /// - withProductIdentifier: The product identifier. + /// - handler: The closure to be executed once the purchase is complete. func addPaymentHandler(withProductIdentifier: String, handler: @escaping PaymentHandler) - /// Add App Store payment handler. + /// Adds an App Store payment handler to the system. func set(shouldAddStorePaymentHandler: @escaping ShouldAddStorePaymentHandler) - /// Common handler for transactions that don't have a dedicated payment handler. + /// Sets a common handler for transactions that do not have a dedicated payment handler. /// - /// - Parameter fallbackHandler: A payment handler. + /// - Parameter fallbackHandler: The closure to be executed for all payments that don't have a dedicated payment handler. func set(fallbackHandler: @escaping PaymentHandler) - /// Remove a finished (i.e. failed or completed) transaction from the queue. + /// Removes a finished (i.e. failed or completed) transaction from the queue. /// Attempting to finish a purchasing transaction will throw an exception. /// - /// - Parameter transaction: An object in the payment queue. + /// - Parameter transaction: The payment transaction. func finish(transaction: PaymentTransaction) } diff --git a/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift index e9177f7c8..77917e866 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift @@ -16,11 +16,11 @@ public typealias ReceiptRefreshHandler = (Result) -> Void public protocol IProductProvider { typealias ProductsHandler = Closure> - /// Retrieve localized information from the App Store about a specified list of products. + /// Retrieves localized information from the App Store about a specified list of products. /// /// - Parameters: - /// - productIds: The list of product identifiers for the products you wish to retrieve descriptions of. - /// - requestId: A request id. - /// - completion: A products handler. + /// - productIds: The list of product identifiers for which you wish to retrieve descriptions. + /// - requestId: The request identifier. + /// - completion: The completion containing the response of retrieving products. func fetch(productIds: Set, requestId: String, completion: @escaping ProductsHandler) } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/IReceiptRefreshRequest.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/IReceiptRefreshRequest.swift index ee7708bf7..aa0f37c5c 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/IReceiptRefreshRequest.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/IReceiptRefreshRequest.swift @@ -5,8 +5,11 @@ import Foundation +/// A type that represents a receipt refresh request. protocol IReceiptRefreshRequest { + /// The request's identifier. var id: String { get set } + /// Performs receipt refreshing logic. func start() } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/IReceiptRefreshRequestFactory.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/IReceiptRefreshRequestFactory.swift new file mode 100644 index 000000000..e64979ac3 --- /dev/null +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/IReceiptRefreshRequestFactory.swift @@ -0,0 +1,19 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import protocol StoreKit.SKRequestDelegate + +/// A type that is responsible for create a receipt request. +protocol IReceiptRefreshRequestFactory { + /// Makes a new instance of `IReceiptRefreshRequest`. + /// + /// - Parameters: + /// - id: The request's identifier. + /// - delegate: The request's delegate. + /// + /// - Returns: A request. + func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest +} diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/ReceiptRefreshRequestFactory.swift similarity index 69% rename from Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory.swift rename to Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/ReceiptRefreshRequestFactory.swift index 0180c5d90..6302dfa29 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/ReceiptRefreshRequestFactory.swift @@ -7,14 +7,6 @@ import Foundation import class StoreKit.SKReceiptRefreshRequest import protocol StoreKit.SKRequestDelegate -// MARK: - IReceiptRefreshRequestFactory - -protocol IReceiptRefreshRequestFactory { - func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest -} - -// MARK: - ReceiptRefreshRequestFactory - final class ReceiptRefreshRequestFactory: IReceiptRefreshRequestFactory { func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest { let request = SKReceiptRefreshRequest() diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift index 738a08bbb..327b91e61 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift @@ -5,19 +5,22 @@ import StoreKit +/// A type that can refresh the bundle's App Store receipt. public protocol IReceiptRefreshProvider { /// The bundle’s App Store receipt. var receipt: String? { get } - /// A request to refresh the receipt, which represents the user’s transactions with your app. + /// Refreshes the receipt, representing the user's transactions with your app. /// /// - Parameters: - /// - requestId: A request identifier. - /// - handler: A receipt refresh handler. + /// - requestId: The request identifier. + /// - handler: The closure to be executed when the refresh operation ends. func refresh(requestId: String, handler: @escaping ReceiptRefreshHandler) - /// A request to refresh the receipt, which represents the user’s transactions with your app. + /// Refreshes the receipt, representing the user's transactions with your app. /// - /// - Parameter requestId: A request identifier. + /// - Parameter requestId: The request identifier. + /// + /// - Throws: `IAPError(error:)` if the request did fail with error. func refresh(requestId: String) async throws } diff --git a/Sources/Flare/IFlare.swift b/Sources/Flare/IFlare.swift index 9f009d4c0..f3d3aea52 100644 --- a/Sources/Flare/IFlare.swift +++ b/Sources/Flare/IFlare.swift @@ -6,56 +6,73 @@ import Foundation import StoreKit +/// `Flare` creates and manages in-app purchases. public protocol IFlare { - /// Retrieve localized information from the App Store about a specified list of products. + /// Retrieves localized information from the App Store about a specified list of products. /// /// - Parameters: - /// - ids: The list of product identifiers for the products you wish to retrieve descriptions of. - /// - completion: A products handler. + /// - ids: The list of product identifiers for which you wish to retrieve descriptions. + /// - completion: The completion containing the response of retrieving products. func fetch(ids: Set, completion: @escaping Closure>) - /// Retrieve localized information from the App Store about a specified list of products. + /// Retrieves localized information from the App Store about a specified list of products. /// - /// - Parameter ids: The list of product identifiers for the products you wish to retrieve descriptions of. + /// - Parameter ids: The list of product identifiers for which you wish to retrieve descriptions. /// - /// - Returns: Products. + /// - Throws: `IAPError(error:)` if the request did fail with error. + /// + /// - Returns: An array of products. func fetch(ids: Set) async throws -> [SKProduct] - /// Perform purchase a product with given id. + /// Performs a purchase of a product with a given ID. + /// + /// - Note: The method automatically checks if the user can buy a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. /// /// - Parameters: - /// - id: A product identifier. - /// - completion: A block object to be executed when the purchase operation ends. + /// - id: The product identifier. + /// - completion: The closure to be executed once the purchase is complete. func buy(id: String, completion: @escaping Closure>) - /// Perform purchase a product with given id. + /// Purchases a product with a given ID. + /// + /// - Note: The method automatically checks if the user can buy a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameter id: The product identifier. /// - /// - Parameter id: A product identifier. + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. func buy(id: String) async throws -> PaymentTransaction - /// A request to refresh the receipt, which represents the user’s transactions with your app. + /// Refreshes the receipt, representing the user's transactions with your app. /// - /// - Parameter completion: A block object to be executed when the refresh operation ends. + /// - Parameter completion: The closure to be executed when the refresh operation ends. func receipt(completion: @escaping Closure>) - /// A request to refresh the receipt, which represents the user’s transactions with your app. + /// Refreshes the receipt, representing the user's transactions with your app. + /// + /// `IAPError(error:)` if the request did fail with error. /// /// - Returns: A receipt. func receipt() async throws -> String - /// Remove a finished (i.e. failed or completed) transaction from the queue. + /// Removes a finished (i.e. failed or completed) transaction from the queue. /// Attempting to finish a purchasing transaction will throw an exception. /// /// - Parameter transaction: An object in the payment queue. func finish(transaction: PaymentTransaction) /// The transactions array will only be synchronized with the server while the queue has observers. - /// This may require that the user authenticate + /// + /// - Note: This may require that the user authenticate. func addTransactionObserver(fallbackHandler: Closure>?) /// The transactions array will only be synchronized with the server while the queue has observers. - /// This may require that the user authenticate + /// + /// - Note: This may require that the user authenticate. func removeTransactionObserver() } From 55254c091f0e3d4a316405c01a8cc09b4c8b96bc Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Tue, 12 Sep 2023 18:37:51 +0400 Subject: [PATCH 11/44] Rewrite `async/await` blocks --- .../Providers/IAPProvider/IAPProvider.swift | 21 +++---------------- .../ReceiptRefreshProvider.swift | 7 +------ 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index 1d27a4475..1bcf7d5e8 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -44,12 +44,7 @@ final class IAPProvider: IIAPProvider { func fetch(productsIDs: Set) async throws -> [SKProduct] { try await withCheckedThrowingContinuation { continuation in self.fetch(productsIds: productsIDs) { result in - switch result { - case let .success(products): - continuation.resume(returning: products) - case let .failure(error): - continuation.resume(throwing: error) - } + continuation.resume(with: result) } } } @@ -82,12 +77,7 @@ final class IAPProvider: IIAPProvider { func purchase(productId: String) async throws -> PaymentTransaction { try await withCheckedThrowingContinuation { continuation in purchase(productId: productId) { result in - switch result { - case let .success(transaction): - continuation.resume(returning: transaction) - case let .failure(error): - continuation.resume(throwing: error) - } + continuation.resume(with: result) } } } @@ -110,12 +100,7 @@ final class IAPProvider: IIAPProvider { func refreshReceipt() async throws -> String { try await withCheckedThrowingContinuation { continuation in refreshReceipt { result in - switch result { - case let .success(receipt): - continuation.resume(returning: receipt) - case let .failure(error): - continuation.resume(throwing: error) - } + continuation.resume(with: result) } } } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift index 2f7e55bf1..bb1ab7295 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift @@ -75,12 +75,7 @@ extension ReceiptRefreshProvider: IReceiptRefreshProvider { func refresh(requestId: String) async throws { try await withCheckedThrowingContinuation { continuation in refresh(requestId: requestId) { result in - switch result { - case .success: - continuation.resume(with: .success(())) - case let .failure(error): - continuation.resume(with: .failure(error)) - } + continuation.resume(with: result) } } } From a5547da3c479eca29ec0c58df2981f1a3ff3c051 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Tue, 12 Sep 2023 18:39:13 +0400 Subject: [PATCH 12/44] Refactor test's target structure --- .../{Classes => }/Helpers/PurchaseManagerTestHelper.swift | 0 .../{Classes => }/Mocks/AppStoreReceiptProviderMock.swift | 0 Tests/FlareTests/{Classes => }/Mocks/FileManagerMock.swift | 0 Tests/FlareTests/{Classes => }/Mocks/IAPProviderMock.swift | 0 .../{Classes => }/Mocks/PaymentProviderMock.swift | 0 Tests/FlareTests/{Classes => }/Mocks/PaymentQueueMock.swift | 0 .../{Classes => }/Mocks/PaymentTransactionMock.swift | 0 Tests/FlareTests/{Classes => }/Mocks/ProductMock.swift | 0 .../{Classes => }/Mocks/ProductProviderMock.swift | 0 .../{Classes => }/Mocks/ProductResponseMock.swift | 0 .../{Classes => }/Mocks/ProductsRequestMock.swift | 0 .../{Classes => }/Mocks/ReceiptRefreshProviderMock.swift | 0 .../{Classes => }/Mocks/ReceiptRefreshRequestFactory.swift | 0 .../{Classes => }/Mocks/ReceiptRefreshRequestMock.swift | 0 .../Factories/ReceiptRefreshFactoryTests.swift | 0 Tests/FlareTests/{Classes => UnitTests}/FlareTests.swift | 6 ++++-- .../Models/PaymentTransactionTests.swift | 0 .../{Classes => UnitTests}/Providers/IAPProviderTests.swift | 0 .../Providers/PaymentProviderTests.swift | 0 .../Providers/ProductProviderTests.swift | 0 .../Providers/ReceiptRefreshProviderTests.swift | 0 21 files changed, 4 insertions(+), 2 deletions(-) rename Tests/FlareTests/{Classes => }/Helpers/PurchaseManagerTestHelper.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/AppStoreReceiptProviderMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/FileManagerMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/IAPProviderMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/PaymentProviderMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/PaymentQueueMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/PaymentTransactionMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/ProductMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/ProductProviderMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/ProductResponseMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/ProductsRequestMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/ReceiptRefreshProviderMock.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/ReceiptRefreshRequestFactory.swift (100%) rename Tests/FlareTests/{Classes => }/Mocks/ReceiptRefreshRequestMock.swift (100%) rename Tests/FlareTests/{Classes => UnitTests}/Factories/ReceiptRefreshFactoryTests.swift (100%) rename Tests/FlareTests/{Classes => UnitTests}/FlareTests.swift (98%) rename Tests/FlareTests/{Classes => UnitTests}/Models/PaymentTransactionTests.swift (100%) rename Tests/FlareTests/{Classes => UnitTests}/Providers/IAPProviderTests.swift (100%) rename Tests/FlareTests/{Classes => UnitTests}/Providers/PaymentProviderTests.swift (100%) rename Tests/FlareTests/{Classes => UnitTests}/Providers/ProductProviderTests.swift (100%) rename Tests/FlareTests/{Classes => UnitTests}/Providers/ReceiptRefreshProviderTests.swift (100%) diff --git a/Tests/FlareTests/Classes/Helpers/PurchaseManagerTestHelper.swift b/Tests/FlareTests/Helpers/PurchaseManagerTestHelper.swift similarity index 100% rename from Tests/FlareTests/Classes/Helpers/PurchaseManagerTestHelper.swift rename to Tests/FlareTests/Helpers/PurchaseManagerTestHelper.swift diff --git a/Tests/FlareTests/Classes/Mocks/AppStoreReceiptProviderMock.swift b/Tests/FlareTests/Mocks/AppStoreReceiptProviderMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/AppStoreReceiptProviderMock.swift rename to Tests/FlareTests/Mocks/AppStoreReceiptProviderMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/FileManagerMock.swift b/Tests/FlareTests/Mocks/FileManagerMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/FileManagerMock.swift rename to Tests/FlareTests/Mocks/FileManagerMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/IAPProviderMock.swift b/Tests/FlareTests/Mocks/IAPProviderMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/IAPProviderMock.swift rename to Tests/FlareTests/Mocks/IAPProviderMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/PaymentProviderMock.swift b/Tests/FlareTests/Mocks/PaymentProviderMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/PaymentProviderMock.swift rename to Tests/FlareTests/Mocks/PaymentProviderMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/PaymentQueueMock.swift b/Tests/FlareTests/Mocks/PaymentQueueMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/PaymentQueueMock.swift rename to Tests/FlareTests/Mocks/PaymentQueueMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/PaymentTransactionMock.swift b/Tests/FlareTests/Mocks/PaymentTransactionMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/PaymentTransactionMock.swift rename to Tests/FlareTests/Mocks/PaymentTransactionMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/ProductMock.swift b/Tests/FlareTests/Mocks/ProductMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/ProductMock.swift rename to Tests/FlareTests/Mocks/ProductMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/ProductProviderMock.swift b/Tests/FlareTests/Mocks/ProductProviderMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/ProductProviderMock.swift rename to Tests/FlareTests/Mocks/ProductProviderMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/ProductResponseMock.swift b/Tests/FlareTests/Mocks/ProductResponseMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/ProductResponseMock.swift rename to Tests/FlareTests/Mocks/ProductResponseMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/ProductsRequestMock.swift b/Tests/FlareTests/Mocks/ProductsRequestMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/ProductsRequestMock.swift rename to Tests/FlareTests/Mocks/ProductsRequestMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift b/Tests/FlareTests/Mocks/ReceiptRefreshProviderMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/ReceiptRefreshProviderMock.swift rename to Tests/FlareTests/Mocks/ReceiptRefreshProviderMock.swift diff --git a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestFactory.swift b/Tests/FlareTests/Mocks/ReceiptRefreshRequestFactory.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestFactory.swift rename to Tests/FlareTests/Mocks/ReceiptRefreshRequestFactory.swift diff --git a/Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestMock.swift b/Tests/FlareTests/Mocks/ReceiptRefreshRequestMock.swift similarity index 100% rename from Tests/FlareTests/Classes/Mocks/ReceiptRefreshRequestMock.swift rename to Tests/FlareTests/Mocks/ReceiptRefreshRequestMock.swift diff --git a/Tests/FlareTests/Classes/Factories/ReceiptRefreshFactoryTests.swift b/Tests/FlareTests/UnitTests/Factories/ReceiptRefreshFactoryTests.swift similarity index 100% rename from Tests/FlareTests/Classes/Factories/ReceiptRefreshFactoryTests.swift rename to Tests/FlareTests/UnitTests/Factories/ReceiptRefreshFactoryTests.swift diff --git a/Tests/FlareTests/Classes/FlareTests.swift b/Tests/FlareTests/UnitTests/FlareTests.swift similarity index 98% rename from Tests/FlareTests/Classes/FlareTests.swift rename to Tests/FlareTests/UnitTests/FlareTests.swift index b842a4b51..db17ba340 100644 --- a/Tests/FlareTests/Classes/FlareTests.swift +++ b/Tests/FlareTests/UnitTests/FlareTests.swift @@ -7,6 +7,8 @@ import StoreKit import XCTest +// MARK: - FlareTests + class FlareTests: XCTestCase { // MARK: - Properties @@ -118,7 +120,7 @@ class FlareTests: XCTestCase { // when var iapError: IAPError? do { - let _ = try await flare.buy(id: .productID) + _ = try await flare.buy(id: .productID) } catch { iapError = error as? IAPError } @@ -206,7 +208,7 @@ class FlareTests: XCTestCase { // when var iapError: IAPError? do { - let _ = try await flare.receipt() + _ = try await flare.receipt() } catch { iapError = error as? IAPError } diff --git a/Tests/FlareTests/Classes/Models/PaymentTransactionTests.swift b/Tests/FlareTests/UnitTests/Models/PaymentTransactionTests.swift similarity index 100% rename from Tests/FlareTests/Classes/Models/PaymentTransactionTests.swift rename to Tests/FlareTests/UnitTests/Models/PaymentTransactionTests.swift diff --git a/Tests/FlareTests/Classes/Providers/IAPProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift similarity index 100% rename from Tests/FlareTests/Classes/Providers/IAPProviderTests.swift rename to Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift diff --git a/Tests/FlareTests/Classes/Providers/PaymentProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/PaymentProviderTests.swift similarity index 100% rename from Tests/FlareTests/Classes/Providers/PaymentProviderTests.swift rename to Tests/FlareTests/UnitTests/Providers/PaymentProviderTests.swift diff --git a/Tests/FlareTests/Classes/Providers/ProductProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift similarity index 100% rename from Tests/FlareTests/Classes/Providers/ProductProviderTests.swift rename to Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift diff --git a/Tests/FlareTests/Classes/Providers/ReceiptRefreshProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift similarity index 100% rename from Tests/FlareTests/Classes/Providers/ReceiptRefreshProviderTests.swift rename to Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift From 57f209c0c1ce4476acc0f414bb3fbcaf9a9794eb Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 12:48:45 +0400 Subject: [PATCH 13/44] Update method names and improve the documentation --- Documentation/Resources/flare.png | Bin 0 -> 326359 bytes Documentation/Usage.md | 73 ++++++++++++++++-- .../Providers/IAPProvider/IAPProvider.swift | 20 ++--- .../Providers/IAPProvider/IIAPProvider.swift | 22 +++--- .../PaymentProvider/IPaymentProvider.swift | 4 +- .../PaymentProvider/PaymentProvider.swift | 8 +- .../ProductProvider/IProductProvider.swift | 6 +- .../ProductProvider/ProductProvider.swift | 8 +- .../IReceiptRefreshRequestFactory.swift | 4 +- .../ReceiptRefreshRequestFactory.swift | 4 +- .../IReceiptRefreshProvider.swift | 8 +- .../ReceiptRefreshProvider.swift | 10 +-- Sources/Flare/Flare.swift | 16 ++-- Sources/Flare/IFlare.swift | 21 ++--- Tests/FlareTests/Mocks/IAPProviderMock.swift | 32 ++++---- .../Mocks/PaymentProviderMock.swift | 8 +- .../Mocks/ProductProviderMock.swift | 10 +-- .../Mocks/ReceiptRefreshProviderMock.swift | 16 ++-- .../Mocks/ReceiptRefreshRequestFactory.swift | 10 +-- .../ReceiptRefreshFactoryTests.swift | 6 +- Tests/FlareTests/UnitTests/FlareTests.swift | 48 ++++++------ .../Providers/IAPProviderTests.swift | 24 +++--- .../Providers/PaymentProviderTests.swift | 24 +++--- .../Providers/ProductProviderTests.swift | 39 +++++----- .../ReceiptRefreshProviderTests.swift | 14 ++-- 25 files changed, 249 insertions(+), 186 deletions(-) create mode 100644 Documentation/Resources/flare.png diff --git a/Documentation/Resources/flare.png b/Documentation/Resources/flare.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac3514757c14ddac508e0257a9e6279be9deec4 GIT binary patch literal 326359 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

h%k0{2MA8 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 z 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≈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%0Dd^Ga%jrH-kP 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ξwl=(uIA{kHI(!- zK6EIs|4;4Vqvsy&jonMKI{>}_dg7Cm&rhL&eKU0mg8gVzncxHM)Q7Xj#>S9m=BK9{ zMLok!O8Z7$F0`c8H#W-4%06kMTT5-x8K{2dwC?$gss6F{C8O>QBSTWT!c8irQ&$f* zNJtc|JOVR#=2ghp@Xt^r&Oy&y|FksHTu1cv;Jc7)K8d?+3J1%FCUY%PplMEcjc4?wf<_>n02^y;b>P58KVS7&CQ5>b$arOz?Q|5t$(kO+54CaTVP$2SX@s?= z@@IpKX)>>)6^8OG`Df4y>eP3)9om-Id1KI}kKl@g{;1w)PyL%sw|zS&!rQgf0z5WU zbr}b3aW?g7Gm5JD&A9E=N^$VRU^Lbpj^|{ZVkHY%cg*vw=aMI*)@gp)E4`5}%itNj zYoeyGf|D>-r=_Bz0&D>-oA!>5^zn}-?HzDQLc8b`AwS)=CNKr=Hv6wU^ZnzG1*FPx zs%;E*9r^gjy~|a`zS|1C78DRjN>0|(*9U+>Ikf?E4y&pxpacOL zA>Tn@W?bie%q$Av)8*E7!35-|yZnJ@1Z_WAIl1Zx>Aj4!^F>|5XiV42zhN1>w-NSZ z(HCiC49`p3HJo*9H#}XS*xD#cX%)zAIQ>ASPQa~Q*>o3io`CqPq2b#U$26nt?j{>^ zLZ=b{*Pxk?Nax5a{nDjcHRn~Qw^n*d6%=g6vnw_lsID+vHMKJ1V~3UV9lLD{ombqh0k~JO<^6`6rSLEe#Xw8Bd znS+mU8MiJ609C<|@}@w}ffkCvK=f=oQD(*0O}Sf_b%z~Vw?mJet`15F^!K%7e=@Ko zz$Zze#H#mzG+h9, completion: @escaping Closure>) { + func fetch(productIDs: Set, completion: @escaping Closure>) { productProvider.fetch( - productIds: productsIds, - requestId: UUID().uuidString, + productIDs: productIDs, + requestID: UUID().uuidString, completion: completion ) } - func fetch(productsIDs: Set) async throws -> [SKProduct] { + func fetch(productIDs: Set) async throws -> [SKProduct] { try await withCheckedThrowingContinuation { continuation in - self.fetch(productsIds: productsIDs) { result in + self.fetch(productIDs: productIDs) { result in continuation.resume(with: result) } } } - func purchase(productId: String, completion: @escaping Closure>) { - productProvider.fetch(productIds: [productId], requestId: UUID().uuidString) { result in + func purchase(productID: String, completion: @escaping Closure>) { + productProvider.fetch(productIDs: [productID], requestID: UUID().uuidString) { result in switch result { case let .success(products): guard let product = products.first else { @@ -74,16 +74,16 @@ final class IAPProvider: IIAPProvider { } } - func purchase(productId: String) async throws -> PaymentTransaction { + func purchase(productID: String) async throws -> PaymentTransaction { try await withCheckedThrowingContinuation { continuation in - purchase(productId: productId) { result in + purchase(productID: productID) { result in continuation.resume(with: result) } } } func refreshReceipt(completion: @escaping Closure>) { - receiptRefreshProvider.refresh(requestId: UUID().uuidString) { [weak self] result in + receiptRefreshProvider.refresh(requestID: UUID().uuidString) { [weak self] result in switch result { case .success: if let receipt = self?.receiptRefreshProvider.receipt { diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift index f2d813f92..c4e88043b 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift @@ -13,42 +13,42 @@ public protocol IIAPProvider { /// Retrieves localized information from the App Store about a specified list of products. /// /// - Parameters: - /// - ids: The list of product identifiers for which you wish to retrieve descriptions. + /// - productIDs: The list of product identifiers for which you wish to retrieve descriptions. /// - completion: The completion containing the response of retrieving products. - func fetch(productsIds: Set, completion: @escaping Closure>) + func fetch(productIDs: Set, completion: @escaping Closure>) /// Retrieves localized information from the App Store about a specified list of products. /// - /// - Parameter ids: The list of product identifiers for which you wish to retrieve descriptions. + /// - Parameter productIDs: The list of product identifiers for which you wish to retrieve descriptions. /// /// - Throws: `IAPError(error:)` if the request did fail with error. /// /// - Returns: An array of products. - func fetch(productsIDs: Set) async throws -> [SKProduct] + func fetch(productIDs: Set) async throws -> [SKProduct] /// Performs a purchase of a product with a given ID. /// - /// - Note: The method automatically checks if the user can buy a product. + /// - Note: The method automatically checks if the user can purchase a product. /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// /// - Parameters: - /// - id: The product identifier. + /// - productID: The product identifier. /// - completion: The closure to be executed once the purchase is complete. - func purchase(productId: String, completion: @escaping Closure>) + func purchase(productID: String, completion: @escaping Closure>) /// Purchases a product with a given ID. /// - /// - Note: The method automatically checks if the user can buy a product. + /// - Note: The method automatically checks if the user can purchase a product. /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// - /// - Parameter id: The product identifier. + /// - Parameter productID: The product identifier. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. - func purchase(productId: String) async throws -> PaymentTransaction + func purchase(productID: String) async throws -> PaymentTransaction /// Refreshes the receipt, representing the user's transactions with your app. /// @@ -68,11 +68,13 @@ public protocol IIAPProvider { /// - Parameter transaction: An object in the payment queue. func finish(transaction: PaymentTransaction) + /// Adds transaction observer to the payment queue. /// The transactions array will only be synchronized with the server while the queue has observers. /// /// - Note: This may require that the user authenticate. func addTransactionObserver(fallbackHandler: Closure>?) + /// Removes transaction observer from the payment queue. /// The transactions array will only be synchronized with the server while the queue has observers. /// /// - Note: This may require that the user authenticate. diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift index 468260459..2d511767d 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift @@ -43,9 +43,9 @@ public protocol IPaymentProvider: AnyObject { /// Adds a handler to the payment queue with a specific ID. /// /// - Parameters: - /// - withProductIdentifier: The product identifier. + /// - productID: The product identifier. /// - handler: The closure to be executed once the purchase is complete. - func addPaymentHandler(withProductIdentifier: String, handler: @escaping PaymentHandler) + func addPaymentHandler(productID: String, handler: @escaping PaymentHandler) /// Adds an App Store payment handler to the system. func set(shouldAddStorePaymentHandler: @escaping ShouldAddStorePaymentHandler) diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift index 4679e52d8..aacf89156 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift @@ -47,17 +47,17 @@ extension PaymentProvider: IPaymentProvider { } func add(payment: SKPayment, handler: @escaping PaymentHandler) { - addPaymentHandler(withProductIdentifier: payment.productIdentifier, handler: handler) + addPaymentHandler(productID: payment.productIdentifier, handler: handler) dispatchQueueFactory.main().async { self.paymentQueue.add(payment) } } - func addPaymentHandler(withProductIdentifier productIdentifier: String, handler: @escaping PaymentHandler) { + func addPaymentHandler(productID: String, handler: @escaping PaymentHandler) { privateQueue.async { - var handlers: [PaymentHandler] = self.paymentHandlers[productIdentifier] ?? [] + var handlers: [PaymentHandler] = self.paymentHandlers[productID] ?? [] handlers.append(handler) - self.paymentHandlers[productIdentifier] = handlers + self.paymentHandlers[productID] = handlers } } diff --git a/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift index 77917e866..f9e5376ba 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift @@ -19,8 +19,8 @@ public protocol IProductProvider { /// Retrieves localized information from the App Store about a specified list of products. /// /// - Parameters: - /// - productIds: The list of product identifiers for which you wish to retrieve descriptions. - /// - requestId: The request identifier. + /// - productIDs: The list of product identifiers for which you wish to retrieve descriptions. + /// - requestID: The request identifier. /// - completion: The completion containing the response of retrieving products. - func fetch(productIds: Set, requestId: String, completion: @escaping ProductsHandler) + func fetch(productIDs: Set, requestID: String, completion: @escaping ProductsHandler) } diff --git a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift index 104fddd44..c9f3dc6b1 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift @@ -17,8 +17,8 @@ final class ProductProvider: NSObject, IProductProvider { // MARK: Internal - func fetch(productIds ids: Set, requestId: String, completion: @escaping ProductsHandler) { - let request = makeRequest(ids: ids, requestId: requestId) + func fetch(productIDs ids: Set, requestID: String, completion: @escaping ProductsHandler) { + let request = makeRequest(ids: ids, requestID: requestID) fetch(request: request, completion: completion) } @@ -29,9 +29,9 @@ final class ProductProvider: NSObject, IProductProvider { private lazy var dispatchQueue: IDispatchQueue = dispatchQueueFactory.privateQueue(label: String(describing: self)) - private func makeRequest(ids: Set, requestId: String) -> SKProductsRequest { + private func makeRequest(ids: Set, requestID: String) -> SKProductsRequest { let request = SKProductsRequest(productIdentifiers: ids) - request.id = requestId + request.id = requestID request.delegate = self return request } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/IReceiptRefreshRequestFactory.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/IReceiptRefreshRequestFactory.swift index e64979ac3..1446ff301 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/IReceiptRefreshRequestFactory.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/IReceiptRefreshRequestFactory.swift @@ -11,9 +11,9 @@ protocol IReceiptRefreshRequestFactory { /// Makes a new instance of `IReceiptRefreshRequest`. /// /// - Parameters: - /// - id: The request's identifier. + /// - requestID: The request's identifier. /// - delegate: The request's delegate. /// /// - Returns: A request. - func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest + func make(requestID: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/ReceiptRefreshRequestFactory.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/ReceiptRefreshRequestFactory.swift index 6302dfa29..1dc2d38ff 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/ReceiptRefreshRequestFactory.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/Factories/ReceiptRefreshRequestFactory/ReceiptRefreshRequestFactory.swift @@ -8,9 +8,9 @@ import class StoreKit.SKReceiptRefreshRequest import protocol StoreKit.SKRequestDelegate final class ReceiptRefreshRequestFactory: IReceiptRefreshRequestFactory { - func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest { + func make(requestID: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest { let request = SKReceiptRefreshRequest() - request.id = id + request.id = requestID request.delegate = delegate return request } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift index 327b91e61..44c9c1c9a 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift @@ -13,14 +13,14 @@ public protocol IReceiptRefreshProvider { /// Refreshes the receipt, representing the user's transactions with your app. /// /// - Parameters: - /// - requestId: The request identifier. + /// - requestID: The request identifier. /// - handler: The closure to be executed when the refresh operation ends. - func refresh(requestId: String, handler: @escaping ReceiptRefreshHandler) + func refresh(requestID: String, handler: @escaping ReceiptRefreshHandler) /// Refreshes the receipt, representing the user's transactions with your app. /// - /// - Parameter requestId: The request identifier. + /// - Parameter requestID: The request identifier. /// /// - Throws: `IAPError(error:)` if the request did fail with error. - func refresh(requestId: String) async throws + func refresh(requestID: String) async throws } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift index bb1ab7295..fcfdc6fd0 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift @@ -51,7 +51,7 @@ final class ReceiptRefreshProvider: NSObject { // MARK: Private private func makeRequest(id: String) -> IReceiptRefreshRequest { - receiptRefreshRequestFactory.make(id: id, delegate: self) + receiptRefreshRequestFactory.make(requestID: id, delegate: self) } private func fetch(request: IReceiptRefreshRequest, handler: @escaping ReceiptRefreshHandler) { @@ -67,14 +67,14 @@ final class ReceiptRefreshProvider: NSObject { // MARK: IReceiptRefreshProvider extension ReceiptRefreshProvider: IReceiptRefreshProvider { - func refresh(requestId: String, handler: @escaping ReceiptRefreshHandler) { - let request = makeRequest(id: requestId) + func refresh(requestID: String, handler: @escaping ReceiptRefreshHandler) { + let request = makeRequest(id: requestID) fetch(request: request, handler: handler) } - func refresh(requestId: String) async throws { + func refresh(requestID: String) async throws { try await withCheckedThrowingContinuation { continuation in - refresh(requestId: requestId) { result in + refresh(requestID: requestID) { result in continuation.resume(with: result) } } diff --git a/Sources/Flare/Flare.swift b/Sources/Flare/Flare.swift index 6f804bc29..e733b19e5 100644 --- a/Sources/Flare/Flare.swift +++ b/Sources/Flare/Flare.swift @@ -26,21 +26,21 @@ public final class Flare { // MARK: IFlare extension Flare: IFlare { - public func fetch(ids: Set, completion: @escaping Closure>) { - iapProvider.fetch(productsIds: ids, completion: completion) + public func fetch(productIDs: Set, completion: @escaping Closure>) { + iapProvider.fetch(productIDs: productIDs, completion: completion) } - public func fetch(ids: Set) async throws -> [SKProduct] { - try await iapProvider.fetch(productsIDs: ids) + public func fetch(productIDs: Set) async throws -> [SKProduct] { + try await iapProvider.fetch(productIDs: productIDs) } - public func buy(id: String, completion: @escaping Closure>) { + public func purchase(productID: String, completion: @escaping Closure>) { guard iapProvider.canMakePayments else { completion(.failure(.paymentNotAllowed)) return } - iapProvider.purchase(productId: id) { result in + iapProvider.purchase(productID: productID) { result in switch result { case let .success(transaction): completion(.success(transaction)) @@ -50,9 +50,9 @@ extension Flare: IFlare { } } - public func buy(id: String) async throws -> PaymentTransaction { + public func purchase(productID: String) async throws -> PaymentTransaction { guard iapProvider.canMakePayments else { throw IAPError.paymentNotAllowed } - return try await iapProvider.purchase(productId: id) + return try await iapProvider.purchase(productID: productID) } public func receipt(completion: @escaping Closure>) { diff --git a/Sources/Flare/IFlare.swift b/Sources/Flare/IFlare.swift index f3d3aea52..36676fa09 100644 --- a/Sources/Flare/IFlare.swift +++ b/Sources/Flare/IFlare.swift @@ -11,42 +11,42 @@ public protocol IFlare { /// Retrieves localized information from the App Store about a specified list of products. /// /// - Parameters: - /// - ids: The list of product identifiers for which you wish to retrieve descriptions. + /// - productIDs: The list of product identifiers for which you wish to retrieve descriptions. /// - completion: The completion containing the response of retrieving products. - func fetch(ids: Set, completion: @escaping Closure>) + func fetch(productIDs: Set, completion: @escaping Closure>) /// Retrieves localized information from the App Store about a specified list of products. /// - /// - Parameter ids: The list of product identifiers for which you wish to retrieve descriptions. + /// - Parameter productIDs: The list of product identifiers for which you wish to retrieve descriptions. /// /// - Throws: `IAPError(error:)` if the request did fail with error. /// /// - Returns: An array of products. - func fetch(ids: Set) async throws -> [SKProduct] + func fetch(productIDs: Set) async throws -> [SKProduct] /// Performs a purchase of a product with a given ID. /// - /// - Note: The method automatically checks if the user can buy a product. + /// - Note: The method automatically checks if the user can purchase a product. /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// /// - Parameters: - /// - id: The product identifier. + /// - productID: The product identifier. /// - completion: The closure to be executed once the purchase is complete. - func buy(id: String, completion: @escaping Closure>) + func purchase(productID: String, completion: @escaping Closure>) /// Purchases a product with a given ID. /// - /// - Note: The method automatically checks if the user can buy a product. + /// - Note: The method automatically checks if the user can purchase a product. /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// - /// - Parameter id: The product identifier. + /// - Parameter productID: The product identifier. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. - func buy(id: String) async throws -> PaymentTransaction + func purchase(productID: String) async throws -> PaymentTransaction /// Refreshes the receipt, representing the user's transactions with your app. /// @@ -71,6 +71,7 @@ public protocol IFlare { /// - Note: This may require that the user authenticate. func addTransactionObserver(fallbackHandler: Closure>?) + /// Removes transaction observer from the payment queue. /// The transactions array will only be synchronized with the server while the queue has observers. /// /// - Note: This may require that the user authenticate. diff --git a/Tests/FlareTests/Mocks/IAPProviderMock.swift b/Tests/FlareTests/Mocks/IAPProviderMock.swift index 070670715..58cda64e8 100644 --- a/Tests/FlareTests/Mocks/IAPProviderMock.swift +++ b/Tests/FlareTests/Mocks/IAPProviderMock.swift @@ -19,26 +19,26 @@ final class IAPProviderMock: IIAPProvider { var invokedFetch = false var invokedFetchCount = 0 - var invokedFetchParameters: (productsIds: Set, completion: Closure>)? - var invokedFetchParametersList = [(productsIds: Set, completion: Closure>)]() + var invokedFetchParameters: (productIDs: Set, completion: Closure>)? + var invokedFetchParametersList = [(productIDs: Set, completion: Closure>)]() - func fetch(productsIds: Set, completion: @escaping Closure>) { + func fetch(productIDs: Set, completion: @escaping Closure>) { invokedFetch = true invokedFetchCount += 1 - invokedFetchParameters = (productsIds, completion) - invokedFetchParametersList.append((productsIds, completion)) + invokedFetchParameters = (productIDs, completion) + invokedFetchParametersList.append((productIDs, completion)) } var invokedPurchase = false var invokedPurchaseCount = 0 - var invokedPurchaseParameters: (productId: String, completion: Closure>)? - var invokedPurchaseParametersList = [(productId: String, completion: Closure>)]() + var invokedPurchaseParameters: (productID: String, completion: Closure>)? + var invokedPurchaseParametersList = [(productID: String, completion: Closure>)]() - func purchase(productId: String, completion: @escaping Closure>) { + func purchase(productID: String, completion: @escaping Closure>) { invokedPurchase = true invokedPurchaseCount += 1 - invokedPurchaseParameters = (productId, completion) - invokedPurchaseParametersList.append((productId, completion)) + invokedPurchaseParameters = (productID, completion) + invokedPurchaseParametersList.append((productID, completion)) } var invokedRefreshReceipt = false @@ -96,11 +96,11 @@ final class IAPProviderMock: IIAPProvider { var invokedFetchAsyncParametersList = [(productIDs: Set, Void)]() var fetchAsyncResult: [SKProduct] = [] - func fetch(productsIDs: Set) async throws -> [SKProduct] { + func fetch(productIDs: Set) async throws -> [SKProduct] { invokedFetchAsync = true invokedFetchAsyncCount += 1 - invokedFetchAsyncParameters = (productsIDs, ()) - invokedFetchAsyncParametersList.append((productsIDs, ())) + invokedFetchAsyncParameters = (productIDs, ()) + invokedFetchAsyncParametersList.append((productIDs, ())) return fetchAsyncResult } @@ -110,11 +110,11 @@ final class IAPProviderMock: IIAPProvider { var invokedAsyncPurchaseParametersList = [(productID: String, Void)?]() var stubbedAsyncPurchase: PaymentTransaction! - func purchase(productId: String) async throws -> PaymentTransaction { + func purchase(productID: String) async throws -> PaymentTransaction { invokedAsyncPurchase = true invokedAsyncPurchaseCount += 1 - invokedAsyncPurchaseParameters = (productId, ()) - invokedAsyncPurchaseParametersList.append((productId, ())) + invokedAsyncPurchaseParameters = (productID, ()) + invokedAsyncPurchaseParametersList.append((productID, ())) return stubbedAsyncPurchase } diff --git a/Tests/FlareTests/Mocks/PaymentProviderMock.swift b/Tests/FlareTests/Mocks/PaymentProviderMock.swift index 5025e5170..902f19210 100644 --- a/Tests/FlareTests/Mocks/PaymentProviderMock.swift +++ b/Tests/FlareTests/Mocks/PaymentProviderMock.swift @@ -74,14 +74,14 @@ final class PaymentProviderMock: IPaymentProvider { var invokedAddPaymentHandler = false var invokedAddPaymentHandlerCount = 0 - var invokedAddPaymentHandlerParameters: (productIdentifier: String, handler: PaymentHandler)? + var invokedAddPaymentHandlerParameters: (productID: String, handler: PaymentHandler)? var invokedAddPaymentHandlerParametersList = [(productIdentifier: String, handler: PaymentHandler)]() - func addPaymentHandler(withProductIdentifier: String, handler: @escaping PaymentHandler) { + func addPaymentHandler(productID: String, handler: @escaping PaymentHandler) { invokedAddPaymentHandler = true invokedAddPaymentHandlerCount += 1 - invokedAddPaymentHandlerParameters = (withProductIdentifier, handler) - invokedAddPaymentHandlerParametersList.append((withProductIdentifier, handler)) + invokedAddPaymentHandlerParameters = (productID, handler) + invokedAddPaymentHandlerParametersList.append((productID, handler)) } var invokedSetAddStorePaymentHandler = false diff --git a/Tests/FlareTests/Mocks/ProductProviderMock.swift b/Tests/FlareTests/Mocks/ProductProviderMock.swift index c3b2ccc7c..5480426d4 100644 --- a/Tests/FlareTests/Mocks/ProductProviderMock.swift +++ b/Tests/FlareTests/Mocks/ProductProviderMock.swift @@ -9,15 +9,15 @@ import class StoreKit.SKProduct final class ProductProviderMock: IProductProvider { var invokedFetch = false var invokedFetchCount = 0 - var invokedFetchParameters: (productIds: Set, requestId: String, completion: ProductsHandler)? - var invokedFetchParamtersList = [(productIds: Set, requestId: String, completion: ProductsHandler)]() + var invokedFetchParameters: (productIDs: Set, requestID: String, completion: ProductsHandler)? + var invokedFetchParamtersList = [(productIDs: Set, requestID: String, completion: ProductsHandler)]() var stubbedFetchResult: Result<[SKProduct], IAPError>? - func fetch(productIds: Set, requestId: String, completion: @escaping ProductsHandler) { + func fetch(productIDs: Set, requestID: String, completion: @escaping ProductsHandler) { invokedFetch = true invokedFetchCount += 1 - invokedFetchParameters = (productIds, requestId, completion) - invokedFetchParamtersList.append((productIds, requestId, completion)) + invokedFetchParameters = (productIDs, requestID, completion) + invokedFetchParamtersList.append((productIDs, requestID, completion)) if let result = stubbedFetchResult { completion(result) diff --git a/Tests/FlareTests/Mocks/ReceiptRefreshProviderMock.swift b/Tests/FlareTests/Mocks/ReceiptRefreshProviderMock.swift index d90321e02..bfcdc3ba4 100644 --- a/Tests/FlareTests/Mocks/ReceiptRefreshProviderMock.swift +++ b/Tests/FlareTests/Mocks/ReceiptRefreshProviderMock.swift @@ -18,15 +18,15 @@ final class ReceiptRefreshProviderMock: IReceiptRefreshProvider { var invokedRefresh = false var invokedRefreshCount = 0 - var invokedRefreshParameters: (requestId: String, handler: ReceiptRefreshHandler)? - var invokedRefreshParametersList = [(requestId: String, handler: ReceiptRefreshHandler)]() + var invokedRefreshParameters: (requestID: String, handler: ReceiptRefreshHandler)? + var invokedRefreshParametersList = [(requestID: String, handler: ReceiptRefreshHandler)]() var stubbedRefreshResult: Result? - func refresh(requestId: String, handler: @escaping ReceiptRefreshHandler) { + func refresh(requestID: String, handler: @escaping ReceiptRefreshHandler) { invokedRefresh = true invokedRefreshCount += 1 - invokedRefreshParameters = (requestId, handler) - invokedRefreshParametersList.append((requestId, handler)) + invokedRefreshParameters = (requestID, handler) + invokedRefreshParametersList.append((requestID, handler)) if let result = stubbedRefreshResult { handler(result) @@ -38,10 +38,10 @@ final class ReceiptRefreshProviderMock: IReceiptRefreshProvider { var invokedAsyncRefreshParameters: (requestID: String, Void)? var invokedAsyncRefreshParametersList = [(requestID: String, Void)]() - func refresh(requestId: String) async throws { + func refresh(requestID: String) async throws { invokedAsyncRefresh = true invokedAsyncRefreshCount += 1 - invokedAsyncRefreshParameters = (requestId, ()) - invokedAsyncRefreshParametersList.append((requestId, ())) + invokedAsyncRefreshParameters = (requestID, ()) + invokedAsyncRefreshParametersList.append((requestID, ())) } } diff --git a/Tests/FlareTests/Mocks/ReceiptRefreshRequestFactory.swift b/Tests/FlareTests/Mocks/ReceiptRefreshRequestFactory.swift index 98ba935fb..256400c75 100644 --- a/Tests/FlareTests/Mocks/ReceiptRefreshRequestFactory.swift +++ b/Tests/FlareTests/Mocks/ReceiptRefreshRequestFactory.swift @@ -10,15 +10,15 @@ import protocol StoreKit.SKRequestDelegate final class ReceiptRefreshRequestFactoryMock: IReceiptRefreshRequestFactory { var invokedMake = false var invokedMakeCount = 0 - var invokedMakeParameters: (id: String, delegate: SKRequestDelegate?)? - var invokedMakeParametersList = [(id: String, delegate: SKRequestDelegate?)]() + var invokedMakeParameters: (requestID: String, delegate: SKRequestDelegate?)? + var invokedMakeParametersList = [(requestID: String, delegate: SKRequestDelegate?)]() var stubbedMakeResult: IReceiptRefreshRequest! - func make(id: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest { + func make(requestID: String, delegate: SKRequestDelegate?) -> IReceiptRefreshRequest { invokedMake = true invokedMakeCount += 1 - invokedMakeParameters = (id, delegate) - invokedMakeParametersList.append((id, delegate)) + invokedMakeParameters = (requestID, delegate) + invokedMakeParametersList.append((requestID, delegate)) return stubbedMakeResult } } diff --git a/Tests/FlareTests/UnitTests/Factories/ReceiptRefreshFactoryTests.swift b/Tests/FlareTests/UnitTests/Factories/ReceiptRefreshFactoryTests.swift index 785c1cd25..96fd2c3da 100644 --- a/Tests/FlareTests/UnitTests/Factories/ReceiptRefreshFactoryTests.swift +++ b/Tests/FlareTests/UnitTests/Factories/ReceiptRefreshFactoryTests.swift @@ -28,15 +28,15 @@ final class IReceiptRefreshRequestFactoryTests: XCTestCase { func test_thatFactoryMakesReceipt() { // when - let receipt = factory.make(id: .productID, delegate: nil) + let receipt = factory.make(requestID: .requestID, delegate: nil) // then - XCTAssertEqual(receipt.id, .productID) + XCTAssertEqual(receipt.id, .requestID) } } // MARK: - Constants private extension String { - static let productID = "product_id" + static let requestID = "request_id" } diff --git a/Tests/FlareTests/UnitTests/FlareTests.swift b/Tests/FlareTests/UnitTests/FlareTests.swift index db17ba340..73842ac65 100644 --- a/Tests/FlareTests/UnitTests/FlareTests.swift +++ b/Tests/FlareTests/UnitTests/FlareTests.swift @@ -31,57 +31,57 @@ class FlareTests: XCTestCase { // MARK: - Tests - func test_thatPurchaseManagerFetchesProducts() { + func test_thatFlareFetchesProductsWithGivenProductIDs() { // when - flare.fetch(ids: .ids, completion: { _ in }) + flare.fetch(productIDs: .ids, completion: { _ in }) // then XCTAssertTrue(iapProviderMock.invokedFetch) } - func test_thatPurchaseManagerFetchesProductsAsync() async throws { + func test_thatFlareFetchesProductsWithGivenProductIDs() async throws { // given let productMocks = [ProductMock(), ProductMock(), ProductMock()] iapProviderMock.fetchAsyncResult = productMocks // when - let products = try await flare.fetch(ids: .ids) + let products = try await flare.fetch(productIDs: .ids) // then XCTAssertEqual(products, productMocks) } - func test_thatPurchaseManagerBuysProduct_whenCanMakePayments() { + func test_thatFlarePurchasesAProduct_whenUserCanMakePayments() { // given iapProviderMock.stubbedCanMakePayments = true // when - flare.buy(id: .productID, completion: { _ in }) + flare.purchase(productID: .productID, completion: { _ in }) // then XCTAssertTrue(iapProviderMock.invokedPurchase) - XCTAssertEqual(iapProviderMock.invokedPurchaseParameters?.productId, .productID) + XCTAssertEqual(iapProviderMock.invokedPurchaseParameters?.productID, .productID) } - func test_thatPurchaseManagerDoesNotBuyProduct_whenCannotMakePayments() { + func test_thatFlareDoesNotAPurchaseProduct_whenUserCannotMakePayments() { // given iapProviderMock.stubbedCanMakePayments = false // when - flare.buy(id: .productID, completion: { _ in }) + flare.purchase(productID: .productID, completion: { _ in }) // then XCTAssertFalse(iapProviderMock.invokedPurchase) } - func test_thatPurchaseManagersBuysProduct_whenCanMakePaymentsSuccess() { + func test_thatFlarePurchasesAProduct_whenRequestCompletedSuccessfully() { // given let paymentTransaction = PaymentTransaction(PaymentTransactionMock()) iapProviderMock.stubbedCanMakePayments = true // when var transaction: PaymentTransaction? - flare.buy(id: .productID, completion: { result in + flare.purchase(productID: .productID, completion: { result in if case let .success(result) = result { transaction = result } @@ -93,14 +93,14 @@ class FlareTests: XCTestCase { XCTAssertEqual(transaction, paymentTransaction) } - func test_thatPurchaseManagersBuysProduct_whenCanMakePaymentsFailed() { + func test_thatFlareDoesNotPurchaseAProduct_whenUnknownErrorOccurred() { // given let errorMock = IAPError.paymentNotAllowed iapProviderMock.stubbedCanMakePayments = true // when var error: IAPError? - flare.buy(id: .productID, completion: { result in + flare.purchase(productID: .productID, completion: { result in if case let .failure(result) = result { error = result } @@ -112,7 +112,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(error, errorMock) } - func test_thatPurchaseManagerDoesNotBuyProductAsync_whenCannotMakePayments() async { + func test_thatFlareDoesNotAPurchaseProduct_whenUserCannotMakePayments() async { // given iapProviderMock.stubbedCanMakePayments = false iapProviderMock.stubbedAsyncPurchase = PaymentTransaction(PaymentTransactionMock()) @@ -120,7 +120,7 @@ class FlareTests: XCTestCase { // when var iapError: IAPError? do { - _ = try await flare.buy(id: .productID) + _ = try await flare.purchase(productID: .productID) } catch { iapError = error as? IAPError } @@ -130,7 +130,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(iapError, .paymentNotAllowed) } - func test_thatPurchaseManagerBuysProduct_whenCannotMakePayments() async { + func test_thatFlareDoesNotPurchaseAProduct_whenUnknownErrorOccurred() async { // given let transactionMock = PaymentTransaction(PaymentTransactionMock()) @@ -141,7 +141,7 @@ class FlareTests: XCTestCase { var transaction: PaymentTransaction? var iapError: IAPError? do { - transaction = try await flare.buy(id: .productID) + transaction = try await flare.purchase(productID: .productID) } catch { iapError = error as? IAPError } @@ -152,7 +152,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(transaction, transactionMock) } - func test_thatPurchaseManagerFetchReceipt_whenRequestCompleted() { + func test_thatFlareFetchesReceipt_whenRequestCompletedSuccessfully() { // when var receipt: String? flare.receipt(completion: { result in @@ -167,7 +167,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(receipt, .receipt) } - func test_thatPurchaseManagerFetchReceipt_whenRequestFailed() { + func test_thatFlareDoesNotFetchReceipt_whenRequestFailed() { // when var error: IAPError? flare.receipt(completion: { result in @@ -182,7 +182,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(error, .paymentNotAllowed) } - func test_thatPurchaseManagerRemovesTransactionObserver() { + func test_thatFlareRemovesTransactionObserver() { // when flare.removeTransactionObserver() @@ -190,7 +190,7 @@ class FlareTests: XCTestCase { XCTAssertTrue(iapProviderMock.invokedRemoveTransactionObserver) } - func test_thatPurchaseManagerFetchReceiptAsync_whenRequestCompleted() async throws { + func test_thatFlareFetchesReceipt_whenRequestCompletedSuccessfully() async throws { // given iapProviderMock.stubbedRefreshReceiptAsyncResult = .success(.receipt) @@ -201,7 +201,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(receipt, .receipt) } - func test_thatPurchaseManagerFetchesReceiptAsync_whenRequestFailed() async throws { + func test_thatFlareDoesNotFetchReceipt_whenRequestFailed() async throws { // given iapProviderMock.stubbedRefreshReceiptAsyncResult = .failure(.paymentNotAllowed) @@ -217,7 +217,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(iapError, .paymentNotAllowed) } - func test_thatPurchaseManagerFinishesTransaction() { + func test_thatFlareFinishesTransaction() { // given let transaction = PaymentTransaction(PaymentTransactionMock()) @@ -228,7 +228,7 @@ class FlareTests: XCTestCase { XCTAssertTrue(iapProviderMock.invokedFinishTransaction) } - func test_thatPurchaseManagerAddsTransactionObserver() { + func test_thatFlareAddsTransactionObserver() { // when flare.addTransactionObserver(fallbackHandler: { _ in }) diff --git a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift index cca833f6f..b97b668fb 100644 --- a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift @@ -55,17 +55,17 @@ class IAPProviderTests: XCTestCase { func test_thatIAPProviderFetchesProducts() throws { // when - iapProvider.fetch(productsIds: .productIDs, completion: { _ in }) + iapProvider.fetch(productIDs: .productIDs, completion: { _ in }) // then let parameters = try XCTUnwrap(productProviderMock.invokedFetchParameters) - XCTAssertEqual(parameters.productIds, .productIDs) - XCTAssertTrue(!parameters.requestId.isEmpty) + XCTAssertEqual(parameters.productIDs, .productIDs) + XCTAssertTrue(!parameters.requestID.isEmpty) } func test_thatIAPProviderPurchasesProduct() throws { // when - iapProvider.purchase(productId: .productID, completion: { _ in }) + iapProvider.purchase(productID: .productID, completion: { _ in }) // then XCTAssertTrue(productProviderMock.invokedFetch) @@ -113,7 +113,7 @@ class IAPProviderTests: XCTestCase { productProviderMock.stubbedFetchResult = .success(productsMock) // when - let products = try await iapProvider.fetch(productsIDs: .productIDs) + let products = try await iapProvider.fetch(productIDs: .productIDs) // then XCTAssertEqual(productsMock, products) @@ -126,7 +126,7 @@ class IAPProviderTests: XCTestCase { // when var errorResult: Error? do { - _ = try await iapProvider.fetch(productsIDs: .productIDs) + _ = try await iapProvider.fetch(productIDs: .productIDs) } catch { errorResult = error } @@ -141,7 +141,7 @@ class IAPProviderTests: XCTestCase { // when var error: Error? - iapProvider.purchase(productId: .productID) { result in + iapProvider.purchase(productID: .productID) { result in if case let .failure(result) = result { error = result } @@ -159,7 +159,7 @@ class IAPProviderTests: XCTestCase { // when var transactionResult: PaymentTransaction? - iapProvider.purchase(productId: .productID) { result in + iapProvider.purchase(productID: .productID) { result in if case let .success(transaction) = result { transactionResult = transaction } @@ -176,7 +176,7 @@ class IAPProviderTests: XCTestCase { // when var errorResult: Error? - iapProvider.purchase(productId: .productID) { result in + iapProvider.purchase(productID: .productID) { result in if case let .failure(error) = result { errorResult = error } @@ -192,7 +192,7 @@ class IAPProviderTests: XCTestCase { // when var errorResult: Error? - iapProvider.purchase(productId: .productID) { result in + iapProvider.purchase(productID: .productID) { result in if case let .failure(error) = result { errorResult = error } @@ -209,7 +209,7 @@ class IAPProviderTests: XCTestCase { // when var errorResult: Error? do { - _ = try await iapProvider.purchase(productId: .productID) + _ = try await iapProvider.purchase(productID: .productID) } catch { errorResult = error } @@ -225,7 +225,7 @@ class IAPProviderTests: XCTestCase { paymentProviderMock.stubbedAddResult = (paymentQueueMock, .success(transactionMock)) // when - let transactionResult = try await iapProvider.purchase(productId: .productID) + let transactionResult = try await iapProvider.purchase(productID: .productID) // then XCTAssertEqual(transactionMock, transactionResult.skTransaction) diff --git a/Tests/FlareTests/UnitTests/Providers/PaymentProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/PaymentProviderTests.swift index d8781cc83..31b765823 100644 --- a/Tests/FlareTests/UnitTests/Providers/PaymentProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/PaymentProviderTests.swift @@ -49,7 +49,7 @@ class PaymentProviderTests: XCTestCase { // MARK: - Tests - func testThatPaymentProviderCanMakePayments() { + func test_thatPaymentProviderCanMakePayments() { // given paymentQueueMock.stubbedCanMakePayments = true @@ -57,7 +57,7 @@ class PaymentProviderTests: XCTestCase { XCTAssertTrue(paymentProvider.canMakePayments) } - func testThatPaymentProviderAddTransactionObserver() throws { + func test_thatPaymentProviderAddsTransactionObserver() throws { // when paymentProvider.addTransactionObserver() @@ -66,7 +66,7 @@ class PaymentProviderTests: XCTestCase { XCTAssertTrue(observer.0 === paymentProvider) } - func testThatPaymentProviderRemoveTransactionObserver() throws { + func test_thatPaymentProviderRemovesTransactionObserver() throws { // given paymentProvider.addTransactionObserver() @@ -80,7 +80,7 @@ class PaymentProviderTests: XCTestCase { XCTAssertTrue(observer.0 === paymentProvider) } - func testThatPaymentProviderRestoreCompletedTransactions() { + func test_thatPaymentProviderRestoresCompletedTransactions() { // given let restoreHandler: RestoreHandler = { _, _ in } @@ -92,7 +92,7 @@ class PaymentProviderTests: XCTestCase { XCTAssertEqual(paymentQueueMock.invokedRestoreCompletedTransactionsCount, 1) } - func testThatPaymentProviderAddPaymentToQueueWithTransactions() { + func test_thatPaymentProviderAddsPaymentToQueueWithTransactions() { // given var handledPaymentQueue: PaymentQueue? let product = SKProduct() @@ -111,7 +111,7 @@ class PaymentProviderTests: XCTestCase { XCTAssertTrue(handledPaymentQueue === paymentQueue) } - func testThatPaymentProviderAddPaymentToQueueWithoutTransactions() { + func test_thatPaymentProviderAddsPaymentToQueueWithoutTransactions() { // given var handledPaymentQueue: PaymentQueue? let product = SKProduct() @@ -129,7 +129,7 @@ class PaymentProviderTests: XCTestCase { XCTAssertNil(handledPaymentQueue) } - func testThatPaymentProviderAddPaymentHandler() { + func test_thatPaymentProviderAddsPaymentHandler() { // given var handledPaymentQueue: PaymentQueue? let paymentQueue = SKPaymentQueue() @@ -138,14 +138,14 @@ class PaymentProviderTests: XCTestCase { .map { PurchaseManagerTestHelper.makePaymentTransaction(identifier: .productId, state: $0) } // when - paymentProvider.addPaymentHandler(withProductIdentifier: .productId, handler: paymentHandler) + paymentProvider.addPaymentHandler(productID: .productId, handler: paymentHandler) paymentProvider.paymentQueue(paymentQueue, updatedTransactions: paymentTransactions) // then XCTAssertTrue(handledPaymentQueue === paymentQueue) } - func testThatPaymentProviderCallFinishTransaction() { + func test_thatPaymentProviderCallsFinishTransaction() { // given let transactions = transactionsStates.map { PurchaseManagerTestHelper.makePaymentTransaction(state: $0) } @@ -157,7 +157,7 @@ class PaymentProviderTests: XCTestCase { XCTAssertEqual(paymentQueueMock.invokedFinishTransactionCount, 2) } - func testThatPaymentProviderCallFallbackHandlerWhenPaymentHandlersDontExist() { + func test_thatPaymentProviderCallsFallbackHandler_whenPaymentHandlersDoNotExist() { // given var handledPaymentQueue: PaymentQueue? let transaction = PurchaseManagerTestHelper.makePaymentTransaction(state: .purchased) @@ -172,7 +172,7 @@ class PaymentProviderTests: XCTestCase { } #if os(iOS) || os(tvOS) || os(macOS) - func testThatPaymentProviderAddAppStoreHandler() { + func test_thatPaymentProviderAddsAppStoreHandler() { // given let payment = SKPayment() let product = SKProduct() @@ -200,7 +200,7 @@ class PaymentProviderTests: XCTestCase { } #endif - func testThatPaymentQueueFinishTransaction() { + func test_thatPaymentQueueFinishesTransaction() { // given let transaction = PurchaseManagerTestHelper.makePaymentTransaction(state: .purchased) diff --git a/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift index d595da40d..c2f1ada71 100644 --- a/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift @@ -9,14 +9,6 @@ import StoreKit import TestConcurrency import XCTest -private extension String { - static let requestId = "request_identifier" -} - -private extension Set where Element == String { - static let productIds: Set = .init(arrayLiteral: "1", "2", "3") -} - // MARK: - ProductProviderTests class ProductProviderTests: XCTestCase { @@ -44,17 +36,17 @@ class ProductProviderTests: XCTestCase { // MARK: - Tests - func testThatProductProviderFetchProductsWithInvalidProductsIdentfiers() { + func test_thatProductProviderReturnsInvalidProductIDs_whenRequestProductsWithInvalidIDs() { // given var fetchResult: Result<[SKProduct], IAPError>? let completionHandler: IProductProvider.ProductsHandler = { result in fetchResult = result } - let request = PurchaseManagerTestHelper.makeRequest(with: .requestId) + let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let response = ProductResponseMock() - response.stubbedInvokedInvalidProductsIdentifiers = ["111"] + response.stubbedInvokedInvalidProductsIdentifiers = [.productID] // when - productProvider.fetch(productIds: .productIds, requestId: .requestId, completion: completionHandler) + productProvider.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) productProvider.productsRequest(request, didReceive: response) // then @@ -65,15 +57,15 @@ class ProductProviderTests: XCTestCase { } } - func testThatProductProviderFetchProductsWithValidProductsIdentfiers() { + func test_thatProductProviderReturnsProducts_whenRequestProductsWithValidProductIDs() { // given var fetchResult: Result<[SKProduct], IAPError>? let completionHandler: IProductProvider.ProductsHandler = { result in fetchResult = result } - let request = PurchaseManagerTestHelper.makeRequest(with: .requestId) + let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let response = ProductResponseMock() // when - productProvider.fetch(productIds: .productIds, requestId: .requestId, completion: completionHandler) + productProvider.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) productProvider.productsRequest(request, didReceive: response) // then @@ -84,15 +76,15 @@ class ProductProviderTests: XCTestCase { } } - func testThatProductProviderHandleRequestError() { + func test_thatProductProviderHandlesError_whenRequestDidFailWithError() { // given var fetchResult: Result<[SKProduct], IAPError>? let completionHandler: IProductProvider.ProductsHandler = { result in fetchResult = result } - let request = PurchaseManagerTestHelper.makeRequest(with: .requestId) + let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let error = IAPError.emptyProducts // when - productProvider.fetch(productIds: .productIds, requestId: .requestId, completion: completionHandler) + productProvider.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) productProvider.request(request, didFailWithError: error) // then @@ -103,3 +95,14 @@ class ProductProviderTests: XCTestCase { } } } + +// MARK: - Constants + +private extension String { + static let productID = "product_ID" + static let requestID = "request_identifier" +} + +private extension Set where Element == String { + static let productIDs: Set = .init(arrayLiteral: "1", "2", "3") +} diff --git a/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift index c2636edc8..cd3b4c67e 100644 --- a/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift @@ -49,7 +49,7 @@ class ReceiptRefreshProviderTests: XCTestCase { // MARK: - Tests - func test_thatReceiptRefreshProviderHandlesRequestError() { + func test_thatReceiptRefreshProviderHandlesRequestError_whenErrorOccurred() { // given receiptRefreshRequestFactoryMock.stubbedMakeResult = ReceiptRefreshRequestMock() @@ -59,7 +59,7 @@ class ReceiptRefreshProviderTests: XCTestCase { let error = IAPError.paymentCancelled // when - receiptRefreshProvider.refresh(requestId: .requestID, handler: handler) + receiptRefreshProvider.refresh(requestID: .requestID, handler: handler) receiptRefreshProvider.request(request, didFailWithError: error) // then @@ -68,7 +68,7 @@ class ReceiptRefreshProviderTests: XCTestCase { } } - func test_thatReceiptRefreshProviderFinishesRequest() { + func test_thatReceiptRefreshProviderFinishesRequest_whenRequestCompletedSuccessfully() { // given receiptRefreshRequestFactoryMock.stubbedMakeResult = ReceiptRefreshRequestMock() @@ -77,7 +77,7 @@ class ReceiptRefreshProviderTests: XCTestCase { let handler: ReceiptRefreshHandler = { result = $0 } // when - receiptRefreshProvider.refresh(requestId: .requestID, handler: handler) + receiptRefreshProvider.refresh(requestID: .requestID, handler: handler) receiptRefreshProvider.requestDidFinish(request) // then @@ -126,7 +126,7 @@ class ReceiptRefreshProviderTests: XCTestCase { var iapError: IAPError? do { - try await receiptRefreshProvider.refresh(requestId: .requestID) + try await receiptRefreshProvider.refresh(requestID: .requestID) } catch { iapError = error as? IAPError } @@ -135,7 +135,7 @@ class ReceiptRefreshProviderTests: XCTestCase { XCTAssertEqual(iapError, IAPError(error: IAPError.paymentNotAllowed)) } - func test_thatReceiptRefreshProviderRefreshesReceipt_whenRequestDid() async { + func test_thatReceiptRefreshProviderRefreshesReceipt_whenRequestCompletedSuccessfully() async { // given let request = ReceiptRefreshRequestMock() request.stubbedId = .requestID @@ -150,7 +150,7 @@ class ReceiptRefreshProviderTests: XCTestCase { var iapError: IAPError? do { - try await receiptRefreshProvider.refresh(requestId: .requestID) + try await receiptRefreshProvider.refresh(requestID: .requestID) } catch { iapError = error as? IAPError } From fd1c79ad704e10240bde672b9eea42e4ab0f7704 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:14:57 +0400 Subject: [PATCH 14/44] Implement `SKProductTests` --- Tests/FlareTests/Mocks/IAPProviderMock.swift | 4 +-- Tests/FlareTests/Mocks/ProductMock.swift | 12 +++++++ Tests/FlareTests/UnitTests/FlareTests.swift | 8 ++--- .../UnitTests/Models/SKProductTests.swift | 36 +++++++++++++++++++ 4 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 Tests/FlareTests/UnitTests/Models/SKProductTests.swift diff --git a/Tests/FlareTests/Mocks/IAPProviderMock.swift b/Tests/FlareTests/Mocks/IAPProviderMock.swift index 58cda64e8..a6ea5b23a 100644 --- a/Tests/FlareTests/Mocks/IAPProviderMock.swift +++ b/Tests/FlareTests/Mocks/IAPProviderMock.swift @@ -43,8 +43,8 @@ final class IAPProviderMock: IIAPProvider { var invokedRefreshReceipt = false var invokedRefreshReceiptCount = 0 - var invokedRefreshReceiptParameters: (Closure>, Void)? - var invokedRefreshReceiptParametersList = [(Closure>, Void)]() + var invokedRefreshReceiptParameters: (completion: Closure>, Void)? + var invokedRefreshReceiptParametersList = [(completion: Closure>, Void)]() var stubbedRefreshReceiptResult: Result? func refreshReceipt(completion: @escaping Closure>) { diff --git a/Tests/FlareTests/Mocks/ProductMock.swift b/Tests/FlareTests/Mocks/ProductMock.swift index d5a3f0b6f..e15937e91 100644 --- a/Tests/FlareTests/Mocks/ProductMock.swift +++ b/Tests/FlareTests/Mocks/ProductMock.swift @@ -15,4 +15,16 @@ final class ProductMock: SKProduct { invokedProductIdentifierCount += 1 return stubbedProductIdentifier } + + var stubbedPriceLocale: Locale! + + override var priceLocale: Locale { + stubbedPriceLocale + } + + var stubbedPrice: NSDecimalNumber! + + override var price: NSDecimalNumber { + stubbedPrice + } } diff --git a/Tests/FlareTests/UnitTests/FlareTests.swift b/Tests/FlareTests/UnitTests/FlareTests.swift index 73842ac65..01e403dbd 100644 --- a/Tests/FlareTests/UnitTests/FlareTests.swift +++ b/Tests/FlareTests/UnitTests/FlareTests.swift @@ -63,7 +63,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(iapProviderMock.invokedPurchaseParameters?.productID, .productID) } - func test_thatFlareDoesNotAPurchaseProduct_whenUserCannotMakePayments() { + func test_thatFlareDoesNotPurchaseAProduct_whenUserCannotMakePayments() { // given iapProviderMock.stubbedCanMakePayments = false @@ -112,7 +112,7 @@ class FlareTests: XCTestCase { XCTAssertEqual(error, errorMock) } - func test_thatFlareDoesNotAPurchaseProduct_whenUserCannotMakePayments() async { + func test_thatFlareDoesNotPurchaseAProduct_whenUserCannotMakePayments() async { // given iapProviderMock.stubbedCanMakePayments = false iapProviderMock.stubbedAsyncPurchase = PaymentTransaction(PaymentTransactionMock()) @@ -160,7 +160,7 @@ class FlareTests: XCTestCase { receipt = result } }) - iapProviderMock.invokedRefreshReceiptParameters?.0(.success(.receipt)) + iapProviderMock.invokedRefreshReceiptParameters?.completion(.success(.receipt)) // then XCTAssertTrue(iapProviderMock.invokedRefreshReceipt) @@ -175,7 +175,7 @@ class FlareTests: XCTestCase { error = result } }) - iapProviderMock.invokedRefreshReceiptParameters?.0(.failure(.paymentNotAllowed)) + iapProviderMock.invokedRefreshReceiptParameters?.completion(.failure(.paymentNotAllowed)) // then XCTAssertTrue(iapProviderMock.invokedRefreshReceipt) diff --git a/Tests/FlareTests/UnitTests/Models/SKProductTests.swift b/Tests/FlareTests/UnitTests/Models/SKProductTests.swift new file mode 100644 index 000000000..b901e091e --- /dev/null +++ b/Tests/FlareTests/UnitTests/Models/SKProductTests.swift @@ -0,0 +1,36 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation +import class StoreKit.SKProduct +import XCTest + +// MARK: - SKProductTests + +final class SKProductTests: XCTestCase { + func test_thatSKProductFormatsPriceValueAccoringToLocale() { + // given + let product = ProductMock() + product.stubbedPrice = NSDecimalNumber(value: UInt.price) + product.stubbedPriceLocale = Locale(identifier: .localeID) + + // when + let localizedPrice = product.localizedPrice + + // then + XCTAssertEqual(localizedPrice, "$100.00") + } +} + +// MARK: - Constants + +private extension UInt { + static let price = 100 +} + +private extension String { + static let localeID = "en_US" +} From 6552f0db5db3bc781b4582c59e0f386221a0e456 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:15:25 +0400 Subject: [PATCH 15/44] Update package's documentation --- Documentation/Usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Usage.md b/Documentation/Usage.md index b8d4b02d2..93f269f3d 100644 --- a/Documentation/Usage.md +++ b/Documentation/Usage.md @@ -15,7 +15,7 @@ ## Introduction -Flare provides an elegant interface for In-App Purchases. It supports non-consumable and consumable purchases and subscriptions. +Flare provides an elegant interface for In-App Purchases, supporting non-consumable and consumable purchases as well as subscriptions. ## Flare Diagram From dc16221a756d89a8706de39ae4cd8ec4b60b7699 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:15:57 +0400 Subject: [PATCH 16/44] Integrate `CodeCov` --- .github/workflows/ci.yml | 6 ++++- Package.swift | 14 +++++++----- codecov.yml | 48 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 codecov.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95c58a62b..e4ed8c1bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,4 +38,8 @@ jobs: steps: - uses: actions/checkout@v3 - name: ${{ matrix.name }} - run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean \ No newline at end of file + run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/Package.swift b/Package.swift index 57dcd4029..14b566909 100644 --- a/Package.swift +++ b/Package.swift @@ -12,10 +12,7 @@ let package = Package( .tvOS(.v11), ], products: [ - .library( - name: "Flare", - targets: ["Flare"] - ), + .library(name: "Flare", targets: ["Flare"]), ], dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), @@ -23,11 +20,16 @@ let package = Package( targets: [ .target( name: "Flare", - dependencies: [.product(name: "Concurrency", package: "concurrency")] + dependencies: [ + .product(name: "Concurrency", package: "concurrency"), + ] ), .testTarget( name: "FlareTests", - dependencies: ["Flare", .product(name: "TestConcurrency", package: "concurrency")] + dependencies: [ + "Flare", + .product(name: "TestConcurrency", package: "concurrency"), + ] ), ] ) diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..b41560430 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,48 @@ +codecov: + # Require CI to pass to show coverage, default yes + require_ci_to_pass: yes + notify: + # Codecov should wait for all CI statuses to complete, default yes + wait_for_ci: yes + +coverage: + # Coverage precision range 0-5, default 2 + precision: 2 + + # Direction to round the coverage value - up, down, nearest, default down + round: nearest + + # Value range for red...green, default 70...100 + range: "70...90" + + status: + # Overall project coverage, compare against pull request base + project: + default: + # The required coverage value + target: 50% + + # The leniency in hitting the target. Allow coverage to drop by X% + threshold: 5% + + # Only measure lines adjusted in the pull request or single commit, if the commit in not in the pr + patch: + default: + # The required coverage value + target: 85% + + # Allow coverage to drop by X% + threshold: 5% + changes: no + +comment: + # Pull request Codecov comment format. + # diff: coverage diff of the pull request + # files: a list of files impacted by the pull request (coverage changes, file is new or removed) + layout: "diff, files" + + # Update Codecov comment, if exists. Otherwise post new + behavior: default + + # If true, only post the Codecov comment if coverage changes + require_changes: false \ No newline at end of file From 2f86173b9c0fdd3ca052b0d4208ae0f6218aa868 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:17:12 +0400 Subject: [PATCH 17/44] Integrate `SwiftLint` validation into GitHub Actions --- .github/workflows/ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4ed8c1bb..f2a56e009 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,8 @@ on: - main - dev pull_request: + paths: + - '.swiftlint.yml' branches: [ main ] concurrency: @@ -13,6 +15,16 @@ concurrency: cancel-in-progress: true jobs: + SwiftLint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: GitHub Action for SwiftLint + uses: norio-nomura/action-swiftlint@3.2.1 + with: + args: --strict + env: + DIFF_BASE: ${{ github.base_ref }} Latest: name: Test Latest (iOS, macOS, tvOS, watchOS) runs-on: macOS-12 From 0a19ee9a5fdd6b0a2e3a70d63e8f43e52919e58f Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:22:24 +0400 Subject: [PATCH 18/44] Update `Usage.md` layout --- Documentation/Usage.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/Usage.md b/Documentation/Usage.md index 93f269f3d..d9a400b4e 100644 --- a/Documentation/Usage.md +++ b/Documentation/Usage.md @@ -3,7 +3,7 @@ ### Overview * [Introduction](#introduction) -* [Flare Diagram](#diagram) +* [Flare Diagram](#flare-diagram) * [In-App Purchases](#in-app-purchases) - [Getting Products](#getting-products) - [Purchasing Product](#purchasing-product) @@ -21,12 +21,12 @@ Flare provides an elegant interface for In-App Purchases, supporting non-consuma ![Flare: Components](https://raw.githubusercontent.com/space-code/flare/dev/Documentation/Resources/flare.png) -`Flare` is a central component that serves as the client API for managing various aspects of in-app purchases and payments in your application. It is designed to simplify the integration of payment processing and in-app purchase functionality into your software. -`IAPProvider` is a fundamental component of `Flare` that handles all in-app purchase operations. It offers an API to initiate, verify, and manage in-app purchases within your application. -`IPaymentProvider` is a central component in `Flare` that orchestrates various payment-related operations within your application. It acts as the bridge between the payment gateway and your app's logic. -`IProductProvider` is a component of `Flare` that helps managing the products or services available for purchase within your app. -`IReceiptRefreshProvider` is responsible for refreshing and managing receipt associated with in-app purchases. -`IAppStoreReceiptProvider` manages and provides access to the app's receipt, which contains a record of all in-app purchases made by the user. +- `Flare` is a central component that serves as the client API for managing various aspects of in-app purchases and payments in your application. It is designed to simplify the integration of payment processing and in-app purchase functionality into your software. +- `IAPProvider` is a fundamental component of `Flare` that handles all in-app purchase operations. It offers an API to initiate, verify, and manage in-app purchases within your application. +- `IPaymentProvider` is a central component in `Flare` that orchestrates various payment-related operations within your application. It acts as the bridge between the payment gateway and your app's logic. +- `IProductProvider` is a component of `Flare` that helps managing the products or services available for purchase within your app. +- `IReceiptRefreshProvider` is responsible for refreshing and managing receipt associated with in-app purchases. +- `IAppStoreReceiptProvider` manages and provides access to the app's receipt, which contains a record of all in-app purchases made by the user. ## In-App Purchases From 98fa01c01696dbb513ca6a0c710aac1a566e0c0a Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:30:27 +0400 Subject: [PATCH 19/44] Update `CHANGELOG.md` --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c64915145..0ca19a1bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ # Change Log All notable changes to this project will be documented in this file. +#### 2.x Releases +- `2.0.x` Releases - [2.0.0](#200) + +## [2.0.0](https://github.com/space-code/flare/releases/tag/2.0.0) +Released on 2023-09-13. + +#### Added +- Support for Swift Concurrency, including async-await for requests. + +#### Updated +- Rename public methods and parameters to increase readability. + #### 1.x Releases - `1.0.x` Releases - [1.0.0](#100) From 8082b2617957fd492d7382e6d3aac2e26cac575a Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:43:13 +0400 Subject: [PATCH 20/44] Update `ci.yml` --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2a56e009..55f7abd30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,9 @@ on: pull_request: paths: - '.swiftlint.yml' - branches: [ main ] + branches: + - main + - dev concurrency: group: ci From b4acafea6d6bdf8d141d23c22b80b539314038e8 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:51:54 +0400 Subject: [PATCH 21/44] Increase the `tvOS` version to `13.0` --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 14b566909..cec0ab93a 100644 --- a/Package.swift +++ b/Package.swift @@ -9,7 +9,7 @@ let package = Package( .macOS(.v10_15), .iOS(.v13), .watchOS(.v7), - .tvOS(.v11), + .tvOS(.v13), ], products: [ .library(name: "Flare", targets: ["Flare"]), From aff52fa69d6063c7127f54bccd103f2e9f7aea33 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 18:53:59 +0400 Subject: [PATCH 22/44] Update `README.md` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9108fe9cb..856ad3a1a 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Flare is a framework written in Swift that makes it easy for you to work with in Check out [flare documentation](https://github.com/space-code/flare/blob/main/Documentation/Usage.md). ## Requirements -- iOS 13.0+ / macOS 10.15+ / tvOS 11.0+ / watchOS 7.0+ +- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 7.0+ - Xcode 14.0 - Swift 5.5 From 1dfbc66e14ec1fcfddae939a1a9368029e0921b7 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 19:33:52 +0400 Subject: [PATCH 23/44] Update `ci.yml` --- .github/workflows/ci.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55f7abd30..6851e244a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,20 +40,26 @@ jobs: - destination: "OS=16.1,name=iPhone 14 Pro" name: "iOS" scheme: "Flare" + sdk: iphonesimulator - destination: "OS=16.1,name=Apple TV" name: "tvOS" scheme: "Flare" + sdk: appletvsimulator - destination: "OS=9.1,name=Apple Watch Series 8 (45mm)" name: "watchOS" scheme: "Flare" + sdk: watchsimulator - destination: "platform=macOS" name: "macOS" scheme: "Flare" + sdk: macosx steps: - uses: actions/checkout@v3 - name: ${{ matrix.name }} - run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES + run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "./${{ matrix.sdk }}.xcresult" | xcpretty -r junit - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v3.1.0 with: - token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file + token: ${{ secrets.CODECOV_TOKEN }} + xcode: true + xcode_archive_path: "./${{ matrix.env.sdk }}.xcresult" \ No newline at end of file From dd3ac6676c74cafa683148fd12ce786871281f0d Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 19:39:45 +0400 Subject: [PATCH 24/44] `Codecov` Integration [#2] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6851e244a..587f5487e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,4 +62,4 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} xcode: true - xcode_archive_path: "./${{ matrix.env.sdk }}.xcresult" \ No newline at end of file + xcode_archive_path: "./${{ matrix.sdk }}.xcresult" \ No newline at end of file From ed90018b13601c39265e9374e7597eb48b472598 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 13 Sep 2023 19:48:08 +0400 Subject: [PATCH 25/44] Update `README.md` --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 856ad3a1a..5836c6f5d 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,9 @@ Liscence Platform Swift5.5 - CI - +CI +CodeCov +

## Description From d28af8b7f295768c8356de7b876e3925b59e58c1 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Thu, 14 Sep 2023 07:33:32 +0400 Subject: [PATCH 26/44] Create `dependabot.yml` --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..0f8f7ed67 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "swift" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" From 2b23a2bf59c0d1824f037c6ca4428e8153965ebe Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Thu, 14 Sep 2023 07:43:57 +0400 Subject: [PATCH 27/44] Update GitHub workflow (#3) * Implement issues and PR templates * Update `README.md` --- .github/ISSUE_TEMPLATE/bug_report.md | 41 +++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 11 +++++ .../PULL_REQUEST_TEMPLATE/bug_template.yml | 9 ++++ .../feature_template.yml | 12 ++++++ README.md | 2 +- 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/bug_template.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE/feature_template.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..8dc7e75ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,41 @@ +--- +name: "🐛 Bug Report" +about: Report a reproducible bug or regression. +title: 'Bug: ' +labels: 'bug' + +--- + + + +Application version: + +## Steps To Reproduce + +1. +2. + + + +Link to code example: + + + +## The current behavior + + +## The expected behavior \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..97d08de18 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,11 @@ +--- +name: 🛠 Feature request +about: If you have a feature request for the Firebase iOS SDK, file it here. +labels: 'type: enhancement' +--- + +**Feature description** +Clearly and concisely describe the feature. + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE/bug_template.yml b/.github/PULL_REQUEST_TEMPLATE/bug_template.yml new file mode 100644 index 000000000..7d6a149d1 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/bug_template.yml @@ -0,0 +1,9 @@ +## Bug description +Clearly and concisely describe the problem. + +## Solution description +Describe your code changes in detail for reviewers. Explain the technical solution you have provided and how it fixes the issue case. + +## Covered unit test cases +- [x] yes +- [x] no \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE/feature_template.yml b/.github/PULL_REQUEST_TEMPLATE/feature_template.yml new file mode 100644 index 000000000..ab3978bc5 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/feature_template.yml @@ -0,0 +1,12 @@ +## Feature description +Clearly and concisely describe the feature. + +## Solution description +Describe your code changes in detail for reviewers. + +## Areas affected and ensured +List out the areas affected by your code changes. + +## Covered unit test cases +- [x] yes +- [x] no \ No newline at end of file diff --git a/README.md b/README.md index 5836c6f5d..b0ec938d4 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Once you have your Swift package set up, adding `flare` as a dependency is as ea ```swift dependencies: [ - .package(url: "https://github.com/space-code/flare.git", .upToNextMajor(from: "1.0.0")) + .package(url: "https://github.com/space-code/flare.git", .upToNextMajor(from: "2.0.0")) ] ``` From 1d2975da20008b95a1cc39a73bdac131e81a7f7f Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sun, 15 Oct 2023 19:01:24 +0300 Subject: [PATCH 28/44] Support `visionOS` (#5) * Support `Apple Vision Pro` * Update `CHANGELOG.md` * Update `ci.yml` * Update `CHANGELOG.md` --- .github/workflows/ci.yml | 26 ++++++++++++++++++++++---- CHANGELOG.md | 6 ++++++ Package.swift | 1 + Package@swift-5.9.swift | 37 +++++++++++++++++++++++++++++++++++++ README.md | 4 ++-- 5 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 Package@swift-5.9.swift diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 587f5487e..4d2fe1aa1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,9 +8,10 @@ on: pull_request: paths: - '.swiftlint.yml' - branches: - - main - - dev + - ".github/workflows/**" + - "Package.swift" + - "Source/**" + - "Tests/**" concurrency: group: ci @@ -62,4 +63,21 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} xcode: true - xcode_archive_path: "./${{ matrix.sdk }}.xcresult" \ No newline at end of file + xcode_archive_path: "./${{ matrix.sdk }}.xcresult" + Beta: + name: "Test Betas" + runs-on: macos-13 + env: + DEVELOPER_DIR: "/Applications/Xcode_15.0.app/Contents/Developer" + timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + include: + - destination: "OS=1.0,name=Apple Vision Pro" + name: "visionOS" + scheme: "Flare" + steps: + - uses: actions/checkout@v3 + - name: ${{ matrix.name }} + run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ca19a1bc..477b2241c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. #### 2.x Releases - `2.0.x` Releases - [2.0.0](#200) +## [Unreleased]() + +#### Added +- Added `visionOS` to list of supported platforms + - Added in Pull Request [#5](https://github.com/space-code/flare/pull/5). + ## [2.0.0](https://github.com/space-code/flare/releases/tag/2.0.0) Released on 2023-09-13. diff --git a/Package.swift b/Package.swift index cec0ab93a..3644a161d 100644 --- a/Package.swift +++ b/Package.swift @@ -1,5 +1,6 @@ // swift-tools-version: 5.5 // The swift-tools-version declares the minimum version of Swift required to build this package. +// swiftlint:disable all import PackageDescription diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift new file mode 100644 index 000000000..bb990c597 --- /dev/null +++ b/Package@swift-5.9.swift @@ -0,0 +1,37 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. +// swiftlint:disable all + +import PackageDescription + +let package = Package( + name: "Flare", + platforms: [ + .macOS(.v10_15), + .iOS(.v13), + .watchOS(.v7), + .tvOS(.v13), + .visionOS(.v1), + ], + products: [ + .library(name: "Flare", targets: ["Flare"]), + ], + dependencies: [ + .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), + ], + targets: [ + .target( + name: "Flare", + dependencies: [ + .product(name: "Concurrency", package: "concurrency"), + ] + ), + .testTarget( + name: "FlareTests", + dependencies: [ + "Flare", + .product(name: "TestConcurrency", package: "concurrency"), + ] + ), + ] +) diff --git a/README.md b/README.md index c8654d0d0..b1baded65 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Flare is a framework written in Swift that makes it easy for you to work with in Check out [flare documentation](https://github.com/space-code/flare/blob/main/Documentation/Usage.md). ## Requirements -- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 7.0+ +- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 7.0+ / visionOS 1.0+ - Xcode 14.0 - Swift 5.5 @@ -69,4 +69,4 @@ Please feel free to help out with this project! If you see something that could Nikita Vasilev, nv3212@gmail.com ## License -flare is available under the MIT license. See the LICENSE file for more info. \ No newline at end of file +flare is available under the MIT license. See the LICENSE file for more info. From ba39791a3248f877b056cbba5acdb2b7410bf501 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sun, 15 Oct 2023 19:40:53 +0300 Subject: [PATCH 29/44] [`StoreKit 2`]: Refunding Purchases Integration (#6) * Bump mint dependencies - Bumps `swiftformat` from `0.47.12` to `0.52.7` - Bumps `SwiftLint` from `0.47.1` to `0.53.0` * Integrate refund purchase feature Implement a refund purchase feature as a step towards supporting `StoreKit 2` * Update `Usage.md` * Update `UML` diagram * Update `.swiftformat` rules * Increase test coverage - Implement unit tests for `IAPError` - Implement unit tests for `ProcessInfo` - Implement unit tests for `SystemInfoProvider` * Implement unit tests - Implement unit tests for `Flare` - Implement unit tests for `IAPProvider` * Implement `RefundRequestProvider` tests * Update `codecov.yml` * Update `CHANGELOG.md` * Update `Package.swift` * Bump min `swift` version from `5.5` to `5.7` * Update `README.md` * Update `CHANGELOG.md` --- .swiftformat | 4 +- .swiftlint.yml | 1 + CHANGELOG.md | 11 +- Documentation/Resources/flare.png | Bin 326359 -> 329034 bytes Documentation/Usage.md | 15 +++ Mintfile | 4 +- Package.resolved | 33 +++--- Package.swift | 10 +- ...swift-5.9.swift => Package@swift-5.7.swift | 5 +- README.md | 4 +- .../Helpers/ProcessInfo/ProcessInfo+.swift | 29 +++++ .../Helpers/ScenesHolder/IScenesHolder.swift | 22 ++++ Sources/Flare/Classes/Models/IAPError.swift | 9 ++ .../Flare/Classes/Models/RefundError.swift | 14 +++ .../Classes/Models/RefundRequestStatus.swift | 18 +++ .../Providers/IAPProvider/IAPProvider.swift | 17 ++- .../Providers/IAPProvider/IIAPProvider.swift | 13 +++ .../RefundProvider/IRefundProvider.swift | 20 ++++ .../RefundProvider/RefundProvider.swift | 84 +++++++++++++ .../IRefundRequestProvider.swift | 47 ++++++++ .../RefundRequestProvider.swift | 71 +++++++++++ .../ISystemInfoProvider.swift | 18 +++ .../SystemInfoProvider.swift | 54 +++++++++ Sources/Flare/Flare.swift | 14 +++ Sources/Flare/IFlare.swift | 13 +++ .../Helpers/WindowSceneFactory.swift | 21 ++++ Tests/FlareTests/Mocks/IAPProviderMock.swift | 13 +++ .../FlareTests/Mocks/RefundProviderMock.swift | 22 ++++ .../Mocks/RefundRequestProviderMock.swift | 67 +++++++++++ Tests/FlareTests/Mocks/ScenesHolderMock.swift | 25 ++++ .../Mocks/SystemInfoProviderMock.swift | 34 ++++++ Tests/FlareTests/UnitTests/FlareTests.swift | 28 +++++ .../UnitTests/Helpers/ProcessInfoTests.swift | 13 +++ .../UnitTests/Models/IAPErrorTests.swift | 62 ++++++++++ .../Providers/IAPProviderTests.swift | 35 +++++- .../Providers/RefundProviderTests.swift | 110 ++++++++++++++++++ .../RefundRequestProviderTests.swift | 61 ++++++++++ .../Providers/SystemInfoProviderTests.swift | 59 ++++++++++ codecov.yml | 2 +- 39 files changed, 1052 insertions(+), 30 deletions(-) rename Package@swift-5.9.swift => Package@swift-5.7.swift (80%) create mode 100644 Sources/Flare/Classes/Helpers/ProcessInfo/ProcessInfo+.swift create mode 100644 Sources/Flare/Classes/Helpers/ScenesHolder/IScenesHolder.swift create mode 100644 Sources/Flare/Classes/Models/RefundError.swift create mode 100644 Sources/Flare/Classes/Models/RefundRequestStatus.swift create mode 100644 Sources/Flare/Classes/Providers/RefundProvider/IRefundProvider.swift create mode 100644 Sources/Flare/Classes/Providers/RefundProvider/RefundProvider.swift create mode 100644 Sources/Flare/Classes/Providers/RefundRequestProvider/IRefundRequestProvider.swift create mode 100644 Sources/Flare/Classes/Providers/RefundRequestProvider/RefundRequestProvider.swift create mode 100644 Sources/Flare/Classes/Providers/SystemInfoProvider/ISystemInfoProvider.swift create mode 100644 Sources/Flare/Classes/Providers/SystemInfoProvider/SystemInfoProvider.swift create mode 100644 Tests/FlareTests/Helpers/WindowSceneFactory.swift create mode 100644 Tests/FlareTests/Mocks/RefundProviderMock.swift create mode 100644 Tests/FlareTests/Mocks/RefundRequestProviderMock.swift create mode 100644 Tests/FlareTests/Mocks/ScenesHolderMock.swift create mode 100644 Tests/FlareTests/Mocks/SystemInfoProviderMock.swift create mode 100644 Tests/FlareTests/UnitTests/Helpers/ProcessInfoTests.swift create mode 100644 Tests/FlareTests/UnitTests/Models/IAPErrorTests.swift create mode 100644 Tests/FlareTests/UnitTests/Providers/RefundProviderTests.swift create mode 100644 Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift create mode 100644 Tests/FlareTests/UnitTests/Providers/SystemInfoProviderTests.swift diff --git a/.swiftformat b/.swiftformat index 2cb62753f..a4294246c 100644 --- a/.swiftformat +++ b/.swiftformat @@ -36,8 +36,8 @@ --enable redundantSelf --enable redundantVoidReturnType --enable semicolons ---enable sortedImports ---enable sortedSwitchCases +--enable sortImports +--enable sortSwitchCases --enable spaceAroundBraces --enable spaceAroundBrackets --enable spaceAroundComments diff --git a/.swiftlint.yml b/.swiftlint.yml index b5956417d..ca37591b9 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,6 +1,7 @@ excluded: - Tests - Package.swift + - Package@swift-5.7.swift - .build # Rules diff --git a/CHANGELOG.md b/CHANGELOG.md index 477b2241c..c6f5e99bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,18 @@ # Change Log All notable changes to this project will be documented in this file. -#### 2.x Releases -- `2.0.x` Releases - [2.0.0](#200) +## [Unreleased] -## [Unreleased]() +## Added +- Implement a refund for purchases + - Added in Pull Request [#6](https://github.com/space-code/flare/pull/6). -#### Added - Added `visionOS` to list of supported platforms - Added in Pull Request [#5](https://github.com/space-code/flare/pull/5). +#### 2.x Releases +- `2.0.x` Releases - [2.0.0](#200) + ## [2.0.0](https://github.com/space-code/flare/releases/tag/2.0.0) Released on 2023-09-13. diff --git a/Documentation/Resources/flare.png b/Documentation/Resources/flare.png index 2ac3514757c14ddac508e0257a9e6279be9deec4..5a1ac4071e43523b46251041f6aa629e05a9e307 100644 GIT binary patch literal 329034 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

N)?h1@6_ioTWTGI%)G5jVNe^}#Wde7 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

B~@Z-u%j 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 owobo$v+~#P*6iB*Lv^dR literal 326359 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

h%k0{2MA8 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 z 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≈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%0Dd^Ga%jrH-kP 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ξwl=(uIA{kHI(!- zK6EIs|4;4Vqvsy&jonMKI{>}_dg7Cm&rhL&eKU0mg8gVzncxHM)Q7Xj#>S9m=BK9{ zMLok!O8Z7$F0`c8H#W-4%06kMTT5-x8K{2dwC?$gss6F{C8O>QBSTWT!c8irQ&$f* zNJtc|JOVR#=2ghp@Xt^r&Oy&y|FksHTu1cv;Jc7)K8d?+3J1%FCUY%PplMEcjc4?wf<_>n02^y;b>P58KVS7&CQ5>b$arOz?Q|5t$(kO+54CaTVP$2SX@s?= z@@IpKX)>>)6^8OG`Df4y>eP3)9om-Id1KI}kKl@g{;1w)PyL%sw|zS&!rQgf0z5WU zbr}b3aW?g7Gm5JD&A9E=N^$VRU^Lbpj^|{ZVkHY%cg*vw=aMI*)@gp)E4`5}%itNj zYoeyGf|D>-r=_Bz0&D>-oA!>5^zn}-?HzDQLc8b`AwS)=CNKr=Hv6wU^ZnzG1*FPx zs%;E*9r^gjy~|a`zS|1C78DRjN>0|(*9U+>Ikf?E4y&pxpacOL zA>Tn@W?bie%q$Av)8*E7!35-|yZnJ@1Z_WAIl1Zx>Aj4!^F>|5XiV42zhN1>w-NSZ z(HCiC49`p3HJo*9H#}XS*xD#cX%)zAIQ>ASPQa~Q*>o3io`CqPq2b#U$26nt?j{>^ zLZ=b{*Pxk?Nax5a{nDjcHRn~Qw^n*d6%=g6vnw_lsID+vHMKJ1V~3UV9lLD{ombqh0k~JO<^6`6rSLEe#Xw8Bd znS+mU8MiJ609C<|@}@w}ffkCvK=f=oQD(*0O}Sf_b%z~Vw?mJet`15F^!K%7e=@Ko zz$Zze#H#mzG+h9 Liscence Platform -Swift5.5 +Swift5.7 CI CodeCov @@ -36,7 +36,7 @@ Check out [flare documentation](https://github.com/space-code/flare/blob/main/Do ## Requirements - iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 7.0+ / visionOS 1.0+ - Xcode 14.0 -- Swift 5.5 +- Swift 5.7 ## Installation ### Swift Package Manager diff --git a/Sources/Flare/Classes/Helpers/ProcessInfo/ProcessInfo+.swift b/Sources/Flare/Classes/Helpers/ProcessInfo/ProcessInfo+.swift new file mode 100644 index 000000000..155c22950 --- /dev/null +++ b/Sources/Flare/Classes/Helpers/ProcessInfo/ProcessInfo+.swift @@ -0,0 +1,29 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +#if DEBUG + extension ProcessInfo { + static var isRunningUnitTests: Bool { + self[.XCTestConfigurationFile] != nil + } + } + + // MARK: - Extensions + + extension ProcessInfo { + static subscript(key: String) -> String? { + processInfo.environment[key] + } + } + + // MARK: - Constants + + private extension String { + static let XCTestConfigurationFile = "XCTestConfigurationFilePath" + } + +#endif diff --git a/Sources/Flare/Classes/Helpers/ScenesHolder/IScenesHolder.swift b/Sources/Flare/Classes/Helpers/ScenesHolder/IScenesHolder.swift new file mode 100644 index 000000000..118d26a5d --- /dev/null +++ b/Sources/Flare/Classes/Helpers/ScenesHolder/IScenesHolder.swift @@ -0,0 +1,22 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if canImport(UIKit) + import UIKit +#endif + +// MARK: - IScenesHolder + +/// A type that holds all connected scenes. +protocol IScenesHolder { + #if os(iOS) || VISION_OS + /// The scenes that are connected to the app. + var connectedScenes: Set { get } + #endif +} + +#if os(iOS) || VISION_OS + extension UIApplication: IScenesHolder {} +#endif diff --git a/Sources/Flare/Classes/Models/IAPError.swift b/Sources/Flare/Classes/Models/IAPError.swift index 65fae3136..2977011e5 100644 --- a/Sources/Flare/Classes/Models/IAPError.swift +++ b/Sources/Flare/Classes/Models/IAPError.swift @@ -26,6 +26,10 @@ public enum IAPError: Swift.Error { case with(error: Swift.Error) /// The App Store receipt wasn't found. case receiptNotFound + /// The transaction wasn't found. + case transactionNotFound(productID: String) + /// The refund error. + case refund(error: RefundError) /// The unknown error occurred. case unknown } @@ -63,6 +67,7 @@ extension IAPError { // MARK: Equatable +// swiftlint:disable cyclomatic_complexity extension IAPError: Equatable { public static func == (lhs: IAPError, rhs: IAPError) -> Bool { switch (lhs, rhs) { @@ -82,6 +87,8 @@ extension IAPError: Equatable { return (lhs as NSError) == (rhs as NSError) case (.receiptNotFound, .receiptNotFound): return true + case let (.refund(lhs), .refund(rhs)): + return lhs == rhs case (.unknown, .unknown): return true default: @@ -89,3 +96,5 @@ extension IAPError: Equatable { } } } + +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/Flare/Classes/Models/RefundError.swift b/Sources/Flare/Classes/Models/RefundError.swift new file mode 100644 index 000000000..b7577599a --- /dev/null +++ b/Sources/Flare/Classes/Models/RefundError.swift @@ -0,0 +1,14 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +/// It encompasses all types of refund errors. +public enum RefundError: Error, Equatable { + /// The duplicate refund request. + case duplicateRequest + /// The refund request failed. + case failed +} diff --git a/Sources/Flare/Classes/Models/RefundRequestStatus.swift b/Sources/Flare/Classes/Models/RefundRequestStatus.swift new file mode 100644 index 000000000..e7c69cf8f --- /dev/null +++ b/Sources/Flare/Classes/Models/RefundRequestStatus.swift @@ -0,0 +1,18 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +/// It encompasses all refund request states. +public enum RefundRequestStatus: Sendable { + /// A user cancelled the refund request. + case userCancelled + /// The request completed successfully. + case success + /// The refund request failed with an error. + case failed(error: Error) + /// The unknown error occurred. + case unknown +} diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index 001843387..85fc9be86 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -12,6 +12,7 @@ final class IAPProvider: IIAPProvider { private let productProvider: IProductProvider private let paymentProvider: IPaymentProvider private let receiptRefreshProvider: IReceiptRefreshProvider + private let refundProvider: IRefundProvider // MARK: Initialization @@ -19,12 +20,16 @@ final class IAPProvider: IIAPProvider { paymentQueue: PaymentQueue = SKPaymentQueue.default(), productProvider: IProductProvider = ProductProvider(), paymentProvider: IPaymentProvider = PaymentProvider(), - receiptRefreshProvider: IReceiptRefreshProvider = ReceiptRefreshProvider() + receiptRefreshProvider: IReceiptRefreshProvider = ReceiptRefreshProvider(), + refundProvider: IRefundProvider = RefundProvider( + systemInfoProvider: SystemInfoProvider() + ) ) { self.paymentQueue = paymentQueue self.productProvider = productProvider self.paymentProvider = paymentProvider self.receiptRefreshProvider = receiptRefreshProvider + self.refundProvider = refundProvider } // MARK: Internal @@ -124,4 +129,14 @@ final class IAPProvider: IIAPProvider { func removeTransactionObserver() { paymentProvider.removeTransactionObserver() } + + #if os(iOS) || VISION_OS + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func beginRefundRequest(productID: String) async throws -> RefundRequestStatus { + try await refundProvider.beginRefundRequest(productID: productID) + } + #endif } diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift index c4e88043b..45d08b835 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift @@ -79,4 +79,17 @@ public protocol IIAPProvider { /// /// - Note: This may require that the user authenticate. func removeTransactionObserver() + + #if os(iOS) || VISION_OS + /// Present the refund request sheet for the specified transaction in a window scene. + /// + /// - Parameter productID: The identifier of the transaction the user is requesting a refund for. + /// + /// - Returns: The result of the refund request. + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func beginRefundRequest(productID: String) async throws -> RefundRequestStatus + #endif } diff --git a/Sources/Flare/Classes/Providers/RefundProvider/IRefundProvider.swift b/Sources/Flare/Classes/Providers/RefundProvider/IRefundProvider.swift new file mode 100644 index 000000000..97ef2dd1c --- /dev/null +++ b/Sources/Flare/Classes/Providers/RefundProvider/IRefundProvider.swift @@ -0,0 +1,20 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +/// A type that can refund purchases. +protocol IRefundProvider { + #if os(iOS) || VISION_OS + /// Present the refund request sheet for the specified transaction in a window scene. + /// + /// - Parameter productID: The identifier of the transaction the user is requesting a refund for. + /// + /// - Returns: The result of the refund request. + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func beginRefundRequest(productID: String) async throws -> RefundRequestStatus + #endif +} diff --git a/Sources/Flare/Classes/Providers/RefundProvider/RefundProvider.swift b/Sources/Flare/Classes/Providers/RefundProvider/RefundProvider.swift new file mode 100644 index 000000000..f4a8adc8e --- /dev/null +++ b/Sources/Flare/Classes/Providers/RefundProvider/RefundProvider.swift @@ -0,0 +1,84 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if canImport(UIKit) + import UIKit +#endif +import StoreKit + +// MARK: - RefundProvider + +final class RefundProvider { + // MARK: Properties + + private let systemInfoProvider: ISystemInfoProvider + private let refundRequestProvider: IRefundRequestProvider + + // MARK: Initialization + + init( + systemInfoProvider: ISystemInfoProvider = SystemInfoProvider(), + refundRequestProvider: IRefundRequestProvider = RefundRequestProvider() + ) { + self.systemInfoProvider = systemInfoProvider + self.refundRequestProvider = refundRequestProvider + } + + // MARK: Private + + #if os(iOS) || VISION_OS + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + @MainActor + private func initRefundRequest( + transactionID: UInt64, + windowScene: UIWindowScene + ) async throws -> RefundRequestStatus { + let status = try await refundRequestProvider.beginRefundRequest( + transactionID: transactionID, + windowScene: windowScene + ) + return mapStatus(status) + } + + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + private func mapStatus(_ status: Result) -> RefundRequestStatus { + switch status { + case let .success(status): + switch status { + case .success: + return .success + case .userCancelled: + return .userCancelled + @unknown default: + return .unknown + } + case let .failure(error): + return .failed(error: error) + } + } + #endif +} + +// MARK: IRefundProvider + +extension RefundProvider: IRefundProvider { + #if os(iOS) || VISION_OS + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func beginRefundRequest(productID: String) async throws -> RefundRequestStatus { + let windowScene = try systemInfoProvider.currentScene + let transactionID = try await refundRequestProvider.verifyTransaction(productID: productID) + return try await initRefundRequest(transactionID: transactionID, windowScene: windowScene) + } + #endif +} diff --git a/Sources/Flare/Classes/Providers/RefundRequestProvider/IRefundRequestProvider.swift b/Sources/Flare/Classes/Providers/RefundRequestProvider/IRefundRequestProvider.swift new file mode 100644 index 000000000..87b84c2d2 --- /dev/null +++ b/Sources/Flare/Classes/Providers/RefundRequestProvider/IRefundRequestProvider.swift @@ -0,0 +1,47 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +#if canImport(UIKit) + import UIKit +#endif + +// MARK: - IRefundRequestProvider + +/// A type can create a refund request. +protocol IRefundRequestProvider { + /// Present the refund request sheet for the specified transaction in a window scene. + /// + /// - Parameters: + /// - transactionID: The identifier of the transaction the user is requesting a refund for. + /// - windowScene: The UIWindowScene that the system displays the sheet on. + /// + /// - Returns: The result of the refund request. + #if os(iOS) || VISION_OS + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + @MainActor + func beginRefundRequest( + transactionID: UInt64, + windowScene: UIWindowScene + ) async throws -> Result + + /// Verifies the latest user's transaction. + /// + /// - Parameter productID: The product identifier. + /// + /// - Returns: The identifier of the transaction. + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + @MainActor + func verifyTransaction(productID: String) async throws -> UInt64 + #endif +} diff --git a/Sources/Flare/Classes/Providers/RefundRequestProvider/RefundRequestProvider.swift b/Sources/Flare/Classes/Providers/RefundRequestProvider/RefundRequestProvider.swift new file mode 100644 index 000000000..360b62ef2 --- /dev/null +++ b/Sources/Flare/Classes/Providers/RefundRequestProvider/RefundRequestProvider.swift @@ -0,0 +1,71 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if canImport(UIKit) + import UIKit +#endif +import StoreKit + +// MARK: - RefundRequestProvider + +final class RefundRequestProvider {} + +// MARK: IRefundRequestProvider + +extension RefundRequestProvider: IRefundRequestProvider { + #if os(iOS) || VISION_OS + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + @MainActor + func beginRefundRequest( + transactionID: UInt64, + windowScene: UIWindowScene + ) async throws -> Result { + do { + let status = try await StoreKit.Transaction.beginRefundRequest(for: transactionID, in: windowScene) + return .success(status) + } catch { + return .failure(mapError(error)) + } + } + + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func verifyTransaction(productID: String) async throws -> UInt64 { + guard let state = await StoreKit.Transaction.latest(for: productID) else { + throw IAPError.transactionNotFound(productID: productID) + } + + switch state { + case let .verified(transaction): + return transaction.id + case let .unverified(_, result): + throw result + } + } + + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + private func mapError(_ error: Error) -> IAPError { + if let skError = error as? StoreKit.Transaction.RefundRequestError { + switch skError { + case .duplicateRequest: + return .refund(error: .duplicateRequest) + case .failed: + return .refund(error: .failed) + @unknown default: + return .unknown + } + } + return .unknown + } + #endif +} diff --git a/Sources/Flare/Classes/Providers/SystemInfoProvider/ISystemInfoProvider.swift b/Sources/Flare/Classes/Providers/SystemInfoProvider/ISystemInfoProvider.swift new file mode 100644 index 000000000..3006113e7 --- /dev/null +++ b/Sources/Flare/Classes/Providers/SystemInfoProvider/ISystemInfoProvider.swift @@ -0,0 +1,18 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if canImport(UIKit) + import UIKit +#endif + +// MARK: - ISystemInfoProvider + +/// A type that provides the system info. +protocol ISystemInfoProvider { + #if os(iOS) || VISION_OS + /// The current window scene. + var currentScene: UIWindowScene { get throws } + #endif +} diff --git a/Sources/Flare/Classes/Providers/SystemInfoProvider/SystemInfoProvider.swift b/Sources/Flare/Classes/Providers/SystemInfoProvider/SystemInfoProvider.swift new file mode 100644 index 000000000..6f7c5b417 --- /dev/null +++ b/Sources/Flare/Classes/Providers/SystemInfoProvider/SystemInfoProvider.swift @@ -0,0 +1,54 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if canImport(UIKit) + import UIKit +#endif + +// MARK: - SystemInfoProvider + +final class SystemInfoProvider { + // MARK: Properties + + #if os(iOS) || VISION_OS + private let scenesHolder: IScenesHolder + + // MARK: Initialization + + init(scenesHolder: IScenesHolder = UIApplication.shared) { + self.scenesHolder = scenesHolder + } + #endif +} + +// MARK: ISystemInfoProvider + +extension SystemInfoProvider: ISystemInfoProvider { + #if os(iOS) || VISION_OS + @available(iOS 13.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + @MainActor + var currentScene: UIWindowScene { + get throws { + var scenes = scenesHolder.connectedScenes + .filter { $0.activationState == .foregroundActive } + + #if DEBUG && targetEnvironment(simulator) + if scenes.isEmpty, ProcessInfo.isRunningUnitTests { + scenes = scenesHolder.connectedScenes + } + #endif + + guard let windowScene = scenes.first as? UIWindowScene else { + throw IAPError.unknown + } + + return windowScene + } + } + #endif +} diff --git a/Sources/Flare/Flare.swift b/Sources/Flare/Flare.swift index e733b19e5..a4505be9b 100644 --- a/Sources/Flare/Flare.swift +++ b/Sources/Flare/Flare.swift @@ -5,6 +5,10 @@ import StoreKit +#if os(iOS) || VISION_OS + import UIKit +#endif + // MARK: - Flare public final class Flare { @@ -81,4 +85,14 @@ extension Flare: IFlare { public func removeTransactionObserver() { iapProvider.removeTransactionObserver() } + + #if os(iOS) || VISION_OS + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + public func beginRefundRequest(productID: String) async throws -> RefundRequestStatus { + try await iapProvider.beginRefundRequest(productID: productID) + } + #endif } diff --git a/Sources/Flare/IFlare.swift b/Sources/Flare/IFlare.swift index 36676fa09..6d6a146b7 100644 --- a/Sources/Flare/IFlare.swift +++ b/Sources/Flare/IFlare.swift @@ -76,4 +76,17 @@ public protocol IFlare { /// /// - Note: This may require that the user authenticate. func removeTransactionObserver() + + #if os(iOS) || VISION_OS + /// Present the refund request sheet for the specified transaction in a window scene. + /// + /// - Parameter productID: The identifier of the transaction the user is requesting a refund for. + /// + /// - Returns: The result of the refund request. + @available(iOS 15.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func beginRefundRequest(productID: String) async throws -> RefundRequestStatus + #endif } diff --git a/Tests/FlareTests/Helpers/WindowSceneFactory.swift b/Tests/FlareTests/Helpers/WindowSceneFactory.swift new file mode 100644 index 000000000..337484a51 --- /dev/null +++ b/Tests/FlareTests/Helpers/WindowSceneFactory.swift @@ -0,0 +1,21 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if os(iOS) || VISION_OS + import ObjectsFactory + import UIKit + + final class WindowSceneFactory { + static func makeWindowScene() -> UIWindowScene { + do { + let session = try ObjectsFactory.create(UISceneSession.self) + let scene = try ObjectsFactory.create(UIWindowScene.self, properties: ["session": session]) + return scene + } catch { + fatalError(error.localizedDescription) + } + } + } +#endif diff --git a/Tests/FlareTests/Mocks/IAPProviderMock.swift b/Tests/FlareTests/Mocks/IAPProviderMock.swift index a6ea5b23a..5b97f58eb 100644 --- a/Tests/FlareTests/Mocks/IAPProviderMock.swift +++ b/Tests/FlareTests/Mocks/IAPProviderMock.swift @@ -137,4 +137,17 @@ final class IAPProviderMock: IIAPProvider { fatalError("An unknown type") } } + + var invokedBeginRefundRequest = false + var invokedBeginRefundRequestCount = 0 + var invokedBeginRefundRequestParameters: (productID: String, Void)? + var invokedBeginRefundRequestParametersList = [(productID: String, Void)]() + var stubbedBeginRefundRequest: RefundRequestStatus! + func beginRefundRequest(productID: String) async throws -> RefundRequestStatus { + invokedBeginRefundRequest = true + invokedBeginRefundRequestCount += 1 + invokedBeginRefundRequestParameters = (productID, ()) + invokedBeginRefundRequestParametersList.append((productID, ())) + return stubbedBeginRefundRequest + } } diff --git a/Tests/FlareTests/Mocks/RefundProviderMock.swift b/Tests/FlareTests/Mocks/RefundProviderMock.swift new file mode 100644 index 000000000..c6a1872ac --- /dev/null +++ b/Tests/FlareTests/Mocks/RefundProviderMock.swift @@ -0,0 +1,22 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare + +final class RefundProviderMock: IRefundProvider { + var invokedBeginRefundRequest = false + var invokedBeginRefundRequestCount = 0 + var invokedBeginRefundRequestParameters: (productID: String, Void)? + var invokedBeginRefundRequestParametersList = [(productID: String, Void)]() + var stubbedBeginRefundRequest: RefundRequestStatus! + + func beginRefundRequest(productID: String) async throws -> RefundRequestStatus { + invokedBeginRefundRequest = true + invokedBeginRefundRequestCount += 1 + invokedBeginRefundRequestParameters = (productID, ()) + invokedBeginRefundRequestParametersList.append((productID, ())) + return stubbedBeginRefundRequest + } +} diff --git a/Tests/FlareTests/Mocks/RefundRequestProviderMock.swift b/Tests/FlareTests/Mocks/RefundRequestProviderMock.swift new file mode 100644 index 000000000..7639d7aa0 --- /dev/null +++ b/Tests/FlareTests/Mocks/RefundRequestProviderMock.swift @@ -0,0 +1,67 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if os(iOS) || VISION_OS + @testable import Flare + import StoreKit + import UIKit + + @available(iOS 15.0, macCatalyst 15.0, *) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + final class RefundRequestProviderMock: IRefundRequestProvider { + var invokedBeginRefundRequest = false + var invokedBeginRefundRequestCount = 0 + var invokedBeginRefundRequestParameters: (transactionID: UInt64, windowScene: UIWindowScene)? + var invokedBeginRefundRequestParametersList = [(transactionID: UInt64, windowScene: UIWindowScene)]() + var stubbedBeginRefundRequest: Result! + + func beginRefundRequest( + transactionID: UInt64, + windowScene: UIWindowScene + ) async throws -> Result { + invokedBeginRefundRequest = true + invokedBeginRefundRequestCount += 1 + invokedBeginRefundRequestParameters = (transactionID, windowScene) + invokedBeginRefundRequestParametersList.append((transactionID, windowScene)) + + switch stubbedBeginRefundRequest { + case let .success(status): + return .success(mapToSkStatus(status)) + case let .failure(error): + return .failure(error) + case .none: + fatalError() + } + } + + var invokedVerifyTransaction = false + var invokedVerifyTransactionCount = 0 + var invokedVerifyTransactionParameters: (productID: String, Void)? + var invokedVerifyTransactionParametersList = [(productID: String, Void)]() + var stubbedVerifyTransaction: UInt64! + + func verifyTransaction(productID: String) async throws -> UInt64 { + invokedVerifyTransaction = true + invokedVerifyTransactionCount += 1 + invokedVerifyTransactionParameters = (productID, ()) + invokedVerifyTransactionParametersList.append((productID, ())) + return stubbedVerifyTransaction + } + + // MARK: Private + + private func mapToSkStatus(_ status: RefundRequestStatus) -> StoreKit.Transaction.RefundRequestStatus { + switch status { + case .success: + return .success + case .userCancelled: + return .userCancelled + default: + fatalError() + } + } + } +#endif diff --git a/Tests/FlareTests/Mocks/ScenesHolderMock.swift b/Tests/FlareTests/Mocks/ScenesHolderMock.swift new file mode 100644 index 000000000..2330df924 --- /dev/null +++ b/Tests/FlareTests/Mocks/ScenesHolderMock.swift @@ -0,0 +1,25 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +#if canImport(UIKit) + import UIKit +#endif + +// MARK: - ScenesHolderMock + +final class ScenesHolderMock: IScenesHolder { + #if os(iOS) || VISION_OS + var invokedConnectedScenesGetter = false + var invokedConnectedScenesGetterCount = 0 + var stubbedConnectedScenes: Set! = [] + + var connectedScenes: Set { + invokedConnectedScenesGetter = true + invokedConnectedScenesGetterCount += 1 + return stubbedConnectedScenes + } + #endif +} diff --git a/Tests/FlareTests/Mocks/SystemInfoProviderMock.swift b/Tests/FlareTests/Mocks/SystemInfoProviderMock.swift new file mode 100644 index 000000000..6f7268a55 --- /dev/null +++ b/Tests/FlareTests/Mocks/SystemInfoProviderMock.swift @@ -0,0 +1,34 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +#if canImport(UIKit) + import UIKit +#endif + +// MARK: - SystemInfoProviderMock + +final class SystemInfoProviderMock: ISystemInfoProvider { + #if os(iOS) || VISION_OS + var invokedCurrentSceneGetter = false + var invokedCurrentSceneGetterCount = 0 + var stubbedCurrentScene: Result! + + var currentScene: UIWindowScene { + get throws { + invokedCurrentSceneGetter = true + invokedCurrentSceneGetterCount += 1 + switch stubbedCurrentScene { + case let .success(scene): + return scene + case let .failure(error): + throw error + default: + fatalError() + } + } + } + #endif +} diff --git a/Tests/FlareTests/UnitTests/FlareTests.swift b/Tests/FlareTests/UnitTests/FlareTests.swift index 01e403dbd..87aed5ebe 100644 --- a/Tests/FlareTests/UnitTests/FlareTests.swift +++ b/Tests/FlareTests/UnitTests/FlareTests.swift @@ -235,6 +235,34 @@ class FlareTests: XCTestCase { // then XCTAssertTrue(iapProviderMock.invokedAddTransactionObserver) } + + #if os(iOS) || VISION_OS + @available(iOS 15.0, *) + func test_thatFlareRefundsPurchase() async throws { + // given + iapProviderMock.stubbedBeginRefundRequest = .success + + // when + let state = try await flare.beginRefundRequest(productID: .productID) + + // then + if case .success = state {} + else { XCTFail("state must be `success`") } + } + + @available(iOS 15.0, *) + func test_thatFlareThrowsAnError_whenBeginRefundRequestFailed() async throws { + // given + iapProviderMock.stubbedBeginRefundRequest = .failed(error: IAPError.unknown) + + // when + let state = try await flare.beginRefundRequest(productID: .productID) + + // then + if case let .failed(error) = state { XCTAssertEqual(error as NSError, IAPError.unknown as NSError) } + else { XCTFail("state must be `failed`") } + } + #endif } // MARK: - Constants diff --git a/Tests/FlareTests/UnitTests/Helpers/ProcessInfoTests.swift b/Tests/FlareTests/UnitTests/Helpers/ProcessInfoTests.swift new file mode 100644 index 000000000..e98c6f155 --- /dev/null +++ b/Tests/FlareTests/UnitTests/Helpers/ProcessInfoTests.swift @@ -0,0 +1,13 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import XCTest + +final class ProcessInfoTests: XCTestCase { + func test_thatProcessInfoReturnsSsRunningUnitTestsEqualsToTrue_whenRuggingUnderTests() { + XCTAssertTrue(ProcessInfo.isRunningUnitTests) + } +} diff --git a/Tests/FlareTests/UnitTests/Models/IAPErrorTests.swift b/Tests/FlareTests/UnitTests/Models/IAPErrorTests.swift new file mode 100644 index 000000000..d1d1fa183 --- /dev/null +++ b/Tests/FlareTests/UnitTests/Models/IAPErrorTests.swift @@ -0,0 +1,62 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import StoreKit +import XCTest + +final class IAPErrorTests: XCTestCase { + func test_thatIAPErrorInstantiatesANewInstanceFromSkError_whenCodeIsEqualToPaymentNotAllowed() { + // given + let skError = SKError(SKError.Code.paymentNotAllowed) + + // when + let error = IAPError(error: skError) + + // then + XCTAssertEqual(error, IAPError.paymentNotAllowed) + } + + func test_thatIAPErrorInstantiatesANewInstanceFromSkError_whenCodeIsEqualToPaymentCancelled() { + // given + let skError = SKError(SKError.Code.paymentCancelled) + + // when + let error = IAPError(error: skError) + + // then + XCTAssertEqual(error, IAPError.paymentCancelled) + } + + func test_thatIAPErrorInstantiatesANewInstanceFromSkError_whenCodeIsEqualToStoreProductNotAvailable() { + // given + let skError = SKError(SKError.Code.storeProductNotAvailable) + + // when + let error = IAPError(error: skError) + + // then + XCTAssertEqual(error, IAPError.storeProductNotAvailable) + } + + func test_thatIAPErrorInstantiatesANewInstanceFromSkError_whenCodeIsEqualToUnknown() { + // given + let skError = SKError(SKError.Code.unknown) + + // when + let error = IAPError(error: skError) + + // then + XCTAssertEqual(error, IAPError.storeTrouble) + } + + func test_thatIAPErrorInstantiatesANewInstanceFromSkError_whenErrorIsNil() { + // when + let error = IAPError(error: nil) + + // then + XCTAssertEqual(error, IAPError.unknown) + } +} diff --git a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift index b97b668fb..06c322ac5 100644 --- a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift @@ -16,6 +16,8 @@ class IAPProviderTests: XCTestCase { private var productProviderMock: ProductProviderMock! private var paymentProviderMock: PaymentProviderMock! private var receiptRefreshProviderMock: ReceiptRefreshProviderMock! + private var refundProviderMock: RefundProviderMock! + private var iapProvider: IIAPProvider! // MARK: - XCTestCase @@ -26,11 +28,13 @@ class IAPProviderTests: XCTestCase { productProviderMock = ProductProviderMock() paymentProviderMock = PaymentProviderMock() receiptRefreshProviderMock = ReceiptRefreshProviderMock() + refundProviderMock = RefundProviderMock() iapProvider = IAPProvider( paymentQueue: paymentQueueMock, productProvider: productProviderMock, paymentProvider: paymentProviderMock, - receiptRefreshProvider: receiptRefreshProviderMock + receiptRefreshProvider: receiptRefreshProviderMock, + refundProvider: refundProviderMock ) } @@ -39,6 +43,7 @@ class IAPProviderTests: XCTestCase { productProviderMock = nil paymentProviderMock = nil receiptRefreshProviderMock = nil + refundProviderMock = nil iapProvider = nil super.tearDown() } @@ -343,6 +348,34 @@ class IAPProviderTests: XCTestCase { // then XCTAssertEqual(errorResult as? NSError, IAPError.unknown as NSError) } + + #if os(iOS) || VISION_OS + @available(iOS 15.0, *) + func test_thatIAPProviderRefundsPurchase() async throws { + // given + refundProviderMock.stubbedBeginRefundRequest = .success + + // when + let state = try await iapProvider.beginRefundRequest(productID: .productID) + + // then + if case .success = state {} + else { XCTFail("state must be `success`") } + } + + @available(iOS 15.0, *) + func test_thatFlareThrowsAnError_whenBeginRefundRequestFailed() async throws { + // given + refundProviderMock.stubbedBeginRefundRequest = .failed(error: IAPError.unknown) + + // when + let state = try await iapProvider.beginRefundRequest(productID: .productID) + + // then + if case let .failed(error) = state { XCTAssertEqual(error as NSError, IAPError.unknown as NSError) } + else { XCTFail("state must be `failed`") } + } + #endif } // MARK: - Constants diff --git a/Tests/FlareTests/UnitTests/Providers/RefundProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/RefundProviderTests.swift new file mode 100644 index 000000000..90908c7ea --- /dev/null +++ b/Tests/FlareTests/UnitTests/Providers/RefundProviderTests.swift @@ -0,0 +1,110 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if os(iOS) || VISION_OS + @testable import Flare + import XCTest + + @available(iOS 15.0, *) + class RefundProviderTests: XCTestCase { + // MARK: - Properties + + private var systemInfoProviderMock: SystemInfoProviderMock! + private var refundRequestProviderMock: RefundRequestProviderMock! + + private var sut: RefundProvider! + + // MARK: - XCTestCase + + override func setUp() { + super.setUp() + refundRequestProviderMock = RefundRequestProviderMock() + systemInfoProviderMock = SystemInfoProviderMock() + sut = RefundProvider(systemInfoProvider: systemInfoProviderMock, refundRequestProvider: refundRequestProviderMock) + } + + override func tearDown() { + refundRequestProviderMock = nil + systemInfoProviderMock = nil + sut = nil + super.tearDown() + } + + // MARK: - Tests + + func testThatRefundProviderThrowsAnErrorWhenVerificationDidFail() async throws { + // given + refundRequestProviderMock.stubbedVerifyTransaction = nil + systemInfoProviderMock.stubbedCurrentScene = .failure(IAPError.unknown) + + // when + var resultError: Error? + do { + _ = try await sut.beginRefundRequest(productID: .productID) + } catch { + resultError = error + } + + // then + XCTAssertEqual(resultError as? NSError, IAPError.unknown as NSError) + } + + func testThatRefundProviderThrowsAnErrorWhenRefundRequestDidFail() async throws { + // given + refundRequestProviderMock.stubbedVerifyTransaction = .transactionID + refundRequestProviderMock.stubbedBeginRefundRequest = .failure(IAPError.unknown) + systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) + + // when + let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) + + // then + if case .failed = status {} + else { XCTFail("The status must be `failed`") } + XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) + } + + func testThatRefundProviderReturnsSuccessStatusWhenRefundRequestCompleted() async throws { + // given + refundRequestProviderMock.stubbedVerifyTransaction = .transactionID + refundRequestProviderMock.stubbedBeginRefundRequest = .success(.success) + systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) + + // when + let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) + + // then + if case .success = status {} + else { XCTFail("The status must be `success`") } + XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) + } + + func testThatRefundProviderReturnsUserCancelledStatusWhenUserCancelledRequest() async throws { + // given + refundRequestProviderMock.stubbedVerifyTransaction = .transactionID + refundRequestProviderMock.stubbedBeginRefundRequest = .success(.userCancelled) + systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) + + // when + let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) + + // then + if case .userCancelled = status {} + else { XCTFail("The status must be `userCancelled`") } + XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) + } + } + + // MARK: - Constants + + private extension UInt64 { + static let transactionID: UInt64 = 5 + } + + private extension String { + static let productID: String = "product_id" + } + +#endif diff --git a/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift new file mode 100644 index 000000000..6488c5ea6 --- /dev/null +++ b/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift @@ -0,0 +1,61 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import XCTest + +#if os(iOS) || VISION_OS + + @available(iOS 15.0, *) + final class RefundRequestProviderTests: XCTestCase { + // MARK: Proeprties + + private var sut: RefundRequestProvider! + + // MARK: XCTestCase + + override func setUp() { + super.setUp() + sut = RefundRequestProvider() + } + + override func tearDown() { + sut = nil + super.tearDown() + } + + // MARK: Tests + + @MainActor + func test_thatRefundRequestProviderThrowsAnUnknownError_whenRequestDidFailed() async throws { + // given + let windowScene = WindowSceneFactory.makeWindowScene() + + // when + let status = try await sut.beginRefundRequest( + transactionID: .transactionID, + windowScene: windowScene + ) + + // then + if case let .failure(error) = status { + XCTAssertEqual(error as NSError, IAPError.refund(error: .failed) as NSError) + } else { + XCTFail("state must be `failure`") + } + } + } + + // MARK: - Constants + + private extension UInt64 { + static let transactionID: UInt64 = 0 + } + + private extension String { + static let productID: String = "product_id" + } + +#endif diff --git a/Tests/FlareTests/UnitTests/Providers/SystemInfoProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/SystemInfoProviderTests.swift new file mode 100644 index 000000000..2dee81c07 --- /dev/null +++ b/Tests/FlareTests/UnitTests/Providers/SystemInfoProviderTests.swift @@ -0,0 +1,59 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if os(iOS) || VISION_OS + @testable import Flare + import XCTest + + final class SystemInfoProviderTests: XCTestCase { + // MARK: Properties + + private var sut: SystemInfoProvider! + private var scenesHolderMock: ScenesHolderMock! + + // MARK: Initialization + + override func setUp() { + super.setUp() + scenesHolderMock = ScenesHolderMock() + sut = SystemInfoProvider(scenesHolder: scenesHolderMock) + } + + override func tearDown() { + scenesHolderMock = nil + sut = nil + super.tearDown() + } + + // MARK: Tests + + @MainActor + func test_thatScenesHolderReturnsCurrentScene() throws { + // given + let windowScene = WindowSceneFactory.makeWindowScene() + scenesHolderMock.stubbedConnectedScenes = Set(arrayLiteral: windowScene) + + // when + let scene = try sut.currentScene + + // then + XCTAssertEqual(windowScene, scene) + } + + @MainActor + func test_thatScenesHolderThrowsAnErrorWhenThereIsNoActiveWindowScene() { + // when + var receivedError: Error? + do { + _ = try sut.currentScene + } catch { + receivedError = error + } + + // then + XCTAssertEqual(receivedError as? NSError, IAPError.unknown as NSError) + } + } +#endif diff --git a/codecov.yml b/codecov.yml index b41560430..8bb858ab5 100644 --- a/codecov.yml +++ b/codecov.yml @@ -32,7 +32,7 @@ coverage: target: 85% # Allow coverage to drop by X% - threshold: 5% + threshold: 50% changes: no comment: From 9f8b083e6132f31c75e5ef319d9efc738ce2248d Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 16 Oct 2023 19:06:23 +0300 Subject: [PATCH 30/44] Integrate `danger` (#7) * Integrate `danger` * Configure `danger` using an external repository * Add `Gemfile` * Update `Makefile` * Update `danger.yml` * Update `CHANGELOG.md` * Update `danger.yml` --- .github/workflows/danger.yml | 29 ++++++++++++++++ CHANGELOG.md | 3 ++ Dangerfile | 1 + Gemfile | 3 ++ Gemfile.lock | 66 ++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 .github/workflows/danger.yml create mode 100644 Dangerfile create mode 100644 Gemfile create mode 100644 Gemfile.lock diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml new file mode 100644 index 000000000..1a0ab5292 --- /dev/null +++ b/.github/workflows/danger.yml @@ -0,0 +1,29 @@ +name: Danger + +on: + pull_request: + types: [synchronize, opened, reopened, labeled, unlabeled, edited] + +env: + LC_CTYPE: en_US.UTF-8 + LANG: en_US.UTF-8 + +jobs: + run-danger: + runs-on: ubuntu-latest + steps: + - name: ruby setup + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7 + bundler-cache: true + - name: Checkout code + uses: actions/checkout@v2 + - name: Setup gems + run: | + gem install bundler + bundle install --clean --path vendor/bundle + - name: danger + env: + DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} + run: bundle exec danger --verbose \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c6f5e99bd..b1cb7c567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Integrate `danger` + - Added in Pull Request [#7](https://github.com/space-code/flare/pull/7). + - Implement a refund for purchases - Added in Pull Request [#6](https://github.com/space-code/flare/pull/6). diff --git a/Dangerfile b/Dangerfile new file mode 100644 index 000000000..b26698244 --- /dev/null +++ b/Dangerfile @@ -0,0 +1 @@ +danger.import_dangerfile(github: 'space-code/dangerfile') \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..20dff646e --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem 'danger' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..15dfc08f2 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,66 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.5) + public_suffix (>= 2.0.2, < 6.0) + base64 (0.1.1) + claide (1.1.0) + claide-plugins (0.9.2) + cork + nap + open4 (~> 1.3) + colored2 (3.1.2) + cork (0.3.0) + colored2 (~> 3.1) + danger (9.3.2) + claide (~> 1.0) + claide-plugins (>= 0.9.2) + colored2 (~> 3.1) + cork (~> 0.1) + faraday (>= 0.9.0, < 3.0) + faraday-http-cache (~> 2.0) + git (~> 1.13) + kramdown (~> 2.3) + kramdown-parser-gfm (~> 1.0) + no_proxy_fix + octokit (~> 6.0) + terminal-table (>= 1, < 4) + faraday (2.7.11) + base64 + faraday-net_http (>= 2.0, < 3.1) + ruby2_keywords (>= 0.0.4) + faraday-http-cache (2.5.0) + faraday (>= 0.8) + faraday-net_http (3.0.2) + git (1.18.0) + addressable (~> 2.8) + rchardet (~> 1.8) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + nap (1.1.0) + no_proxy_fix (0.1.2) + octokit (6.1.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) + open4 (1.3.4) + public_suffix (5.0.3) + rchardet (1.8.0) + rexml (3.2.6) + ruby2_keywords (0.0.5) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.5.0) + +PLATFORMS + x86_64-darwin-22 + +DEPENDENCIES + danger + +BUNDLED WITH + 2.4.10 From 96b1786237a05789e97d829f85add3abb3f28fc2 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Tue, 24 Oct 2023 19:06:05 +0300 Subject: [PATCH 31/44] Add badges for `Swift Version Compatibility` and `Platform Compatibility` (#8) * Add `Swift Version Compatibility` & `Platform Compatibility` badges * Update `CHANGELOG.md` --- CHANGELOG.md | 3 +++ README.md | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1cb7c567..1b7ef5e23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Add badges for `Swift Version Compatibility` and `Platform Compatibility` + - Added in Pull Request [#7](https://github.com/space-code/flare/pull/8). + - Integrate `danger` - Added in Pull Request [#7](https://github.com/space-code/flare/pull/7). diff --git a/README.md b/README.md index 4505f73b7..18bfb339a 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,11 @@

Liscence -Platform -Swift5.7 +Swift Compability +Platform Compability CI CodeCov -CI

## Description From d64f9b947cd2ca6ef374688c2307647768fc5e26 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 5 Jan 2024 09:16:00 +0100 Subject: [PATCH 32/44] Integrate the `StoreKit2` purchase method (#10) * Implement a common store kit product - Create an `ISKProduct` interface that describes a common `StoreKit` object - Create `SK1StoreProduct` and `SK2StoreProduct` classes that describe products for StoreKit and StoreKit2, respectively * Implement fetching products using the `StoreKit2` API Currently, a `ProductProvider` provides the ability to fetch products via the new `StoreKit` API. If the current OS version is higher than iOS 15, tvOS 15, watchOS 8, macOS 12, the new API can be used when calling `fetch(_:) async throws -> [StoreProduct]`; otherwise, the old API will be called. Additionally, this commit includes: - Remove unnecessary access control modifiers - Write code comments and provide usage examples * Write comments for public interfaces - Write comments for the `IAPProvider` - Write comments for the `ReceiptRefreshProvider` * Update `ci.yml` * Fix action errors - Update `Flare.xcscheme` - Update `test_thatIAPProviderFetchesSK2Products_whenProductsAreAvailable` test * Update the `Ruby` version from `2.7` to `3.1.4` * Implement `StoreTransaction` model The `StoreTransaction` model is a wrapper for both `SK1StoreTransaction` and `SK2StoreTransaction` * Create a `StoreTransaction` object The `StoreTransaction` object serves as a wrapper for both `SKTransaction` and `StoreKit.Transaction`. * Update `purchase(_:)` methods' parameters Replace purchasing a product by ID with passing a product object. * Integrate a host app for unit-tests A host app provides a means to test in-app purchases using the StoreKit2 API. * Refactor unit tests - Write unit tests for the new methods - Improve the readability of the existing test cases * Refactor the test target for supported platforms * Update `ci.yml` - Implement testing on different OS versions - Temporarily drop testing on watchOS * Remove `ObjectFactory` dependency * Update `project.yml` * Refactor test cases * Update `ci.yml` * Update `CHANGELOG.md` * Fix `Package.swift` & `Package@swift-5.7.swift` * Add `Package@swift-5.8.swift` * Implement integration tests - Create a new target that contains the integration tests - Implement three test plans: `AllTests`, `UnitTests`, `IntegrationTests` * Update configuration - Update the GitHub Actions CI script to enable testing on various platforms * Fix typos * Write a script for merging test results from various platforms * Implement the `finish(_:)` transaction method * Upload test coverate reports * Rename step --- .github/workflows/ci.yml | 214 ++++++++++++--- .github/workflows/danger.yml | 2 +- .gitignore | 1 + .swiftlint.yml | 2 + .../xcshareddata/xcschemes/Flare.xcscheme | 17 ++ .../xcschemes/FlareTests.xcscheme | 52 ++++ CHANGELOG.md | 3 + Makefile | 8 +- Package.resolved | 9 - Package.swift | 2 - Package@swift-5.7.swift | 2 - Package@swift-5.8.swift | 36 +++ Sources/Flare/Classes/Common/Types.swift | 2 + .../Formatters/NumberFormatter+.swift | 23 ++ .../Locale/Locale+CurrencyCode.swift | 20 ++ .../Classes/Extensions/ProductType+.swift | 40 +++ .../Classes/Helpers/Async/AsyncHandler.swift | 22 ++ .../AsyncSequence/AsyncSequence+Stream.swift | 15 ++ .../PaymentTransaction.swift | 4 + .../ITransactionListener.swift | 14 + .../TransactionListener.swift | 81 ++++++ Sources/Flare/Classes/Models/IAPError.swift | 32 +++ .../Internal/Protocols/ISKProduct.swift | 36 +++ .../Protocols/IStoreTransaction.swift | 32 +++ .../Models/Internal/SK1StoreProduct.swift | 72 +++++ .../Models/Internal/SK1StoreTransaction.swift | 65 +++++ .../Models/Internal/SK2StoreProduct.swift | 71 +++++ .../Models/Internal/SK2StoreTransaction.swift | 69 +++++ .../Models/Internal/StoreEnvironment.swift | 59 ++++ .../Classes/Models/ProductCategory.swift | 14 + .../Flare/Classes/Models/ProductType.swift | 21 ++ .../Flare/Classes/Models/StoreProduct.swift | 88 ++++++ .../Classes/Models/StoreTransaction.swift | 91 +++++++ .../Classes/Models/SubscriptionPeriod.swift | 100 +++++++ .../Classes/Models/VerificationError.swift | 10 + .../Providers/IAPProvider/IAPProvider.swift | 124 ++++++--- .../Providers/IAPProvider/IIAPProvider.swift | 57 +++- .../PaymentProvider/IPaymentProvider.swift | 2 +- .../PaymentProvider/PaymentProvider.swift | 13 + .../ProductProvider/IProductProvider.swift | 24 +- .../ProductProvider/ProductProvider.swift | 41 ++- .../PurchaseProvider/IPurchaseProvider.swift | 53 ++++ .../PurchaseProvider/PurchaseProvider.swift | 146 ++++++++++ .../IReceiptRefreshProvider.swift | 2 +- .../ReceiptRefreshProvider.swift | 25 ++ .../RefundProvider/IRefundProvider.swift | 1 + .../RefundProvider/RefundProvider.swift | 1 + Sources/Flare/Flare.swift | 44 ++- Sources/Flare/IFlare.swift | 59 +++- .../Helpers/WindowSceneFactory.swift | 21 -- .../Mocks/ProductProviderMock.swift | 26 -- Tests/FlareTests/UnitTests/FlareTests.swift | 132 +++------ .../Providers/IAPProviderTests.swift | 253 ++++-------------- .../Providers/ProductProviderTests.swift | 51 ++-- .../Providers/PurchaseProviderTests.swift | 104 +++++++ .../ReceiptRefreshProviderTests.swift | 43 ++- .../Providers/RefundProviderTests.swift | 108 ++++---- .../RefundRequestProviderTests.swift | 40 +-- .../Providers/SystemInfoProviderTests.swift | 50 ++-- .../TestHelpers/Extensions/Result+.swift | 26 ++ .../TestHelpers/Extensions/XCTestCase+.swift | 35 +++ .../TestHelpers/Fakes/SKProduct+Fake.swift | 15 ++ .../TestHelpers/Fakes/StoreProduct+Fake.swift | 13 + .../Fakes/StoreTransactionFake.swift | 12 + .../Helpers/AvailabilityChecker.swift | 14 + .../Helpers/PurchaseManagerTestHelper.swift | 0 .../Helpers/WindowSceneFactory.swift | 14 + .../Mocks/AppStoreReceiptProviderMock.swift | 0 .../TestHelpers}/Mocks/FileManagerMock.swift | 0 .../TestHelpers}/Mocks/IAPProviderMock.swift | 78 ++++-- .../Mocks/PaymentProviderMock.swift | 0 .../TestHelpers}/Mocks/PaymentQueueMock.swift | 0 .../Mocks/PaymentTransactionMock.swift | 0 .../TestHelpers}/Mocks/ProductMock.swift | 0 .../Mocks/ProductProviderMock.swift | 53 ++++ .../Mocks/ProductResponseMock.swift | 0 .../Mocks/ProductsRequestMock.swift | 0 .../Mocks/PurchaseProviderMock.swift | 81 ++++++ .../Mocks/ReceiptRefreshProviderMock.swift | 0 .../Mocks/ReceiptRefreshRequestFactory.swift | 0 .../Mocks/ReceiptRefreshRequestMock.swift | 0 .../Mocks/RefundProviderMock.swift | 0 .../Mocks/RefundRequestProviderMock.swift | 0 .../TestHelpers}/Mocks/ScenesHolderMock.swift | 0 .../Mocks/StoreTransactionMock.swift | 89 ++++++ .../Mocks/SystemInfoProviderMock.swift | 0 .../Stubs/StoreTransactionStub.swift | 57 ++++ Tests/IntegrationTests/Flare.storekit | 63 +++++ .../Helpers/Extensions/Result+.swift | 26 ++ .../Helpers/Extensions/XCTestCase+.swift | 35 +++ .../StoreSessionTestCase.swift | 31 +++ Tests/IntegrationTests/Tests/FlareTests.swift | 158 +++++++++++ .../Tests/IAPProviderTests.swift | 151 +++++++++++ .../Tests/ProductProviderHelper.swift | 44 +++ .../Tests/ProductProviderTests.swift | 59 ++++ .../Tests/PurchaseProviderTests.swift | 90 +++++++ Tests/TestPlans/AllTests.xctestplan | 44 +++ Tests/TestPlans/IntegrationTests.xctestplan | 37 +++ Tests/TestPlans/UnitTests.xctestplan | 37 +++ Tests/UnitTestHostApp/AppDelegate.swift | 30 +++ .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 98 +++++++ .../Assets.xcassets/Contents.json | 6 + Tests/UnitTestHostApp/Info.plist | 45 ++++ project.yml | 80 ++++++ scripts/setup_build_tools.sh | 8 + 106 files changed, 3643 insertions(+), 646 deletions(-) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/FlareTests.xcscheme create mode 100644 Package@swift-5.8.swift create mode 100644 Sources/Flare/Classes/Extensions/Formatters/NumberFormatter+.swift create mode 100644 Sources/Flare/Classes/Extensions/Locale/Locale+CurrencyCode.swift create mode 100644 Sources/Flare/Classes/Extensions/ProductType+.swift create mode 100644 Sources/Flare/Classes/Helpers/Async/AsyncHandler.swift create mode 100644 Sources/Flare/Classes/Helpers/AsyncSequence/AsyncSequence+Stream.swift create mode 100644 Sources/Flare/Classes/Listeners/TransactionListener/ITransactionListener.swift create mode 100644 Sources/Flare/Classes/Listeners/TransactionListener/TransactionListener.swift create mode 100644 Sources/Flare/Classes/Models/Internal/Protocols/ISKProduct.swift create mode 100644 Sources/Flare/Classes/Models/Internal/Protocols/IStoreTransaction.swift create mode 100644 Sources/Flare/Classes/Models/Internal/SK1StoreProduct.swift create mode 100644 Sources/Flare/Classes/Models/Internal/SK1StoreTransaction.swift create mode 100644 Sources/Flare/Classes/Models/Internal/SK2StoreProduct.swift create mode 100644 Sources/Flare/Classes/Models/Internal/SK2StoreTransaction.swift create mode 100644 Sources/Flare/Classes/Models/Internal/StoreEnvironment.swift create mode 100644 Sources/Flare/Classes/Models/ProductCategory.swift create mode 100644 Sources/Flare/Classes/Models/ProductType.swift create mode 100644 Sources/Flare/Classes/Models/StoreProduct.swift create mode 100644 Sources/Flare/Classes/Models/StoreTransaction.swift create mode 100644 Sources/Flare/Classes/Models/SubscriptionPeriod.swift create mode 100644 Sources/Flare/Classes/Models/VerificationError.swift create mode 100644 Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift create mode 100644 Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift delete mode 100644 Tests/FlareTests/Helpers/WindowSceneFactory.swift delete mode 100644 Tests/FlareTests/Mocks/ProductProviderMock.swift create mode 100644 Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Extensions/Result+.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Extensions/XCTestCase+.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Fakes/SKProduct+Fake.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Fakes/StoreProduct+Fake.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Fakes/StoreTransactionFake.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Helpers/AvailabilityChecker.swift rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Helpers/PurchaseManagerTestHelper.swift (100%) create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Helpers/WindowSceneFactory.swift rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/AppStoreReceiptProviderMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/FileManagerMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/IAPProviderMock.swift (60%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/PaymentProviderMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/PaymentQueueMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/PaymentTransactionMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/ProductMock.swift (100%) create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductProviderMock.swift rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/ProductResponseMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/ProductsRequestMock.swift (100%) create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/ReceiptRefreshProviderMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/ReceiptRefreshRequestFactory.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/ReceiptRefreshRequestMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/RefundProviderMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/RefundRequestProviderMock.swift (100%) rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/ScenesHolderMock.swift (100%) create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/StoreTransactionMock.swift rename Tests/FlareTests/{ => UnitTests/TestHelpers}/Mocks/SystemInfoProviderMock.swift (100%) create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Stubs/StoreTransactionStub.swift create mode 100644 Tests/IntegrationTests/Flare.storekit create mode 100644 Tests/IntegrationTests/Helpers/Extensions/Result+.swift create mode 100644 Tests/IntegrationTests/Helpers/Extensions/XCTestCase+.swift create mode 100644 Tests/IntegrationTests/Helpers/StoreSessionTestCase/StoreSessionTestCase.swift create mode 100644 Tests/IntegrationTests/Tests/FlareTests.swift create mode 100644 Tests/IntegrationTests/Tests/IAPProviderTests.swift create mode 100644 Tests/IntegrationTests/Tests/ProductProviderHelper.swift create mode 100644 Tests/IntegrationTests/Tests/ProductProviderTests.swift create mode 100644 Tests/IntegrationTests/Tests/PurchaseProviderTests.swift create mode 100644 Tests/TestPlans/AllTests.xctestplan create mode 100644 Tests/TestPlans/IntegrationTests.xctestplan create mode 100644 Tests/TestPlans/UnitTests.xctestplan create mode 100644 Tests/UnitTestHostApp/AppDelegate.swift create mode 100644 Tests/UnitTestHostApp/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 Tests/UnitTestHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Tests/UnitTestHostApp/Assets.xcassets/Contents.json create mode 100644 Tests/UnitTestHostApp/Info.plist create mode 100644 project.yml create mode 100644 scripts/setup_build_tools.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d2fe1aa1..ca56e598a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,6 @@ on: - "Source/**" - "Tests/**" -concurrency: - group: ci - cancel-in-progress: true - jobs: SwiftLint: runs-on: ubuntu-latest @@ -28,56 +24,202 @@ jobs: args: --strict env: DIFF_BASE: ${{ github.base_ref }} - Latest: - name: Test Latest (iOS, macOS, tvOS, watchOS) - runs-on: macOS-12 + macOS: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} env: - DEVELOPER_DIR: "/Applications/Xcode_14.1.app/Contents/Developer" - timeout-minutes: 10 + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 strategy: fail-fast: false matrix: include: - - destination: "OS=16.1,name=iPhone 14 Pro" - name: "iOS" - scheme: "Flare" - sdk: iphonesimulator - - destination: "OS=16.1,name=Apple TV" - name: "tvOS" - scheme: "Flare" - sdk: appletvsimulator - - destination: "OS=9.1,name=Apple Watch Series 8 (45mm)" - name: "watchOS" - scheme: "Flare" - sdk: watchsimulator - - destination: "platform=macOS" - name: "macOS" - scheme: "Flare" - sdk: macosx + - xcode: "Xcode_15.0" + runsOn: macos-13 + name: "macOS 13, Xcode 15.0, Swift 5.9.0" + - xcode: "Xcode_14.3.1" + runsOn: macos-13 + name: "macOS 13, Xcode 14.3.1, Swift 5.8.0" + - xcode: "Xcode_14.2" + runsOn: macOS-12 + name: "macOS 12, Xcode 14.2, Swift 5.7.2" + - xcode: "Xcode_14.1" + runsOn: macOS-12 + name: "macOS 12, Xcode 14.1, Swift 5.7.1" steps: - uses: actions/checkout@v3 - name: ${{ matrix.name }} - run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "./${{ matrix.sdk }}.xcresult" | xcpretty -r junit + run: xcodebuild test -scheme "Flare" -destination "platform=macOS" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1 - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3.1.0 with: token: ${{ secrets.CODECOV_TOKEN }} xcode: true - xcode_archive_path: "./${{ matrix.sdk }}.xcresult" - Beta: - name: "Test Betas" - runs-on: macos-13 + xcode_archive_path: test_output/${{ matrix.name }}.xcresult + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }} + path: test_output + + iOS: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} + env: + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - destination: "OS=17.0.1,name=iPhone 14 Pro" + name: "iOS 17.0.1" + xcode: "Xcode_15.0" + runsOn: macos-13 + - destination: "OS=16.4,name=iPhone 14 Pro" + name: "iOS 16.4" + xcode: "Xcode_14.3.1" + runsOn: macos-13 + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: make setup_build_tools + - name: Generate project + run: make generate + - name: ${{ matrix.name }} + run: xcodebuild test -scheme "Flare" -destination "${{ matrix.destination }}" -testPlan AllTests clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1 + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }} + path: test_output + + tvOS: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} + env: + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - destination: "OS=17.0,name=Apple TV" + name: "tvOS 17.0" + xcode: "Xcode_15.0" + runsOn: macos-13 + - destination: "OS=16.4,name=Apple TV" + name: "tvOS 16.4" + xcode: "Xcode_14.3.1" + runsOn: macos-13 + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: make setup_build_tools + - name: Generate project + run: make generate + - name: ${{ matrix.name }} + run: xcodebuild test -scheme "Flare" -destination "${{ matrix.destination }}" -testPlan AllTests clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1 + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3.1.0 + with: + token: ${{ secrets.CODECOV_TOKEN }} + xcode: true + xcode_archive_path: test_output/${{ matrix.name }}.xcresult + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }} + path: test_output + + watchOS: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} env: - DEVELOPER_DIR: "/Applications/Xcode_15.0.app/Contents/Developer" - timeout-minutes: 10 + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 strategy: fail-fast: false matrix: include: - - destination: "OS=1.0,name=Apple Vision Pro" - name: "visionOS" - scheme: "Flare" + - destination: "OS=10.0,name=Apple Watch Series 9 (45mm)" + name: "watchOS 10.0" + xcode: "Xcode_15.0" + runsOn: macos-13 + - destination: "OS=9.4,name=Apple Watch Series 8 (45mm)" + name: "watchOS 9.4" + xcode: "Xcode_14.3.1" + runsOn: macos-13 + - destination: "OS=8.5,name=Apple Watch Series 7 (45mm)" + name: "watchOS 8.5" + xcode: "Xcode_14.3.1" + runsOn: macos-13 steps: - uses: actions/checkout@v3 + - name: Install Dependencies + run: make setup_build_tools + - name: Generate project + run: make generate - name: ${{ matrix.name }} - run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean \ No newline at end of file + run: xcodebuild test -scheme "Flare" -destination "${{ matrix.destination }}" -testPlan UnitTests clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1 + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3.1.0 + with: + token: ${{ secrets.CODECOV_TOKEN }} + xcode: true + xcode_archive_path: test_output/${{ matrix.name }}.xcresult + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }} + path: test_output + + spm: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} + env: + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - name: "Xcode 15" + xcode: "Xcode_15.0" + runsOn: macos-13 + - name: "Xcode 14" + xcode: "Xcode_14.3.1" + runsOn: macos-13 + steps: + - uses: actions/checkout@v3 + - name: ${{ matrix.name }} + run: swift build -c release --target Flare + + merge-test-reports: + needs: [iOS, macOS, watchOS, tvOS] + runs-on: macos-13 + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: test_output + - run: xcrun xcresulttool merge test_output/**/*.xcresult --output-path test_output/final/final.xcresult + - name: Upload Merged Artifact + uses: actions/upload-artifact@v4 + with: + name: MergedResult + path: test_output/final + + # Beta: + # name: ${{ matrix.name }} + # runs-on: firebreak + # env: + # DEVELOPER_DIR: "/Applications/Xcode_15.0.app/Contents/Developer" + # timeout-minutes: 10 + # strategy: + # fail-fast: false + # matrix: + # include: + # - destination: "OS=1.0,name=Apple Vision Pro" + # name: "visionOS 1.0" + # scheme: "Flare" + # steps: + # - uses: actions/checkout@v3 + # - name: ${{ matrix.name }} + # run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean || exit 1 \ No newline at end of file diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 1a0ab5292..158ca8723 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -15,7 +15,7 @@ jobs: - name: ruby setup uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7 + ruby-version: 3.1.4 bundler-cache: true - name: Checkout code uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 330d1674f..5ca27c72b 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,4 @@ fastlane/test_output # https://github.com/johnno1962/injectionforxcode iOSInjectionProject/ +*.xcodeproj \ No newline at end of file diff --git a/.swiftlint.yml b/.swiftlint.yml index ca37591b9..66d17c089 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -2,6 +2,7 @@ excluded: - Tests - Package.swift - Package@swift-5.7.swift + - Package@swift-5.8.swift - .build # Rules @@ -10,6 +11,7 @@ disabled_rules: - trailing_comma - todo - opening_brace + - unneeded_synthesized_initializer opt_in_rules: # some rules are only opt-in - anyobject_protocol diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme index 46bcfc41a..866e55a53 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Flare.xcscheme @@ -34,6 +34,20 @@ ReferencedContainer = "container:"> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b7ef5e23..cec795e73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Integrate the `StoreKit2` purchase method + - Added in Pull Request [#10](https://github.com/space-code/flare/pull/10). + - Add badges for `Swift Version Compatibility` and `Platform Compatibility` - Added in Pull Request [#7](https://github.com/space-code/flare/pull/8). diff --git a/Makefile b/Makefile index 856d64b45..f11937816 100644 --- a/Makefile +++ b/Makefile @@ -16,4 +16,10 @@ lint: fmt: mint run swiftformat Sources Tests -.PHONY: all bootstrap hook mint lint fmt \ No newline at end of file +generate: + xcodegen generate + +setup_build_tools: + sh scripts/setup_build_tools.sh + +.PHONY: all bootstrap hook mint lint fmt generate setup_build_tools \ No newline at end of file diff --git a/Package.resolved b/Package.resolved index ff7b43099..a03aac1cb 100644 --- a/Package.resolved +++ b/Package.resolved @@ -8,15 +8,6 @@ "revision" : "f9611694f77f64e43d9467a16b2f5212cd04099b", "version" : "0.0.1" } - }, - { - "identity" : "objects-factory", - "kind" : "remoteSourceControl", - "location" : "https://github.com/space-code/objects-factory.git", - "state" : { - "revision" : "be016801934d18d91e33845e5e5b9a12617698b0", - "version" : "1.0.0" - } } ], "version" : 2 diff --git a/Package.swift b/Package.swift index 1a48e0820..fea55f4e2 100644 --- a/Package.swift +++ b/Package.swift @@ -20,7 +20,6 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), - .package(url: "https://github.com/space-code/objects-factory.git", .upToNextMajor(from: "1.0.0")), ], targets: [ .target( @@ -34,7 +33,6 @@ let package = Package( name: "FlareTests", dependencies: [ "Flare", - .product(name: "ObjectsFactory", package: "objects-factory"), .product(name: "TestConcurrency", package: "concurrency"), ] ), diff --git a/Package@swift-5.7.swift b/Package@swift-5.7.swift index f933cf240..e645e1d10 100644 --- a/Package@swift-5.7.swift +++ b/Package@swift-5.7.swift @@ -17,7 +17,6 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), - .package(url: "https://github.com/space-code/objects-factory.git", .upToNextMajor(from: "1.0.0")), ], targets: [ .target( @@ -30,7 +29,6 @@ let package = Package( name: "FlareTests", dependencies: [ "Flare", - .product(name: "ObjectsFactory", package: "objects-factory"), .product(name: "TestConcurrency", package: "concurrency"), ] ), diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift new file mode 100644 index 000000000..256bf4f11 --- /dev/null +++ b/Package@swift-5.8.swift @@ -0,0 +1,36 @@ +// swift-tools-version: 5.8 +// The swift-tools-version declares the minimum version of Swift required to build this package. +// swiftlint:disable all + +import PackageDescription + +let package = Package( + name: "Flare", + platforms: [ + .macOS(.v10_15), + .iOS(.v13), + .watchOS(.v7), + .tvOS(.v13), + ], + products: [ + .library(name: "Flare", targets: ["Flare"]), + ], + dependencies: [ + .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), + ], + targets: [ + .target( + name: "Flare", + dependencies: [ + .product(name: "Concurrency", package: "concurrency"), + ] + ), + .testTarget( + name: "FlareTests", + dependencies: [ + "Flare", + .product(name: "TestConcurrency", package: "concurrency"), + ] + ), + ] +) diff --git a/Sources/Flare/Classes/Common/Types.swift b/Sources/Flare/Classes/Common/Types.swift index 6d71b8f40..74d4d65d2 100644 --- a/Sources/Flare/Classes/Common/Types.swift +++ b/Sources/Flare/Classes/Common/Types.swift @@ -7,3 +7,5 @@ import Foundation public typealias Closure = (T) -> Void public typealias Closure2 = (T, U) -> Void + +public typealias SendableClosure = @Sendable (T) -> Void diff --git a/Sources/Flare/Classes/Extensions/Formatters/NumberFormatter+.swift b/Sources/Flare/Classes/Extensions/Formatters/NumberFormatter+.swift new file mode 100644 index 000000000..c044972af --- /dev/null +++ b/Sources/Flare/Classes/Extensions/Formatters/NumberFormatter+.swift @@ -0,0 +1,23 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +extension NumberFormatter { + static func numberFormatter(with locale: Locale) -> NumberFormatter { + let formatter = NumberFormatter() + formatter.numberStyle = .currency + formatter.locale = locale + return formatter + } + + func numberFormatter(with currencyCode: String, locale: Locale = .autoupdatingCurrent) -> NumberFormatter { + let formatter = NumberFormatter() + formatter.numberStyle = .currency + formatter.locale = locale + formatter.currencyCode = currencyCode + return formatter + } +} diff --git a/Sources/Flare/Classes/Extensions/Locale/Locale+CurrencyCode.swift b/Sources/Flare/Classes/Extensions/Locale/Locale+CurrencyCode.swift new file mode 100644 index 000000000..c54b4cccc --- /dev/null +++ b/Sources/Flare/Classes/Extensions/Locale/Locale+CurrencyCode.swift @@ -0,0 +1,20 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +extension Locale { + var currencyCodeID: String? { + #if swift(>=5.9) + if #available(macOS 13, iOS 16, tvOS 16, watchOS 9, visionOS 1.0, *) { + return self.currency?.identifier + } else { + return currencyCode + } + #else + return currencyCode + #endif + } +} diff --git a/Sources/Flare/Classes/Extensions/ProductType+.swift b/Sources/Flare/Classes/Extensions/ProductType+.swift new file mode 100644 index 000000000..73c936ca6 --- /dev/null +++ b/Sources/Flare/Classes/Extensions/ProductType+.swift @@ -0,0 +1,40 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) +extension ProductType { + init(_ type: StoreKit.Product.ProductType) { + switch type { + case .consumable: + self = .consumable + case .nonConsumable: + self = .nonConsumable + case .nonRenewable: + self = .nonRenewableSubscription + case .autoRenewable: + self = .autoRenewableSubscription + default: + self = .nonConsumable + } + } +} + +extension ProductType { + var productCategory: ProductCategory { + switch self { + case .consumable: + return .nonSubscription + case .nonConsumable: + return .nonSubscription + case .nonRenewableSubscription: + return .subscription + case .autoRenewableSubscription: + return .subscription + } + } +} diff --git a/Sources/Flare/Classes/Helpers/Async/AsyncHandler.swift b/Sources/Flare/Classes/Helpers/Async/AsyncHandler.swift new file mode 100644 index 000000000..f819b1bf5 --- /dev/null +++ b/Sources/Flare/Classes/Helpers/Async/AsyncHandler.swift @@ -0,0 +1,22 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.2, *) +enum AsyncHandler { + static func call( + completion: @escaping (Result) -> Void, + asyncMethod method: @escaping () async throws -> T + ) { + _ = Task { + do { + try completion(.success(await method())) + } catch { + completion(.failure(error)) + } + } + } +} diff --git a/Sources/Flare/Classes/Helpers/AsyncSequence/AsyncSequence+Stream.swift b/Sources/Flare/Classes/Helpers/AsyncSequence/AsyncSequence+Stream.swift new file mode 100644 index 000000000..ef1f60823 --- /dev/null +++ b/Sources/Flare/Classes/Helpers/AsyncSequence/AsyncSequence+Stream.swift @@ -0,0 +1,15 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +extension AsyncSequence { + func toAsyncStream() -> AsyncStream { + var asyncIterator = makeAsyncIterator() + return AsyncStream { + try? await asyncIterator.next() + } + } +} diff --git a/Sources/Flare/Classes/Helpers/PaymentTransaction/PaymentTransaction.swift b/Sources/Flare/Classes/Helpers/PaymentTransaction/PaymentTransaction.swift index ff71880d3..fde5d04da 100644 --- a/Sources/Flare/Classes/Helpers/PaymentTransaction/PaymentTransaction.swift +++ b/Sources/Flare/Classes/Helpers/PaymentTransaction/PaymentTransaction.swift @@ -77,6 +77,10 @@ public struct PaymentTransaction: Equatable { return skTransaction.error } + public var transactionDate: Date? { + skTransaction.transactionDate + } + /// A `Bool` value indicating that the user canceled a payment request. public var isCancelled: Bool { (skTransaction.error as? SKError)?.code == SKError.Code.paymentCancelled diff --git a/Sources/Flare/Classes/Listeners/TransactionListener/ITransactionListener.swift b/Sources/Flare/Classes/Listeners/TransactionListener/ITransactionListener.swift new file mode 100644 index 000000000..faefa7cb8 --- /dev/null +++ b/Sources/Flare/Classes/Listeners/TransactionListener/ITransactionListener.swift @@ -0,0 +1,14 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +protocol ITransactionListener: Sendable { + func listenForTransaction() async + + @available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) + func handle(purchaseResult: StoreKit.Product.PurchaseResult) async throws -> StoreTransaction? +} diff --git a/Sources/Flare/Classes/Listeners/TransactionListener/TransactionListener.swift b/Sources/Flare/Classes/Listeners/TransactionListener/TransactionListener.swift new file mode 100644 index 000000000..1078ed1c3 --- /dev/null +++ b/Sources/Flare/Classes/Listeners/TransactionListener/TransactionListener.swift @@ -0,0 +1,81 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - TransactionListener + +@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) +actor TransactionListener { + // MARK: Types + + typealias TransactionResult = StoreKit.VerificationResult + + // MARK: Private + + private let updates: AsyncStream + private var task: Task? + + // MARK: Initialization + + init(updates: S) where S.Element == TransactionResult { + self.updates = updates.toAsyncStream() + } + + // MARK: Private + + private func handle( + transactionResult: TransactionResult, + fromTransactionUpdate _: Bool + ) async throws -> StoreTransaction { + switch transactionResult { + case let .verified(transaction): + return StoreTransaction( + transaction: transaction, + jwtRepresentation: transactionResult.jwsRepresentation + ) + case let .unverified(transaction, verificationError): + throw IAPError.verification( + error: .unverified(productID: transaction.productID, error: verificationError) + ) + } + } +} + +// MARK: ITransactionListener + +@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) +extension TransactionListener: ITransactionListener { + func listenForTransaction() async { + task?.cancel() + task = Task(priority: .utility) { [weak self] in + guard let self = self else { return } + + for await update in self.updates { + Task.detached { + do { + _ = try await self.handle(transactionResult: update, fromTransactionUpdate: true) + } catch { + debugPrint("[TransactionListener] Error occurred: \(error.localizedDescription)") + } + } + } + } + } + + func handle(purchaseResult: Product.PurchaseResult) async throws -> StoreTransaction? { + switch purchaseResult { + case let .success(verificationResult): + return try await handle(transactionResult: verificationResult, fromTransactionUpdate: false) + case .userCancelled: + throw IAPError.paymentCancelled + case .pending: + throw IAPError.paymentDefferred + @unknown default: + throw IAPError.unknown + } + } +} diff --git a/Sources/Flare/Classes/Models/IAPError.swift b/Sources/Flare/Classes/Models/IAPError.swift index 2977011e5..83537685e 100644 --- a/Sources/Flare/Classes/Models/IAPError.swift +++ b/Sources/Flare/Classes/Models/IAPError.swift @@ -30,12 +30,44 @@ public enum IAPError: Swift.Error { case transactionNotFound(productID: String) /// The refund error. case refund(error: RefundError) + /// The verification error. + /// + /// - Note: This is only available for StoreKit 2 transactions. + case verification(error: VerificationError) + /// + /// + /// - Note: This is only available for StoreKit 2 transactions. + case paymentDefferred /// The unknown error occurred. case unknown } extension IAPError { init(error: Swift.Error?) { + if #available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) { + if let storeKitError = error as? StoreKitError { + self.init(storeKitError: storeKitError) + } else { + self.init(error) + } + } else { + self.init(error) + } + } + + @available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) + private init(storeKitError: StoreKit.StoreKitError) { + switch storeKitError { + case .unknown: + self = .unknown + case .userCancelled: + self = .paymentCancelled + default: + self = .with(error: storeKitError) + } + } + + private init(_ error: Swift.Error?) { switch (error as? SKError)?.code { case .paymentNotAllowed: self = .paymentNotAllowed diff --git a/Sources/Flare/Classes/Models/Internal/Protocols/ISKProduct.swift b/Sources/Flare/Classes/Models/Internal/Protocols/ISKProduct.swift new file mode 100644 index 000000000..825632ca4 --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/Protocols/ISKProduct.swift @@ -0,0 +1,36 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +/// Protocol representing a Store Kit product. +protocol ISKProduct { + /// A localized description of the product. + var localizedDescription: String { get } + + /// A localized title or name of the product. + var localizedTitle: String { get } + + /// The currency code for the product's price. + var currencyCode: String? { get } + + /// The price of the product in decimal format. + var price: Decimal { get } + + /// A localized string representing the price of the product. + var localizedPriceString: String? { get } + + /// The unique identifier for the product. + var productIdentifier: String { get } + + /// The type of product (e.g., consumable, non-consumable). + var productType: ProductType? { get } + + /// The category to which the product belongs. + var productCategory: ProductCategory? { get } + + /// The subscription period for the product, if applicable. + var subscriptionPeriod: SubscriptionPeriod? { get } +} diff --git a/Sources/Flare/Classes/Models/Internal/Protocols/IStoreTransaction.swift b/Sources/Flare/Classes/Models/Internal/Protocols/IStoreTransaction.swift new file mode 100644 index 000000000..db8a4cce7 --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/Protocols/IStoreTransaction.swift @@ -0,0 +1,32 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +/// A type that represents a store transaction. +protocol IStoreTransaction { + /// The unique identifier for the product. + var productIdentifier: String { get } + /// The date when the transaction occurred. + var purchaseDate: Date { get } + /// A boolean indicating whether the purchase date is known. + var hasKnownPurchaseDate: Bool { get } + /// A unique identifier for the transaction. + var transactionIdentifier: String { get } + /// A boolean indicating whether the transaction identifier is known. + var hasKnownTransactionIdentifier: Bool { get } + /// The quantity of the product involved in the transaction. + var quantity: Int { get } + + /// The raw JWS repesentation of the transaction. + /// + /// - Note: This is only available for StoreKit 2 transactions. + var jwsRepresentation: String? { get } + + /// The server environment where the receipt was generated. + /// + /// - Note: This is only available for StoreKit 2 transactions. + var environment: StoreEnvironment? { get } +} diff --git a/Sources/Flare/Classes/Models/Internal/SK1StoreProduct.swift b/Sources/Flare/Classes/Models/Internal/SK1StoreProduct.swift new file mode 100644 index 000000000..92d48806c --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/SK1StoreProduct.swift @@ -0,0 +1,72 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - SK1StoreProduct + +final class SK1StoreProduct { + // MARK: Properties + + /// The store kit product. + let product: SKProduct + + /// The price formatter. + private lazy var numberFormatter: NumberFormatter = .numberFormatter(with: self.product.priceLocale) + + // MARK: Initialization + + init(_ product: SKProduct) { + self.product = product + } +} + +// MARK: ISKProduct + +extension SK1StoreProduct: ISKProduct { + var localizedDescription: String { + product.localizedDescription + } + + var localizedTitle: String { + product.localizedTitle + } + + var currencyCode: String? { + product.priceLocale.currencyCodeID + } + + var price: Decimal { + product.price as Decimal + } + + var localizedPriceString: String? { + numberFormatter.string(from: product.price) + } + + var productIdentifier: String { + product.productIdentifier + } + + var productType: ProductType? { + nil + } + + var productCategory: ProductCategory? { + guard #available(iOS 11.2, macOS 10.13.2, tvOS 11.2, watchOS 6.2, *) else { + return .nonSubscription + } + return subscriptionPeriod == nil ? .nonSubscription : .subscription + } + + @available(iOS 11.2, macOS 10.13.2, tvOS 11.2, watchOS 6.2, *) + var subscriptionPeriod: SubscriptionPeriod? { + guard let subscriptionPeriod = product.subscriptionPeriod, subscriptionPeriod.numberOfUnits > 0 else { + return nil + } + return SubscriptionPeriod.from(subscriptionPeriod: subscriptionPeriod) + } +} diff --git a/Sources/Flare/Classes/Models/Internal/SK1StoreTransaction.swift b/Sources/Flare/Classes/Models/Internal/SK1StoreTransaction.swift new file mode 100644 index 000000000..e7f02aa29 --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/SK1StoreTransaction.swift @@ -0,0 +1,65 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import StoreKit + +// MARK: - SK1StoreTransaction + +/// A struct representing the first version of the transaction. +struct SK1StoreTransaction { + // MARK: Properties + + /// The StoreKit transaction. + let transaction: PaymentTransaction + + // MARK: Initialization + + /// Creates a new `SK1StoreTransaction` instance. + /// + /// - Parameter transaction: The StoreKit transaction. + init(transaction: PaymentTransaction) { + self.transaction = transaction + } +} + +// MARK: IStoreTransaction + +extension SK1StoreTransaction: IStoreTransaction { + var productIdentifier: String { + transaction.productIdentifier + } + + var purchaseDate: Date { + guard let date = transaction.transactionDate else { + return Date(timeIntervalSince1970: 0) + } + return date + } + + var hasKnownPurchaseDate: Bool { + transaction.transactionDate != nil + } + + var transactionIdentifier: String { + transaction.transactionIdentifier ?? "" + } + + var hasKnownTransactionIdentifier: Bool { + transaction.transactionIdentifier != nil + } + + var quantity: Int { + let payment = transaction.skTransaction.payment + return payment.quantity + } + + var jwsRepresentation: String? { + nil + } + + var environment: StoreEnvironment? { + nil + } +} diff --git a/Sources/Flare/Classes/Models/Internal/SK2StoreProduct.swift b/Sources/Flare/Classes/Models/Internal/SK2StoreProduct.swift new file mode 100644 index 000000000..c8fa0527d --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/SK2StoreProduct.swift @@ -0,0 +1,71 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - SK2StoreProduct + +@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) +final class SK2StoreProduct { + // MARK: Properties + + /// The store kit product. + let product: StoreKit.Product + /// The currency format. + private var currencyFormat: Decimal.FormatStyle.Currency { + product.priceFormatStyle + } + + // MARK: Initialization + + init(_ product: StoreKit.Product) { + self.product = product + } +} + +// MARK: ISKProduct + +@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) +extension SK2StoreProduct: ISKProduct { + var localizedDescription: String { + product.description + } + + var localizedTitle: String { + product.displayName + } + + var currencyCode: String? { + currencyFormat.currencyCode + } + + var price: Decimal { + product.price + } + + var localizedPriceString: String? { + product.displayPrice + } + + var productIdentifier: String { + product.id + } + + var productType: ProductType? { + ProductType(product.type) + } + + var productCategory: ProductCategory? { + productType?.productCategory + } + + var subscriptionPeriod: SubscriptionPeriod? { + guard let subscriptionPeriod = product.subscription?.subscriptionPeriod else { + return nil + } + return SubscriptionPeriod.from(subscriptionPeriod: subscriptionPeriod) + } +} diff --git a/Sources/Flare/Classes/Models/Internal/SK2StoreTransaction.swift b/Sources/Flare/Classes/Models/Internal/SK2StoreTransaction.swift new file mode 100644 index 000000000..5ccde0c40 --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/SK2StoreTransaction.swift @@ -0,0 +1,69 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - SK2StoreTransaction + +/// A struct representing the second version of the transaction. +@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) +struct SK2StoreTransaction { + // MARK: Properties + + /// The StoreKit transaction. + let transaction: StoreKit.Transaction + /// The raw JWS repesentation of the transaction. + private let _jwsRepresentation: String? + + // MARK: Initialization + + /// Creates a new `SK1StoreTransaction` instance. + /// + /// - Parameters: + /// - transaction: The StoreKit transaction. + /// - jwsRepresentation: The raw JWS repesentation of the transaction. + init(transaction: StoreKit.Transaction, jwsRepresentation: String) { + self.transaction = transaction + _jwsRepresentation = jwsRepresentation + } +} + +// MARK: IStoreTransaction + +@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) +extension SK2StoreTransaction: IStoreTransaction { + var productIdentifier: String { + transaction.productID + } + + var purchaseDate: Date { + transaction.purchaseDate + } + + var hasKnownPurchaseDate: Bool { + true + } + + var transactionIdentifier: String { + String(transaction.id) + } + + var hasKnownTransactionIdentifier: Bool { + true + } + + var quantity: Int { + transaction.purchasedQuantity + } + + var jwsRepresentation: String? { + _jwsRepresentation + } + + var environment: StoreEnvironment? { + StoreEnvironment(transaction: transaction) + } +} diff --git a/Sources/Flare/Classes/Models/Internal/StoreEnvironment.swift b/Sources/Flare/Classes/Models/Internal/StoreEnvironment.swift new file mode 100644 index 000000000..0744220ac --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/StoreEnvironment.swift @@ -0,0 +1,59 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - StoreEnvironment + +enum StoreEnvironment { + case production + case sandbox + case xcode +} + +extension StoreEnvironment { + @available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *) + init?(environment: StoreKit.AppStore.Environment) { + switch environment { + case .production: + self = .production + case .sandbox: + self = .sandbox + case .xcode: + self = .xcode + default: + return nil + } + } + + init?(environment: String) { + switch environment { + case "Production": + self = .production + case "Sandbox": + self = .sandbox + case "Xcode": + self = .xcode + default: + return nil + } + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + init?(transaction: StoreKit.Transaction) { + if #available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *) { + self.init(environment: transaction.environment) + } else { + #if VISION_OS + self.init(environment: transaction.environment) + #else + self.init( + environment: transaction.environmentStringRepresentation + ) + #endif + } + } +} diff --git a/Sources/Flare/Classes/Models/ProductCategory.swift b/Sources/Flare/Classes/Models/ProductCategory.swift new file mode 100644 index 000000000..b9522c35b --- /dev/null +++ b/Sources/Flare/Classes/Models/ProductCategory.swift @@ -0,0 +1,14 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +public enum ProductCategory: Int { + /// A non-renewable or auto-renewable subscription. + case subscription + + /// A consumable or non-consumable in-app purchase. + case nonSubscription +} diff --git a/Sources/Flare/Classes/Models/ProductType.swift b/Sources/Flare/Classes/Models/ProductType.swift new file mode 100644 index 000000000..482b86073 --- /dev/null +++ b/Sources/Flare/Classes/Models/ProductType.swift @@ -0,0 +1,21 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +/// The type of product, equivalent to StoreKit's `Product.ProductType`. +public enum ProductType: Int { + /// A consumable in-app purchase. + case consumable + + /// A non-consumable in-app purchase. + case nonConsumable + + /// A non-renewing subscription. + case nonRenewableSubscription + + /// An auto-renewable subscription. + case autoRenewableSubscription +} diff --git a/Sources/Flare/Classes/Models/StoreProduct.swift b/Sources/Flare/Classes/Models/StoreProduct.swift new file mode 100644 index 000000000..d240cbcde --- /dev/null +++ b/Sources/Flare/Classes/Models/StoreProduct.swift @@ -0,0 +1,88 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - StoreProduct + +/// An object represents a StoreKit product. +public final class StoreProduct: NSObject { + // MARK: Properties + + /// Protocol representing a Store Kit product. + private let product: ISKProduct + + /// <#Description#> + var underlyingProduct: ISKProduct { product } + + // MARK: Initialization + + /// Creates a new `StoreProduct` instance. + /// + /// - Parameter product: The StoreKit product. + init(_ product: ISKProduct) { + self.product = product + } +} + +// MARK: - Convinience Initializators + +public extension StoreProduct { + /// Creates a new `StoreProduct` instance. + /// + /// - Parameter skProduct: The StoreKit product. + convenience init(skProduct: SKProduct) { + self.init(SK1StoreProduct(skProduct)) + } + + /// Creates a new `StoreProduct` instance. + /// + /// - Parameter product: The StoreKit product. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + convenience init(product: StoreKit.Product) { + self.init(SK2StoreProduct(product)) + } +} + +// MARK: ISKProduct + +extension StoreProduct: ISKProduct { + var localizedDescription: String { + product.localizedDescription + } + + var localizedTitle: String { + product.localizedTitle + } + + var currencyCode: String? { + product.currencyCode + } + + var price: Decimal { + product.price + } + + var localizedPriceString: String? { + product.localizedPriceString + } + + var productIdentifier: String { + product.productIdentifier + } + + var productType: ProductType? { + product.productType + } + + var productCategory: ProductCategory? { + product.productCategory + } + + var subscriptionPeriod: SubscriptionPeriod? { + product.subscriptionPeriod + } +} diff --git a/Sources/Flare/Classes/Models/StoreTransaction.swift b/Sources/Flare/Classes/Models/StoreTransaction.swift new file mode 100644 index 000000000..fa16b2478 --- /dev/null +++ b/Sources/Flare/Classes/Models/StoreTransaction.swift @@ -0,0 +1,91 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - StoreTransaction + +/// A class represent a StoreKit transaction. +public final class StoreTransaction { + // MARK: Properties + + /// The StoreKit transaction. + let storeTransaction: IStoreTransaction + + // MARK: Initialization + + /// Creates a new `StoreTransaction` instance. + /// + /// - Parameter storeTransaction: The StoreKit transaction. + init(storeTransaction: IStoreTransaction) { + self.storeTransaction = storeTransaction + } +} + +// MARK: - Convinience Initializators + +extension StoreTransaction { + /// Creates a new `StoreTransaction` instance. + /// + /// - Parameter paymentTransaction: The StoreKit transaction. + convenience init(paymentTransaction: PaymentTransaction) { + self.init(storeTransaction: SK1StoreTransaction(transaction: paymentTransaction)) + } + + /// Creates a new `StoreTransaction` instance. + /// + /// - Parameters: + /// - transaction: The StoreKit transaction. + /// - jwtRepresentation: The server environment where the receipt was generated. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + convenience init(transaction: StoreKit.Transaction, jwtRepresentation: String) { + self.init(storeTransaction: SK2StoreTransaction(transaction: transaction, jwsRepresentation: jwtRepresentation)) + } +} + +// MARK: IStoreTransaction + +extension StoreTransaction: IStoreTransaction { + var productIdentifier: String { + storeTransaction.productIdentifier + } + + var purchaseDate: Date { + storeTransaction.purchaseDate + } + + var hasKnownPurchaseDate: Bool { + storeTransaction.hasKnownPurchaseDate + } + + var transactionIdentifier: String { + storeTransaction.transactionIdentifier + } + + var hasKnownTransactionIdentifier: Bool { + storeTransaction.hasKnownTransactionIdentifier + } + + var quantity: Int { + storeTransaction.quantity + } + + var jwsRepresentation: String? { + storeTransaction.jwsRepresentation + } + + var environment: StoreEnvironment? { + storeTransaction.environment + } +} + +// MARK: Equatable + +extension StoreTransaction: Equatable { + public static func == (lhs: StoreTransaction, rhs: StoreTransaction) -> Bool { + lhs.transactionIdentifier == rhs.transactionIdentifier + } +} diff --git a/Sources/Flare/Classes/Models/SubscriptionPeriod.swift b/Sources/Flare/Classes/Models/SubscriptionPeriod.swift new file mode 100644 index 000000000..9dedab4cb --- /dev/null +++ b/Sources/Flare/Classes/Models/SubscriptionPeriod.swift @@ -0,0 +1,100 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - SubscriptionPeriod + +// A class representing a subscription period with a specific value and unit. +public final class SubscriptionPeriod: NSObject { + // MARK: Types + + public enum Unit: Int { + /// A subscription period unit of a day. + case day = 0 + /// A subscription period unit of a week. + case week = 1 + /// A subscription period unit of a month. + case month = 2 + /// A subscription period unit of a year. + case year = 3 + } + + // MARK: Properties + + /// The numeric value of the subscription period. + public let value: Int + /// The unit of the subscription period (day, week, month, year). + public let unit: Unit + + // MARK: Initialization + + /// Initializes a new `SubscriptionPeriod` instance. + /// + /// - Parameters: + /// - value: The numeric value of the subscription period. + /// - unit: The unit of the subscription period. + public init(value: Int, unit: Unit) { + self.value = value + self.unit = unit + } +} + +// MARK: - Helpers + +extension SubscriptionPeriod { + @available(iOS 11.2, macOS 10.13.2, tvOS 11.2, watchOS 6.2, *) + static func from(subscriptionPeriod: SKProductSubscriptionPeriod) -> SubscriptionPeriod? { + guard let unit = SubscriptionPeriod.Unit.from(unit: subscriptionPeriod.unit) else { + return nil + } + return SubscriptionPeriod(value: subscriptionPeriod.numberOfUnits, unit: unit) + } + + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8, *) + static func from(subscriptionPeriod: StoreKit.Product.SubscriptionPeriod) -> SubscriptionPeriod? { + guard let unit = SubscriptionPeriod.Unit.from(unit: subscriptionPeriod.unit) else { + return nil + } + return SubscriptionPeriod(value: subscriptionPeriod.value, unit: unit) + } +} + +// MARK: - Extensions + +private extension SubscriptionPeriod.Unit { + @available(iOS 11.2, macOS 10.13.2, tvOS 11.2, watchOS 6.2, *) + static func from(unit: SKProduct.PeriodUnit) -> Self? { + switch unit { + case .day: + return .day + case .week: + return .week + case .month: + return .month + case .year: + return .year + @unknown default: + return nil + } + } + + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8, *) + static func from(unit: StoreKit.Product.SubscriptionPeriod.Unit) -> Self? { + switch unit { + case .day: + return .day + case .week: + return .week + case .month: + return .month + case .year: + return .year + @unknown default: + return nil + } + } +} diff --git a/Sources/Flare/Classes/Models/VerificationError.swift b/Sources/Flare/Classes/Models/VerificationError.swift new file mode 100644 index 000000000..9ca93b178 --- /dev/null +++ b/Sources/Flare/Classes/Models/VerificationError.swift @@ -0,0 +1,10 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +public enum VerificationError: Swift.Error { + case unverified(productID: String, error: Error) +} diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index 85fc9be86..f2ed8c0a0 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -5,21 +5,35 @@ import StoreKit +/// A class that provides in-app purchase functionality. final class IAPProvider: IIAPProvider { // MARK: Properties + /// The queue of payment transactions to be processed by the App Store. private let paymentQueue: PaymentQueue + /// The provider is responsible for fetching StoreKit products. private let productProvider: IProductProvider - private let paymentProvider: IPaymentProvider + /// The provider is responsible for purchasing products. + private let purchaseProvider: IPurchaseProvider + /// The provider is responsible for refreshing receipts. private let receiptRefreshProvider: IReceiptRefreshProvider + /// The provider is responsible for refunding purchases private let refundProvider: IRefundProvider // MARK: Initialization + /// Creates a new `IAPProvider` instance. + /// + /// - Parameters: + /// - paymentQueue: The queue of payment transactions to be processed by the App Store. + /// - productProvider: The provider is responsible for fetching StoreKit products. + /// - purchaseProvider: + /// - receiptRefreshProvider: The provider is responsible for refreshing receipts. + /// - refundProvider: The provider is responsible for refunding purchases. init( paymentQueue: PaymentQueue = SKPaymentQueue.default(), productProvider: IProductProvider = ProductProvider(), - paymentProvider: IPaymentProvider = PaymentProvider(), + purchaseProvider: IPurchaseProvider = PurchaseProvider(), receiptRefreshProvider: IReceiptRefreshProvider = ReceiptRefreshProvider(), refundProvider: IRefundProvider = RefundProvider( systemInfoProvider: SystemInfoProvider() @@ -27,7 +41,7 @@ final class IAPProvider: IIAPProvider { ) { self.paymentQueue = paymentQueue self.productProvider = productProvider - self.paymentProvider = paymentProvider + self.purchaseProvider = purchaseProvider self.receiptRefreshProvider = receiptRefreshProvider self.refundProvider = refundProvider } @@ -38,15 +52,27 @@ final class IAPProvider: IIAPProvider { paymentQueue.canMakePayments } - func fetch(productIDs: Set, completion: @escaping Closure>) { - productProvider.fetch( - productIDs: productIDs, - requestID: UUID().uuidString, - completion: completion - ) + func fetch(productIDs: Set, completion: @escaping Closure>) { + if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) { + AsyncHandler.call( + completion: { [weak self] result in + self?.handleFetchResult(result: result, completion) + }, + asyncMethod: { + try await self.productProvider.fetch(productIDs: productIDs) + } + ) + } else { + productProvider.fetch( + productIDs: productIDs, + requestID: UUID().uuidString + ) { [weak self] result in + self?.handleFetchResult(result: result, completion) + } + } } - func fetch(productIDs: Set) async throws -> [SKProduct] { + func fetch(productIDs: Set) async throws -> [StoreProduct] { try await withCheckedThrowingContinuation { continuation in self.fetch(productIDs: productIDs) { result in continuation.resume(with: result) @@ -54,34 +80,38 @@ final class IAPProvider: IIAPProvider { } } - func purchase(productID: String, completion: @escaping Closure>) { - productProvider.fetch(productIDs: [productID], requestID: UUID().uuidString) { result in + func purchase(product: StoreProduct, completion: @escaping Closure>) { + purchaseProvider.purchase(product: product) { result in switch result { - case let .success(products): - guard let product = products.first else { - completion(.failure(.storeProductNotAvailable)) - return - } - - let payment = SKPayment(product: product) - - self.paymentProvider.add(payment: payment) { _, result in - switch result { - case let .success(transaction): - completion(.success(PaymentTransaction(transaction))) - case let .failure(error): - completion(.failure(error)) - } - } + case let .success(transaction): + completion(.success(transaction)) case let .failure(error): completion(.failure(error)) } } } - func purchase(productID: String) async throws -> PaymentTransaction { + func purchase(product: StoreProduct) async throws -> StoreTransaction { try await withCheckedThrowingContinuation { continuation in - purchase(productID: productID) { result in + self.purchase(product: product) { result in + continuation.resume(with: result) + } + } + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping SendableClosure> + ) { + purchaseProvider.purchase(product: product, options: options, completion: completion) + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase(product: StoreProduct, options: Set) async throws -> StoreTransaction { + try await withCheckedThrowingContinuation { continuation in + purchase(product: product, options: options) { result in continuation.resume(with: result) } } @@ -110,24 +140,16 @@ final class IAPProvider: IIAPProvider { } } - func finish(transaction: PaymentTransaction) { - paymentProvider.finish(transaction: transaction) + func finish(transaction: StoreTransaction, completion: (@Sendable () -> Void)?) { + purchaseProvider.finish(transaction: transaction, completion: completion) } func addTransactionObserver(fallbackHandler: Closure>?) { - paymentProvider.set { _, result in - switch result { - case let .success(transaction): - fallbackHandler?(.success(PaymentTransaction(transaction))) - case let .failure(error): - fallbackHandler?(.failure(error)) - } - } - paymentProvider.addTransactionObserver() + purchaseProvider.addTransactionObserver(fallbackHandler: fallbackHandler) } func removeTransactionObserver() { - paymentProvider.removeTransactionObserver() + purchaseProvider.removeTransactionObserver() } #if os(iOS) || VISION_OS @@ -139,4 +161,22 @@ final class IAPProvider: IIAPProvider { try await refundProvider.beginRefundRequest(productID: productID) } #endif + + // MARK: Private + + private func handleFetchResult( + result: Result<[T], E>, + _ completion: @escaping (Result<[StoreProduct], IAPError>) -> Void + ) { + switch result { + case let .success(products): + completion(.success(products.map { StoreProduct($0) })) + case let .failure(error): + if let iapError = error as? IAPError { + completion(.failure(iapError)) + } else { + completion(.failure(IAPError(error: error))) + } + } + } } diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift index 45d08b835..ac7cf0bac 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift @@ -15,7 +15,7 @@ public protocol IIAPProvider { /// - Parameters: /// - productIDs: The list of product identifiers for which you wish to retrieve descriptions. /// - completion: The completion containing the response of retrieving products. - func fetch(productIDs: Set, completion: @escaping Closure>) + func fetch(productIDs: Set, completion: @escaping Closure>) /// Retrieves localized information from the App Store about a specified list of products. /// @@ -24,18 +24,31 @@ public protocol IIAPProvider { /// - Throws: `IAPError(error:)` if the request did fail with error. /// /// - Returns: An array of products. - func fetch(productIDs: Set) async throws -> [SKProduct] + func fetch(productIDs: Set) async throws -> [StoreProduct] - /// Performs a purchase of a product with a given ID. + /// Performs a purchase of a product. /// /// - Note: The method automatically checks if the user can purchase a product. /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// /// - Parameters: - /// - productID: The product identifier. + /// - product: The product to be purchased. /// - completion: The closure to be executed once the purchase is complete. - func purchase(productID: String, completion: @escaping Closure>) + func purchase(product: StoreProduct, completion: @escaping Closure>) + + /// Purchases a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameter product: The product to be purchased. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + func purchase(product: StoreProduct) async throws -> StoreTransaction /// Purchases a product with a given ID. /// @@ -43,12 +56,36 @@ public protocol IIAPProvider { /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// - /// - Parameter productID: The product identifier. + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// - completion: The closure to be executed once the purchase is complete. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. - func purchase(productID: String) async throws -> PaymentTransaction + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping SendableClosure> + ) + + /// Purchases a product with a given ID. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase(product: StoreProduct, options: Set) async throws -> StoreTransaction /// Refreshes the receipt, representing the user's transactions with your app. /// @@ -65,8 +102,10 @@ public protocol IIAPProvider { /// Removes a finished (i.e. failed or completed) transaction from the queue. /// Attempting to finish a purchasing transaction will throw an exception. /// - /// - Parameter transaction: An object in the payment queue. - func finish(transaction: PaymentTransaction) + /// - Parameters: + /// - transaction: An object in the payment queue. + /// - completion: If a completion closure is provided, call it after finishing the transaction. + func finish(transaction: StoreTransaction, completion: (@Sendable () -> Void)?) /// Adds transaction observer to the payment queue. /// The transactions array will only be synchronized with the server while the queue has observers. diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift index 2d511767d..dcc812907 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/IPaymentProvider.swift @@ -6,7 +6,7 @@ import StoreKit /// Type that provides payment functionality. -public protocol IPaymentProvider: AnyObject { +protocol IPaymentProvider: AnyObject { /// False if this device is not able or allowed to make payments var canMakePayments: Bool { get } diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift index aacf89156..3261143d0 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift @@ -8,20 +8,33 @@ import StoreKit // MARK: - PaymentProvider +/// A class provides functionality to make payments. final class PaymentProvider: NSObject { // MARK: Properties + /// The queue of payment transactions to be processed by the App Store. private let paymentQueue: PaymentQueue + /// Dictionary to store payment handlers associated with transaction identifiers. private var paymentHandlers: [String: [PaymentHandler]] = [:] + /// Array to store restore handlers for completed transactions. private var restoreHandlers: [RestoreHandler] = [] + /// Optional fallback handler for handling payments if no specific handler is found. private var fallbackHandler: PaymentHandler? + /// Optional handler to determine whether to add a payment to the App Store. private var shouldAddStorePaymentHandler: ShouldAddStorePaymentHandler? + /// The dispatch queue factory for handling concurrent tasks. private var dispatchQueueFactory: IDispatchQueueFactory + /// Lazy-initialized private dispatch queue for handling tasks related to payment processing. private lazy var privateQueue: IDispatchQueue = dispatchQueueFactory.privateQueue(label: String(describing: self)) // MARK: Initialization + /// Creates a new `PaymentProvider` instance. + /// + /// - Parameters: + /// - paymentQueue: The queue of payment transactions to be processed by the App Store. + /// - dispatchQueueFactory: The dispatch queue factory. init( paymentQueue: PaymentQueue = SKPaymentQueue.default(), dispatchQueueFactory: IDispatchQueueFactory = DispatchQueueFactory() diff --git a/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift index f9e5376ba..156263321 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift @@ -5,16 +5,16 @@ import StoreKit -public typealias ProductHandler = (_ result: Result<[SKProduct], IAPError>) -> Void -public typealias PaymentHandler = (_ queue: PaymentQueue, _ result: Result) -> Void -public typealias RestoreHandler = (_ queue: SKPaymentQueue, _ error: IAPError?) -> Void -public typealias ShouldAddStorePaymentHandler = (_ queue: SKPaymentQueue, _ payment: SKPayment, _ product: SKProduct) -> Bool -public typealias ReceiptRefreshHandler = (Result) -> Void +typealias PaymentHandler = (_ queue: PaymentQueue, _ result: Result) -> Void +typealias RestoreHandler = (_ queue: SKPaymentQueue, _ error: IAPError?) -> Void +typealias ShouldAddStorePaymentHandler = (_ queue: SKPaymentQueue, _ payment: SKPayment, _ product: SKProduct) -> Bool +typealias ReceiptRefreshHandler = (Result) -> Void // MARK: - IProductProvider -public protocol IProductProvider { - typealias ProductsHandler = Closure> +/// A type that is responsible for retrieving StoreKit products. +protocol IProductProvider { + typealias ProductsHandler = Closure> /// Retrieves localized information from the App Store about a specified list of products. /// @@ -23,4 +23,14 @@ public protocol IProductProvider { /// - requestID: The request identifier. /// - completion: The completion containing the response of retrieving products. func fetch(productIDs: Set, requestID: String, completion: @escaping ProductsHandler) + + /// Retrieves localized information from the App Store about a specified list of products. + /// + /// - Note:This method utilizes the new `StoreKit2` API. + /// + /// - Parameter productIDs: The list of product identifiers for which you wish to retrieve descriptions. + /// + /// - Returns: The requested products. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func fetch(productIDs: Set) async throws -> [SK2StoreProduct] } diff --git a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift index c9f3dc6b1..183741bbb 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift @@ -8,9 +8,29 @@ import StoreKit // MARK: - ProductProvider +/// A class is responsible for fetching StoreKit products. +/// +/// This implementation supports two ways of fetching products using the old way API and the new StoreKit2 API. +/// +/// Example: +/// +/// ``` +/// let productProvider = ProductProvider() +/// productProvider.fetch(productIDs: ["productID"], requestID: UUID().uuidString) { result in +/// switch result { +/// case let .success(products): +/// // The `products` array contains all fetched products with the given IDs. +/// case let .failure(error): +/// // An error occurred; you can handle it here. +/// } +/// } +/// ``` final class ProductProvider: NSObject, IProductProvider { // MARK: Lifecycle + /// Creates a new `ProductProvider` instance. + /// + /// - Parameter dispatchQueueFactory: The dispatch queue factory. init(dispatchQueueFactory: IDispatchQueueFactory = DispatchQueueFactory()) { self.dispatchQueueFactory = dispatchQueueFactory } @@ -22,13 +42,27 @@ final class ProductProvider: NSObject, IProductProvider { fetch(request: request, completion: completion) } + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func fetch(productIDs ids: Set) async throws -> [SK2StoreProduct] { + try await StoreKit.Product.products(for: ids).map(SK2StoreProduct.init) + } + // MARK: Private + /// Dictionary to store request handlers with their corresponding request IDs. private var handlers: [String: ProductsHandler] = [:] + /// The dispatch queue factory for handling concurrent tasks. private let dispatchQueueFactory: IDispatchQueueFactory + /// Lazy-initialized private dispatch queue for handling tasks related to product fetching. private lazy var dispatchQueue: IDispatchQueue = dispatchQueueFactory.privateQueue(label: String(describing: self)) + /// Creates a StoreKit product request with the specified product IDs and request ID. + /// + /// - Parameters: + /// - ids: The set of product IDs to include in the request. + /// - requestID: The identifier for the request. + /// - Returns: An instance of `SKProductsRequest`. private func makeRequest(ids: Set, requestID: String) -> SKProductsRequest { let request = SKProductsRequest(productIdentifiers: ids) request.id = requestID @@ -36,6 +70,11 @@ final class ProductProvider: NSObject, IProductProvider { return request } + /// Initiates the product fetch request and handles the associated completion closure. + /// + /// - Parameters: + /// - request: The `SKProductsRequest` to be initiated. + /// - completion: A closure to be called upon completion with the fetched products. private func fetch(request: SKProductsRequest, completion: @escaping ProductsHandler) { dispatchQueue.async { self.handlers[request.id] = completion @@ -70,7 +109,7 @@ extension ProductProvider: SKProductsRequestDelegate { } self.dispatchQueueFactory.main().async { - handler?(.success(response.products)) + handler?(.success(response.products.map { SK1StoreProduct($0) })) } } } diff --git a/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift b/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift new file mode 100644 index 000000000..a02d3fad4 --- /dev/null +++ b/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift @@ -0,0 +1,53 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +public typealias PurchaseCompletionHandler = @MainActor @Sendable (Result) -> Void + +// MARK: - IPurchaseProvider + +protocol IPurchaseProvider { + /// Removes a finished (i.e. failed or completed) transaction from the queue. + /// Attempting to finish a purchasing transaction will throw an exception. + /// + /// - Parameters: + /// - transaction: An object in the payment queue. + /// - completion: If a completion closure is provided, call it after finishing the transaction. + func finish(transaction: StoreTransaction, completion: (@Sendable () -> Void)?) + + /// Adds transaction observer to the payment queue. + /// The transactions array will only be synchronized with the server while the queue has observers. + /// + /// - Note: This may require that the user authenticate. + func addTransactionObserver(fallbackHandler: Closure>?) + + /// Removes transaction observer from the payment queue. + /// The transactions array will only be synchronized with the server while the queue has observers. + /// + /// - Note: This may require that the user authenticate. + func removeTransactionObserver() + + /// Purchases a product. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - completion: The closure to be executed once the purchase is complete. + func purchase(product: StoreProduct, completion: @escaping PurchaseCompletionHandler) + + /// Purchases a product. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// - completion: The closure to be executed once the purchase is complete. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping PurchaseCompletionHandler + ) +} diff --git a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift new file mode 100644 index 000000000..50cf3a690 --- /dev/null +++ b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift @@ -0,0 +1,146 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - PurchaseProvider + +final class PurchaseProvider { + // MARK: Properties + + /// The provider is responsible for making in-app payments. + private let paymentProvider: IPaymentProvider + /// The transaction listener. + private let transactionListener: ITransactionListener? + + // MARK: Initialization + + /// Creates a new `PurchaseProvider` isntance. + /// + /// - Parameters: + /// - paymentProvider: The provider is responsible for purchasing products. + /// - transactionListener: The transaction listener. + init( + paymentProvider: IPaymentProvider = PaymentProvider(), + transactionListener: ITransactionListener? = nil + ) { + self.paymentProvider = paymentProvider + + if let transactionListener = transactionListener { + self.transactionListener = transactionListener + } else if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) { + self.transactionListener = TransactionListener(updates: StoreKit.Transaction.updates) + } else { + self.transactionListener = nil + } + } + + // MARK: Private + + private func purchase( + sk1StoreProduct: SK1StoreProduct, + completion: @escaping @MainActor (Result) -> Void + ) { + let payment = SKPayment(product: sk1StoreProduct.product) + paymentProvider.add(payment: payment) { _, result in + Task { + switch result { + case let .success(transaction): + await completion(.success(StoreTransaction(paymentTransaction: PaymentTransaction(transaction)))) + case let .failure(error): + await completion(.failure(error)) + } + } + } + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + private func purchase( + sk2StoreProduct: SK2StoreProduct, + options: Set? = nil, + completion: @escaping @MainActor (Result) -> Void + ) { + AsyncHandler.call(completion: { result in + Task { + switch result { + case let .success(result): + if let transaction = try await self.transactionListener?.handle(purchaseResult: result) { + await completion(.success(transaction)) + } else { + await completion(.failure(IAPError.unknown)) + } + case let .failure(error): + await completion(.failure(IAPError(error: error))) + } + } + }, asyncMethod: { + try await sk2StoreProduct.product.purchase(options: options ?? []) + }) + } +} + +// MARK: IPurchaseProvider + +extension PurchaseProvider: IPurchaseProvider { + func purchase(product: StoreProduct, completion: @escaping PurchaseCompletionHandler) { + if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *), + let sk2Product = product.underlyingProduct as? SK2StoreProduct + { + self.purchase(sk2StoreProduct: sk2Product, completion: completion) + } else if let sk1Product = product.underlyingProduct as? SK1StoreProduct { + purchase(sk1StoreProduct: sk1Product, completion: completion) + } + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping PurchaseCompletionHandler + ) { + if let sk2Product = product.underlyingProduct as? SK2StoreProduct { + purchase(sk2StoreProduct: sk2Product, options: options, completion: completion) + } else { + Task { + await completion(.failure(.unknown)) + } + } + } + + func finish(transaction: StoreTransaction, completion: (@Sendable () -> Void)?) { + if #available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *), + let sk2Transaction = transaction.storeTransaction as? SK2StoreTransaction + { + AsyncHandler.call( + completion: { _ in + completion?() + }, + asyncMethod: { + await sk2Transaction.transaction.finish() + } + ) + } else if let sk1Transaction = transaction.storeTransaction as? SK1StoreTransaction { + paymentProvider.finish(transaction: sk1Transaction.transaction) + completion?() + } + } + + func addTransactionObserver(fallbackHandler: Closure>?) { + paymentProvider.set { _, result in + switch result { + case let .success(transaction): + fallbackHandler?(.success(PaymentTransaction(transaction))) + case let .failure(error): + fallbackHandler?(.failure(error)) + } + } + paymentProvider.addTransactionObserver() + } + + func removeTransactionObserver() { + paymentProvider.removeTransactionObserver() + } +} diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift index 44c9c1c9a..9344e93ff 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/IReceiptRefreshProvider.swift @@ -6,7 +6,7 @@ import StoreKit /// A type that can refresh the bundle's App Store receipt. -public protocol IReceiptRefreshProvider { +protocol IReceiptRefreshProvider { /// The bundle’s App Store receipt. var receipt: String? { get } diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift index fcfdc6fd0..5585f0b34 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift @@ -9,20 +9,34 @@ import StoreKit // MARK: - ReceiptRefreshProvider +/// A class that can refresh the bundle's App Store receipt. final class ReceiptRefreshProvider: NSObject { // MARK: Properties + /// The dispatch queue factory. private let dispatchQueueFactory: IDispatchQueueFactory + /// A convenient interface to the contents of the file system, and the primary means of interacting with it. private let fileManager: IFileManager + /// The type that retrieves the App Store receipt URL. private let appStoreReceiptProvider: IAppStoreReceiptProvider + /// The receipt refresh request factory. private let receiptRefreshRequestFactory: IReceiptRefreshRequestFactory + /// Collection of handlers for receipt refresh requests. private var handlers: [String: ReceiptRefreshHandler] = [:] + /// Lazy-initialized private dispatch queue for handling tasks related to refreshing receipts. private lazy var dispatchQueue: IDispatchQueue = dispatchQueueFactory.privateQueue(label: String(describing: self)) // MARK: Initialization + /// Creates a new `ReceiptRefreshProvider` instance. + /// + /// - Parameters: + /// - dispatchQueueFactory: The dispatch queue factory. + /// - fileManager: A convenient interface to the contents of the file system, and the primary means of interacting with it. + /// - appStoreReceiptProvider: The type that retrieves the App Store receipt URL. + /// - receiptRefreshRequestFactory: The receipt refresh request factory. init( dispatchQueueFactory: IDispatchQueueFactory = DispatchQueueFactory(), fileManager: IFileManager = FileManager.default, @@ -37,6 +51,7 @@ final class ReceiptRefreshProvider: NSObject { // MARK: Internal + /// Computed property to retrieve the base64-encoded app store receipt string. var receipt: String? { if let appStoreReceiptURL = appStoreReceiptProvider.appStoreReceiptURL, fileManager.fileExists(atPath: appStoreReceiptURL.path) @@ -50,10 +65,20 @@ final class ReceiptRefreshProvider: NSObject { // MARK: Private + /// Creates a refresh receipt request. + /// + /// - Parameter id: The request identifier. + /// + /// - Returns: A receipt refresh request. private func makeRequest(id: String) -> IReceiptRefreshRequest { receiptRefreshRequestFactory.make(requestID: id, delegate: self) } + /// Fetches receipt information using a refresh request. + /// + /// - Parameters: + /// - request: The refresh request. + /// - handler: The closure to be executed once the refresh is complete. private func fetch(request: IReceiptRefreshRequest, handler: @escaping ReceiptRefreshHandler) { dispatchQueue.async { self.handlers[request.id] = handler diff --git a/Sources/Flare/Classes/Providers/RefundProvider/IRefundProvider.swift b/Sources/Flare/Classes/Providers/RefundProvider/IRefundProvider.swift index 97ef2dd1c..350c1a3f7 100644 --- a/Sources/Flare/Classes/Providers/RefundProvider/IRefundProvider.swift +++ b/Sources/Flare/Classes/Providers/RefundProvider/IRefundProvider.swift @@ -15,6 +15,7 @@ protocol IRefundProvider { @available(macOS, unavailable) @available(watchOS, unavailable) @available(tvOS, unavailable) + @MainActor func beginRefundRequest(productID: String) async throws -> RefundRequestStatus #endif } diff --git a/Sources/Flare/Classes/Providers/RefundProvider/RefundProvider.swift b/Sources/Flare/Classes/Providers/RefundProvider/RefundProvider.swift index f4a8adc8e..d77bf4f0a 100644 --- a/Sources/Flare/Classes/Providers/RefundProvider/RefundProvider.swift +++ b/Sources/Flare/Classes/Providers/RefundProvider/RefundProvider.swift @@ -75,6 +75,7 @@ extension RefundProvider: IRefundProvider { @available(macOS, unavailable) @available(watchOS, unavailable) @available(tvOS, unavailable) + @MainActor func beginRefundRequest(productID: String) async throws -> RefundRequestStatus { let windowScene = try systemInfoProvider.currentScene let transactionID = try await refundRequestProvider.verifyTransaction(productID: productID) diff --git a/Sources/Flare/Flare.swift b/Sources/Flare/Flare.swift index a4505be9b..159ac18fc 100644 --- a/Sources/Flare/Flare.swift +++ b/Sources/Flare/Flare.swift @@ -11,40 +11,46 @@ import StoreKit // MARK: - Flare +/// The class creates and manages in-app purchases. public final class Flare { // MARK: Initialization + /// Creates a new `Flare` instance. + /// + /// - Parameter iapProvider: The in-app purchase provider. init(iapProvider: IIAPProvider = IAPProvider()) { self.iapProvider = iapProvider } // MARK: Public + /// Returns a default `Flare` object. public static let `default`: IFlare = Flare() // MARK: Private + /// The in-app purchase provider. private let iapProvider: IIAPProvider } // MARK: IFlare extension Flare: IFlare { - public func fetch(productIDs: Set, completion: @escaping Closure>) { + public func fetch(productIDs: Set, completion: @escaping Closure>) { iapProvider.fetch(productIDs: productIDs, completion: completion) } - public func fetch(productIDs: Set) async throws -> [SKProduct] { + public func fetch(productIDs: Set) async throws -> [StoreProduct] { try await iapProvider.fetch(productIDs: productIDs) } - public func purchase(productID: String, completion: @escaping Closure>) { + public func purchase(product: StoreProduct, completion: @escaping Closure>) { guard iapProvider.canMakePayments else { completion(.failure(.paymentNotAllowed)) return } - iapProvider.purchase(productID: productID) { result in + iapProvider.purchase(product: product) { result in switch result { case let .success(transaction): completion(.success(transaction)) @@ -54,9 +60,31 @@ extension Flare: IFlare { } } - public func purchase(productID: String) async throws -> PaymentTransaction { + public func purchase(product: StoreProduct) async throws -> StoreTransaction { guard iapProvider.canMakePayments else { throw IAPError.paymentNotAllowed } - return try await iapProvider.purchase(productID: productID) + return try await iapProvider.purchase(product: product) + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + public func purchase( + product: StoreProduct, + options: Set, + completion: @escaping SendableClosure> + ) { + guard iapProvider.canMakePayments else { + completion(.failure(.paymentNotAllowed)) + return + } + iapProvider.purchase(product: product, options: options, completion: completion) + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + public func purchase( + product: StoreProduct, + options: Set + ) async throws -> StoreTransaction { + guard iapProvider.canMakePayments else { throw IAPError.paymentNotAllowed } + return try await iapProvider.purchase(product: product, options: options) } public func receipt(completion: @escaping Closure>) { @@ -74,8 +102,8 @@ extension Flare: IFlare { try await iapProvider.refreshReceipt() } - public func finish(transaction: PaymentTransaction) { - iapProvider.finish(transaction: transaction) + public func finish(transaction: StoreTransaction, completion: (@Sendable () -> Void)?) { + iapProvider.finish(transaction: transaction, completion: completion) } public func addTransactionObserver(fallbackHandler: Closure>?) { diff --git a/Sources/Flare/IFlare.swift b/Sources/Flare/IFlare.swift index 6d6a146b7..69cc89aa3 100644 --- a/Sources/Flare/IFlare.swift +++ b/Sources/Flare/IFlare.swift @@ -13,7 +13,7 @@ public protocol IFlare { /// - Parameters: /// - productIDs: The list of product identifiers for which you wish to retrieve descriptions. /// - completion: The completion containing the response of retrieving products. - func fetch(productIDs: Set, completion: @escaping Closure>) + func fetch(productIDs: Set, completion: @escaping Closure>) /// Retrieves localized information from the App Store about a specified list of products. /// @@ -22,31 +22,68 @@ public protocol IFlare { /// - Throws: `IAPError(error:)` if the request did fail with error. /// /// - Returns: An array of products. - func fetch(productIDs: Set) async throws -> [SKProduct] + func fetch(productIDs: Set) async throws -> [StoreProduct] - /// Performs a purchase of a product with a given ID. + /// Performs a purchase of a product. /// /// - Note: The method automatically checks if the user can purchase a product. /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// /// - Parameters: - /// - productID: The product identifier. + /// - product: The product to be purchased. /// - completion: The closure to be executed once the purchase is complete. - func purchase(productID: String, completion: @escaping Closure>) + func purchase(product: StoreProduct, completion: @escaping Closure>) - /// Purchases a product with a given ID. + /// Purchases a product. /// /// - Note: The method automatically checks if the user can purchase a product. /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// - /// - Parameter productID: The product identifier. + /// - Parameter product: The product to be purchased. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. - func purchase(productID: String) async throws -> PaymentTransaction + func purchase(product: StoreProduct) async throws -> StoreTransaction + + /// Purchases a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// - completion: The closure to be executed once the purchase is complete. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping SendableClosure> + ) + + /// Purchases a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase(product: StoreProduct, options: Set) async throws -> StoreTransaction /// Refreshes the receipt, representing the user's transactions with your app. /// @@ -63,8 +100,10 @@ public protocol IFlare { /// Removes a finished (i.e. failed or completed) transaction from the queue. /// Attempting to finish a purchasing transaction will throw an exception. /// - /// - Parameter transaction: An object in the payment queue. - func finish(transaction: PaymentTransaction) + /// - Parameters: + /// - transaction: An object in the payment queue. + /// - completion: If a completion closure is provided, call it after finishing the transaction. + func finish(transaction: StoreTransaction, completion: (@Sendable () -> Void)?) /// The transactions array will only be synchronized with the server while the queue has observers. /// diff --git a/Tests/FlareTests/Helpers/WindowSceneFactory.swift b/Tests/FlareTests/Helpers/WindowSceneFactory.swift deleted file mode 100644 index 337484a51..000000000 --- a/Tests/FlareTests/Helpers/WindowSceneFactory.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// Flare -// Copyright © 2023 Space Code. All rights reserved. -// - -#if os(iOS) || VISION_OS - import ObjectsFactory - import UIKit - - final class WindowSceneFactory { - static func makeWindowScene() -> UIWindowScene { - do { - let session = try ObjectsFactory.create(UISceneSession.self) - let scene = try ObjectsFactory.create(UIWindowScene.self, properties: ["session": session]) - return scene - } catch { - fatalError(error.localizedDescription) - } - } - } -#endif diff --git a/Tests/FlareTests/Mocks/ProductProviderMock.swift b/Tests/FlareTests/Mocks/ProductProviderMock.swift deleted file mode 100644 index 5480426d4..000000000 --- a/Tests/FlareTests/Mocks/ProductProviderMock.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// Flare -// Copyright © 2023 Space Code. All rights reserved. -// - -@testable import Flare -import class StoreKit.SKProduct - -final class ProductProviderMock: IProductProvider { - var invokedFetch = false - var invokedFetchCount = 0 - var invokedFetchParameters: (productIDs: Set, requestID: String, completion: ProductsHandler)? - var invokedFetchParamtersList = [(productIDs: Set, requestID: String, completion: ProductsHandler)]() - var stubbedFetchResult: Result<[SKProduct], IAPError>? - - func fetch(productIDs: Set, requestID: String, completion: @escaping ProductsHandler) { - invokedFetch = true - invokedFetchCount += 1 - invokedFetchParameters = (productIDs, requestID, completion) - invokedFetchParamtersList.append((productIDs, requestID, completion)) - - if let result = stubbedFetchResult { - completion(result) - } - } -} diff --git a/Tests/FlareTests/UnitTests/FlareTests.swift b/Tests/FlareTests/UnitTests/FlareTests.swift index 87aed5ebe..33cc4debc 100644 --- a/Tests/FlareTests/UnitTests/FlareTests.swift +++ b/Tests/FlareTests/UnitTests/FlareTests.swift @@ -13,19 +13,20 @@ class FlareTests: XCTestCase { // MARK: - Properties private var iapProviderMock: IAPProviderMock! - private var flare: Flare! + + private var sut: Flare! // MARK: - XCTestCase override func setUp() { super.setUp() iapProviderMock = IAPProviderMock() - flare = Flare(iapProvider: iapProviderMock) + sut = Flare(iapProvider: iapProviderMock) } override func tearDown() { iapProviderMock = nil - flare = nil + sut = nil super.tearDown() } @@ -33,7 +34,7 @@ class FlareTests: XCTestCase { func test_thatFlareFetchesProductsWithGivenProductIDs() { // when - flare.fetch(productIDs: .ids, completion: { _ in }) + sut.fetch(productIDs: .ids, completion: { _ in }) // then XCTAssertTrue(iapProviderMock.invokedFetch) @@ -41,11 +42,15 @@ class FlareTests: XCTestCase { func test_thatFlareFetchesProductsWithGivenProductIDs() async throws { // given - let productMocks = [ProductMock(), ProductMock(), ProductMock()] + let productMocks = [ + StoreProduct(skProduct: ProductMock()), + StoreProduct(skProduct: ProductMock()), + StoreProduct(skProduct: ProductMock()), + ] iapProviderMock.fetchAsyncResult = productMocks // when - let products = try await flare.fetch(productIDs: .ids) + let products = try await sut.fetch(productIDs: .ids) // then XCTAssertEqual(products, productMocks) @@ -56,54 +61,50 @@ class FlareTests: XCTestCase { iapProviderMock.stubbedCanMakePayments = true // when - flare.purchase(productID: .productID, completion: { _ in }) + sut.purchase(product: .fake(skProduct: .fake(id: .productID)), completion: { _ in }) // then XCTAssertTrue(iapProviderMock.invokedPurchase) - XCTAssertEqual(iapProviderMock.invokedPurchaseParameters?.productID, .productID) + XCTAssertEqual(iapProviderMock.invokedPurchaseParameters?.product.productIdentifier, .productID) } - func test_thatFlareDoesNotPurchaseAProduct_whenUserCannotMakePayments() { + func test_thatFlareThrowsAnError_whenUserCannotMakePayments() { // given iapProviderMock.stubbedCanMakePayments = false // when - flare.purchase(productID: .productID, completion: { _ in }) + sut.purchase(product: .fake(skProduct: .fake(id: .productID)), completion: { _ in }) // then XCTAssertFalse(iapProviderMock.invokedPurchase) } - func test_thatFlarePurchasesAProduct_whenRequestCompletedSuccessfully() { + func test_thatFlarePurchasesAProduct_whenRequestCompleted() { // given - let paymentTransaction = PaymentTransaction(PaymentTransactionMock()) + let paymentTransaction = StoreTransaction(storeTransaction: StoreTransactionStub()) iapProviderMock.stubbedCanMakePayments = true // when - var transaction: PaymentTransaction? - flare.purchase(productID: .productID, completion: { result in - if case let .success(result) = result { - transaction = result - } + var transaction: IStoreTransaction? + sut.purchase(product: .fake(skProduct: .fake(id: .productID)), completion: { result in + transaction = result.success }) iapProviderMock.invokedPurchaseParameters?.completion(.success(paymentTransaction)) // then XCTAssertTrue(iapProviderMock.invokedPurchase) - XCTAssertEqual(transaction, paymentTransaction) + XCTAssertEqual(transaction?.productIdentifier, paymentTransaction.productIdentifier) } - func test_thatFlareDoesNotPurchaseAProduct_whenUnknownErrorOccurred() { + func test_thatFlareDoesNotPurchaseAProduct_whenPurchaseReturnsUnkownError() { // given let errorMock = IAPError.paymentNotAllowed iapProviderMock.stubbedCanMakePayments = true // when var error: IAPError? - flare.purchase(productID: .productID, completion: { result in - if case let .failure(result) = result { - error = result - } + sut.purchase(product: .fake(skProduct: .fake(id: .productID)), completion: { result in + error = result.error }) iapProviderMock.invokedPurchaseParameters?.completion(.failure(errorMock)) @@ -115,15 +116,10 @@ class FlareTests: XCTestCase { func test_thatFlareDoesNotPurchaseAProduct_whenUserCannotMakePayments() async { // given iapProviderMock.stubbedCanMakePayments = false - iapProviderMock.stubbedAsyncPurchase = PaymentTransaction(PaymentTransactionMock()) + iapProviderMock.stubbedAsyncPurchase = StoreTransaction(storeTransaction: StoreTransactionStub()) // when - var iapError: IAPError? - do { - _ = try await flare.purchase(productID: .productID) - } catch { - iapError = error as? IAPError - } + let iapError: IAPError? = await error(for: { try await sut.purchase(product: .fake(skProduct: .fake(id: .productID))) }) // then XCTAssertFalse(iapProviderMock.invokedAsyncPurchase) @@ -132,34 +128,24 @@ class FlareTests: XCTestCase { func test_thatFlareDoesNotPurchaseAProduct_whenUnknownErrorOccurred() async { // given - let transactionMock = PaymentTransaction(PaymentTransactionMock()) + let transactionMock = StoreTransaction(storeTransaction: StoreTransactionStub()) iapProviderMock.stubbedCanMakePayments = true iapProviderMock.stubbedAsyncPurchase = transactionMock // when - var transaction: PaymentTransaction? - var iapError: IAPError? - do { - transaction = try await flare.purchase(productID: .productID) - } catch { - iapError = error as? IAPError - } + let transaction = await value(for: { try await sut.purchase(product: .fake(skProduct: .fake(id: .productID))) }) // then XCTAssertTrue(iapProviderMock.invokedAsyncPurchase) - XCTAssertNil(iapError) - XCTAssertEqual(transaction, transactionMock) + XCTAssertEqual(transaction?.productIdentifier, transactionMock.productIdentifier) } - func test_thatFlareFetchesReceipt_whenRequestCompletedSuccessfully() { + func test_thatFlareFetchesReceipt_whenRequestCompleted() { // when var receipt: String? - flare.receipt(completion: { result in - if case let .success(result) = result { - receipt = result - } - }) + sut.receipt { receipt = $0.success } + iapProviderMock.invokedRefreshReceiptParameters?.completion(.success(.receipt)) // then @@ -170,11 +156,8 @@ class FlareTests: XCTestCase { func test_thatFlareDoesNotFetchReceipt_whenRequestFailed() { // when var error: IAPError? - flare.receipt(completion: { result in - if case let .failure(result) = result { - error = result - } - }) + sut.receipt { error = $0.error } + iapProviderMock.invokedRefreshReceiptParameters?.completion(.failure(.paymentNotAllowed)) // then @@ -184,18 +167,18 @@ class FlareTests: XCTestCase { func test_thatFlareRemovesTransactionObserver() { // when - flare.removeTransactionObserver() + sut.removeTransactionObserver() // then XCTAssertTrue(iapProviderMock.invokedRemoveTransactionObserver) } - func test_thatFlareFetchesReceipt_whenRequestCompletedSuccessfully() async throws { + func test_thatFlareFetchesReceipt_whenRequestCompleted() async throws { // given iapProviderMock.stubbedRefreshReceiptAsyncResult = .success(.receipt) // when - let receipt = try await flare.receipt() + let receipt = try await sut.receipt() // then XCTAssertEqual(receipt, .receipt) @@ -206,15 +189,10 @@ class FlareTests: XCTestCase { iapProviderMock.stubbedRefreshReceiptAsyncResult = .failure(.paymentNotAllowed) // when - var iapError: IAPError? - do { - _ = try await flare.receipt() - } catch { - iapError = error as? IAPError - } + let error: IAPError? = await self.error(for: { try await sut.receipt() }) // then - XCTAssertEqual(iapError, .paymentNotAllowed) + XCTAssertEqual(error, .paymentNotAllowed) } func test_thatFlareFinishesTransaction() { @@ -222,7 +200,7 @@ class FlareTests: XCTestCase { let transaction = PaymentTransaction(PaymentTransactionMock()) // when - flare.finish(transaction: transaction) + sut.finish(transaction: StoreTransaction(paymentTransaction: transaction), completion: nil) // then XCTAssertTrue(iapProviderMock.invokedFinishTransaction) @@ -230,39 +208,11 @@ class FlareTests: XCTestCase { func test_thatFlareAddsTransactionObserver() { // when - flare.addTransactionObserver(fallbackHandler: { _ in }) + sut.addTransactionObserver(fallbackHandler: { _ in }) // then XCTAssertTrue(iapProviderMock.invokedAddTransactionObserver) } - - #if os(iOS) || VISION_OS - @available(iOS 15.0, *) - func test_thatFlareRefundsPurchase() async throws { - // given - iapProviderMock.stubbedBeginRefundRequest = .success - - // when - let state = try await flare.beginRefundRequest(productID: .productID) - - // then - if case .success = state {} - else { XCTFail("state must be `success`") } - } - - @available(iOS 15.0, *) - func test_thatFlareThrowsAnError_whenBeginRefundRequestFailed() async throws { - // given - iapProviderMock.stubbedBeginRefundRequest = .failed(error: IAPError.unknown) - - // when - let state = try await flare.beginRefundRequest(productID: .productID) - - // then - if case let .failed(error) = state { XCTAssertEqual(error as NSError, IAPError.unknown as NSError) } - else { XCTFail("state must be `failed`") } - } - #endif } // MARK: - Constants diff --git a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift index 06c322ac5..319d97f15 100644 --- a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift @@ -14,11 +14,11 @@ class IAPProviderTests: XCTestCase { private var paymentQueueMock: PaymentQueueMock! private var productProviderMock: ProductProviderMock! - private var paymentProviderMock: PaymentProviderMock! + private var purchaseProvider: PurchaseProviderMock! private var receiptRefreshProviderMock: ReceiptRefreshProviderMock! private var refundProviderMock: RefundProviderMock! - private var iapProvider: IIAPProvider! + private var sut: IIAPProvider! // MARK: - XCTestCase @@ -26,13 +26,13 @@ class IAPProviderTests: XCTestCase { super.setUp() paymentQueueMock = PaymentQueueMock() productProviderMock = ProductProviderMock() - paymentProviderMock = PaymentProviderMock() + purchaseProvider = PurchaseProviderMock() receiptRefreshProviderMock = ReceiptRefreshProviderMock() refundProviderMock = RefundProviderMock() - iapProvider = IAPProvider( + sut = IAPProvider( paymentQueue: paymentQueueMock, productProvider: productProviderMock, - paymentProvider: paymentProviderMock, + purchaseProvider: purchaseProvider, receiptRefreshProvider: receiptRefreshProviderMock, refundProvider: refundProviderMock ) @@ -41,10 +41,10 @@ class IAPProviderTests: XCTestCase { override func tearDown() { paymentQueueMock = nil productProviderMock = nil - paymentProviderMock = nil + purchaseProvider = nil receiptRefreshProviderMock = nil refundProviderMock = nil - iapProvider = nil + sut = nil super.tearDown() } @@ -55,12 +55,14 @@ class IAPProviderTests: XCTestCase { paymentQueueMock.stubbedCanMakePayments = true // then - XCTAssertTrue(iapProvider.canMakePayments) + XCTAssertTrue(sut.canMakePayments) } func test_thatIAPProviderFetchesProducts() throws { + try AvailabilityChecker.iOS15APINotAvailableOrSkipTest() + // when - iapProvider.fetch(productIDs: .productIDs, completion: { _ in }) + sut.fetch(productIDs: .productIDs, completion: { _ in }) // then let parameters = try XCTUnwrap(productProviderMock.invokedFetchParameters) @@ -70,15 +72,15 @@ class IAPProviderTests: XCTestCase { func test_thatIAPProviderPurchasesProduct() throws { // when - iapProvider.purchase(productID: .productID, completion: { _ in }) + sut.purchase(product: .fake(skProduct: .fake(id: .productID)), completion: { _ in }) // then - XCTAssertTrue(productProviderMock.invokedFetch) + XCTAssertTrue(purchaseProvider.invokedPurchase) } func test_thatIAPProviderRefreshesReceipt() { // when - iapProvider.refreshReceipt(completion: { _ in }) + sut.refreshReceipt(completion: { _ in }) // then XCTAssertTrue(receiptRefreshProviderMock.invokedRefresh) @@ -89,168 +91,92 @@ class IAPProviderTests: XCTestCase { let transaction = PurchaseManagerTestHelper.makePaymentTransaction(state: .purchased) // when - iapProvider.finish(transaction: PaymentTransaction(transaction)) + sut.finish(transaction: StoreTransaction(paymentTransaction: PaymentTransaction(transaction)), completion: nil) // then - XCTAssertTrue(paymentProviderMock.invokedFinishTransaction) + XCTAssertTrue(purchaseProvider.invokedFinish) } func test_thatIAPProviderAddsTransactionObserver() { // when - iapProvider.addTransactionObserver(fallbackHandler: { _ in }) + sut.addTransactionObserver(fallbackHandler: { _ in }) // then - XCTAssertTrue(paymentProviderMock.invokedFallbackHandler) - XCTAssertTrue(paymentProviderMock.invokedAddTransactionObserver) + XCTAssertTrue(purchaseProvider.invokedAddTransactionObserver) } func test_thatIAPProviderRemovesTransactionObserver() { // when - iapProvider.removeTransactionObserver() + sut.removeTransactionObserver() // then - XCTAssertTrue(paymentProviderMock.invokedRemoveTransactionObserver) + XCTAssertTrue(purchaseProvider.invokedRemoveTransactionObserver) } - func test_thatIAPProviderFetchesProducts_whenProducts() async throws { + // FIXME: Update test + func test_thatIAPProviderFetchesSK1Products_whenProductsAvailable() async throws { + try AvailabilityChecker.iOS15APINotAvailableOrSkipTest() + // given - let productsMock = [SKProduct(), SKProduct(), SKProduct()] + let productsMock = [0 ... 2].map { _ in SK1StoreProduct(ProductMock()) } productProviderMock.stubbedFetchResult = .success(productsMock) // when - let products = try await iapProvider.fetch(productIDs: .productIDs) + let products = try await sut.fetch(productIDs: .productIDs) // then - XCTAssertEqual(productsMock, products) + XCTAssertEqual(productsMock.count, products.count) } - func test_thatIAPProviderThrowsNoProductsError_whenProductsProductProviderReturnsError() async { + func test_thatIAPProviderThrowsNoProductsError_whenProductsProductProviderReturnsError() async throws { + try AvailabilityChecker.iOS15APINotAvailableOrSkipTest() + // given productProviderMock.stubbedFetchResult = .failure(IAPError.unknown) // when - var errorResult: Error? - do { - _ = try await iapProvider.fetch(productIDs: .productIDs) - } catch { - errorResult = error - } + let errorResult: Error? = await error(for: { try await sut.fetch(productIDs: .productIDs) }) // then XCTAssertEqual(errorResult as? NSError, IAPError.unknown as NSError) } - func test_thatIAPProviderThrowsStoreProductNotAvailableError_whenProductProviderDoesNotHaveProducts() { - // given - productProviderMock.stubbedFetchResult = .success([]) - - // when - var error: Error? - iapProvider.purchase(productID: .productID) { result in - if case let .failure(result) = result { - error = result - } - } - - // then - XCTAssertEqual(error as? NSError, IAPError.storeProductNotAvailable as NSError) - } - - func test_thatIAPProviderReturnsPaymentTransaction_whenProductsExist() { - // given - let paymentTransactionMock = PaymentTransactionMock() - productProviderMock.stubbedFetchResult = .success([ProductMock()]) - paymentProviderMock.stubbedAddResult = (paymentQueueMock, .success(paymentTransactionMock)) - - // when - var transactionResult: PaymentTransaction? - iapProvider.purchase(productID: .productID) { result in - if case let .success(transaction) = result { - transactionResult = transaction - } - } - - // then - XCTAssertEqual(transactionResult?.skTransaction, paymentTransactionMock) - } - func test_thatIAPProviderReturnsError_whenAddingPaymentFailed() { // given - productProviderMock.stubbedFetchResult = .success([ProductMock()]) - paymentProviderMock.stubbedAddResult = (paymentQueueMock, .failure(.unknown)) + productProviderMock.stubbedFetchResult = .success([SK1StoreProduct(ProductMock())]) + purchaseProvider.stubbedPurchaseCompletionResult = (.failure(.unknown), ()) // when - var errorResult: Error? - iapProvider.purchase(productID: .productID) { result in - if case let .failure(error) = result { - errorResult = error - } - } + var error: Error? + sut.purchase(product: .fake(skProduct: .fake(id: .productID))) { error = $0.error } // then - XCTAssertEqual(errorResult as? NSError, IAPError.unknown as NSError) + XCTAssertEqual(error as? NSError, IAPError.unknown as NSError) } func test_thatIAPProviderReturnsError_whenFetchRequestFailed() { // given - productProviderMock.stubbedFetchResult = .failure(.storeProductNotAvailable) - - // when - var errorResult: Error? - iapProvider.purchase(productID: .productID) { result in - if case let .failure(error) = result { - errorResult = error - } - } - - // then - XCTAssertEqual(errorResult as? NSError, IAPError.storeProductNotAvailable as NSError) - } - - func test_thatIAPProviderThrowsStoreProductNotAvailableError_whenProductsDoNotExist() async throws { - // given - productProviderMock.stubbedFetchResult = .success([]) - - // when - var errorResult: Error? - do { - _ = try await iapProvider.purchase(productID: .productID) - } catch { - errorResult = error - } - - // then - XCTAssertEqual(errorResult as? NSError, IAPError.storeProductNotAvailable as NSError) - } - - func test_thatIAPProviderPurchasesForAProduct_whenProductsExist() async throws { - // given - let transactionMock = SKPaymentTransaction() - productProviderMock.stubbedFetchResult = .success([ProductMock()]) - paymentProviderMock.stubbedAddResult = (paymentQueueMock, .success(transactionMock)) + purchaseProvider.stubbedPurchaseCompletionResult = (.failure(IAPError.unknown), ()) // when - let transactionResult = try await iapProvider.purchase(productID: .productID) + var error: Error? + sut.purchase(product: .fake(skProduct: .fake(id: .productID))) { error = $0.error } // then - XCTAssertEqual(transactionMock, transactionResult.skTransaction) + XCTAssertEqual(error as? NSError, IAPError.unknown as NSError) } - func test_thatIAPProviderRefreshesReceipt_when() { + func test_thatIAPProviderRefreshesReceipt_whenReceiptExist() { // given receiptRefreshProviderMock.stubbedReceipt = .receipt receiptRefreshProviderMock.stubbedRefreshResult = .success(()) // when - var receiptResult: String? - iapProvider.refreshReceipt { result in - if case let .success(receipt) = result { - receiptResult = receipt - } - } + var receipt: String? + sut.refreshReceipt { receipt = $0.success } // then - XCTAssertEqual(receiptResult, .receipt) + XCTAssertEqual(receipt, .receipt) } func test_thatIAPProviderDoesNotRefreshReceipt_whenRequestFailed() { @@ -259,15 +185,11 @@ class IAPProviderTests: XCTestCase { receiptRefreshProviderMock.stubbedRefreshResult = .failure(.receiptNotFound) // when - var errorResult: Error? - iapProvider.refreshReceipt { result in - if case let .failure(error) = result { - errorResult = error - } - } + var error: Error? + sut.refreshReceipt { error = $0.error } // then - XCTAssertEqual(errorResult as? NSError, IAPError.receiptNotFound as NSError) + XCTAssertEqual(error as? NSError, IAPError.receiptNotFound as NSError) } func test_thatIAPProviderReturnsReceiptNotFoundError_whenReceiptIsNil() { @@ -276,15 +198,11 @@ class IAPProviderTests: XCTestCase { receiptRefreshProviderMock.stubbedRefreshResult = .success(()) // when - var errorResult: Error? - iapProvider.refreshReceipt { result in - if case let .failure(error) = result { - errorResult = error - } - } + var error: Error? + sut.refreshReceipt { error = $0.error } // then - XCTAssertEqual(errorResult as? NSError, IAPError.receiptNotFound as NSError) + XCTAssertEqual(error as? NSError, IAPError.receiptNotFound as NSError) } func test_thatIAPProviderRefreshesReceipt_whenReceiptIsNotNil() async throws { @@ -293,7 +211,7 @@ class IAPProviderTests: XCTestCase { receiptRefreshProviderMock.stubbedRefreshResult = .success(()) // when - let receipt = try await iapProvider.refreshReceipt() + let receipt = try await sut.refreshReceipt() // then XCTAssertEqual(receipt, .receipt) @@ -305,77 +223,11 @@ class IAPProviderTests: XCTestCase { receiptRefreshProviderMock.stubbedRefreshResult = .success(()) // when - var errorResult: Error? - do { - _ = try await iapProvider.refreshReceipt() - } catch { - errorResult = error - } + let errorResult: Error? = await error(for: { try await sut.refreshReceipt() }) // then XCTAssertEqual(errorResult as? NSError, IAPError.receiptNotFound as NSError) } - - func test_thatIAPProviderReturnsTransaction() { - // given - let transactionMock = SKPaymentTransaction() - paymentProviderMock.stubbedFallbackHandlerResult = (paymentQueueMock, .success(transactionMock)) - - // when - var transactionResult: PaymentTransaction? - iapProvider.addTransactionObserver { result in - if case let .success(transaction) = result { - transactionResult = transaction - } - } - - // then - XCTAssertEqual(transactionResult?.skTransaction, transactionMock) - } - - func test_thatIAPProviderReturnsError() { - // given - paymentProviderMock.stubbedFallbackHandlerResult = (paymentQueueMock, .failure(.unknown)) - - // when - var errorResult: Error? - iapProvider.addTransactionObserver { result in - if case let .failure(error) = result { - errorResult = error - } - } - - // then - XCTAssertEqual(errorResult as? NSError, IAPError.unknown as NSError) - } - - #if os(iOS) || VISION_OS - @available(iOS 15.0, *) - func test_thatIAPProviderRefundsPurchase() async throws { - // given - refundProviderMock.stubbedBeginRefundRequest = .success - - // when - let state = try await iapProvider.beginRefundRequest(productID: .productID) - - // then - if case .success = state {} - else { XCTFail("state must be `success`") } - } - - @available(iOS 15.0, *) - func test_thatFlareThrowsAnError_whenBeginRefundRequestFailed() async throws { - // given - refundProviderMock.stubbedBeginRefundRequest = .failed(error: IAPError.unknown) - - // when - let state = try await iapProvider.beginRefundRequest(productID: .productID) - - // then - if case let .failed(error) = state { XCTAssertEqual(error as NSError, IAPError.unknown as NSError) } - else { XCTFail("state must be `failed`") } - } - #endif } // MARK: - Constants @@ -383,6 +235,7 @@ class IAPProviderTests: XCTestCase { private extension String { static let receipt = "receipt" static let productID = "product_identifier" + static let transactionID = "transaction_identifier" } private extension Set where Element == String { diff --git a/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift index c2f1ada71..fc0a2edf1 100644 --- a/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift @@ -11,12 +11,13 @@ import XCTest // MARK: - ProductProviderTests -class ProductProviderTests: XCTestCase { +final class ProductProviderTests: XCTestCase { // MARK: - Properties private var testDispatchQueue: TestDispatchQueue! private var dispatchQueueFactory: IDispatchQueueFactory! - private var productProvider: ProductProvider! + + private var sut: ProductProvider! // MARK: - XCTestCase @@ -24,21 +25,21 @@ class ProductProviderTests: XCTestCase { super.setUp() testDispatchQueue = TestDispatchQueue() dispatchQueueFactory = TestDispatchQueueFactory(testQueue: testDispatchQueue) - productProvider = ProductProvider(dispatchQueueFactory: dispatchQueueFactory) + sut = ProductProvider(dispatchQueueFactory: dispatchQueueFactory) } override func tearDown() { testDispatchQueue = nil dispatchQueueFactory = nil - productProvider = nil + sut = nil super.tearDown() } // MARK: - Tests - func test_thatProductProviderReturnsInvalidProductIDs_whenRequestProductsWithInvalidIDs() { + func test_thatProductProviderReturnsInvalidProductIDs_whenRequestProductsAreFetchedWithInvalidIDs() { // given - var fetchResult: Result<[SKProduct], IAPError>? + var fetchResult: Result<[SK1StoreProduct], IAPError>? let completionHandler: IProductProvider.ProductsHandler = { result in fetchResult = result } let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let response = ProductResponseMock() @@ -46,8 +47,8 @@ class ProductProviderTests: XCTestCase { response.stubbedInvokedInvalidProductsIdentifiers = [.productID] // when - productProvider.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) - productProvider.productsRequest(request, didReceive: response) + sut.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) + sut.productsRequest(request, didReceive: response) // then if case let .failure(error) = fetchResult, case let .invalid(products) = error { @@ -57,49 +58,41 @@ class ProductProviderTests: XCTestCase { } } - func test_thatProductProviderReturnsProducts_whenRequestProductsWithValidProductIDs() { + func test_thatProductProviderReturnsProducts_whenRequestProductsAreFetchedWithValidProductIDs() { // given - var fetchResult: Result<[SKProduct], IAPError>? - let completionHandler: IProductProvider.ProductsHandler = { result in fetchResult = result } + var products: [SK1StoreProduct]? = [] + let completionHandler: IProductProvider.ProductsHandler = { products = $0.success } let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let response = ProductResponseMock() // when - productProvider.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) - productProvider.productsRequest(request, didReceive: response) + sut.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) + sut.productsRequest(request, didReceive: response) // then - if case let .success(products) = fetchResult { - XCTAssertEqual(products, response.products) - } else { - XCTFail() - } + XCTAssertEqual(products?.map(\.product), response.products) } func test_thatProductProviderHandlesError_whenRequestDidFailWithError() { // given - var fetchResult: Result<[SKProduct], IAPError>? - let completionHandler: IProductProvider.ProductsHandler = { result in fetchResult = result } + var error: IAPError? + let completionHandler: IProductProvider.ProductsHandler = { error = $0.error } let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) - let error = IAPError.emptyProducts + let errorStub = IAPError.emptyProducts // when - productProvider.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) - productProvider.request(request, didFailWithError: error) + sut.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) + sut.request(request, didFailWithError: errorStub) // then - if case let .failure(resultError) = fetchResult { - XCTAssertEqual(resultError.plainError as NSError, error.plainError as NSError) - } else { - XCTFail() - } + XCTAssertEqual(error?.plainError as? NSError, errorStub.plainError as NSError) } } // MARK: - Constants private extension String { - static let productID = "product_ID" + static let productID = "com.flare.test_purchase_1" static let requestID = "request_identifier" } diff --git a/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift new file mode 100644 index 000000000..af4b7a49a --- /dev/null +++ b/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift @@ -0,0 +1,104 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import StoreKit +import StoreKitTest +import XCTest + +// MARK: - PurchaseProviderTests + +final class PurchaseProviderTests: XCTestCase { + // MARK: Properties + + private var paymentQueueMock: PaymentQueueMock! + private var paymentProviderMock: PaymentProviderMock! + + private var sut: PurchaseProvider! + + // MARK: XCTestCase + + override func setUp() { + super.setUp() + paymentQueueMock = PaymentQueueMock() + paymentProviderMock = PaymentProviderMock() + sut = PurchaseProvider( + paymentProvider: paymentProviderMock + ) + } + + override func tearDown() { + paymentQueueMock = nil + paymentProviderMock = nil + sut = nil + super.tearDown() + } + + // MARK: Tests + + func test_thatPurchaseProviderReturnsPaymentTransaction_whenSK1ProductExist() { + // given + let productMock = StoreProduct(skProduct: ProductMock()) + + paymentProviderMock.stubbedAddResult = (paymentQueueMock, .success(SKPaymentTransaction())) + + // when + sut.purchase(product: productMock) { result in + if case let .success(transaction) = result { + XCTAssertEqual(transaction.productIdentifier, productMock.productIdentifier) + } else { + XCTFail("The products' ids must be equal") + } + } + } + + func test_thatPurchaseProviderFinishesTransaction() { + // given + let transaction = PurchaseManagerTestHelper.makePaymentTransaction(state: .purchased) + + // when + sut.finish(transaction: StoreTransaction(paymentTransaction: PaymentTransaction(transaction)), completion: nil) + + // then + XCTAssertTrue(paymentProviderMock.invokedFinishTransaction) + } + + func test_thatPurchaseProviderAddsTransactionObserver_whenPaymentDidSuccess() { + // given + let paymentTransactionMock = SKPaymentTransaction() + paymentProviderMock.stubbedFallbackHandlerResult = (paymentQueueMock, .success(paymentTransactionMock)) + + // when + sut.addTransactionObserver(fallbackHandler: { result in + if case let .success(transaction) = result { + XCTAssertTrue(transaction.productIdentifier.isEmpty) + } else { + XCTFail("The products' ids must be equal") + } + }) + } + + func test_thatPurchaseProviderThrowsAnError_whenTransactionObserverDidFail() { + // given + paymentProviderMock.stubbedFallbackHandlerResult = (paymentQueueMock, .failure(IAPError.unknown)) + + // when + sut.addTransactionObserver(fallbackHandler: { result in + if case let .failure(error) = result { + XCTAssertEqual(error, .unknown) + } else { + XCTFail("The errors' types must be equal") + } + }) + } + + func test_thatIAPProviderRemovesTransactionObserver() { + // when + sut.removeTransactionObserver() + + // then + XCTAssertTrue(paymentProviderMock.invokedRemoveTransactionObserver) + } +} diff --git a/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift index cd3b4c67e..61b25272c 100644 --- a/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/ReceiptRefreshProviderTests.swift @@ -15,11 +15,12 @@ class ReceiptRefreshProviderTests: XCTestCase { private var testDispatchQueue: TestDispatchQueue! private var dispatchQueueFactory: TestDispatchQueueFactory! - private var receiptRefreshProvider: ReceiptRefreshProvider! private var appStoreReceiptProviderMock: AppStoreReceiptProviderMock! private var fileManagerMock: FileManagerMock! private var receiptRefreshRequestFactoryMock: ReceiptRefreshRequestFactoryMock! + private var sut: ReceiptRefreshProvider! + // MARK: - XCTestCase override func setUp() { @@ -29,7 +30,7 @@ class ReceiptRefreshProviderTests: XCTestCase { dispatchQueueFactory = TestDispatchQueueFactory(testQueue: testDispatchQueue) fileManagerMock = FileManagerMock() receiptRefreshRequestFactoryMock = ReceiptRefreshRequestFactoryMock() - receiptRefreshProvider = ReceiptRefreshProvider( + sut = ReceiptRefreshProvider( dispatchQueueFactory: dispatchQueueFactory, fileManager: fileManagerMock, appStoreReceiptProvider: appStoreReceiptProviderMock, @@ -40,7 +41,7 @@ class ReceiptRefreshProviderTests: XCTestCase { override func tearDown() { testDispatchQueue = nil dispatchQueueFactory = nil - receiptRefreshProvider = nil + sut = nil appStoreReceiptProviderMock = nil fileManagerMock = nil receiptRefreshRequestFactoryMock = nil @@ -59,8 +60,8 @@ class ReceiptRefreshProviderTests: XCTestCase { let error = IAPError.paymentCancelled // when - receiptRefreshProvider.refresh(requestID: .requestID, handler: handler) - receiptRefreshProvider.request(request, didFailWithError: error) + sut.refresh(requestID: .requestID, handler: handler) + sut.request(request, didFailWithError: error) // then if case let .failure(resultError) = result { @@ -77,13 +78,11 @@ class ReceiptRefreshProviderTests: XCTestCase { let handler: ReceiptRefreshHandler = { result = $0 } // when - receiptRefreshProvider.refresh(requestID: .requestID, handler: handler) - receiptRefreshProvider.requestDidFinish(request) + sut.refresh(requestID: .requestID, handler: handler) + sut.requestDidFinish(request) // then - if case .failure = result { - XCTFail() - } + if case .failure = result { XCTFail("The result must be `success`") } } func test_thatReceiptRefreshProviderLoadsAppStoreReceipt_whenReceiptExists() { @@ -92,7 +91,7 @@ class ReceiptRefreshProviderTests: XCTestCase { fileManagerMock.stubbedFileExistsResult = true // when - let receipt = receiptRefreshProvider.receipt + let receipt = sut.receipt // then XCTAssertNotNil(receipt) @@ -104,7 +103,7 @@ class ReceiptRefreshProviderTests: XCTestCase { fileManagerMock.stubbedFileExistsResult = false // when - let receipt = receiptRefreshProvider.receipt + let receipt = sut.receipt // then XCTAssertNil(receipt) @@ -116,20 +115,14 @@ class ReceiptRefreshProviderTests: XCTestCase { receiptRefreshRequestFactoryMock.stubbedMakeResult = request request.stubbedStartAction = { - self.receiptRefreshProvider.request( + self.sut.request( self.makeSKRequest(id: request.id), didFailWithError: IAPError.paymentNotAllowed ) } // when - var iapError: IAPError? - - do { - try await receiptRefreshProvider.refresh(requestID: .requestID) - } catch { - iapError = error as? IAPError - } + let iapError: IAPError? = await error(for: { try await sut.refresh(requestID: .requestID) }) // then XCTAssertEqual(iapError, IAPError(error: IAPError.paymentNotAllowed)) @@ -143,17 +136,11 @@ class ReceiptRefreshProviderTests: XCTestCase { receiptRefreshRequestFactoryMock.stubbedMakeResult = request request.stubbedStartAction = { - self.receiptRefreshProvider.requestDidFinish(self.makeSKRequest(id: .requestID)) + self.sut.requestDidFinish(self.makeSKRequest(id: .requestID)) } // when - var iapError: IAPError? - - do { - try await receiptRefreshProvider.refresh(requestID: .requestID) - } catch { - iapError = error as? IAPError - } + let iapError: IAPError? = await error(for: { try await sut.refresh(requestID: .requestID) }) // then XCTAssertNil(iapError) diff --git a/Tests/FlareTests/UnitTests/Providers/RefundProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/RefundProviderTests.swift index 90908c7ea..4dbe95d6e 100644 --- a/Tests/FlareTests/UnitTests/Providers/RefundProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/RefundProviderTests.swift @@ -34,75 +34,71 @@ // MARK: - Tests - func testThatRefundProviderThrowsAnErrorWhenVerificationDidFail() async throws { + func testThatRefundProviderThrowsAnError_whenVerificationDidFail() async throws { // given refundRequestProviderMock.stubbedVerifyTransaction = nil systemInfoProviderMock.stubbedCurrentScene = .failure(IAPError.unknown) // when - var resultError: Error? - do { - _ = try await sut.beginRefundRequest(productID: .productID) - } catch { - resultError = error - } + let error: Error? = await error(for: { try await sut.beginRefundRequest(productID: .productID) }) // then - XCTAssertEqual(resultError as? NSError, IAPError.unknown as NSError) + XCTAssertEqual(error as? NSError, IAPError.unknown as NSError) } - func testThatRefundProviderThrowsAnErrorWhenRefundRequestDidFail() async throws { - // given - refundRequestProviderMock.stubbedVerifyTransaction = .transactionID - refundRequestProviderMock.stubbedBeginRefundRequest = .failure(IAPError.unknown) - systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) - - // when - let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) - - // then - if case .failed = status {} - else { XCTFail("The status must be `failed`") } - XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) - } - - func testThatRefundProviderReturnsSuccessStatusWhenRefundRequestCompleted() async throws { - // given - refundRequestProviderMock.stubbedVerifyTransaction = .transactionID - refundRequestProviderMock.stubbedBeginRefundRequest = .success(.success) - systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) - - // when - let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) - - // then - if case .success = status {} - else { XCTFail("The status must be `success`") } - XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) - } - - func testThatRefundProviderReturnsUserCancelledStatusWhenUserCancelledRequest() async throws { - // given - refundRequestProviderMock.stubbedVerifyTransaction = .transactionID - refundRequestProviderMock.stubbedBeginRefundRequest = .success(.userCancelled) - systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) - - // when - let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) - - // then - if case .userCancelled = status {} - else { XCTFail("The status must be `userCancelled`") } - XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) - } +// func testThatRefundProviderThrowsAnErrorWhenRefundRequestDidFail() async throws { +// // given +// refundRequestProviderMock.stubbedVerifyTransaction = .transactionID +// refundRequestProviderMock.stubbedBeginRefundRequest = .failure(IAPError.unknown) +// systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) +// +// // when +// let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) +// +// // then +// if case .failed = status {} +// else { XCTFail("The status must be `failed`") } +// XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) +// } +// +// func testThatRefundProviderReturnsSuccessStatusWhenRefundRequestCompleted() async throws { +// // given +// refundRequestProviderMock.stubbedVerifyTransaction = .transactionID +// refundRequestProviderMock.stubbedBeginRefundRequest = .success(.success) +// systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) +// +// // when +// let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) +// +// // then +// if case .success = status {} +// else { XCTFail("The status must be `success`") } +// XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) +// } +// +// func testThatRefundProviderReturnsUserCancelledStatusWhenUserCancelledRequest() async throws { +// // given +// refundRequestProviderMock.stubbedVerifyTransaction = .transactionID +// refundRequestProviderMock.stubbedBeginRefundRequest = .success(.userCancelled) +// systemInfoProviderMock.stubbedCurrentScene = .success(WindowSceneFactory.makeWindowScene()) +// +// // when +// let status: RefundRequestStatus? = try await sut.beginRefundRequest(productID: .productID) +// +// // then +// if case .userCancelled = status {} +// else { XCTFail("The status must be `userCancelled`") } +// XCTAssertEqual(refundRequestProviderMock.invokedBeginRefundRequestCount, 1) +// } } // MARK: - Constants - private extension UInt64 { - static let transactionID: UInt64 = 5 - } - +// +// private extension UInt64 { +// static let transactionID: UInt64 = 5 +// } +// private extension String { static let productID: String = "product_id" } diff --git a/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift index 6488c5ea6..b35747c15 100644 --- a/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift @@ -4,6 +4,8 @@ // @testable import Flare +import StoreKit +import StoreKitTest import XCTest #if os(iOS) || VISION_OS @@ -28,24 +30,24 @@ import XCTest // MARK: Tests - @MainActor - func test_thatRefundRequestProviderThrowsAnUnknownError_whenRequestDidFailed() async throws { - // given - let windowScene = WindowSceneFactory.makeWindowScene() - - // when - let status = try await sut.beginRefundRequest( - transactionID: .transactionID, - windowScene: windowScene - ) - - // then - if case let .failure(error) = status { - XCTAssertEqual(error as NSError, IAPError.refund(error: .failed) as NSError) - } else { - XCTFail("state must be `failure`") - } - } +// @MainActor +// func test_thatRefundRequestProviderThrowsAnUnknownError_whenRequestDidFailed() async throws { +// // given +// let windowScene = WindowSceneFactory.makeWindowScene() +// +// // when +// let status = try await sut.beginRefundRequest( +// transactionID: .transactionID, +// windowScene: windowScene +// ) +// +// // then +// if case let .failure(error) = status { +// XCTAssertEqual(error as NSError, IAPError.refund(error: .failed) as NSError) +// } else { +// XCTFail("state must be `failure`") +// } +// } } // MARK: - Constants @@ -55,7 +57,7 @@ import XCTest } private extension String { - static let productID: String = "product_id" + static let productID: String = "com.flare.test_purchase_1" } #endif diff --git a/Tests/FlareTests/UnitTests/Providers/SystemInfoProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/SystemInfoProviderTests.swift index 2dee81c07..5d92412bb 100644 --- a/Tests/FlareTests/UnitTests/Providers/SystemInfoProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/SystemInfoProviderTests.swift @@ -10,9 +10,10 @@ final class SystemInfoProviderTests: XCTestCase { // MARK: Properties - private var sut: SystemInfoProvider! private var scenesHolderMock: ScenesHolderMock! + private var sut: SystemInfoProvider! + // MARK: Initialization override func setUp() { @@ -29,31 +30,26 @@ // MARK: Tests - @MainActor - func test_thatScenesHolderReturnsCurrentScene() throws { - // given - let windowScene = WindowSceneFactory.makeWindowScene() - scenesHolderMock.stubbedConnectedScenes = Set(arrayLiteral: windowScene) - - // when - let scene = try sut.currentScene - - // then - XCTAssertEqual(windowScene, scene) - } - - @MainActor - func test_thatScenesHolderThrowsAnErrorWhenThereIsNoActiveWindowScene() { - // when - var receivedError: Error? - do { - _ = try sut.currentScene - } catch { - receivedError = error - } - - // then - XCTAssertEqual(receivedError as? NSError, IAPError.unknown as NSError) - } +// @MainActor +// func test_thatScenesHolderReturnsCurrentScene() throws { +// // given +// let windowScene = WindowSceneFactory.makeWindowScene() +// scenesHolderMock.stubbedConnectedScenes = Set(arrayLiteral: windowScene) +// +// // when +// let scene = try sut.currentScene +// +// // then +// XCTAssertEqual(windowScene, scene) +// } +// +// @MainActor +// func test_thatScenesHolderThrowsAnErrorWhenThereIsNoActiveWindowScene() async throws { +// // when +// let error: Error? = await self.error(for: { try sut.currentScene }) +// +// // then +// XCTAssertEqual(error as? NSError, IAPError.unknown as NSError) +// } } #endif diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Extensions/Result+.swift b/Tests/FlareTests/UnitTests/TestHelpers/Extensions/Result+.swift new file mode 100644 index 000000000..9c779804a --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Extensions/Result+.swift @@ -0,0 +1,26 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +extension Result { + var error: Failure? { + switch self { + case let .failure(error): + return error + default: + return nil + } + } + + var success: Success? { + switch self { + case let .success(value): + return value + default: + return nil + } + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Extensions/XCTestCase+.swift b/Tests/FlareTests/UnitTests/TestHelpers/Extensions/XCTestCase+.swift new file mode 100644 index 000000000..8d55a0f50 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Extensions/XCTestCase+.swift @@ -0,0 +1,35 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import XCTest + +extension XCTestCase { + func value(for closure: () async throws -> U) async -> U? { + do { + let value = try await closure() + return value + } catch { + return nil + } + } + + func error(for closure: () async throws -> U) async -> T? { + do { + _ = try await closure() + return nil + } catch { + return error as? T + } + } + + func result(for closure: () async throws -> U) async -> Result { + do { + let value = try await closure() + return .success(value) + } catch { + return .failure(error as! T) + } + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Fakes/SKProduct+Fake.swift b/Tests/FlareTests/UnitTests/TestHelpers/Fakes/SKProduct+Fake.swift new file mode 100644 index 000000000..a748b6270 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Fakes/SKProduct+Fake.swift @@ -0,0 +1,15 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +extension SKProduct { + static func fake(id: String) -> SKProduct { + let product = ProductMock() + product.stubbedProductIdentifier = id + return product + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Fakes/StoreProduct+Fake.swift b/Tests/FlareTests/UnitTests/TestHelpers/Fakes/StoreProduct+Fake.swift new file mode 100644 index 000000000..4f93ff255 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Fakes/StoreProduct+Fake.swift @@ -0,0 +1,13 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Flare +import StoreKit + +extension StoreProduct { + static func fake(skProduct: SKProduct = ProductMock()) -> StoreProduct { + StoreProduct(skProduct: skProduct) + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Fakes/StoreTransactionFake.swift b/Tests/FlareTests/UnitTests/TestHelpers/Fakes/StoreTransactionFake.swift new file mode 100644 index 000000000..002b7311b --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Fakes/StoreTransactionFake.swift @@ -0,0 +1,12 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare + +extension StoreTransaction { + static func fakeSK1(storeTransaction: IStoreTransaction? = nil) -> StoreTransaction { + StoreTransaction(storeTransaction: storeTransaction ?? StoreTransactionStub()) + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Helpers/AvailabilityChecker.swift b/Tests/FlareTests/UnitTests/TestHelpers/Helpers/AvailabilityChecker.swift new file mode 100644 index 000000000..7cec99218 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Helpers/AvailabilityChecker.swift @@ -0,0 +1,14 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import XCTest + +enum AvailabilityChecker { + static func iOS15APINotAvailableOrSkipTest() throws { + if #available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) { + throw XCTSkip("Test only for older devices") + } + } +} diff --git a/Tests/FlareTests/Helpers/PurchaseManagerTestHelper.swift b/Tests/FlareTests/UnitTests/TestHelpers/Helpers/PurchaseManagerTestHelper.swift similarity index 100% rename from Tests/FlareTests/Helpers/PurchaseManagerTestHelper.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Helpers/PurchaseManagerTestHelper.swift diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Helpers/WindowSceneFactory.swift b/Tests/FlareTests/UnitTests/TestHelpers/Helpers/WindowSceneFactory.swift new file mode 100644 index 000000000..4c21b2c38 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Helpers/WindowSceneFactory.swift @@ -0,0 +1,14 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +#if os(iOS) || VISION_OS + import UIKit + + final class WindowSceneFactory { + static func makeWindowScene() -> UIWindowScene { + UIApplication.shared.connectedScenes.first as! UIWindowScene + } + } +#endif diff --git a/Tests/FlareTests/Mocks/AppStoreReceiptProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/AppStoreReceiptProviderMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/AppStoreReceiptProviderMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/AppStoreReceiptProviderMock.swift diff --git a/Tests/FlareTests/Mocks/FileManagerMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/FileManagerMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/FileManagerMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/FileManagerMock.swift diff --git a/Tests/FlareTests/Mocks/IAPProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift similarity index 60% rename from Tests/FlareTests/Mocks/IAPProviderMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift index 5b97f58eb..e6a194485 100644 --- a/Tests/FlareTests/Mocks/IAPProviderMock.swift +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift @@ -19,10 +19,10 @@ final class IAPProviderMock: IIAPProvider { var invokedFetch = false var invokedFetchCount = 0 - var invokedFetchParameters: (productIDs: Set, completion: Closure>)? - var invokedFetchParametersList = [(productIDs: Set, completion: Closure>)]() + var invokedFetchParameters: (productIDs: Set, completion: Closure>)? + var invokedFetchParametersList = [(productIDs: Set, completion: Closure>)]() - func fetch(productIDs: Set, completion: @escaping Closure>) { + func fetch(productIDs: Set, completion: @escaping Closure>) { invokedFetch = true invokedFetchCount += 1 invokedFetchParameters = (productIDs, completion) @@ -31,14 +31,14 @@ final class IAPProviderMock: IIAPProvider { var invokedPurchase = false var invokedPurchaseCount = 0 - var invokedPurchaseParameters: (productID: String, completion: Closure>)? - var invokedPurchaseParametersList = [(productID: String, completion: Closure>)]() + var invokedPurchaseParameters: (product: StoreProduct, completion: Closure>)? + var invokedPurchaseParametersList = [(product: StoreProduct, completion: Closure>)]() - func purchase(productID: String, completion: @escaping Closure>) { + func purchase(product: StoreProduct, completion: @escaping Closure>) { invokedPurchase = true invokedPurchaseCount += 1 - invokedPurchaseParameters = (productID, completion) - invokedPurchaseParametersList.append((productID, completion)) + invokedPurchaseParameters = (product, completion) + invokedPurchaseParametersList.append((product, completion)) } var invokedRefreshReceipt = false @@ -60,10 +60,10 @@ final class IAPProviderMock: IIAPProvider { var invokedFinishTransaction = false var invokedFinishTransactionCount = 0 - var invokedFinishTransactionParameters: (PaymentTransaction, Void)? - var invokedFinishTransactionParanetersList = [(PaymentTransaction, Void)]() + var invokedFinishTransactionParameters: (StoreTransaction, Void)? + var invokedFinishTransactionParanetersList = [(StoreTransaction, Void)]() - func finish(transaction: PaymentTransaction) { + func finish(transaction: StoreTransaction, completion _: (@Sendable () -> Void)?) { invokedFinishTransaction = true invokedFinishTransactionCount += 1 invokedFinishTransactionParameters = (transaction, ()) @@ -94,9 +94,9 @@ final class IAPProviderMock: IIAPProvider { var invokedFetchAsyncCount = 0 var invokedFetchAsyncParameters: (productIDs: Set, Void)? var invokedFetchAsyncParametersList = [(productIDs: Set, Void)]() - var fetchAsyncResult: [SKProduct] = [] + var fetchAsyncResult: [StoreProduct] = [] - func fetch(productIDs: Set) async throws -> [SKProduct] { + func fetch(productIDs: Set) async throws -> [StoreProduct] { invokedFetchAsync = true invokedFetchAsyncCount += 1 invokedFetchAsyncParameters = (productIDs, ()) @@ -106,15 +106,15 @@ final class IAPProviderMock: IIAPProvider { var invokedAsyncPurchase = false var invokedAsyncPurchaseCount = 0 - var invokedAsyncPurchaseParameters: (productID: String, Void)? - var invokedAsyncPurchaseParametersList = [(productID: String, Void)?]() - var stubbedAsyncPurchase: PaymentTransaction! + var invokedAsyncPurchaseParameters: (product: StoreProduct, Void)? + var invokedAsyncPurchaseParametersList = [(product: StoreProduct, Void)?]() + var stubbedAsyncPurchase: StoreTransaction! - func purchase(productID: String) async throws -> PaymentTransaction { + func purchase(product: StoreProduct) async throws -> StoreTransaction { invokedAsyncPurchase = true invokedAsyncPurchaseCount += 1 - invokedAsyncPurchaseParameters = (productID, ()) - invokedAsyncPurchaseParametersList.append((productID, ())) + invokedAsyncPurchaseParameters = (product, ()) + invokedAsyncPurchaseParametersList.append((product, ())) return stubbedAsyncPurchase } @@ -150,4 +150,44 @@ final class IAPProviderMock: IIAPProvider { invokedBeginRefundRequestParametersList.append((productID, ())) return stubbedBeginRefundRequest } + + var invokedPurchaseWithOptions = false + var invokedPurchaseWithOptionsCount = 0 + var invokedPurchaseWithOptionsParameters: (product: StoreProduct, options: Any)? + var invokedPurchaseWithOptionsParametersList = [(product: StoreProduct, options: Any)]() + var stubbedPurchaseWithOptionsResult: Result? + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping SendableClosure> + ) { + invokedPurchaseWithOptions = true + invokedPurchaseWithOptionsCount += 1 + invokedPurchaseWithOptionsParameters = (product, options) + invokedPurchaseWithOptionsParametersList.append((product, options)) + + if let result = stubbedPurchaseWithOptionsResult { + completion(result) + } + } + + var invokedAsyncPurchaseWithOptions = false + var invokedAsyncPurchaseWithOptionsCount = 0 + var invokedAsyncPurchaseWithOptionsParameters: (product: StoreProduct, options: Any)? + var invokedAsyncPurchaseWithOptionsParametersList = [(product: StoreProduct, options: Any)]() + var stubbedAsyncPurchaseWithOptions: StoreTransaction! + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set + ) async throws -> StoreTransaction { + invokedAsyncPurchaseWithOptions = true + invokedAsyncPurchaseWithOptionsCount += 1 + invokedAsyncPurchaseWithOptionsParameters = (product, options) + invokedAsyncPurchaseWithOptionsParametersList.append((product, options)) + return stubbedAsyncPurchaseWithOptions + } } diff --git a/Tests/FlareTests/Mocks/PaymentProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PaymentProviderMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/PaymentProviderMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/PaymentProviderMock.swift diff --git a/Tests/FlareTests/Mocks/PaymentQueueMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PaymentQueueMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/PaymentQueueMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/PaymentQueueMock.swift diff --git a/Tests/FlareTests/Mocks/PaymentTransactionMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PaymentTransactionMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/PaymentTransactionMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/PaymentTransactionMock.swift diff --git a/Tests/FlareTests/Mocks/ProductMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/ProductMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductMock.swift diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductProviderMock.swift new file mode 100644 index 000000000..38a26470a --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductProviderMock.swift @@ -0,0 +1,53 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import StoreKit + +final class ProductProviderMock: IProductProvider { + var invokedFetch = false + var invokedFetchCount = 0 + var invokedFetchParameters: (productIDs: Set, requestID: String, completion: ProductsHandler)? + var invokedFetchParamtersList = [(productIDs: Set, requestID: String, completion: ProductsHandler)]() + var stubbedFetchResult: Result<[SK1StoreProduct], IAPError>? + + func fetch(productIDs: Set, requestID: String, completion: @escaping ProductsHandler) { + invokedFetch = true + invokedFetchCount += 1 + invokedFetchParameters = (productIDs, requestID, completion) + invokedFetchParamtersList.append((productIDs, requestID, completion)) + + if let result = stubbedFetchResult { + completion(result) + } + } + + var invokedAsyncFetch = false + var invokedAsyncFetchCount = 0 + var invokedAsyncFetchParameters: (productIDs: Set, Void)? + var invokedAsyncFetchParamtersList = [(productIDs: Set, Void)]() + var stubbedAsyncFetchResult: Result<[ISKProduct], Error>? + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func fetch(productIDs: Set) async throws -> [SK2StoreProduct] { + invokedAsyncFetch = true + invokedAsyncFetchCount += 1 + invokedAsyncFetchParameters = (productIDs, ()) + invokedAsyncFetchParamtersList.append((productIDs, ())) + + switch stubbedAsyncFetchResult { + case let .success(products): + if let products = products as? [SK2StoreProduct] { + return products + } else { + return [] + } + case let .failure(error): + throw error + default: + return [] + } + } +} diff --git a/Tests/FlareTests/Mocks/ProductResponseMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductResponseMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/ProductResponseMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductResponseMock.swift diff --git a/Tests/FlareTests/Mocks/ProductsRequestMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductsRequestMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/ProductsRequestMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductsRequestMock.swift diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift new file mode 100644 index 000000000..b24200266 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift @@ -0,0 +1,81 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import StoreKit + +final class PurchaseProviderMock: IPurchaseProvider { + var invokedFinish = false + var invokedFinishCount = 0 + var invokedFinishParameters: (transaction: StoreTransaction, Void)? + var invokedFinishParametersList = [(transaction: StoreTransaction, Void)]() + + func finish(transaction: StoreTransaction, completion _: (@Sendable () -> Void)?) { + invokedFinish = true + invokedFinishCount += 1 + invokedFinishParameters = (transaction, ()) + invokedFinishParametersList.append((transaction, ())) + } + + var invokedAddTransactionObserver = false + var invokedAddTransactionObserverCount = 0 + var invokedAddTransactionObserverParameters: (fallbackHandler: Closure>?, Void)? + var invokedAddTransactionObserverParametersList = [(fallbackHandler: Closure>?, Void)]() + + func addTransactionObserver(fallbackHandler: Closure>?) { + invokedAddTransactionObserver = true + invokedAddTransactionObserverCount += 1 + invokedAddTransactionObserverParameters = (fallbackHandler, ()) + invokedAddTransactionObserverParametersList.append((fallbackHandler, ())) + } + + var invokedRemoveTransactionObserver = false + var invokedRemoveTransactionObserverCount = 0 + + func removeTransactionObserver() { + invokedRemoveTransactionObserver = true + invokedRemoveTransactionObserverCount += 1 + } + + var invokedPurchase = false + var invokedPurchaseCount = 0 + var invokedPurchaseParameters: (product: StoreProduct, Void)? + var invokedPurchaseParametersList = [(product: StoreProduct, Void)]() + var stubbedPurchaseCompletionResult: (Result, Void)? + + @MainActor + func purchase(product: StoreProduct, completion: @escaping PurchaseCompletionHandler) { + invokedPurchase = true + invokedPurchaseCount += 1 + invokedPurchaseParameters = (product, ()) + invokedPurchaseParametersList.append((product, ())) + if let result = stubbedPurchaseCompletionResult { + completion(result.0) + } + } + + var invokedPurchaseWithOptions = false + var invokedPurchaseWithOptionsCount = 0 + var invokedPurchaseWithOptionsParameters: (product: StoreProduct, Any)? + var invokedPurchaseWithOptionsParametersList = [(product: StoreProduct, Any)]() + var stubbedinvokedPurchaseWithOptionsCompletionResult: (Result, Void)? + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + @MainActor + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping PurchaseCompletionHandler + ) { + invokedPurchaseWithOptions = true + invokedPurchaseWithOptionsCount += 1 + invokedPurchaseWithOptionsParameters = (product, options) + invokedPurchaseWithOptionsParametersList.append((product, options)) + + if let result = stubbedinvokedPurchaseWithOptionsCompletionResult { + completion(result.0) + } + } +} diff --git a/Tests/FlareTests/Mocks/ReceiptRefreshProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ReceiptRefreshProviderMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/ReceiptRefreshProviderMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/ReceiptRefreshProviderMock.swift diff --git a/Tests/FlareTests/Mocks/ReceiptRefreshRequestFactory.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ReceiptRefreshRequestFactory.swift similarity index 100% rename from Tests/FlareTests/Mocks/ReceiptRefreshRequestFactory.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/ReceiptRefreshRequestFactory.swift diff --git a/Tests/FlareTests/Mocks/ReceiptRefreshRequestMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ReceiptRefreshRequestMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/ReceiptRefreshRequestMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/ReceiptRefreshRequestMock.swift diff --git a/Tests/FlareTests/Mocks/RefundProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/RefundProviderMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/RefundProviderMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/RefundProviderMock.swift diff --git a/Tests/FlareTests/Mocks/RefundRequestProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/RefundRequestProviderMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/RefundRequestProviderMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/RefundRequestProviderMock.swift diff --git a/Tests/FlareTests/Mocks/ScenesHolderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ScenesHolderMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/ScenesHolderMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/ScenesHolderMock.swift diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/StoreTransactionMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/StoreTransactionMock.swift new file mode 100644 index 000000000..225e403ef --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/StoreTransactionMock.swift @@ -0,0 +1,89 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class StoreTransactionMock: IStoreTransaction { + var invokedProductIdentifierGetter = false + var invokedProductIdentifierGetterCount = 0 + var stubbedProductIdentifier: String! = "" + + var productIdentifier: String { + invokedProductIdentifierGetter = true + invokedProductIdentifierGetterCount += 1 + return stubbedProductIdentifier + } + + var invokedPurchaseDateGetter = false + var invokedPurchaseDateGetterCount = 0 + var stubbedPurchaseDate: Date! + + var purchaseDate: Date { + invokedPurchaseDateGetter = true + invokedPurchaseDateGetterCount += 1 + return stubbedPurchaseDate + } + + var invokedHasKnownPurchaseDateGetter = false + var invokedHasKnownPurchaseDateGetterCount = 0 + var stubbedHasKnownPurchaseDate: Bool! = false + + var hasKnownPurchaseDate: Bool { + invokedHasKnownPurchaseDateGetter = true + invokedHasKnownPurchaseDateGetterCount += 1 + return stubbedHasKnownPurchaseDate + } + + var invokedTransactionIdentifierGetter = false + var invokedTransactionIdentifierGetterCount = 0 + var stubbedTransactionIdentifier: String! = "" + + var transactionIdentifier: String { + invokedTransactionIdentifierGetter = true + invokedTransactionIdentifierGetterCount += 1 + return stubbedTransactionIdentifier + } + + var invokedHasKnownTransactionIdentifierGetter = false + var invokedHasKnownTransactionIdentifierGetterCount = 0 + var stubbedHasKnownTransactionIdentifier: Bool! = false + + var hasKnownTransactionIdentifier: Bool { + invokedHasKnownTransactionIdentifierGetter = true + invokedHasKnownTransactionIdentifierGetterCount += 1 + return stubbedHasKnownTransactionIdentifier + } + + var invokedQuantityGetter = false + var invokedQuantityGetterCount = 0 + var stubbedQuantity: Int! = 0 + + var quantity: Int { + invokedQuantityGetter = true + invokedQuantityGetterCount += 1 + return stubbedQuantity + } + + var invokedJwsRepresentationGetter = false + var invokedJwsRepresentationGetterCount = 0 + var stubbedJwsRepresentation: String! + + var jwsRepresentation: String? { + invokedJwsRepresentationGetter = true + invokedJwsRepresentationGetterCount += 1 + return stubbedJwsRepresentation + } + + var invokedEnvironmentGetter = false + var invokedEnvironmentGetterCount = 0 + var stubbedEnvironment: StoreEnvironment! + + var environment: StoreEnvironment? { + invokedEnvironmentGetter = true + invokedEnvironmentGetterCount += 1 + return stubbedEnvironment + } +} diff --git a/Tests/FlareTests/Mocks/SystemInfoProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/SystemInfoProviderMock.swift similarity index 100% rename from Tests/FlareTests/Mocks/SystemInfoProviderMock.swift rename to Tests/FlareTests/UnitTests/TestHelpers/Mocks/SystemInfoProviderMock.swift diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Stubs/StoreTransactionStub.swift b/Tests/FlareTests/UnitTests/TestHelpers/Stubs/StoreTransactionStub.swift new file mode 100644 index 000000000..7b8a0c7cb --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Stubs/StoreTransactionStub.swift @@ -0,0 +1,57 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class StoreTransactionStub: IStoreTransaction { + var stubbedProductIdentifier: String! = UUID().uuidString + + var productIdentifier: String { + stubbedProductIdentifier + } + + var stubbedPurchaseDate: Date! + + var purchaseDate: Date { + stubbedPurchaseDate + } + + var stubbedHasKnownPurchaseDate: Bool! = false + + var hasKnownPurchaseDate: Bool { + stubbedHasKnownPurchaseDate + } + + var stubbedTransactionIdentifier: String! = "" + + var transactionIdentifier: String { + stubbedTransactionIdentifier + } + + var stubbedHasKnownTransactionIdentifier: Bool! = false + + var hasKnownTransactionIdentifier: Bool { + stubbedHasKnownTransactionIdentifier + } + + var stubbedQuantity: Int! = 0 + + var quantity: Int { + stubbedQuantity + } + + var stubbedJwsRepresentation: String! + + var jwsRepresentation: String? { + stubbedJwsRepresentation + } + + var stubbedEnvironment: StoreEnvironment! + + var environment: StoreEnvironment? { + stubbedEnvironment + } +} diff --git a/Tests/IntegrationTests/Flare.storekit b/Tests/IntegrationTests/Flare.storekit new file mode 100644 index 000000000..102d022b8 --- /dev/null +++ b/Tests/IntegrationTests/Flare.storekit @@ -0,0 +1,63 @@ +{ + "identifier" : "95D98A48", + "nonRenewingSubscriptions" : [ + + ], + "products" : [ + { + "displayPrice" : "0.99", + "familyShareable" : false, + "internalID" : "169432A7", + "localizations" : [ + { + "description" : "com.flare.test_purchase_1", + "displayName" : "com.flare.test_purchase_1", + "locale" : "en_US" + } + ], + "productID" : "com.flare.test_purchase_1", + "referenceName" : "com.flare.test_purchase_1", + "type" : "Consumable" + }, + { + "displayPrice" : "0.99", + "familyShareable" : false, + "internalID" : "33E61322", + "localizations" : [ + { + "description" : "com.flare.test_purchase_2", + "displayName" : "com.flare.test_purchase_2", + "locale" : "en_US" + } + ], + "productID" : "com.flare.test_purchase_2", + "referenceName" : "com.flare.test_purchase_2", + "type" : "Consumable" + }, + { + "displayPrice" : "0.99", + "familyShareable" : false, + "internalID" : "1CBF43E6", + "localizations" : [ + { + "description" : "com.flare.test_non_consumable_purchase_1", + "displayName" : "com.flare.test_non_consumable_", + "locale" : "en_US" + } + ], + "productID" : "com.flare.test_non_consumable_purchase_1", + "referenceName" : null, + "type" : "NonConsumable" + } + ], + "settings" : { + + }, + "subscriptionGroups" : [ + + ], + "version" : { + "major" : 2, + "minor" : 0 + } +} diff --git a/Tests/IntegrationTests/Helpers/Extensions/Result+.swift b/Tests/IntegrationTests/Helpers/Extensions/Result+.swift new file mode 100644 index 000000000..9c779804a --- /dev/null +++ b/Tests/IntegrationTests/Helpers/Extensions/Result+.swift @@ -0,0 +1,26 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import Foundation + +extension Result { + var error: Failure? { + switch self { + case let .failure(error): + return error + default: + return nil + } + } + + var success: Success? { + switch self { + case let .success(value): + return value + default: + return nil + } + } +} diff --git a/Tests/IntegrationTests/Helpers/Extensions/XCTestCase+.swift b/Tests/IntegrationTests/Helpers/Extensions/XCTestCase+.swift new file mode 100644 index 000000000..8d55a0f50 --- /dev/null +++ b/Tests/IntegrationTests/Helpers/Extensions/XCTestCase+.swift @@ -0,0 +1,35 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import XCTest + +extension XCTestCase { + func value(for closure: () async throws -> U) async -> U? { + do { + let value = try await closure() + return value + } catch { + return nil + } + } + + func error(for closure: () async throws -> U) async -> T? { + do { + _ = try await closure() + return nil + } catch { + return error as? T + } + } + + func result(for closure: () async throws -> U) async -> Result { + do { + let value = try await closure() + return .success(value) + } catch { + return .failure(error as! T) + } + } +} diff --git a/Tests/IntegrationTests/Helpers/StoreSessionTestCase/StoreSessionTestCase.swift b/Tests/IntegrationTests/Helpers/StoreSessionTestCase/StoreSessionTestCase.swift new file mode 100644 index 000000000..4e33a5234 --- /dev/null +++ b/Tests/IntegrationTests/Helpers/StoreSessionTestCase/StoreSessionTestCase.swift @@ -0,0 +1,31 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import StoreKitTest +import XCTest + +@available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 7.0, *) +class StoreSessionTestCase: XCTestCase { + // MARK: Properties + + var session: SKTestSession? + + // MARK: XCTestCase + + override func setUp() { + super.setUp() + + session = try? SKTestSession(configurationFileNamed: "Flare") + session?.resetToDefaultState() + session?.askToBuyEnabled = false + session?.disableDialogs = true + } + + override func tearDown() { + session?.clearTransactions() + session = nil + super.tearDown() + } +} diff --git a/Tests/IntegrationTests/Tests/FlareTests.swift b/Tests/IntegrationTests/Tests/FlareTests.swift new file mode 100644 index 000000000..c3ff08793 --- /dev/null +++ b/Tests/IntegrationTests/Tests/FlareTests.swift @@ -0,0 +1,158 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +@testable import Flare +import StoreKit +import XCTest + +// MARK: - FlareTests + +@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) +final class FlareTests: StoreSessionTestCase { + // MARK: - Properties + + private var sut: Flare! + + // MARK: - XCTestCase + + override func setUp() { + super.setUp() + sut = Flare() + } + + override func tearDown() { + sut = nil + super.tearDown() + } + + // MARK: Tests + + func test_thatFlarePurchasesAProductWithCompletion_whenPurchaseCompleted() async throws { + try await test_purchaseWithOptions( + options: [], + expectedResult: .success(()) + ) + } + + func test_thatFlarePurchasesAProductWithCompletion_whenUnkownErrorOccurred() async throws { + // given + session?.failTransactionsEnabled = true + session?.failureError = .unknown + + // when + try await test_purchaseWithOptions( + options: [], + expectedResult: .failure(.unknown) + ) + } + + func test_thatFlarePurchasesAProductWithOptions_whenPurchaseCompleted() async throws { + try await test_purchaseWithOptionsAndCompletion( + expectedResult: .success(()) + ) + } + + func test_thatFlarePurchaseThrowsAnError_whenUnkownErrorOccurred() async throws { + // given + session?.failTransactionsEnabled = true + session?.failureError = .unknown + + // when + try await test_purchaseWithOptionsAndCompletion( + expectedResult: .failure(IAPError.unknown) + ) + } + + func test_thatFlarePurchasesAsyncAProductWithOptionsAndCompletionHandler_whenPurchaseCompleted() async throws { + try await test_purchaseWithOptions( + expectedResult: .success(()) + ) + } + + func test_thatFlarePurchaseAsyncThrowsAnError_whenUnkownErrorOccurred() async throws { + // given + session?.failTransactionsEnabled = true + session?.failureError = .unknown + + // when + try await test_purchaseWithOptions( + expectedResult: .failure(IAPError.unknown) + ) + } + + // MARK: Private + + private func test_purchaseWithOptionsAndCompletion( + expectedResult: Result + ) async throws { + // given + let product = try await ProductProviderHelper.purchases.randomElement() + + // when + let result: Result = await result(for: { + try await sut.purchase( + product: StoreProduct(product: product!), + options: [.simulatesAskToBuyInSandbox(false)] + ) + }) + + // then + switch expectedResult { + case .success: + XCTAssertEqual(result.success?.productIdentifier, product?.id) + case let .failure(error): + XCTAssertEqual(error, result.error) + } + } + + private func test_purchaseWithOptions( + options: Set = [.simulatesAskToBuyInSandbox(true)], + expectedResult: Result + ) async throws { + // given + let expectation = XCTestExpectation(description: "Purchase a product") + + let product = try await ProductProviderHelper.purchases.randomElement() + + // when + let handler: Closure> = { result in + switch expectedResult { + case .success: + XCTAssertEqual(result.success?.productIdentifier, product?.id) + case let .failure(error): + XCTAssertEqual(error, result.error) + } + expectation.fulfill() + } + + if options.isEmpty { + sut.purchase(product: StoreProduct(product: product!)) { handler($0) } + } else { + sut.purchase( + product: StoreProduct(product: product!), + options: options + ) { [handler] result in + Task { handler(result) } + } + } + + // then + #if swift(>=5.9) + await fulfillment(of: [expectation]) + #else + wait(for: [expectation], timeout: .second) + #endif + } +} + +// MARK: - Constants + +private extension TimeInterval { + static let second: CGFloat = 1.0 +} + +private extension String { + static let productID = "com.flare.test_purchase_2" +} diff --git a/Tests/IntegrationTests/Tests/IAPProviderTests.swift b/Tests/IntegrationTests/Tests/IAPProviderTests.swift new file mode 100644 index 000000000..d1c0d99d4 --- /dev/null +++ b/Tests/IntegrationTests/Tests/IAPProviderTests.swift @@ -0,0 +1,151 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +////// +////// Flare +////// Copyright © 2023 Space Code. All rights reserved. +////// +// +// @testable import Flare +// import XCTest +// +//// MARK: - IAPProviderStoreKit2Tests +// +// @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) +// final class IAPProviderStoreKit2Tests: StoreSessionTestCase { +// // MARK: - Properties +// +// private var productProviderMock: ProductProviderMock! +// private var purchaseProvider: PurchaseProviderMock! +// private var refundProviderMock: RefundProviderMock! +// +// private var sut: IIAPProvider! +// +// // MARK: - XCTestCase +// +// override func setUp() { +// super.setUp() +// productProviderMock = ProductProviderMock() +// purchaseProvider = PurchaseProviderMock() +// refundProviderMock = RefundProviderMock() +// sut = IAPProvider( +// paymentQueue: PaymentQueueMock(), +// productProvider: productProviderMock, +// purchaseProvider: purchaseProvider, +// receiptRefreshProvider: ReceiptRefreshProviderMock(), +// refundProvider: refundProviderMock +// ) +// } +// +// override func tearDown() { +// productProviderMock = nil +// purchaseProvider = nil +// refundProviderMock = nil +// sut = nil +// super.tearDown() +// } +// +// // MARK: Tests +// +// func test_thatIAPProviderFetchesSK2Products_whenProductsAreAvailable() async throws { +// let productsMock = try await ProductProviderHelper.purchases.map(SK2StoreProduct.init) +// productProviderMock.stubbedAsyncFetchResult = .success(productsMock) +// +// // when +// let products = try await sut.fetch(productIDs: [.productID]) +// +// // then +// XCTAssertFalse(products.isEmpty) +// XCTAssertEqual(productsMock.count, products.count) +// } +// +// func test_thatIAPProviderThrowsAnIAPError_whenFetchingProductsFailed() async { +// productProviderMock.stubbedAsyncFetchResult = .failure(IAPError.unknown) +// +// // when +// let error: IAPError? = await error(for: { try await sut.fetch(productIDs: [.productID]) }) +// +// // then +// XCTAssertEqual(error, .unknown) +// } +// +// func test_thatIAPProviderThrowsAPlainError_whenFetchingProductsFailed() async { +// productProviderMock.stubbedAsyncFetchResult = .failure(URLError(.unknown)) +// +// // when +// let error: IAPError? = await error(for: { try await sut.fetch(productIDs: [.productID]) }) +// +// // then +// XCTAssertEqual(error, .with(error: URLError(.unknown))) +// } +// +// #if os(iOS) || VISION_OS +// func test_thatIAPProviderRefundsPurchase() async throws { +// // given +// refundProviderMock.stubbedBeginRefundRequest = .success +// +// // when +// let state = try await sut.beginRefundRequest(productID: .productID) +// +// // then +// if case .success = state {} +// else { XCTFail("state must be `success`") } +// } +// +// func test_thatFlareThrowsAnError_whenBeginRefundRequestFailed() async throws { +// // given +// refundProviderMock.stubbedBeginRefundRequest = .failed(error: IAPError.unknown) +// +// // when +// let state = try await sut.beginRefundRequest(productID: .productID) +// +// // then +// if case let .failed(error) = state { XCTAssertEqual(error as NSError, IAPError.unknown as NSError) } +// else { XCTFail("state must be `failed`") } +// } +// #endif +// +// func test_thatIAPProviderPurchasesAProduct() async throws { +// // given +// let transactionMock = StoreTransactionMock() +// transactionMock.stubbedTransactionIdentifier = .transactionID +// +// let storeTransaction = StoreTransaction(storeTransaction: transactionMock) +// purchaseProvider.stubbedPurchaseCompletionResult = (.success(storeTransaction), ()) +// +// let product = try await ProductProviderHelper.purchases[0] +// +// // when +// let transaction = try await sut.purchase(product: StoreProduct(product: product)) +// +// // then +// XCTAssertEqual(transaction.transactionIdentifier, .transactionID) +// } +// +// func test_thatIAPProviderPurchasesAProductWithOptions() async throws { +// // given +// let transactionMock = StoreTransactionMock() +// transactionMock.stubbedTransactionIdentifier = .transactionID +// +// let storeTransaction = StoreTransaction(storeTransaction: transactionMock) +// purchaseProvider.stubbedinvokedPurchaseWithOptionsCompletionResult = (.success(storeTransaction), ()) +// +// let product = try await ProductProviderHelper.purchases[0] +// +// // when +// let transaction = try await sut.purchase(product: StoreProduct(product: product), options: []) +// +// // then +// XCTAssertEqual(transaction.transactionIdentifier, .transactionID) +// } +// } +// +//// MARK: - Constants +// +// private extension String { +//// static let receipt = "receipt" +// static let productID = "product_identifier" +// static let transactionID = "transaction_identifier" +// } diff --git a/Tests/IntegrationTests/Tests/ProductProviderHelper.swift b/Tests/IntegrationTests/Tests/ProductProviderHelper.swift new file mode 100644 index 000000000..2deb3d05b --- /dev/null +++ b/Tests/IntegrationTests/Tests/ProductProviderHelper.swift @@ -0,0 +1,44 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import StoreKit + +// MARK: - ProductProviderHelper + +@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) +enum ProductProviderHelper { + static var purchases: [StoreKit.Product] { + get async throws { + try await StoreKit.Product.products(for: [.testNonConsumableID]) + } + } + +// static var subscriptions: [StoreKit.Product] { +// get async throws { +// try await StoreKit.Product.products(for: [.testSubscription1ID, .testSubscription2ID]) +// } +// } +// +// static var all: [StoreKit.Product] { +// get async throws { +// let purchases = try await self.purchases +// let subscriptions = try await self.subscriptions +// +// return purchases + subscriptions +// } +// } +} + +// MARK: - Constants + +private extension String { + static let testPurchase1ID = "com.flare.test_purchase_1" + static let testPurchase2ID = "com.flare.test_purchase_2" + + static let testNonConsumableID = "com.flare.test_non_consumable_purchase_1" + +// static let testSubscription1ID = "com.flare.test_subscription_1" +// static let testSubscription2ID = "com.flare.test_subscription_2" +} diff --git a/Tests/IntegrationTests/Tests/ProductProviderTests.swift b/Tests/IntegrationTests/Tests/ProductProviderTests.swift new file mode 100644 index 000000000..3edf243fb --- /dev/null +++ b/Tests/IntegrationTests/Tests/ProductProviderTests.swift @@ -0,0 +1,59 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +//// +//// Flare +//// Copyright © 2023 Space Code. All rights reserved. +//// +// +// import Concurrency +// @testable import Flare +// import TestConcurrency +// import XCTest +// +//// MARK: - ProductProviderStoreKit2Tests +// +// @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) +// final class ProductProviderStoreKit2Tests: StoreSessionTestCase { +// // MARK: - Properties +// +// private var testDispatchQueue: TestDispatchQueue! +// private var dispatchQueueFactory: IDispatchQueueFactory! +// +// private var sut: ProductProvider! +// +// // MARK: - XCTestCase +// +// override func setUp() { +// super.setUp() +// testDispatchQueue = TestDispatchQueue() +// dispatchQueueFactory = TestDispatchQueueFactory(testQueue: testDispatchQueue) +// sut = ProductProvider(dispatchQueueFactory: dispatchQueueFactory) +// } +// +// override func tearDown() { +// testDispatchQueue = nil +// dispatchQueueFactory = nil +// sut = nil +// super.tearDown() +// } +// +// // MARK: - Tests +// +// func test_thatProductProviderFetchesProductsWithIDs() async throws { +// // when +// let products = try await sut.fetch(productIDs: [.productID]) +// +// // then +// XCTAssertEqual(products.count, 1) +// XCTAssertEqual(products.first?.productIdentifier, .productID) +// } +// } +// +//// MARK: - Constants +// +// private extension String { +// static let productID = "com.flare.test_purchase_1" +// } diff --git a/Tests/IntegrationTests/Tests/PurchaseProviderTests.swift b/Tests/IntegrationTests/Tests/PurchaseProviderTests.swift new file mode 100644 index 000000000..31170ffb3 --- /dev/null +++ b/Tests/IntegrationTests/Tests/PurchaseProviderTests.swift @@ -0,0 +1,90 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +//// +//// Flare +//// Copyright © 2023 Space Code. All rights reserved. +//// +// +// @testable import Flare +// import XCTest +// +//// MARK: - PurchaseProviderStoreKit2Tests +// +// @available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) +// final class PurchaseProviderStoreKit2Tests: StoreSessionTestCase { +// // MARK: Properties +// +// private var paymentProviderMock: PaymentProviderMock! +// +// private var sut: PurchaseProvider! +// +// // MARK: XCTestCase +// +// override func setUp() { +// super.setUp() +// paymentProviderMock = PaymentProviderMock() +// sut = PurchaseProvider( +// paymentProvider: paymentProviderMock +// ) +// } +// +// override func tearDown() { +// sut = nil +// super.tearDown() +// } +// +// // MARK: Tests +// +// func test_thatPurchaseProviderReturnsPaymentTransaction_whenPurchasesAProductWithOptions() async throws { +// let expectation = XCTestExpectation(description: "Purchase a product") +// let productMock = try StoreProduct(product: await ProductProviderHelper.purchases.randomElement()!) +// +// // when +// sut.purchase(product: productMock, options: [.simulatesAskToBuyInSandbox(false)]) { result in +// switch result { +// case let .success(transaction): +// XCTAssertEqual(transaction.productIdentifier, productMock.productIdentifier) +// expectation.fulfill() +// case let .failure(error): +// XCTFail(error.localizedDescription) +// } +// } +// +// #if swift(>=5.9) +// await fulfillment(of: [expectation]) +// #else +// wait(for: [expectation], timeout: .second) +// #endif +// } +// +// func test_thatPurchaseProviderReturnsPaymentTransaction_whenSK2ProductExist() async throws { +// let expectation = XCTestExpectation(description: "Purchase a product") +// let productMock = try StoreProduct(product: await ProductProviderHelper.purchases.randomElement()!) +// +// // when +// sut.purchase(product: productMock) { result in +// switch result { +// case let .success(transaction): +// XCTAssertEqual(transaction.productIdentifier, productMock.productIdentifier) +// expectation.fulfill() +// case let .failure(error): +// XCTFail(error.localizedDescription) +// } +// } +// +// #if swift(>=5.9) +// await fulfillment(of: [expectation]) +// #else +// wait(for: [expectation], timeout: .second) +// #endif +// } +// } +// +//// MARK: - Constants +// +// private extension TimeInterval { +// static let second: TimeInterval = 1.0 +// } diff --git a/Tests/TestPlans/AllTests.xctestplan b/Tests/TestPlans/AllTests.xctestplan new file mode 100644 index 000000000..259da0494 --- /dev/null +++ b/Tests/TestPlans/AllTests.xctestplan @@ -0,0 +1,44 @@ +{ + "configurations" : [ + { + "id" : "1CA61D79-6551-4DA7-8DEF-CC28563C2658", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "AAEFF2D6694AA197C07481DA", + "name" : "Flare" + } + ] + }, + "targetForVariableExpansion" : { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "AAEFF2D6694AA197C07481DA", + "name" : "Flare" + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "2053CB2B5F4780EC86D0DE04", + "name" : "FlareTests" + } + }, + { + "target" : { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "5A649E8F4319C5B59E9588FD", + "name" : "IntegrationTests" + } + } + ], + "version" : 1 +} diff --git a/Tests/TestPlans/IntegrationTests.xctestplan b/Tests/TestPlans/IntegrationTests.xctestplan new file mode 100644 index 000000000..57f3054e2 --- /dev/null +++ b/Tests/TestPlans/IntegrationTests.xctestplan @@ -0,0 +1,37 @@ +{ + "configurations" : [ + { + "id" : "1CA61D79-6551-4DA7-8DEF-CC28563C2658", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "AAEFF2D6694AA197C07481DA", + "name" : "Flare" + } + ] + }, + "targetForVariableExpansion" : { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "AAEFF2D6694AA197C07481DA", + "name" : "Flare" + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "5A649E8F4319C5B59E9588FD", + "name" : "IntegrationTests" + } + } + ], + "version" : 1 +} diff --git a/Tests/TestPlans/UnitTests.xctestplan b/Tests/TestPlans/UnitTests.xctestplan new file mode 100644 index 000000000..98e230890 --- /dev/null +++ b/Tests/TestPlans/UnitTests.xctestplan @@ -0,0 +1,37 @@ +{ + "configurations" : [ + { + "id" : "1CA61D79-6551-4DA7-8DEF-CC28563C2658", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "AAEFF2D6694AA197C07481DA", + "name" : "Flare" + } + ] + }, + "targetForVariableExpansion" : { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "AAEFF2D6694AA197C07481DA", + "name" : "Flare" + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Flare.xcodeproj", + "identifier" : "2053CB2B5F4780EC86D0DE04", + "name" : "FlareTests" + } + } + ], + "version" : 1 +} diff --git a/Tests/UnitTestHostApp/AppDelegate.swift b/Tests/UnitTestHostApp/AppDelegate.swift new file mode 100644 index 000000000..4f3e9b07c --- /dev/null +++ b/Tests/UnitTestHostApp/AppDelegate.swift @@ -0,0 +1,30 @@ +// +// Flare +// Copyright © 2023 Space Code. All rights reserved. +// + +import SwiftUI + +#if os(macOS) + + import Cocoa + + @main + class AppDelegate: NSObject, NSApplicationDelegate {} + +#elseif os(watchOS) + + @main + struct TestApp: App { + var body: some Scene { + WindowGroup { + Text("Hello World") + } + } + } + +#else + @main + class AppDelegate: UIResponder, UIApplicationDelegate {} + +#endif diff --git a/Tests/UnitTestHostApp/Assets.xcassets/AccentColor.colorset/Contents.json b/Tests/UnitTestHostApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 000000000..eb8789700 --- /dev/null +++ b/Tests/UnitTestHostApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tests/UnitTestHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/Tests/UnitTestHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..9221b9bb1 --- /dev/null +++ b/Tests/UnitTestHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tests/UnitTestHostApp/Assets.xcassets/Contents.json b/Tests/UnitTestHostApp/Assets.xcassets/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Tests/UnitTestHostApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tests/UnitTestHostApp/Info.plist b/Tests/UnitTestHostApp/Info.plist new file mode 100644 index 000000000..c468f022f --- /dev/null +++ b/Tests/UnitTestHostApp/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + UnitTestsHostApp + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSupportsIndirectInputEvents + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/project.yml b/project.yml new file mode 100644 index 000000000..59e13d92d --- /dev/null +++ b/project.yml @@ -0,0 +1,80 @@ +name: Flare +options: + deploymentTarget: + iOS: 13.0 + macOS: 10.15 + tvOS: 13.0 + watchOS: 7.0 +packages: + # External + + Concurrency: + url: https://github.com/space-code/concurrency.git + from: 0.0.1 +targets: + UnitTestHostApp: + type: application + supportedDestinations: [iOS, tvOS, macOS] + sources: Tests/UnitTestHostApp + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: com.spacecode.flare + TARGETED_DEVICE_FAMILY: "1,2,3,4" + SUPPORTED_PLATFORMS: "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator" + scheme: + storeKitConfiguration: "Tests/IntegrationTests/Flare.storekit" + testTargets: + - IntegrationTests + Flare: + type: framework + supportedDestinations: [iOS, tvOS, macOS] + dependencies: + - package: Concurrency + product: Concurrency + settings: + base: + GENERATE_INFOPLIST_FILE: YES + TARGETED_DEVICE_FAMILY: "1,2,3,4" + SUPPORTED_PLATFORMS: "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator" + sources: + - path: Sources + scheme: + testPlans: + - path: Tests/TestPlans/AllTests.xctestplan + defaultPlan: true + - path: Tests/TestPlans/UnitTests.xctestplan + - path: Tests/TestPlans/IntegrationTests.xctestplan + gatherCoverageData: true + coverageTargets: + - Flare + FlareTests: + type: bundle.unit-test + supportedDestinations: [iOS, tvOS, macOS] + dependencies: + - package: Concurrency + product: TestConcurrency + - target: Flare + settings: + base: + GENERATE_INFOPLIST_FILE: YES + PRODUCT_BUNDLE_IDENTIFIER: com.spacecode.flare-unit-tests + SUPPORTED_PLATFORMS: "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator" + TARGETED_DEVICE_FAMILY: "1,2,3,4" + sources: + - Tests/FlareTests/UnitTests + IntegrationTests: + type: bundle.unit-test + supportedDestinations: [iOS, tvOS, macOS] + dependencies: + - package: Concurrency + product: TestConcurrency + - target: Flare + - target: UnitTestHostApp + settings: + base: + BUNDLE_LOADER: $(TEST_HOST) + GENERATE_INFOPLIST_FILE: YES + TEST_HOST: $(BUILT_PRODUCTS_DIR)/UnitTestHostApp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/UnitTestHostApp + PRODUCT_BUNDLE_IDENTIFIER: com.spacecode.flare.storekit-unit-tests + sources: + - Tests/IntegrationTests \ No newline at end of file diff --git a/scripts/setup_build_tools.sh b/scripts/setup_build_tools.sh new file mode 100644 index 000000000..a0b9e5235 --- /dev/null +++ b/scripts/setup_build_tools.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +which -s xcodegen +if [[ $? != 0 ]] ; then + # Install xcodegen + echo "Installing xcodegen." + brew install xcodegen +fi \ No newline at end of file From 1dbdccd214584b538446c692461e5f079dae9c44 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 5 Jan 2024 10:48:22 +0100 Subject: [PATCH 33/44] Build a documentation using `Docc` (#11) * Update Flare's documentation * Implement an action for building a documentation web page * Update `CHANGELOG.md` * Update `publish-pages.yml` * Update `README.md` --- .github/workflows/publish-pages.yml | 42 ++++ CHANGELOG.md | 3 + Documentation/Resources/flare.png | Bin 329034 -> 0 bytes Documentation/Usage.md | 186 ------------------ Package.resolved | 18 ++ Package.swift | 1 + Package@swift-5.7.swift | 1 + Package@swift-5.8.swift | 1 + README.md | 2 +- Sources/Flare/{ => Classes}/Flare.swift | 2 +- Sources/Flare/{ => Classes}/IFlare.swift | 2 +- .../Classes/Models/ProductCategory.swift | 3 +- .../Classes/Models/SubscriptionPeriod.swift | 4 +- .../Classes/Models/VerificationError.swift | 6 +- .../Flare.docc/Articles/perform-purchase.md | 94 +++++++++ .../Flare.docc/Articles/refund-purchase.md | 17 ++ .../Flare.docc/Articles/restore-purchase.md | 36 ++++ Sources/Flare/Flare.docc/Flare.md | 66 +++++++ 18 files changed, 290 insertions(+), 194 deletions(-) create mode 100644 .github/workflows/publish-pages.yml delete mode 100644 Documentation/Resources/flare.png delete mode 100644 Documentation/Usage.md rename Sources/Flare/{ => Classes}/Flare.swift (98%) rename Sources/Flare/{ => Classes}/IFlare.swift (99%) create mode 100644 Sources/Flare/Flare.docc/Articles/perform-purchase.md create mode 100644 Sources/Flare/Flare.docc/Articles/refund-purchase.md create mode 100644 Sources/Flare/Flare.docc/Articles/restore-purchase.md create mode 100644 Sources/Flare/Flare.docc/Flare.md diff --git a/.github/workflows/publish-pages.yml b/.github/workflows/publish-pages.yml new file mode 100644 index 000000000..c5e2c6c7f --- /dev/null +++ b/.github/workflows/publish-pages.yml @@ -0,0 +1,42 @@ +name: Deploy DocC + +on: + push: + branches: + - main + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: macos-12 + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v3 + - name: Build DocC + run: | + swift build; + swift package \ + --allow-writing-to-directory ./docs \ + generate-documentation \ + --target Flare \ + --output-path ./docs \ + --transform-for-static-hosting \ + --hosting-base-path flare; + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + path: 'docs' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v1 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index cec795e73..8deb14f03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Build a documentation using `Docc` + - Added in Pull Request [#11](https://github.com/space-code/flare/pull/11). + - Integrate the `StoreKit2` purchase method - Added in Pull Request [#10](https://github.com/space-code/flare/pull/10). diff --git a/Documentation/Resources/flare.png b/Documentation/Resources/flare.png deleted file mode 100644 index 5a1ac4071e43523b46251041f6aa629e05a9e307..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 329034 zcmeFZWmuGJ+dnE6DhSI&KtM$aDFG=d6C@-=Kw=mbhVHHb6hS3KrKFK=q)SSqhHe;A zx`u|K+2`nb-nCrM@;&zcf7tuW=F2+ZU@`Z7UFUV4zq))QCnJ9R7}c?T`}Q4|xPSNI zzJ278`}Q5oJhC5t!gkPA6#jG7^4?=hO%qc)LzK4VK5>*W%KWJ%O6$Tiy9>IOmZlar zI5Ai=DhcbS#s*7hUGbwx77Hynt@s z1kb0)n2t+yJHo-?J2UGpJN;py-s4QJC)8P|jIv!kNgjVVQE=P#sO0C@HRrV|kADqp zAss!)dxv~r-secniNhrK11`8J)DSmEd6_={u6te5;^zI8{+6d?lIw_r_b)q(acJCK zoKjlJt>J#ncrW(^TiuJZdhf+KkYdhvqnWUww}KlrJHr*3g|Unhs;mJ5F$rb0?q_ah zvnO+f9oXOdcHkz-Yh8|~$67vAA=V2KX&%=uEq@Hycj{g4%?ovn*j#dog8^Niy(nv! zNZx4_AKLsJ8(s#rCrH|gp(X{EV=-lak^UbR~;9b3J-Ec5x zrk`If-tN7I5x-;5g2(*GcSjLi2K+ku{=jrq#)T z!diDZFul(^&b*{JNn&~^2cdKARiMjli>>$%&J3?^c;nkVtWgL<@0@bn{^2>Sc61k( zxs1^;OP}d!wzI-%f%%r~=X`r{H?JSvyBLi*V$=>?pHV^ zmHPep@TPM9S(Ju4ZPn!Np2hW|x>&h`Zl7w;iN^=-BeIy?82wncFuJaYv^3({l6z`p zs9eKhSIwC0uVApKP`6+6BbU?_adYuQQ=S$AEmG)=JAM_XT*^_!0i8oR?Ox?{j`v=E zIM=LjbD~PyZ+kE6g}+z%io1y+K3=ql&3RiTuy(U<^4zt>V9Ckck*wN0^tb);afLYT z28MLpesj;Zb53r0_db37z=vyOQV1n|!75%KjAp*iRabsRVly%$x-GQlO~HxCZu>85 z8T*b%6(Ytf57iuc*edBi8SKXNtcstQ;u=K}k)PW`3R0f6tl^ZJi`=MJm%f%w8GZel zEOr0*7vlZR&(|$XSg^!n9j9O9U3qC6U2Z3sWyG6t>Ul-ebwvr%hVR8?Pd}cFZy1io ze0qJ2^6j||+cQ%4-To-oYrW{6*%DzdIA^4Ix8Ph$x7f$Kz3Aa?1Fmf9srN=LySzU7 z2J~;Zi1OKrqmJ?SzN=*>3ovy+W#djCPv`GFtKA!Ah`(z5j6~JWeUP0~F8`1CeYUT+ zC7(|%$W*s{6%+4#B1L5=;Hu^ySQsKfnjURcnk6^I$KAKPBB39oSyIc=Lh@=$iU&{xyz9naL^3~TwxCt;QgQnMc~ zk3Va*7dTK*f|z-nCE}us2s_bp)31vX^SZGAB(Z~-WuBOrC12=?jrb!0e&0U4C!Itf zV<{b%T2P!X%O za2AHPF}q!J_Ek2ef03`6eIl9vc^dk%$<1}DQ6>Z1cO672ena>}{SC{*hqYBlXv>)E zEqWNvzYKnV2YKMzaQ}H;v<^x>ai03_1m|csRdtDB_tWy4)>@lsZK=2>wH&*vj&7dR zvs@t`UZbO#dv}f~b5io+5wXmdU$}GUq9)zs>UeRz39v5$4w z_Ok2Mw;PANj3joIUYrgb8mE8aD|JeZTf8E-c%S~fv(mSrBdo^{++lt~8VFI^a?7jC&ftNmO2S?BtC^KI!}i<>TIa9TJChVoy0J zPaNyCcy=S&zM%B*<&7C@{lO>-8(Q=B<@+fMGfFGZDbM(E)-C(rmd>X!c!XYm*wVUl z!K+H+Ta~$?iC(&J|E}d z=RSfK=knXs&KMRMPtQ4;OwWBWIW(`HXJwPjvDFzpu0XCoy+Nai$f>_cY*&doZp`&r zk@?MM5sCRm(YvvCzK<5QqTc3xU<~SLPRp(zdAKe@Ox5K0tz%xsvSGw?f|kX3ghbw7 z_vnBnYXgRKg${qG%j$q`?Q{wL@vZd}{*EcZ^Tc%hwLv7p&92jmS#O2U%TptE*Xg6P zB&MdCHXZ!O4JuQr4q^@^9BmIIR<(QY;o`-4Cbn59O6OSqlkd-8+YTykcXU2&YfamU z8`hR)Wpz$-&9xfTq~l8xZfIF{X;jp~$F-5Li3x}Inuo|0b#3+@$Z&6YEq&FC(rH5a zHY$>%IC${kh@x@d{Z4+G%V(}gC=D0%4{glQiW{ewaa*eRyQm$J;WgT{a0ITYQmt6z`hpXvkYWlC)Px$TjQPOLj~b1xIOTMFj++XyBag0?UBSQsv=`ADB=9fg6e^TcWb;@!BfL zT$>qI>p|*k*9t=7#-;dgaio@qTH3p6TZ&gn7>e{09b`JQoaKk=f)eNR@*1ks@ANOn|8Z*T)q5tn<O5&N#-Sh!4dBK2yM1zke`X<9^xNVU!dOD`tSXnxYfx8Ll+^R9Z)fA6{UpZHuIonifAmAD|HJ?9Zy(z-d7b!Uc*J?}dR31}lP}BbEhCJA zBa4S(h9n%*=B(@*zjEL8IBTkTx>Q*B?fvql^XE{nYi17e+H0V<&%$;I^b zSuOft+IH_2q7pIG^MXh(r%l^S&!cP(g|U-db%_w|cXHLe?$5A2Qmc#XZ=@N@uK8w> zwwzUgn-{O%hg7Pc{w(~xMWg&IlZncp?gAM12br)Nv3uFS>}S<&!m=O0etvpj%DU{y^vp~k2Quy7e@Qjt znVSeTN#vNXPws9T+223&90_4dNng7NKDqzvjz6&_e1Gl2{yCS6Cw?gqm+yq{%Us}T z-S7Uo`R?LBp6b%jTZW;D37gFoJv58cgWvsO-F8i{7-Xqa@q-ZF((NVBk^`j-`{(}t zc-Mpo-=F(~2+tT>QX(QM>b$!h^U0Oiea(KLtBWsN8UOSS@fAi!siKu>oAop8ot@Jm zRO-d{tDIu3t)aq7$ahm&`3JMxJdRpQZS4Bgdd|sf>F@ zP}y+)k|@gIdwugq3j55eOJBY8^qKqZ!iWpyK=M0lbhLI;Zb$6fyiFB2H7Sv8^B8y&L-e zJ;MP%S6EnhMJix@bMvY{w@#y_jm==5Nra)YqGBS=dlA_D2OF-FO)eSeE? zZ@s!DT0Gg6PnBMLswZorz+ytHC^9lKCgz*!n3_p(j_LQ?J>7*?GvD5vLTRoqd>0T9 zm|kD!`L!4PRXu#MSSGPVDK^r@gsG>4>7UbaZ>;Atp(< z-Q8X1y{*9xDjORcl$wWsb(*J_m)GQ^E=tXDsg{vm%~v-k59j9Tc3>faVMoT$6<3mfBx)E%_mvsBf6`rqob^(6nC0c zh~10! zA9P&y4h#$|_`Zmkrb90A@e@JZ zIx#~bCMC>FOrMns&|7OzM=Yo;ou;(ZR79p$?R$Fhc7Y+~A1(B+=l!4NHE?}t*@w)l zIli|kWoGoL`R6uM>r8TTv)W)hT_L8M2)(qtyy~jo&iC&4*wn1^W?KYB|X2O zKzMI^nV9Un9Of+R<7==sxVMRki30-z@Ypm0=A&bEf&OBNi?I32%USZip`m>xXb0cg z(aAx2&|cWY%kI)`ebMQ7SvWzP_ujs(e<{?WnqdDYcg1-yTNq@|NOK)i~!D zMN8AzmfFTf8FUfnl;|kVMT5cULE{qpomXTnW^~^rD_3j{*IyLxBscTr%NGw%&(&1j2fr_vc$c@a$jNA201-YarOd{u zO=+NncH~p)d$gd{v1amPkAF;>f89KL;l1?u&uVeK9WF&mYUHoBW%pZS{LsRHhZaqHS*AynG zY*wABmS@R>PmGHb8+e82LZ`kD!^m6MT6QEksaV*yelg7rz2E67=R9Qb)O`6f*=cjj?!iB@a!k|Y98u#VXId99W`G$qj(9+J0j%FKl zvFl08%FcJDhJ0CFUY3%SOiE4dAoFB=@!O|p@9L^9Zq^*xzG-B*Q(q{fVN7OC#rcV$ z&T^~DPv>xTWz7+IfN!pc`?$Hd$jT6LtEM8>gJEL1;ObDwijk$jQhW z;RRS&>S}9`l9EbGOMfv?7drYoyzpSW*?IoW;{4mR6LMApjGqY8T3x-2trHYD*h=|Cvnh^7EKS6J9cJS@_ zQDm-S#IwA$515vU2w6#cq-e8i7HNJ2zgg7e+u&d-L<4efv#YzidkxoH1Yd=Pl3TEa z?ZHb+=BUS%cLV*EJxm5mcIGulBrg1JbW6hM9ucebrW!^1Sx_GL}=Y8?Y z0b%|+m!dIWY{wdGS4%~OW^0Uuot>SVo163QazreGiVZJpJ^S&Cu=(igV1MQIj*fnw z>%r%LSAwUKQ&YnPbtLbmyLc}jV7r5xma?bcvJ46ITYub&8z&~srxUh+#49N!<-Z1) z;4w-5U|w$8VgGC z&*huGRjxF_2Fp=BD<(9oEhoIFQIhg4Vpg5I)rc6K%(vUwjGIy*Ar`~E#t#luIB zvh9|~{rvo#$vqff{-y+XBofopo0^)WBtPD`%#dQ^qvME1JK!gIFY}r^J-qGYR03$w z_B#1#(?DE~K^MkP9f8o))Z{blenLOQu9T|U5iL%xqoc#emsf(`O4BG-?fred(_Fj! z8%%0b_U?BJLv-hNh>e)^&2Qf7|D_Mgepczx5W?qtui8wKV3EF>a}alfTdwj4dRcG(cHLvK%>}Raj@k{`HMqPw{3YM#+dU?+l%68;yEi< zLkB-J^%*Lv%}NU7q?#J%zrJ^KG;v=Y26O)Wd6Au!wxy*d507JLd_OG{hcW#DG!Dxn zE8Fzq#eQ`4$lA?QoqCo?oCI_4SD5Z~bu2G#{I3Gd^)_w@06muJ|!hdDoLTy z#kq^}hW&*+moJZUl6ANKJH(_F9&%b=cq%AZ1RQZjkg83$vxka$V~SjK`x;=`L3?Ll z3@Z;hg_~bmQT2Cm4LQyA6##M~pyL|i`DXsWn^TWoSXn{LwDl!n3I#$8=4 zDJfxQW|k~E=`~R5?5wMskdwiLnKw^6qx{d(Id7DtlYxcA(+(0b58CZ~nxiC+CjPG3gZ z&b(Zuf1d=@MEL%D)edPv;~6VF8_d0%bAq`>z3@6V-@m$f9B$)U`G3Wysd*OkhL=Qcms}o0+NP8HeTO{W&PjSEoCs+T!zIp0o_x45A76 zMY1bNF&UdyST)K$O>?Ex=ezI^xY52JLd zKT6F;+yTI*@$>UP<~1JpGBrD!f(z!>dCT?GfC%rh9i@MCXQDj6G&D3Q4q~j7!b_b*DU`=^8+zNaMfF334KCMJFP??XaZsHd~aI@oa+9M)#v2LQdk zhhyX5P%eB+BdDF)ZO$bb=nb=<{c4@BBDK-MKG2D9RQu<6czC{l{|*y$q}pc?UgZOS zSBAAE^@MJ&`BR{tacGtaeqEg%(f#cchzn))cS4 zi6yqv(=S8h#@<7=-=sh)En&ppo@XvpLmqqTUo89A&Ru?KYqvIcBYfl z_3KV|zBL{>-*C3Nqd{S7O@w3Cb-=O?O=p~RL#Q0#`L7*Hi*1OuaE+$_RNs&13lxBv zotvCIQ{_!PpSCHAsp#r><>m>ktKesaDXcoDxP_o792~YnL(d~n+S+kgP(A)Qc`^#8 zSY2SZ9Ovt+ASULH%CHm=6f~%Q(+K9~=iAN?6eEhP6&W>+cD=(> zfWh?@Sb!7-;FIe`sIr{gyY>+3@WvAJF$~PY0{2r4(m-aD)6w_qouXvznL-UQ=q7^SNF*^aagUTt)Jad`0H!Lw&k=Ye@7LhWFu6qS{mf_Y{Vt=N)>N|a)){WF3_xBPPekQkU%h?j?dt`-BR8$1Wu(gI$z#EPI zdz0baKiAL$lOLoyv$;Nju~gJc8lQV4g`eS3kCTxp(VCNU{|ffA_Y)@BwaBwnrW8;- zaQqZ=)#S*EPVO_MJ zRllW?3SdSb`$nb zP*4y(NY8IM`Hs|fby^WE?s|yitQR$(%;07|v&H&iHQg#rgP5-FBn8s(lgYj0Uy1*9 zVvuB0)6=^csa>jn5Qf75Y4DkuT*Sn$2=Wn#4N+0IVQvy*JbRDiBa5sXKzxskyg9g- z{}W3oJ3PeXe$LCoFD)G-Cr5sMQVv`$dljE;HPZ=wV^`;&FFrmL?IY4!P32NutzU-z z&mv?yQu7+FPl)a%B8T@q(Pg0(_$Qzn@1+7@@&6pqJyTOu^oQqzGG3+8?N|C$!)e$@ zWV4+_MNXin&p?{lREB_w?0GZ_%wT_oSRO}uZ!e#NC|iPYS`^<#MWK&l!aBO{}z zXeo3XELN4e(#pz8PfridyuUpXIq2tiIu=puJU>_}di{EPPmcgA>nzC8N`*1^tmSh% zFaUQF5|}6`0$p5O{8^Nz?O{SyR8)-pQDluvN=ytAv`MRfFn|&2N>PbEE7djIlhq4I zg)2zR>)iXGAib_X9(Kjza=u#`EO&(`_J{fAkmehl+6Ju?z&rpag#o9v9vx6n-@b*3 zXsw=W7^E5pQv1hRU&a}=mcn0KM+4EHFVBG}%m(=sNs|2-dR0(R(54&NzA6;`P|3vb zn}yX<{I+h)wx1CiPXjs#JaG|-)%OnQ1&KO4nVOnfTU&!T0ND4*lPAy>a-O{hnH+~J z1~CrsFF-}(?$5XMl$Qpf8`m{8aWFBx20{1j+kiDVkUhPR)U#>Q&tRnN{9K&H;{@Qb7nOuTVe)RqnPA+=z(e{PoBJe`*wD* z{>^Qez_4V6!$U()dh%he!m{QXG=>TQ7{!N{u4#3MLAe(@;3YK`6+2-2P$N(bSPe7i zjzOu`-5`m=(kUw|8zePj|GBLaBWKH-n&#oNH#-AdTm)4;p_qMsZYtZ*fKGqC-qrxp z-Z63MgOOef1y6HjzHBJ}MU(#PK=xzDK$r=r9Cy#p%~mh8lpui4LFc{VH5`cGVELf# zpcx9Wu{2tsjI}P+ag-($gFqzNm7!Ukaz;%?Y%24FX0oW0i?~x(92dtR zB-B?|XRy7#sFrJ(2s&AS-q`494Lg{6T{e+tezlo`4}7R9{ZM^Qq7>FOgxAO~LDBP0 z8BOXTXxynDIW9#Ltz9BDQVIv=GTGQRqYf9I%R5OYYCd|urGI*Qn$@!b4-ZlA$0BRW z!OGgM7!VMU#1=qgV-@OfxR34cpo{MM5IZvMhV^WMAuQ%R@PaBYN|-R|C7VgP(w>a@ z6(@h070u_nWvIHkx+W$jnj!-EEf-vxHJUayH{I9fL<}e2jgD&R1#0Y&rF!M)JOfJo ziHhuKxym#X;|(EDQNWP`DqF_@?b9%dh-e5T zd`N;5Cx?a6-BJ5Eq;#w{c>auOdP)i@8Ckdp!Z|U|u;-G0YqEhdt6FXf%!5s(Y~x>u z-A#)p^m?HV>vHOr>tzW#4+qKWRcLLs(Gwmx#OQ=``efk(`OY)qm*iB}nfUmWOVvCT z!6Fg5{K)R(IC6I>aB^}IJh1ikb<4@-?@%v~Fr6tXrzj}+?3T3j_7*D0XJ%&FT3h$; z-!IM3_WA^U8Zezlk49l1fhCTQGXQ$$3E;uV0dygBw^->yGFl;B<8{ydbr|TOCA*t5 znLwRC329}uRHJ!i5B43uACQk72oH*3; z<@A(`!tKU`K%=d@V9=H3KX1CEnBHRc(vicD!wuT{hiA+dKWS;}YNO!15QrmOZ>1Fr zv3Vxx=d%Gk!t4OV!N$%$P-J5QTTa*}=V$_f7qyuSb>v}XW%WBT`UPCJn1Q|pLx+vI z$8vHPx=g>mJPK+9W-vz5!PNBg+KbY~D(cc5oJmKXOVBS+MVFT90aaILXGz30Ht@PY z#bn8~$ymdNo;`DhlGkKF$bg*7MF<=fA78T9+=E>$JCnXIy%ooG%)&+8aanr;BHnbNdcl~jRuK(5QjMd7>HSWJ* zHhj0|oQPxo+G2DAB@ur7>z^G{k3$vJ5fHig9*YRhyG?rWZx24WeJ6$`C24IZ5I^v>=Nc8ykbDfhe}m!LF7Q)79j0 z{sg=4({(-1vK=EOwY0SKLs|fVmMrpiaZptaCQZ&xMr`5deO|vdH8Wep<7H)KyH@oN z5Xj@3H*d^Y85!f@DC)&4BM`zs5aPq_FjOpU2TdG1?A%A##t6$zvUZ1wa1Q(yPIS{%faxe-pu(Y z{$us6`XO~6r{!UaWST+x80PI1<_oNQcMXGY)*Zz?2O_r_h*V9X0^GI>LoqRz#{}jo zUXd%)QQMDU&VVEq;j}4{OH6w19rz~M;6H-q?u_rZ!SvSG*8>>o`N)OBMBVc=Y_D;l zrKJU?A{p&1*#k2gs7rjo_wpX#K@!r^tXHodJ9g~DQ3D&3a8=DR#GHbY)9$w2@~f)j z$8jehLqUz@w(NfQDbqLxVdtTLs>ps-A38TU;1pj6Eca&T0Kt$#Z6Bq;77FW8T%Dpxx;bQmQ%hA9La#M1jPr7DVx ziz_NR+TUogmNCNX9OrG`uN4*e*&fYk2FNTxxdTOVn3Gje z30j(<0Gs8ZY5)gvpuj@MxAwABJOFG}Et=9L42$G^sDQ<@XU`fVMCbq0{l-T|6ciNN zCf`P&*Lprbt%#G27y#E3pe9TxNy^c$ZX{-AX0*o-AE&y^24yKvb}^Zojg9TXg_~9H zEA2tQpdP7_PfAX12(G1;_C3@GpD#(f*i!ofcE26jha}D;eGtb?VNG&8-xI6@nBrG^ zQw4@-si+E3b!X8ms=~i;nn;1>E8gU|!ILd@rKTgr5&dcCGe%BnNUgzFGB^=4^ArEK zJ##Iud-nF5o*X5%I_I)TGtI{&r+9*-0ZQ=dE2TWNulunzbr=~uz=U~os_*TV9dFE(rr-q8j?v*6j(Jyw(v@50d zrjVte(6GI==HcUmEVN9_W>wGs3=&=@6ErX8;On)}R#icsZi|<7-kgeuR!&gQ z3NAVb+pp+aC5YLC@)`vLhbVU?MhSv0#K0iN93a_)c*{}=1jaW2y5d#mmL+J1_r%4K zC5{09oT2Umb?QGp)eHqf1T3zlZ-Gv{rnXj|$~&fZ|D5~wy3mOwj+8&EU-CijXEoz8 zL^2O?-*d5l);X_@G7?GGyVpZ7py+4ujz$vBR*>sp!&ByDX*XQGdUbQIXdVI^&x~zJ z^P;0Qp`V4ez|+Ff*BeX3f#3_r`4RpGybc@*4vjC55r|^lmZ*2{-eE8p_$`8E?Vc%b zF;qqb>j06K`{jfaBPaJH)f~w7&K6!7qumsaP*W??s{KGO{x-ovcU)Df3}IaVvSmd4 z-domS#V3^dUBxlutGA*VWj@;OQQ{#l@woGO%DIh?SFT)vFb;Ze2hZR;1tlwa3&c2} zTmHC>A7o9 z;02&aAgwZeyQ#k3%fo|9jZR!d>SvSklT`(cC3DmJrHg}S1)J+do}RC~Vr4WgWdA^M zx)wIh!k@3)=#vdp7tKoZeN|g7Q_)i^BJ}Nw!GLogqKAil+--Z?@qtLxl|+*Z)R?xO zy_I;;2ci6n{>mC=78VX5!GdTJ>Bsi?^ONcJL@W)QQ&2YG@dV9BYhWg_ct0Eg*>Pe* zCz?S(fRLnM@MQ)Y0}8nF>ey?bYutlDAFZSB>9P^wV_wF{pP;WB_GBBG^)887TD_Id z(sZjd9wc~`QveD)eSDmk8~FUIQc_sO#l_PFg@lEnr$<_%q0W|WDeh_>^!PIs(=D%5 zY8Wc&tdaQsO+%=FLQg;k-KkR}BO}~;t(SvbvzeS)Y!Syj3Sc z_)O;D$siFT#Zi3O0Aa-E&OqW%H9xW(V_Ns*KGf&Y|B9?#C&u>m_t_vN(1JH9O!u@E zCI-I@8Jp+kWo3DiaM!X7t0;>T3pzLmBC2*O@PqedWI9LbRX-;x#IvjAN)LJvcU|2- z_llh6tu1@h0{H}+>nyLvL%K6({X;^M>C!mOEB~jNT)R?G0^S?oikX@EaR{SqZf?p1 zUuWj!RU!yj+&>xzrdP~nd#%?bR%~bF4aCM$5D;Nl*uf9tr`mLCKR^*)fwEa$U7ebm z;wV{4BAhxmnoO{UPJ_cr&H(VO&3-tbT$1*K+f&b z0dswkV8f@UOevt6mseI;nV6bwgp7Sonwo$WSSg=NkOcz+m2GX;UmPL|}6SNO?2l z&MQQ3fz(O}$jHl^f$s(%zB<=0$iy@WoC%8vcHR0C?;XCR36aGsgD=+R2h-z#Ma&;4>P-&2Z9UgENgTK7al^*zsWVvHf!r&i5s0!lOv? zo!6EaC8LC|URW~!8k@O3EJAZTC_A*My)`%?E? z3jd$fk0KVOC6KMEJ>u1_fvY#r*B@^TW6{K@Q98p3)z7eO2p28_qQ~H?2kjP!JLb%1 zGgJzKxTr|aru}eVPU0dAV&J==8YQx+c9Ln0So+Ao{~t8|dv{Of2P}6CD!a*Kbz##ZT{_Te`8S zWUNNPAxqKJH%KGIFHqf3+fY4f@k~EFjdj9i%bkoeiS9I;9Mr3kqoXiK_AP)xMk)MojKiRGcv0s_wd@kiu0;dErFvF3RJNh_-y6>dAJhVKEwW|_3Z zhrb=4<-WEWTh!@g$ZJ%k6(;QK!*Kv2`&nl}vV@iJP7#28@dhcHfB~Jf(RjMI= zxvRwjputj{J`F)kOt5?*unvfJU08kC1_IyWNVSxvnOR10@y>9i zCnTW6wPQ~cSRy#Lf`V!RW->Bw9Xq6?rTqwcsYJ0?v|o@>_28&?D7_sh%3$iPbWcF6_3$=P~V;-gS9@rWA18$cnM_7EsTdtTMAR}~1OAECY% znI3RR^+#B6+plXmENt-gD*q;bt zYS<}UAo=*ADJr^WNl*i1WMl-WYG+pv9BX$s;1(64>rQ>vQC*Id#RGH2x9!7>UcXc= zDY4beiZ0f4QFbW}ERA*@S<65^?yM;(c3ABs_c)tSdpp+K$x+|HU@(G*Z@Az!VO$0V zZDNJkSdvWIfey4+_o-U^Ne3`cUGQF4*&qTk3-eM!;>|YwR?*;&F{H&>*DJ_HYea9x z%SHq^Zx!0iJB?Hwx2T9c2NBvEkD>)-LU8VrEr=?6zP{1dr-gdd*1px=lOeE}E#Xe-&JgD})2Hl24XWHbKZgeU zFsOBdrA6I@UagP!m6po>z6_>+0>Zm0-`|J_?KIQL2KK`0 zOxGag$e^F(n7c=l=-wA-|Ck5~Lb|UX^7AG9;X-x~r$N9?#-*mDTo00le4M_Nl2U+= zkB?!Es{dwG)TNxdD$2y->3WnK^v)>{Xbz|mkQhN+!KMjVj58^hVf_mxtaMkl(*BGQ z$cqSOq6zx+N3It+2YUEvmc#BOIFo(`9%+}nyXf`BUoCo@-a@oXE>3@>Bmvbav*8qn zoy=^}Ag+Yj2ePKWs0%0Qe-HMPI;0YiHG7pgvwtoChgHTpaDWMu9Ie8j)A)130RX?{ zdN`5u17nTY=GetJdq@NI$lDz;jAo@*#JB4X-|t=hW7%*&mc#(y6yu&utVKzVwA!mbf{Es&%&>tEscx>n!za65|K|cwcM~Rk354vHIIwFU>jsh=}yJ+Vlch zCW9h&Tgy$N$(6tXz|RLA9rEZ9+uouJ0ePB8k4czroyQ*;Ts3 z{5mQDLQD$_rimc_1$y_3Zq0H-EE6L5V7?I;j@~1&?tkXJaQ3h5I@{ap|A7arc~2?i ziW^vBgX^9E;xF=M%&(hiXqLcO*$Qs6)eRgQJ31$<)_tmvy21Msbh-e#h;Ni{=qof> zJUMdJpLmyGPI^>-*>+z#Zy*H{9$=SZYn-a1<2EGu6R&HdP_+|%Gi1Q+;l>9O0)jKK zDX+lKNusY2wSz28MusLt?fztqLG=XIC;}>_w6vFxPg9J9uitF6^f-(sa2Mcqi=_AZ zsITnkAP4oxYcTL_;Pho?F2x3FNIrO=*sCbJ03%i6s6_N7F_E(1Hylpr=9x~Iq^UXr zJaj-LVJ11G1l_Qj?~APtyvp%2{4|#LX0w`9dxprSz<+w41`(L^C8sCq;m+6Qwj}?!;frapF%#Y;m{g)sPUENj&8<-uR@Z@ zAjA1rJbvH0Kgb2Et5zBE2);)0_Nq?8)rPV0C-Emv>1RsknaIqDg7gY9q1APR+8}B^ zW9g6Az5_H-WC74Zcm8~6SQrADtFP~=bLT#O{Fq>Q})2L}^KaAjw&K=KM8O#TFW zK=tt-0Am8OD{!?52d)q39Vylm8DgCa-+Jk zzaQb0^XJVR{pZpqV;KL=s`s0KL@<8P>#yt?6WG40>@*bYPaR_TR+m@1xSI-sn>YKz zSi9r(p0Bz8o%7o8eisy!m|N3T0vU%Mxy+HJ4spG}y0qQ7=AGdpLT}7d1Lrb~bGHG@ z7ZNS*gVnp#p2^GV%xTnmeKox%p)gmt5G}omVyH&HPV>m6#Q>V;_ml{j}`R)yTCo>?OkJIVO+5y)w7AHr=F{BWUD?-dX2kfI3jJloRYtL2 zUNE>ds;b0j)@f-}B2ma;Ed?7ZC&q8P5V^Dl4c7$Zt_Kgiv8$2Gk4`FJNw{YQiT|rm3c@`@kC=7s3bK_ zP0pa&q0U=rv7r?E8S8SK_GnRq+G)^FZT3_iq75I1+!G~^3I#C=>~Y9WwQJTM+k^0ywy~`} zK5x*;z<53StxmX|HYlK6wooTAW0Nh>n5;awB}u`idU@|{oo;8<2Hb}GRdPLaLv|Dj z)qH1Uvr@P(xHfn@u-r8zjgnfm;-|QxMw0(3eQ&2e{R7zpPcTe=rMvQj z4}%bXF&PcQ&qG!ew)CsxM3_xD;C;#o2xYWhVL=APc(Z8YZqyukNIw{#u3ivTM1@VS z!{oVv{7HGMkp-~MPBec37o=RK=Z$|9d*__nSnpP;JMUbbuHb)1QF zatY7je}Kr(_5H}RiHFmN#gK-b&E6z_M zx<4#3_iIOoqN*|Y@_=f4@-3%Y5hK_>LgDAoLmER|m0)h=C{yI1^AmY*K>dr@byoc| zZ7OAClxlr&>}lV0FHDAnUh*5Vby7*{@90vA`;5G_9k7_#Yffcw?P{Z?Nqpv6WTF|f z5uz8PIN8Rz@^!umy|ZQUlxC|&%|v@89)p)0iPB7EE8RRi?yd%g3)l_Du_@016v+f}jRA)M zTSYEHyBK=(l^d*aGGWu-zh5*+Y@vxo!7Tu2=((*dGmu&5#fV}s&QES%J#gTF|NGd7 zVhUIPsj>H-6A#NOY)N1=uM5xL{<8gCcx6wke?C}($s1?mb)rIR@BagWoeX9nt##?rS2zt&;ae__dV$DGt+c03!L^#FI>JNjdD<;e z_spZmY(iPj6cm7AjC@Ei`rR%gb)WsX855Zu0a2)-vgertqkMtV5+&S;uO8><`?Jb} z__RUQ4yh$j3|MeWAu@4VYG%s4Df=q9OD zi#Wy|!j>R0+69OF%AOYpNV5H1=l-GVm2uf9t0@St`7gkExTk`5dRx@~MI@>Tt{%6W zW?_J_AHMAbMk(>ZgG>Uw1WMZlmp(n_l$4cqf~u5$wtguosSfl!_t0*nf|2F*ez{zm zz&j9?{VP7BA5Gs~)7>{A zagH&bMv#-IsjX5$?>&2t;mCS@xf$N}yg4xQ;$pO_s%kX3igFr=m_=wuM+VvOl&$mA z#?w$#T1>d*4)xfrAUQwbUbmBw)tFjOi!IPt?N#X`cpB}h|?QFyOaFev7q6KBm;7ee zC%QWISVTjEw6{brJTd&ykwO2o_v6U|eY5k6w(3hD?4A4P#@)RfzPYPt(0PA|=xoJl zdm3|0oK?b zWV?tzdr$7}{lTxIpW)*aKcquL*(8EkCud)rNWp>UlWLT(-GD4LoF zG(7r#+CD}0{)(4GA(Ko`PoIMjw3&M}FpzInQCkaPojd)?B3EJ2#sxjadU*&?!tAkH zWT!|WmI^Ii*9G()SFIx#k)O^mpQDZtAH*2V43A9>2W=I(5;IQZ3lwa8bd-^9X!EDB z-zx=JoFwq3bL>rDCZn-wd!)Duw?JtxpXL1-1UK7lUp7Ms;%&ujU1_}?8x!M2BdFBF zTSY0X!Zu0e?(UB1LZS`o{uZkp$^cJk3|4w&ubOmD&Dwem>TV_Q%)TdCFysi^#jK8^z;PC0*O@R)yJJ;S-eI#HzT-c&1s`OT(i)H0rOHb8q7=c6_V%= zA3m%cP%#5Fsz3))Hjq((Bn+6M%2kOU`gtWiU>zc*;$V>*BxR==NRao)tx^# zbY^INY<_YmA3aMEz~d|{bc%}Ve>OEu`F=WVYNpA&M)9g^lz?8Q+k>+H4~vZnQ)b5_ z`2PkKd=Ob4$Ft?&IlGWb`&?Rjb`Pn7bnLuh+8R1YM%f*2<8uMDfdS#d$<@O?J?m|0{uC?MKo9dsQF@>Nya1Y@43tb%Qou1CA7@N}kWfv#L?>Z%CMN_)wn_ z$<$SPj=KB^{~@?#NBqG#zE3TCYvsb=a+U#w5}_U!oEgIGH4TK_yk|9LQ1O4!_1*DY z@9qEEQz|J@oCZRYh%$>pWMxx!_A0VhNlK)W5m}jqkdf>P4SVyk_a-Zw-}9q7=XCDx z@BDM0$9deR!~6YuU$5(Wu8TGQC5gMs%ky#vKAbtcnIOD<2ivC{E3Hn-w%Ohy#-dcg zf-^4UY=)E1NADkA&o3i$(&gA8Nw&Wx3iaQtapO2u;1{N8PIC8V!l>obvYa-7VXK)N zp|`b??sm?xC?v?*kEIxeT3FS-dP^ha`wZPfLs{9Q9pR~TaeOerK{x;$E!#sXY~#97 zARU6fyzOPtNLuj@1e*OhO{&8q?@J%$LKBC9>l?NHZixw%d1jU8Qmlzjz4X;-iVxWj z&rccFy$HXBG4Y7i)`SO*^j4GWMoB8R9{NKXT+yi_Zye@zs!6efgrvew>BknikhPmW zM3hm#^LNQg=I_ci9AKjLuC&(^E|v{n^fq*KpNqFOyH#B^(v8Fi1qB7z3QzO%7W%WO z>Yk*8Ki5Xwi@`-&UQO*y{SfM!tt$vXGBPrS>qbV@?m6o!gL6MZSvbJ^}ecz{)aI#P_UP<#LC2GPRqo{8Ahx=GZTXT34 z#J%6b+Ayex;Xd9F{5;yiF!vM3j)gIyZQ?WlQGh%YPE25ni;I|{K~jcFMdO)4i3iqB z)(kfraM5_?!P^87D}K+O9orE|p{^Q;7PkjReh@AKWKk1}OG}>k& z*K0Yjd+f(}m5rDEarfcmpl+U5XD#m4Ia++?K3;9zcP2>}a5YU0)xr_4Ax`o`2OL1k266 z?X-hjU(IYQJlF^HAPFm=Akd{aQXr5g!TraU)C6|6{JIc>y8@~gvbJTA+vz=j@+8@= zagec#-rK?OXwFz<6Ju9QJgJIMkC$WH9Kd9vZUMrfjjrbt>t{xqtkGOROcSrbUx-`6 zz{toRxOt(9q#7KjmgyELc=@Zyw1#d}Ai)YEz{M6+Mq7bkeP>s$!%nntg{txB109 z7I=QJ?L($e;)yrvtaF1wQTyzz2NK>@GL&7~8R&MRAshHtU2QOrb-!rkI9dc_8JS94 zixeP0si}(%qsV&!gmDPreB8CQfpY*q8&MDALoadD+FDQEJGjWGS^KPxcgrB%7}^A5 zyX)&h*$pEnZ>vo~S|T_pW-RBeW>s+5;z`~{Chl8@C*&f=HO;pKm763PW$U>ZtW{r=4Ja@iZRmpVgHF-w51tlrGCygK(`UG{WL_xFaB z8zOm2o~8!R#T<$j9yu3{b-(iI3>@+P^{okwtlwI3n4q11kidY?+K=CnU%--J_QmGV zoopwq@8nie{g#p0fRr=TV)o8mAxVcL=j zCjl|LW^qMw^TDlOCDU4A#At-`f|@!A0a~U_>0T6rG(}sVf4=#JCd-q3zmw2nAg^A? zxb402{ii>6pe=}Sy>jhZX&j1Nc23T~W_mih$^)2yC{_|r!)4dIgm5V|OT;huHIDTi zS65s4h+Y@1aLdQWXHTE5g*d>`0_U1_t-jK9V%omKG~1&6zdRA3(qT{zjKD02~-3 z3O)SlUbtj+W=_PAB)@$-SQWL6k55QY5CXW!ktk3o-5nj34J%2TOg8-MQU{RBBFV-n zZ97v(?QCOF(Eo(`u#mUY!gB&`t=%IUim6tnSTrFn0!P2ID;IXvg& zYAK0%lV0ZB&5klJe&kCzncbs{6g&j05*3>t&3C5C?v=&geQlGn^iT_qU<|wI{pRaEzPBXs1Y)sv0V0a)4zIgE>97Iqo!-F1g zh*J#xp%nDC$Bu0#BSW?bwYa9?`sP|YcxPh9(RDxPJj%@ca9(Gq==105Oe9U^DtJ?z z^6q)eXJuKyFh9#>QZ^h+&TiX@szlZC-4UTlmij2T#c^;Eo!@2|8Cwbo589K)0}bFU zK4>(g=#iJ%Wi)aBzoi8oUF^z;M!6vyDF~(XK&`a ztbqutNOr7$BM_N-;Q(;K0=)n9tgP}K4eq!I6+~Z3J zNzxuJrTBT&_j-GHQ1LsQq2M1cAcrWc*IjAcZbf*SmNYD6Al#PSi={J-e)-OMa;J7d z6M=pj`fD=tdmb-Kk=VVgEKtiZKg7BVw2#H|;+z(v()xc5qWFANUhE{+wuK_v))x~C zdfwemOx`KX%QD4%>Q0)l*jG6bD1Kc_B1Xk6x82U8nr$OiGXcj|N0#r`6a78bPV|K9 z6bcy54R$NS-F9S3J6?(cEH302PMrl0&@O>C)ayCEOw596Xleok#g|&Vr8u6;qgOU2%dknnd@gHm$Zpv$9Y`ZQJ+u_Jq)(Eg zam9Yn{WQCw>8`}n=eTUpRWZ~qXA6>wPwUE+ z-Co4XLP#|*zGg5l`<;@kQCmdB`G<2!$mr7B2Nu1)Z4#k8_NJ~D_cRw4fn=g717bbF z67rP z?{;FQgr=b7lNw*n1?}LpQ(ejrcfGgph?3hb;PH*N18LW*x-S8Vf0}6RGzrpuaFBJG z?ip7p@Ij;w&H#ZPoSp~AuyOr*q(Drn6ejL_k46}c%~uiq!-cF|`+t3Cn}W|leUL}d zUI}5&>c^(wFb_++S*ucrj2?Hl$?0?3uh|M-&UUe9?#ZZ_sN)Cm8G5kuvX=rh&cW)i!Mu* zr+n{w4JNn5&C+h9;yt!#O;WSWdUyQ1c%jiGVhxMh+S(c$-vgW+79r99#;7)?-X*fG zp?F&!J-74bLKHiRg$?V{R#raEcsfu>1{75Z7RHbWu})-e0>g}myw^FzPH&9~?SDH3 zDr!;gkYV=LnQ%*cH9|p~RNa6jUgOR&O(`!bt?Cc=M!79-?p!-M)i>j*E_`p6odEoB z>c3Rn%4lzq6~6)AO-k z8u|Ph$~bmt{@`zEZf*u=3V9^}wZ0JhN3~l+rEpvQp1QuK8dSr;)i{BP3g7`eF9>lH z3&sJ0%q&2jMfq(cj8jueQ{nnRc)&UiyNW?|>!=oZ+DHLD9|&0BjVc$&kDc~={(SYZ z4;wSRfL%E*j(LIXLk)WZ_5S_Jh$eH$H6+Dw#53Ip3y*VNxYNX0@`>imEk~BeYPda}}<|&580MY4Je!VCkAbMX(T>^1wzc;|F%i!e65xC%1>$tmc69aSp?1`zYFg z9@>!8Kl_ci4b42x->dFTNz<6eTxZ%vU8|j?xXiv|!i8sL|EAo%iH0W|SOnfiVn9I@ zgt(Mc9j;%_^basBhH24Gq2<)8f&|b!N!!B z)C*e`&EIMKcStiZ){x16T4>bzRJYF6D!y{S(y?Ws$RXL=_kuG`QgFib}~Mfz*NqG<`60i0Tm*Xs0CR0v?xw{H{zw`M)u@PT@pI{!U4H&QAN(ZqT{ z#c$M>#+Zj{|7f#qJTJ_gRQU4u4Pb#AfaLcL@T1zDUt8zJSEZ#ods!zg+wS%!Q*0XD zkDruF2D~*bC3t#n_oBT`^pz097;V05%+G#s(lNxqxF{0cJ^mTa%PRL!7|odL-j-Zf zP}rMAO+&+P+;Gxxti2rwUq5EX&*E0*OC$)udh(z>I*2TstUXz6CmJFEtr()=)|j~+kMOUdL;C9D7%!`i&IYD z2w|rQ7Q$W*{Q7dWH8txuY^W4b<~E;7_A4jVUfM(ekyP2ILrqO>m;^Ji+V%P0$I3v% z_LP!#e!|^G`gG7kH6icz(%5@%YR0HmAUxeL>bvZ@F7I$Iq5RDEwAt}1Sq*tIbx&za zVI2@;c;IaYCjZPg;jgQgi3<(k+czc_7B7E&<6Vh8U6r%vUFa9{-HM!~7Y}Xoig8I^ z4$W_FY1zkeC3lLyG2MhH4=A{jwE6!yVlP%Q1nAtv*@q$+W-7? z79>`sH>_aFU+Z~_&{IHHj(1*ESco(haaP&F+^slA#=^qF&{icTCWeO6`XU^tv7zBR zYX!7Uv5km#0&|0_jEF~(UDnsv59N1kI5lK})*LoRTm(eRsv4!_d`}nHoR*fBS6p@( zsF%ol3k&tp_1ej02?6hZ?7-! z^iVA@iaJvN>opKoUxRJ_5~gFY&{;QowoadGI<1jUVpvX99dg6k+CTS9c>r72biI0? z^@pc_<_=bLMke2mxyMHlWGfx0JjNI1Eg2)8`vN_1@yd=D;*hsKbI8%2nw(V4vPwu^ zKJ1Dg8G@j{61CJfgq*o?r-ctvDzFU5Ak&{Cdc$CwP_~8O8fMJ#59QK$LrX?WoA5?r zvk^Kr8zxoAY&%XE%UfB76(3*=v})PP#>Vl;bE>=>7r@vnT=GNy3<*gp&6k!BN1~8g zLcKQi28JM$4^p&VWK7;`ckEX>nj&Egqdb7h(SvhVeF?192`ZT_v+azbC_!Ca+9xTI zsQ@IU$f(w-=sXR%BF?u;ey|?|3mDNMY(w4)aSD7-m|pf`5}?wE&y!x$(o>rHPL%(q z7wvlek7QS4M>a)Nktu&!H(K!R+iSGyKxa|V7WeVqEh?H{acb}HCyLfvN&dHUrK0X{ ziFx<$rLGh%e>?`(X(rS zq8S{v!L^`G@k4mzZ&kb=-a)C#$jB%tC^$+_PiSgN*{0#^=cl5qOia2xKeMu%ii!{; zMVns2-9e@)w;M&Kz#RZzouWW7%A}&ht@sRSw&394;Gu2;|G(BZ&p2ASs7D~hp%+HkW@xGFcO!^-^Nt<5q#SEUb)c&Pl@!2fg6ScrNbF02 zT~+Zl+~b+=-{-*XGJIkPzvMkG48K#~zdx?4I#Q*A)DYxo_mpP*o`e|{DDhi_M%NySdg_|F+X@Of6X=!E{F|7#HuZQk!nzni44f$A&fU-AzFs6#BJo~`Qo5%gsL((GY4 zqM}x!N!1z;d>8qA`pEmxM?u_bG1ZNhN#m4fZEC7p`C6_Hn7(5O?qa3ix@M*wj->?E z&zamXp5i6rz1#K`&BrBVy?>v4H`5AHyk>c6>FLol(2W%;mVf;^Ku8;MUhZ>_j)~c~ zcdrwCqd5FHnnY=As?Y6pn}Geuy8d0m#Elw{RGoob{AceK7!;J{yy6s+O}2e|Bok9O z4YKecG*Ys~ESo^{tCboz{Dn#B>y9Fha1aH#Y9+1k^r7|;e}68=`6(iH*U(V${w7j2 z(7#=mr~eVnMq`5w0`5OP8jnSePZ=vx-GiADhlP=M z+`%V+-!(|*2Sf9y2?@mFiAn#w#p^KCp$gUyP2;CjPS&~z2qp1)u=ENtWH-8o10};C zA;{uf0MDZ4r+bYA0{59So-}-RsLt`(>FHJgFoB3+C;^xW48D)gxFP8S6dD9V;CzRh zFuT(#2rlCKKFf&9?BT`eC!yqNE$=PdC6&5to%^j|4|0!gio` z+`*Dm_stk}7nlwJCLtSXzUFkPC&@*sUm@P++vA^R6_<68$EsW2hmJ9 zVd0Hw2w~mFJU9SgwJ{3P%PfUFK`c;z|gD7O;o}{-h zL}NawWGrxYt1cCO} zMGIL`(JzoK6<$d(D!a#_ckSZTn|XK`fcNbD@2|g;`i$*hWM99`_&%TRT~=Osslz^) zwfKl>gK_lCjEr;Dq02gEX3hXclHa_FEq~W)R}8UKy#AKo&%&$un#r}6v3DUF&S^|5 z)8bS?%9)l1sMzG>U~7_?6u9CG7=!@zh_>k##wSgY+89|s#} z#o7c($8SfzS?ZR5`SPW#><1j2lat!aC%{e?783hwj+*=T@8j?s+d&bSn6R-K9uxhL zv>IpIXB(RvPj&V8pRwq@Y-i8#=KHzg9YPXFas*X4u;1u!(gz8?&*Yy|mYOY}0V~1< zh$csk*oTz!FIHPak<2u%eOob7lnn%K{E;@Ir`AM@>&v~oDyz=FnhQ0C6 zF{|&IH#ik6S&vx}I{)OC`@wG@m`7l)n>_g?-S2iD=%?w-ICEZ`U8mZJ8Jo4r-ngOh zFB0(3BqW$vT5=>3H&^iL3Y}tSM;F)AbM*M}62vp&E#jwD&2_Lv&z^W?`$*D9q;G~_ zpfVS@(YZd3`=3@N)-J~haIixHf-@Cc&!*l_r!qHFo^V-!umC-j-;*b7I$s{c%NP_66)5CYlpz%v#F zm#9DONMVIvwb$WK1VUUk$(r~0`>jv)H&%}Ky|Y}vjU;TeWhs^R_raXo^6V??s{?z# zZ)w?Dyq4xYW{pTUNLSQub$@w6UtkP2;i-=g+6_FA3y6V$2qNWXVZ{#S<0nq+6^mSB zz0AWjY^to>hzwSP@T8>2iM6TWcNl4Gi77|A$fQEa!lSDQJ5QuON}<(({S=2sN*?L1 z=#JufnV1Y=LjqtR#XDYrFLLg-e>qKhypQeo&3Q|q+wG(WLpLTtHL%S8R5S!F6Ov%E_}FWoKa0wUA3TSJMMZ-;QrW~DR-++kZA7;+DXyfa}T``?Mw z{_%@`r%zi4jthH#X^JI1*X6j`z5=Jsi|VuoO${O%Sy{bX?^Qj2GFmm_%e*qb5<&Px z-g-9HB(YN=VAk(aS2GKjMQ;fL0UkzaF#eYm@JPOmb|C@tPU={Hsf=oOxYZATKWC;> zCk!EE#W!Ohci_v!?{8y|R9M=rPWh(B+GeBcit@e5`}dlgHP+Z*pkD0Kr6<-qSYB4HnK@$H=kT(1;O#B$ma4Z(*QD(9AFMG}|(wbm7M_7m3 zOR8Rb1UKB!=%{3hJ3SsD+5lAq+s3KQy_La1;mT?6a9?);k0jqAEu_J;ECgA ze}wm5_Fzi#S=9N4jDz#m7w29rEMNEY2%Q(51l}Ii97V`QP_Vm3$l2 zj8q_p!6LiUnxVE9i{Y+y&&NZTd%8PVeSSFa-FJZM6u!^bQJkHI|B$KU>xom@k+JP$ zIe<@_2!x`7g72?gTu2UO6O^z3rMFU@TUOQ#GK$BXk3~$omFd-rN2_e$y`8dKf)Zy= z1uh2TUg`4^U28{0Cd#Ils)rcfsKv+U3cX8>r}XS{_d8gOT_kE0l$8CWqo(oR(fhaG z!?om`7=0Ap&krBM-#EQ7DxtYYF9xKh(R(d+R5Z1=^7HWp*BAYylh)dw5*10)D%{Hd zDUz=`0T$@QL{_7s*I1@9=aK#M^}=3o$zJ$|A56(I3;^N};3tMJ9Oui1!kHi%XyoO? z3cuAI`GaT7!;l$(?j}{WUjwDeJ8>GA&DLP3fsDR9K4ht6dx=^L1CF5-t^V;}?EnZY z?i*Q)0x7^d%(U%};e>a-YCgsjr2nEa&}#Ry(4f0q+i`PM`BhC;;)8s3l#9#1MV{KF zXkllUtEsIR|A`ZiMkk!@UuIc4=_o3nyl#_vDB3u&lTmenh1`r@z?#~(RRB3s)zp?h zy4W>r|NC|c$+w|y1fz(QNQq!>BL7=h=tktoV_&!h=KmVd4hh`u^_TmhZWr74aovOf zQ;dp%wt7hH)DpGnH@&uHEL_N$R9;qGJOMr- za#?*g{JLUS%-0Wb4P={|bL{<>qFquwB3|{5jY*NGqP$^_sewh{W9(Ub&uL9o1ZTqV zmy!j-I%4CF-SKfyOwI|3JD0gkmneX`!+$H#MP79v)mQSvf+D!tU`;PpLy^mDJ2=eIFc`5avE_Fd%eH(Xa? zL#ris_Rz#i{MT}C2jwhU!cN(A#qnneOMVZyd_uEqwc$?sjg#+1R^-2?E0?|Q4d*7G z|KgScZP)thy2Jn2X4@Bx)&S$IR515x#N^PV>{590FA&l7LsP&bor-(MCpm??0-Mf~<4Ns=Sg8gKV%h-1&ha)6yJPp`PWN>koi7K&Bj-XKf z17o$$x%zWPx&wb+C7?pSzfHU$Y(%&u?PU5iG_ZE<=rDv@{I^?bXVndDCv%_}_2jJ}E~Vh~9!0tfuzc!65ziMpqHYmiti^yYVE< zhAEJySUhd#NNn{GXokW1WS#ocW{s23LM_{;*{M5>yKxAm!+d*4jb6%txGL;t&izwU zPoN<`=WpM=r#P5YRhx)B&u-Y`XOFG5rC^n5I^d@ILq zL`Ox9XL+n1(`P1O->H~$;`n%5@zB1#`*=+G-B}?DB#tNG_rd_P^*;klGiG_@?-#J@ z=Ih|IN88kCx`Bj5yuPIQ8uhJ?j~lpwzxTkDkHp8~4<8O;^e|q}5`JU#-k)C{m?l?b zRZwUPS5=ALom}~eEgrZjo*o|~7{=qqVkby;T56)?EWB}K45*6eIMi)c=pMpxCj*`T`RRjLMx0=aL(_hPJ6s@Q-s7w zZG_C^h1{)e4)2|o=eqF;BwL>aPD{r&|``lh2Qc zFHv514#{d8cgb4pDaSuNrmEt5P2Z2(y*tCC4F&Q2wP_MfGb*8t37} zmX@w?pN3utnrchzoCAU9fani_8qh^Z0@#%oU?5R*A|b{RgR|z>tVhKzchO}0F??ewz~TV20Wxb&HwnsKbC#$V%pqzA#b{LI zo0~`#PS4qF>FNj$ICC`p<)~&hb2t}jU=rdMDxX=vQV0SDDJDwqJD25#)sv$h+)Y3V zZ5`j4b4Bwp9ayzt(;J|ks+uL1%WxKq1Z@Azk;$KHp85G%4b}`)F45ePBfmG3ae&+M zOG``6SAi~)g#S?TR795Bao#dn?wWzYK=HKx`FNw#xRAk80A{P$vuhU{pc*W|gEzwp zeHWtoP}sz;Q80>1DwL3!*=EM~ zVcAf=%Dsw`Xq>^+6|y?%?WCb0!gs+}&M2|i+9G2eWuE)K$3CrnZ=y=KDk}m858I#; zJpXJ{^nj1lznM4H8*sBt84MBuD!F;j8thFf4CfRJ;?bEZ2tSyM;3&c^NSH0#?`}-J zs-VD$y^4tJD~_AJW)OJwh8dSqZFd)4sJIu^ZdI8ZhF|Tw>V8g+w1wEYh%j1E{>X%l zy=vn8Z9&n9k*n;!oj+37%pu_ z(&~w?VG2=VmqU2Zvak>nuV6GSm6hT<4aWk;INA3Ndq_yaE^*wnCMk7y;aO}#LIzY< zcn#c^{UhqP+eeVC%r;-@sPU{5I{TrY5lB zHxS7NI@uYM`?9&`;g-d4UcRyt9@;hTi=TZ~oa zzK31=&uyiOS0X~|c+`(SUgBy-@O$T#T@YWTNEZsz!;ABKmN16{_zs>07wRM@JVm zHDw_w8feXfhYyKgO6mu+)BO=$p(~4eIcl`Dw5;*WIm{A1#WU%Q@)G=NA8lq;=y$w= z>43nJxvAr35gZ+2{h!|dSbk>pvaaevyb#qTQ`1qPz5{a;HL_CB#y))Ako#1C6hm~J zOyPoDiBJ%BgR~ds_HswcpeU*Z+5XkCI&v7Re}=K@2-TM3$}p9@a1=kWqN4LXzWYz=%MiUN zzGp;`@gQ>>h{pX|lfjQ82g=hXBkdz7y^3TagdwWj+=ImCVl;i2lveQ66O>bW@$FJj z5sRlNoAsuOD>U-?(9$(S&5zGBruxCH3SO%Bmnt;ym3CH(gn0S&#q4)-z#w8`Vxq03 zWh0NwKi>MLW2hPFZ{KRIxjG*vn9~Av7~vd$R`-YNwz==)<1Z)HLwK}0KYY{OQQNSQ z?0M>Ae)b``n;riM(Hxc+ZC`(bxatQUyvLzC-Z7tA* zH@;PI7xe9{(Ta>a`OjdJdgZT{P%4Q3Obrgt?Lv%+Uilt7s;XR%M~`}mQX{|{sbMnL zf0p8N43A#giz(~aXg zM2x>d5T|vARWD`%{MnYw$GOA+ks{o~87A@Mm$*dUK~|6JwEU+1|U7@LfiOj6wIhQ zrdT-bruNKuYiU{pu*fkv&v*Y9Eg2Zc#@0(PqXEzc=K_o12!i1=q<)vq{{t}TCqEb$ z#sBIZFfAk~9C~{^_*&KOa0NS0$bc%KD~1cvE-W@SmLb&PDY3-a2uM`m*dM%)%NMq# z>K&m!MPc^49*@6xRrHF122ZY!%ss%C{C{U=^yD2xGQeAXn)ne!-bawERIurUPT2V2sFjaNKCLa3a{qxzpg-)09WJ`6z(gKh^!!oM#oJ6p^GqjAyPum>K%(( zM)0mTgfggVm7qI&c>n%Raat>=sr}XL41mMoa^E$CKkwNW3u_XV{wM33aYsZ|4 zQ6V4<%S(?N@)jO_p%p%GnU>Q2F9=`oC=4$7(5i$z2{PV8IBXE_^C~uWXOqDx$9MYD z%>o{7(LQ7)#^F`E{Em^I-(_ab2V1v-l#WA?9D-c&HSU>tKzKI$kAmy}1HM$Lt30-* zW7%aG^*I(KGm4ef&6_X7bH9Jw2GC5d@B~Ghj>+g_N2pdn^7q%gA|ElKr4219xg5Sm zy=Qj3OYW(!@5N&D;c#WeXip(F6bSg_wb#k-B;u>|qi4dS_>7%M9};&;vC_jh0nVjnF6_K(LjzTOmCczHiQ&EAE7TQBg>Up`uPiS> zCD~zZpuoe;T}3WdwLX9CpJqP|50pX3N~68-9?5r)2)4FZBCZ|n$*~p>irtVSBgGx~ zk`_P&7Y~eoB&mE)U3jFno+_G`YbJKNTZyPZHk)`tCC^DSGqcwcVq#i!ARDM*X8xdo zUFTnmi+PZW;_tt&C8`NEIq4SEH3)$-H8NT#AeTZQRFFtp_d03jqbPVBNA2{fT5;ap zj>TANI8c}v7lL7Zs9q4vFiGX<9{9F4{`yY>CiXRO31|lqK$OSk_^{@1z+T&I%xfmS z)t^rpH)kZnpQmMTq~q~(iH8SRPd@qScJxS$Gi3dUWO?uh#J9!-QI%7NvzL5i-(MrL zO`jOycHx^K7pIMV^Jcka%*p@p!ns(1tJi zku&$XgGYgM55H`eBd#CU)9Zso27N9d2_WqlQ<92~S959=Y*xvDehD05xfq140FWVX zE5ZeBSaS^9c~Gd{W?>JGam!EPJro*MOu)&bxZWD#5nqK+3p73w8(|>)hlP1c=IJYL z)Kh7$1|xD`fB%;gon>N|w`2t2arZ#jzh_1-B3;yk`S_U4{!&UJ)TNY;0TDl7MJm|* zn6q6l?XH&!B5@zCwB7T0+hxdc5_XvjJhd)k7z{q48dJ@}^01cdi@M@zwYv}m4a6fE zg5T~58dfZ$)as#%6D>bah~b>u9}Ywr|FDcPeoe|xlH}6=K7J<$h(kfvIgA(XBW5vS z#Kf#RK@8Pz5Ou56k4z)0H&MV>AW&y=Dg4ZbTvu)^N!@T zBqZl#slT-V{Un}47JEB88ra-A?DV~;4w{=K70jBO20bHMSmr@~wEhJVAbi1uGi+>6 z>fi1TQ6W0OvLN2+wMN5{pSbc30au8x+^l%npY!oP1lIqeK>Ts6EC&J-0h)S#0kbZ)`}1|BzM2OsbZ&Q8C*$F343=34=r^VInNq*6-`NJMqN+y z%=(`Bdi?NJ85zi;F+bZZL_G2r?)L9qf@78^D#2r+0 z#oHeP@qehI#4k|~W$PXO#VV)~&o4VWyBoQPYaAsV#E|ihgHJ+sNrv)E&@ImJ1>lS^ zK_nKPx-lLPb{YR($8r>AE{4-rFu=YRNH&R=hWwk7g5oqJZNT^$LTt34%n;=Dm3#<;lwA%# zBjcqTx6tcWR7j_n{BnO)?bdfI*=5ek${O>E9G*Ao^&2O=AthP$C@Y)F==dqU{DXOFl@3r_#9TTt+AOlpeS1mKi&Zm-!^}spS>u26 zDt~;tZa05FXm+OHUH!X2Q~(mO*%EG@iO35dKN2OHKPZ9xwfI261T57%FZsK>e}>g9 z@IZaK1{I@~*Kigi{#``MECRzop6cSLbsmzUb$bMsXS?83P`4YPQ$vXilVCBpY&bMn zlx=-?*(q=OLc$eJRsn&wZ{G}Yy#Yrn1=)A`vQ7_h&7Zee{b2IPzb~K=UfY|H1Wonc z_Dw0M#G)hp+w*e>4DE?adA2K|OhGf zm2H>xbak=2NBrFra)s?%wj`&dXln!V9jr@e0urQOf+-ZNjsR`S1JzQ0z$F1MUR+*a zKYaMkd`!+a6;8v4-E^Kk2U#QbuNy^tB%Pz*PFfnOE)*oocr49exY5T?1*sv8Zb$NS)aTqJ0Tt%6jUtkIn8DV#tYsz0|>jkc4QQ< z6bOsSMq!S_M{>+v_nQm(nz&2`vF-T9j>xc!j|IWP5 z&<#5x@DEbb(xNU2AQ^?96PF{0p&OIcE^GeunwlC6l+@er{r1-f<<=TMpT`LccS8Sj z(d>jWd(jljQ~#5G*4duA+cSIsM>}mUJtsxVzS2*zV}HQy=L|s5gA1;QTDHw)e)2Q0 z6ff4AUiWtgh#ft+@=}tM!>d2zZBk#oNN{!~_8=g|p4oMgf+OlTwg*(MwpQcGAJec) zI&rBUK9UHft-DFpBCd7Kk49scT`vGa{E>wocKG15cA;b5ofdgxG;Jc+?BJB@Ez7FF zn#LwcGSbiQgGP+&?T{0wUK&z6oerdN? zc*yhb{Mr7STm(vlY^J~b?rfndN#qJ}F_T6h{9cybjx z{(O81)fmy2@qH0Dzk`gyk(!54pd>Nw=7O3!(s+d z@~4+<7+^M<7KlRXYSlYonL8I#ja?kb^hi1;^Sk7ogOmxQBb;l{oKMt#1+WfT%$KIe zU_-OP)ex^PqVk!T%%HDGP{8B8yt>sCAN|k2QYA6T;btr@Eu~-%qvI`dSpc2{zuq?t z_GWy zl(qfid5_72#l?raZ5W)ie&jhjj;Psm}K`!)= z*!IIp#CMe};mOU_&BfrNwNzcwfhrimfx0vh6I$?K2Z_dem7~8hWs02Nij311kcwk82Fj(i&8C3HK0g>l ztS2;cxJJP-#3_Mf9l1iiHA6@>@_;!5G7>aN_I7lknFAeB$cUeyGLY7sm5B)i<}%D5 zkkVj{w=f-Grqqgdvuuur%SYDYfD=WzpwUyZ;(PFMe>ab-6TD$VYU-p7hdui3hz&e< zIZ6M}wVX`B=W(QdxgqVI3lA2{1i}7@g+faBwnhN5eiwa3EH5NsBZf}-M3e>BJep0d zizx={o3SKw2^RhDSsq(%o=4WHlFo_f?TK?gMXRWCgD z8CjD4RaIA#!ITi_);D)NSv@KFYflTbzp)P(@6g~@m6VW}{zDfo7W6+1Uh3`6OgWfG zzWI5HX}8DyOIVKW*s*x+vWmY{r?#C}yKe8<6kUg)a~7}HNO74m|D{m9s%>LDi6s_@ z&Feu14D$}$XMi{2NzJ0qaK4AH9xKY!kGom@nIdF!0gfGhqDmRR1If8U98_t5;q=rb zDw|hqn)OWc4x`_VOEbaGQI|@lv=^rxh30>$|VF^VpX)ZLe_&Y3_ zO}*{Vf=XrR4D{96>zu)Mhv`+N`1ED6JqHg;7{O$7!Yi3S$IIs zpi~P11n4knS=l2d2nxBlZ6B*zH{VIap%9Fv-z+RF-2AH8z6*wk?L&`>={jkJ=JgN! zZa$q$Xrw5KGDOj2x8CpilNb)C{uTxyZo;3_$J@&f1KX?TsZF!9Hb1);wY4LA|HN~y zz?*^?li{A8G$6NN(jL|lzg$vWaa&xAY%qJ_x)Fb;wc*R^P^WRbX6@)FYu2mgmbIIn z(+rI>9 zsiW{7$Di5l>z{o;v>#pAvbJrxNg=Hb&Wq1^vSdH-Ew!;xR8iq?1v2Yga=tNqw2;190)PmWN zn>$c(!|Ld_xir!m123*k7;!?Cwh{{=@mT!&OCuB7b_RNS2%YsHe%Cs9?je?>^dZq0 z7c~Drd+w{BmB*vcCKyfhk-2Jg=`oB#=_mL-WzMS}Wf;K={0E7>? zTKu3`2aFJFBHDJ4^Gx>Ns;&nLKv~|c(gfbw`}2xv9^LDMUZrIcnPxVS2F+d5FaM)< zyKGznk4Rj~h;3C!sBd+clpr3JU8#&%U>UAdGmlVVE%5MYRrfOEA%v-kiEYiY;vurR zq-0=e@mz?7!E1WIb!e=0rg5<3JHr7hZSnQZc>v3|kkdoecqy@-82+fM`)y%Y9Vsd4 zK|VVUW<5^hhW5@*EfW(7lgN>|L1HsPXlQJlTUZdec=4;q;cHJ`*KAxZ>m$(;LFlZE zjg8?S!Hm7q{)C!R4ME({oF@p9as1LDQPdXEC*q#^)wrndBe4JR0iA1VTUnktByWi?aTSI$w|3V{nAea{Laf9-e%2BKt<@ENSM5jm8^dE0R?L@Dl>te`wECXByLmooUkc#inV(W-9{r z)@$kIZF{#})e+%1rlE2_wiWc~7Kzfc$*{#fxN!01OVKvZ zV-HWhd})3})8}?ZWRzy-{ZEH?8tmQj@JlX-CD*ZURjrfeZ~FXVvOKiLUN0|&@GiZu zYa4Uu_y%IPN<#9Ny$PIy zs78ucZ(IboM&meD2?bz*$T|8ZP$f7)L=GWQDfw{gI+u9A&L9HwlCHHN4(emK9enNl zP!ZrqLO6rNh>?00_Dn}`5SJu_aBR%DLBxR6Z`I1f`|4el!>AH2=31!9W|LTl7#j=@ z#EmtL;h&!12Qr4Mv%&;fvOwQH)>TUhv;eHZ!wj(^7yz}~_V8;jF&Y7;vvTgC_;z!w zT7}qQ$Ixd-d8Nyq$2T$9jOENA5b}7#_zR0NTO>GsVyjFNtFHrifUT7r<4qY**4884 z%zpGe!;Q8}KJ>TX4uVUzZMKMO<95oOq;IBb)?#cXtJ@iWRH+>A1a{rJB$})cgiq?@ z8P$+pbzYkOkYaJpXT6k|x!Q+|59u#uOMf28QuzAD>aDc>V2UKC>f62(H+qpPam}Li zG)7;wbYtas-!o@kus7bm!W+)0)|adu=7 z;uI3@c)^+nrsyb-rIjXiH(uXupHz;7ly5Qc@VAYP@+TM3az^TJ5^wZkJDK zHBJfsX%0By^URb2I1foQ3wP#{0w|Spmwq$_aTx3lX=g9zl?BZY5gWsfxQujkL>rB^ zwR+zBbQlyCAE1FxBj#-><@{NlC0`{+ux`?%*pJ240OgVw0?EBBDiBLE-$?JbD+}UE zgv}ZuQe;_xGvm|&7qI47p7Xg|y!nJ~153iN3SAcA!M>zUt0=u-t#qC8YaEj}YAYSI z%N;Kto={2Am58U{_hjlAI@x&pDPMRLqk7+i&tfYR8@rfKOgvx+IWt+p9^t<0_iN!t z1|R-whz-}vUelB%YgDR<$TBCMFaIQ=OrnI<{9(z zZS8tV!H2tOh!=`iE> zHHWY;2aTu#J|yCEp2zO=+_!y-7bg+oj0NeLh=qCJE&4tiFDqUxCli5z4;T>DSB}n& zp7?wLYi*oH2P0zdhW2h>4fyJ-^F6uA&t16^KL|&~q~j;Rr%7Bp=ZoR!1)AUvtHPm1 zROn;x_z(s~F2xH^f!8LEuRLSfhoOZwv?#c}O@}9;5mcfm(ylcK0=97(z_u*5&>PW&%^p3ds~N#Rl8YOt= zTDN|mJZV6rSf`x*gJ6VQmM%ULlD9QZlS2y<`HHHm<@f1^W+{i^K=-Zl!fR$Ucw!4S z`TAjY`Hb?NJrEs)i5oJng=UL#w_U9#Te7g!SziZkMg!*8a+fcP6rP;A8n{?NAwpjU zCx{>535Y8qa6N!dmtd1Bbh&wSdZKDehT_#GZ1pgziQVPt`D5!ek~Od;mh9c94-~A| z&R7)6Zd059peOubgm^o>Y<%gv{*J9A_dq1h)p6DIcoZ(g7V%eH`e}OeBucE@*tXpgB&_o1>MTXKgA^Cq2Xo zoai^0(2T!rs}P*Odh6c&^kBXHnIBAI??{MQggLlO5=Ex2;D9HZ#GHSk00FWs z{t;qy*#_;KI3&;%q%bA;_z-drBi|qQO8hVc1ouq*YdPq2ZYyb?a4T8uwd8+ z88;VpF};R&H-3~{s)i_iaJ09mfZ?(rvwE#vYqYlhg(e7NOObLBH*tiMSriSsiiWlB z%-2Mnp8a*S?lipgINE^>k8q=Y_a!9{_47gQ_S;iKogOON^L%WI)zS? zxV{i(|0_<{$(WZ%0Xf1lk{>GiVCa^qcPIYl+1_W=k@8=k zGsa8$+L)Cvs!Q zF_8-O@u%?YpN?NK4*!v7yl`N*)eqBqjo2&{L_kSkkE$%}r3FkPI0W|#n5%jLp*U$a z>%l2W9Eh|0SY%JjiZ>Y=0`rjDJ_x%WZsJW)MyL#TLxKbgL>>fR2}-RoR;k@3=j z#n?RPJwDF;5C+Z6?UZ(x;?lvsa_IB5y(>21fso z`AY%2#Zz+ObPu==^L+pQMc-prr$SjpT zzq{-Cr*rlQ(G;>P!;$N;M(qvqhx;zuz-?xZHi@ZkZn{OV7nnm}FZCxJ?qR{~9&Sdp zrmlPLY!1NeA_2d{pJ2@38UqnlAnp%uCIAZ(ED&G&VA_G}Wrpfp40vDmJ#yupdww%A zo-WyL%5zwC4O=yXa6CgqG|_s)Pd68X9i$tjTA;-(byKDKz$$ zEArG7&|S6b8pH3&84-`7)N>%dO$LvsF4M08DR&wpr9z<9qSe)73QgHa&4$_l4Mpk^ z&o(l9Q*kN7U>)m|`U|FFNqNoZz)!9S<zz3m-_?XbZ@i+&DG{WE zEi2{OPV3}oK0>7VT$x$5xy^2{!!egxGB1*w4$fuC<};>gDc7eMaE%2ZQMkaqb7&tf zM%559dj!bK&R_{V;d^-mhQhf&(m>C?J)xU{VtV7mnL~2trapL?5XP?)cPg*h1*vY+ z_wO}U1w0eK0w)flXRSqUy;iiZrP>`~H$Mu$hel-O@FRq0RAEFR2UVu*L&T-biLp*7 zy1NCr$y94V9G`ntUp~_!6&QqP5VTEu?1SpWK=@GYIR=~MCVnM1dLKd)mo%#(?kkGi zoS7rlo#t?gmZ>-ekQMc4k2p-T{M;L%2K!kWS!RQG+2WCKQon_a-&k806BVKd~rv9ZLR(F0ZKq1-^F}%+}ojz`vEHot{{z$ zV!DwAKwM?&^wAksjOV0UrUZa@qxaU1$@uJ1!MU;93{|YvNJoKY8cpwXj13Ahgsp@2 z(G1%+X=!rllqKq%bYhN)zv+aK1G=*vw=oG(@&rbW=DE!Y8Jau&WWl@_zTE(dM1XIP zlx8=tr7$YfQQLnL>7`-V8u)yEdu*;e=axRI{o?DqlIDj&v%;#$V8&q(21rhv{jhnp zZ8=;9^ry}M#BMIRp4QObLD7OHrp-{2CcvL(=hijjsdH~2uQFI;ZxLrNt|DFvyv_9m z>3j^l`D~Vxg#@~DsiyXo$~WFz5fTdeR%4)K-eWHMfhQlzG6oVrH?CXC=S|2fWbrPU z$9+Xs_Hr~z--rjmJ(q5O@tL4X&YSO_W6C6Aya4Mj2ea#uY{Jp!`I0%R`)gvg@T$i} zH}!6s>4cqZ{S@{VNcaBGk!C#l$>QLATFdH+DwBSA?J_=w*iJ`K4z%NJm%wGY}=s;2?xz6}&&VM72u33u?qf~;FlOqaAI9)jaBM`8~ z`ovHi?tJ}gD6i8IT9Rp72-ySC#gG67UTLYPxXlq$fr~3ZXbjx0SbE?7xQ7kNB#O)H zhsgC53J&4?<_e-sr#ZqUHf076(n*P&ZU60YJwX|$E(4I3?s>f;y8|pa>lbcs^-bzf zx+SkO>#2giHQRFwV zP2nop^W!hR)2B?d<}vb${@@y&mw59?Rj%-vg^o3GMv5eUpF2004)st{INa=v$|_9& z;S8*`wvAptjG}cDNK6Aa24{p-5RUTeV7iionzX78{F{ZGd}xk}zzn-DLaDkoNsRT-nh1Wu**eNxLl0RjcADsKs<%5~qC$rQYQ4D})i<9XJb?sQNpY>Ebt z(Z5k8@&AsHkW6v$QdJk}4~wytVQu*3zPkstlrve;f_D+KX!T$x9gIReTteRR=@?P! z9K5dmw;ReB2hD3CuZfYed}5kvaFOE$&Z7mmAY0(f-_<7utfHA1#5kuJCt696s8erJ zKXIu&h>h=s`rYmNfL246h&!@#8RkIYyGR4I%8Qr@htQBgz-B`(%#~|=8x$^A`?J9L zxD?`SUuyS*qrc3)ryPqNHwG2$;GIL}YpZLm6xXtSD;}n|NblD|^&1Jrxdr@9u_VQ> z%NtxuQO^UF>3HbPJw)mQpo=qi-#7pmtvr1DeqoDzcaHE_m1n<0qQ4jA6_>?K))0#X z*4_6d)~<loqcE+8n81Ku8*{WJo`pdqZ~1TkY@qTICU z_|GOsKOugIhB@7?>-Fwcs9jUXdy4V)P>^Hr%=1IyyEF*x-J5}6^E3xz!Sd?j+!CXX zx@N?4r1k-O0cKTbRCcJO!0SDqX0Y*#(4b0Sn+N78;V{tXH-?&w!!Oj_^U;{|2sA_l zMFIr_93FUgR*AlYqbw15eq5}XD?-w@{b3}!z@Y@2H@xE@$H6-~v@eKuKO~bG{np)o zULu*?Iqkl={efy7Mk;GF@TBBe1KJi;?oCk1p_Bh&c}V>x4PThj4W=D)wyPYn524z} z@n|%-47eS+0bU9Mv2=*|#v?<<15G!#mFL2mmc;1UV?&F*5!}3c|K5wY=07n4+r#1H zMC|>L@H6y9JaF}pQ^to}W<7BDrs+whMC6Lk7Os8b09~dSW-pv~ zKxHFL6Pk1;!H(x;*N%RdoalQZH;bNud8r0A({MaU^Jn<&$7v-T2CQL>;|`ksp)f

N)?h1@6_ioTWTGI%)G5jVNe^}#Wde7 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

B~@Z-u%j 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 owobo$v+~#P*6iB*Lv^dR diff --git a/Documentation/Usage.md b/Documentation/Usage.md deleted file mode 100644 index fc6e788c1..000000000 --- a/Documentation/Usage.md +++ /dev/null @@ -1,186 +0,0 @@ -# Documentation - -### Overview - -* [Introduction](#introduction) -* [Flare Diagram](#flare-diagram) -* [In-App Purchases](#in-app-purchases) - - [Getting Products](#getting-products) - - [Purchasing Product](#purchasing-product) - - [Refreshing Receipt](#refreshing-receipt) - - [Finishing Transaction](#finishing-transaction) - - [Setup Observers](#setup-observers) -* [Errors](#handling-errors) - - [IAPError](#iaperror) - -## Introduction - -Flare provides an elegant interface for In-App Purchases, supporting non-consumable and consumable purchases as well as subscriptions. - -## Flare Diagram - -![Flare: Components](https://raw.githubusercontent.com/space-code/flare/dev/Documentation/Resources/flare.png) - -- `Flare` is a central component that serves as the client API for managing various aspects of in-app purchases and payments in your application. It is designed to simplify the integration of payment processing and in-app purchase functionality into your software. -- `IAPProvider` is a fundamental component of `Flare` that handles all in-app purchase operations. It offers an API to initiate, verify, and manage in-app purchases within your application. -- `IPaymentProvider` is a central component in `Flare` that orchestrates various payment-related operations within your application. It acts as the bridge between the payment gateway and your app's logic. -- `IProductProvider` is a component of `Flare` that helps managing the products or services available for purchase within your app. -- `IReceiptRefreshProvider` is responsible for refreshing and managing receipt associated with in-app purchases. -- `IAppStoreReceiptProvider` manages and provides access to the app's receipt, which contains a record of all in-app purchases made by the user. -- `IRefundProvider` is responsible for refunding purchases. This API is available starting from iOS 15. - -## In-App Purchases - -### Getting Products - -Before attempting to add a payment always check if the user can actually make payments. The `Flare` does it under the hood, if a user cannot make payments, you will get an `IAPError` with the value `paymentNotAllowed`. - -The `fetch` method sends a request to the App Store, which retrieves the products if they are available. The `productIDs` parameter takes the product ids, which should be given from the App Store. - -```swift -Flare.default.fetch(productIDs: Set(arrayLiteral: ["product_id"])) { result in - switch result { - case let .success(products): - debugPrint("Fetched products: \(products)") - case let .failure(error): - debugPrint("An error occurred while fetching products: \(error.localizedDescription)") - } -} -``` - -Additionally, there are versions of both `fetch` that provide an `async` method, allowing the use of `await`. - -```swift - do { - let products = try await Flare.default.fetch(productIDs: Set(arrayLiteral: ["product_id"])) - } catch { - debugPrint("An error occurred while fetching products: \(error.localizedDescription)") - } -``` - -### Purchasing Product - -The `purchase` method performs a purchase of the product. The method accepts an `productID` parameter which represents a product's id. - -```swift -Flare.default.purchase(productID: "product_id") { result in - switch result { - case let .success(transaction): - debugPrint("A transaction was received: \(transaction)") - case let .failure(error): - debugPrint("An error occurred while purchasing product: \(error.localizedDescription)") - } -} -``` - -You can also use the `async/await` implementation of the `purchase` method. - -```swift - do { - let products = try await Flare.default.purchase(productID: "product_id") - } catch { - debugPrint("An error occurred while purchasing product: \(error.localizedDescription)") - } -``` - -### Refreshing Receipt - -The `refresh` method refreshes the receipt, representing the user's transactions with your app. - -```swift -Flare.default.refresh { result in - switch result { - case let .success(receipt): - debugPrint("A receipt was received: \(receipt)") - case let .failure(error): - debugPrint("An error occurred while fetching receipt: \(error.localizedDescription)") - } -} -``` - -You can also use the `async/await` implementation of the `refresh` method. - -```swift - do { - let receipt = try await Flare.default.refresh() - } catch { - debugPrint("An error occurred while fetching receipt: \(error.localizedDescription)") - } -``` - -### Finishing Transaction - -The `finish` method removes a finished (i.e. failed or completed) transaction from the queue. - -```swift -Flare.default.finish(transaction: ) -``` - -### Setup Observers - -The transactions array will only be synchronized with the server while the queue has observers. These methods may require that the user authenticate. -It is important to set an observer on this queue as early as possible after your app launch. Observer is responsible for processing all events triggered by the queue. - -```swift -// Adds transaction observer to the payment queue and handles payment transactions. -Flare.default.addTransactionObserver { result in - switch result { - case let .success(transaction): - debugPrint("A transaction was received: \(transaction)") - case let .failure(error): - debugPrint("An error occurred while adding transaction observer: \(error.localizedDescription)") - } -} -``` - -```swift -// Removes transaction observer from the payment queue. -Flare.default.removeTransactionObserver() -``` - -### Refunding Purchase - -Starting with iOS 15, `Flare` now includes support for refunding purchases as part of `StoreKit 2`. Under the hood, 'Flare' obtains the active window scene and displays the sheets on it. You can read more about the refunding process in the official Apple documentation [here](https://developer.apple.com/documentation/storekit/transaction/3803220-beginrefundrequest/). - -```swift -do { - let status = try await Flare.default.beginRefundRequest(productID: "product_id") -} catch { - debugPrint("An error occurred while refunding purchase: \(error.localizedDescription)") -} -``` - -## Handling Errors - -### IAPError - -By default, all methods handlers in public interfaces produced the `IAPError` error type. The `IAPError` describes frequently used error types in the app. - -```swift -/// `IAPError` is the error type returned by Flare. -/// It encompasses a few different types of errors, each with their own associated reasons. -public enum IAPError: Swift.Error { - /// The empty array of products were fetched. - case emptyProducts - /// The attempt to fetch products with invalid identifiers. - case invalid(productIds: [String]) - /// The attempt to purchase a product when payments are not allowed. - case paymentNotAllowed - /// The payment was cancelled. - case paymentCancelled - /// The attempt to fetch a product that doesn't available. - case storeProductNotAvailable - /// The `SKPayment` returned unknown error. - case storeTrouble - /// The operation failed with an underlying error. - case with(error: Swift.Error) - /// The App Store receipt wasn't found. - case receiptNotFound - /// The refund error. - case refund(error: RefundError) - /// The unknown error occurred. - case unknown -} -``` - -If you need a `SKError`, you can simply look at the `plainError` property in the `IAPError`. diff --git a/Package.resolved b/Package.resolved index a03aac1cb..df6a8652a 100644 --- a/Package.resolved +++ b/Package.resolved @@ -8,6 +8,24 @@ "revision" : "f9611694f77f64e43d9467a16b2f5212cd04099b", "version" : "0.0.1" } + }, + { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-plugin", + "state" : { + "revision" : "26ac5758409154cc448d7ab82389c520fa8a8247", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-docc-symbolkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-symbolkit", + "state" : { + "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", + "version" : "1.0.0" + } } ], "version" : 2 diff --git a/Package.swift b/Package.swift index fea55f4e2..8953275aa 100644 --- a/Package.swift +++ b/Package.swift @@ -20,6 +20,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), ], targets: [ .target( diff --git a/Package@swift-5.7.swift b/Package@swift-5.7.swift index e645e1d10..4a19d4f04 100644 --- a/Package@swift-5.7.swift +++ b/Package@swift-5.7.swift @@ -17,6 +17,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), ], targets: [ .target( diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift index 256bf4f11..5c077121e 100644 --- a/Package@swift-5.8.swift +++ b/Package@swift-5.8.swift @@ -17,6 +17,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), ], targets: [ .target( diff --git a/README.md b/README.md index 18bfb339a..73cd4116a 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Flare is a framework written in Swift that makes it easy for you to work with in - [x] Complete Unit Test Coverage ## Documentation -Check out [flare documentation](https://github.com/space-code/flare/blob/main/Documentation/Usage.md). +Check out [flare documentation](https://space-code.github.io/flare/documentation/flare/). ## Requirements - iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 7.0+ / visionOS 1.0+ diff --git a/Sources/Flare/Flare.swift b/Sources/Flare/Classes/Flare.swift similarity index 98% rename from Sources/Flare/Flare.swift rename to Sources/Flare/Classes/Flare.swift index 159ac18fc..f27396447 100644 --- a/Sources/Flare/Flare.swift +++ b/Sources/Flare/Classes/Flare.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import StoreKit diff --git a/Sources/Flare/IFlare.swift b/Sources/Flare/Classes/IFlare.swift similarity index 99% rename from Sources/Flare/IFlare.swift rename to Sources/Flare/Classes/IFlare.swift index 69cc89aa3..6643cdd14 100644 --- a/Sources/Flare/IFlare.swift +++ b/Sources/Flare/Classes/IFlare.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation diff --git a/Sources/Flare/Classes/Models/ProductCategory.swift b/Sources/Flare/Classes/Models/ProductCategory.swift index b9522c35b..cf7dc9e8f 100644 --- a/Sources/Flare/Classes/Models/ProductCategory.swift +++ b/Sources/Flare/Classes/Models/ProductCategory.swift @@ -1,10 +1,11 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation +/// Enumeration representing different categories of products in an app. public enum ProductCategory: Int { /// A non-renewable or auto-renewable subscription. case subscription diff --git a/Sources/Flare/Classes/Models/SubscriptionPeriod.swift b/Sources/Flare/Classes/Models/SubscriptionPeriod.swift index 9dedab4cb..9bf8a2f52 100644 --- a/Sources/Flare/Classes/Models/SubscriptionPeriod.swift +++ b/Sources/Flare/Classes/Models/SubscriptionPeriod.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -8,7 +8,7 @@ import StoreKit // MARK: - SubscriptionPeriod -// A class representing a subscription period with a specific value and unit. +/// A class representing a subscription period with a specific value and unit. public final class SubscriptionPeriod: NSObject { // MARK: Types diff --git a/Sources/Flare/Classes/Models/VerificationError.swift b/Sources/Flare/Classes/Models/VerificationError.swift index 9ca93b178..8f098d05e 100644 --- a/Sources/Flare/Classes/Models/VerificationError.swift +++ b/Sources/Flare/Classes/Models/VerificationError.swift @@ -1,10 +1,12 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation -public enum VerificationError: Swift.Error { +/// Enumeration representing errors that can occur during verification. +public enum VerificationError: Error { + // Case for unverified product with associated productID and error details. case unverified(productID: String, error: Error) } diff --git a/Sources/Flare/Flare.docc/Articles/perform-purchase.md b/Sources/Flare/Flare.docc/Articles/perform-purchase.md new file mode 100644 index 000000000..55d439082 --- /dev/null +++ b/Sources/Flare/Flare.docc/Articles/perform-purchase.md @@ -0,0 +1,94 @@ +# Perform Purchase + +Learn how to perform a purchase. + +## Setup Observers + +> tip: This step isn't required if the app uses system higher than iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0. + +The transactions array will only be synchronized with the server while the queue has observers. These methods may require that the user authenticate. It is important to set an observer on this queue as early as possible after your app launch. Observer is responsible for processing all events triggered by the queue. + +```swift +// Adds transaction observer to the payment queue and handles payment transactions. +Flare.default.addTransactionObserver { result in + switch result { + case let .success(transaction): + debugPrint("A transaction was received: \(transaction)") + case let .failure(error): + debugPrint("An error occurred while adding transaction observer: \(error.localizedDescription)") + } +} +``` + +```swift +// Removes transaction observer from the payment queue. +Flare.default.removeTransactionObserver() +``` + +## Getting Products + +The fetch method sends a request to the App Store, which retrieves the products if they are available. The productIDs parameter takes the product ids, which should be given from the App Store. + +> important: Before attempting to add a payment always check if the user can actually make payments. The Flare does it under the hood, if a user cannot make payments, you will get an ``IAPError`` with the value ``IAPError/paymentNotAllowed``. + +```swift +Flare.default.fetch(productIDs: ["product_id"]) { result in + switch result { + case let .success(products): + debugPrint("Fetched products: \(products)") + case let .failure(error): + debugPrint("An error occurred while fetching products: \(error.localizedDescription)") + } +} +``` + +Additionally, there are versions of both fetch that provide an `async` method, allowing the use of await. + +```swift +do { + let products = try await Flare.default.fetch(productIDs: Set(arrayLiteral: ["product_id"])) +} catch { + debugPrint("An error occurred while fetching products: \(error.localizedDescription)") +} +``` + +## Purchasing Product + +Flare provides a few methods to perform a purchase: + +- ``IFlare/purchase(product:completion:)`` +- ``IFlare/purchase(product:)`` +- ``IFlare/purchase(product:options:)`` +- ``IFlare/purchase(product:options:completion:)`` + +The method accepts a product parameter which represents a product: + +```swift +Flare.default.purchase(product: product) { result in + switch result { + case let .success(transaction): + debugPrint("A transaction was received: \(transaction)") + case let .failure(error): + debugPrint("An error occurred while purchasing product: \(error.localizedDescription)") + } +} +``` + +If your app has a deployment target higher than iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, you can pass a set of [`options`](https://developer.apple.com/documentation/storekit/product/purchaseoption) along with a purchase request. + +```swift +let transaction = try await Flare.default.purchase(product: product, options: [.appAccountToken(UUID())]) +``` + +## Finishing Transaction + +Finishing a transaction tells StoreKit that your app completed its workflow to make a purchase complete. Unfinished transactions remain in the queue until they’re finished, so be sure to add the transaction queue observer every time your app launches, to enable your app to finish the transactions. Your app needs to finish each transaction, whether it succeeds or fails. + +To finish the transaction, call the ``IFlare/finish(transaction:completion:)`` method. + +```swift +Flare.default.finish(transaction: transaction, completion: nil) +``` + +> important: Don’t call the ``IFlare/finish(transaction:completion:)`` method before the transaction is actually complete and attempt to use some other mechanism in your app to track the transaction as unfinished. StoreKit doesn’t function that way, and doing that prevents your app from downloading Apple-hosted content and can lead to other issues. + diff --git a/Sources/Flare/Flare.docc/Articles/refund-purchase.md b/Sources/Flare/Flare.docc/Articles/refund-purchase.md new file mode 100644 index 000000000..f4f551738 --- /dev/null +++ b/Sources/Flare/Flare.docc/Articles/refund-purchase.md @@ -0,0 +1,17 @@ +# Refund Purchase + +Learn how to process a refund through an iOS app. + +## Refund a Purchase + +Starting with iOS 15, Flare now includes support for refunding purchases as part of StoreKit 2. Under the hood, `Flare` obtains the active window scene and displays the sheets on it. You can read more about the refunding process in the official [Apple documentation](https://developer.apple.com/documentation/storekit/transaction/3803220-beginrefundrequest/). + +Flare suggest to use ``IFlare/beginRefundRequest(productID:)`` for refunding purchase. + +```swift +let status = try await Flare.default.beginRefundRequest(productID: "product_id") +``` + +> important: If an issue occurs during the refund process, this method throws an ``IAPError/refund(error:)`` error. + +Call this function from account settings or a help menu to enable customers to request a refund for an in-app purchase within your app. When you call this function, the system displays a refund sheet with the customer’s purchase details and list of reason codes for the customer to choose from. diff --git a/Sources/Flare/Flare.docc/Articles/restore-purchase.md b/Sources/Flare/Flare.docc/Articles/restore-purchase.md new file mode 100644 index 000000000..18dae9f76 --- /dev/null +++ b/Sources/Flare/Flare.docc/Articles/restore-purchase.md @@ -0,0 +1,36 @@ +# Restore Purchase + +Learn how to restore a purchase. + +## Overview + +Users sometimes need to restore purchased content, such as when they upgrade to a new phone. Include some mechanism in your app, such as a Restore Purchases button, to let them restore their purchases. + +## Refresh the app receipt + +A request to the App Store to get the app receipt, which represents the user’s transactions with your app. + +> note: The receipt isn’t necessary if you use StoreKit2. Only use the receipt if your app supports deployment target is lower than iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0. + +Use this API to request a new app receipt from the App Store if the receipt is invalid or missing from its expected location. To request the receipt using the ``IFlare/receipt(completion:)``. + +> important: The receipt refresh request displays a system prompt that asks users to authenticate with their App Store credentials. For a better user experience, initiate the request after an explicit user action, like tapping or clicking a button. + +```swift +Flare.default.receipt { result in + switch result { + case let .success(receipt): + // Handle a receipt + case let .failure(error): + // Handle an error + } +} +``` + +> important: If a receipt isn't found, Flare throws an ``IAPError/receiptNotFound`` error. + +There is an ``IFlare/receipt()`` method for obtaining a receipt using async/await. + +```swift +let receipt = try await Flare.default.receipt() +``` diff --git a/Sources/Flare/Flare.docc/Flare.md b/Sources/Flare/Flare.docc/Flare.md new file mode 100644 index 000000000..0682d736d --- /dev/null +++ b/Sources/Flare/Flare.docc/Flare.md @@ -0,0 +1,66 @@ +# ``Flare`` + +Flare provides an elegant interface for In-App Purchases, supporting non-consumable and consumable purchases as well as subscriptions. + +## Overview + +Flare provides a clear and convenient API for making in-app purchases. + +```swift +import Flare + +/// Fetch a product with the given id +guard let product = try await Flare.default.products(productIDs: ["product_identifier"]) else { return } +/// Purchase a product +let transaction = try await Flare.default.purchase(product: product) +/// Finish a transaction +Flare.default.finish(transaction: transaction, completion: nil) +``` + +Flare supports both StoreKit and StoreKit2; it decides which one to use under the hood based on the operating system version. Flare provides two ways to work with in-app purchases (IAP): it supports the traditional closure-based syntax and the modern async/await approach. + +```swift +import Flare + +/// Fetch a product with the given id +Flare.default.products(productIDs: ["product_identifier"]) { result in + switch result { + case let .success(products): + // Purchase a product + case let .failure(error): + // Handler an error + } +} +``` + +## Minimum Requirements + +| Flare | Date | Swift | Xcode | Platforms | +|-------|------------|-------|---------|-------------------------------------------------------------| +| 3.0 | unreleased | 5.7 | 14.1 | iOS 13.0, watchOS 6.0, macOS 10.15, tvOS 13.0, visionOS 1.0 | +| 2.0 | 14/09/2023 | 5.7 | 14.1 | iOS 13.0, watchOS 6.0, macOS 10.15, tvOS 13.0, visionOS 1.0 | +| 1.0 | 21/01/2023 | 5.5 | 13.4.1 | iOS 13.0, watchOS 6.0, macOS 10.15, tvOS 13.0 | + +## License + +flare is available under the MIT license. See the LICENSE file for more info. + +## Topics + +### Essentials + +- ``IFlare`` +- ``IIAPProvider`` + +### Misc + +- ``IAPError`` +- ``ProductType`` +- ``StoreProduct`` +- ``StoreTransaction`` + +### Articles + +- +- +- From 4f429a7522342a3585da98d4370d3f2f0ef88f66 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 5 Jan 2024 13:29:55 +0100 Subject: [PATCH 34/44] Implement typo checking (#12) * Implement typo checking * Update `CHANGELOG.md` * Fix typos --- .github/workflows/ci.yml | 14 ++++++++++++++ CHANGELOG.md | 5 ++++- README.md | 8 ++++---- .../Internal/Protocols/IStoreTransaction.swift | 4 ++-- .../Models/Internal/SK2StoreTransaction.swift | 6 +++--- Sources/Flare/Classes/Models/StoreProduct.swift | 4 ++-- .../Flare/Classes/Models/StoreTransaction.swift | 4 ++-- .../PurchaseProvider/PurchaseProvider.swift | 4 ++-- .../Providers/RefundRequestProviderTests.swift | 4 ++-- 9 files changed, 35 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca56e598a..33acbd8d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -206,6 +206,20 @@ jobs: name: MergedResult path: test_output/final + discover-typos: + name: Discover Typos + runs-on: macOS-12 + env: + DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer + steps: + - uses: actions/checkout@v2 + - name: Discover typos + run: | + export PATH="$PATH:/Library/Frameworks/Python.framework/Versions/3.11/bin" + python3 -m pip install --upgrade pip + python3 -m pip install codespell + codespell --ignore-words-list="hart,inout,msdos,sur" --skip="./.build/*,./.git/*" + # Beta: # name: ${{ matrix.name }} # runs-on: firebreak diff --git a/CHANGELOG.md b/CHANGELOG.md index 8deb14f03..ba76780bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Implement typo checking + - Added in Pull Request [#12](https://github.com/space-code/flare/pull/12). + - Build a documentation using `Docc` - Added in Pull Request [#11](https://github.com/space-code/flare/pull/11). @@ -11,7 +14,7 @@ All notable changes to this project will be documented in this file. - Added in Pull Request [#10](https://github.com/space-code/flare/pull/10). - Add badges for `Swift Version Compatibility` and `Platform Compatibility` - - Added in Pull Request [#7](https://github.com/space-code/flare/pull/8). + - Added in Pull Request [#8](https://github.com/space-code/flare/pull/8). - Integrate `danger` - Added in Pull Request [#7](https://github.com/space-code/flare/pull/7). diff --git a/README.md b/README.md index 73cd4116a..136ed554b 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@

flare

-Liscence -Swift Compability -Platform Compability +Licence +Swift Compatibility +Platform Compatibility CI CodeCov @@ -15,7 +15,7 @@ Flare is a framework written in Swift that makes it easy for you to work with in-app purchases and subscriptions. - [Features](#features) -- [Documentaton](#documentation) +- [Documentation](#documentation) - [Requirements](#requirements) - [Installation](#installation) - [Communication](#communication) diff --git a/Sources/Flare/Classes/Models/Internal/Protocols/IStoreTransaction.swift b/Sources/Flare/Classes/Models/Internal/Protocols/IStoreTransaction.swift index db8a4cce7..4a346da3d 100644 --- a/Sources/Flare/Classes/Models/Internal/Protocols/IStoreTransaction.swift +++ b/Sources/Flare/Classes/Models/Internal/Protocols/IStoreTransaction.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -20,7 +20,7 @@ protocol IStoreTransaction { /// The quantity of the product involved in the transaction. var quantity: Int { get } - /// The raw JWS repesentation of the transaction. + /// The raw JWS representation of the transaction. /// /// - Note: This is only available for StoreKit 2 transactions. var jwsRepresentation: String? { get } diff --git a/Sources/Flare/Classes/Models/Internal/SK2StoreTransaction.swift b/Sources/Flare/Classes/Models/Internal/SK2StoreTransaction.swift index 5ccde0c40..75871ca13 100644 --- a/Sources/Flare/Classes/Models/Internal/SK2StoreTransaction.swift +++ b/Sources/Flare/Classes/Models/Internal/SK2StoreTransaction.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -15,7 +15,7 @@ struct SK2StoreTransaction { /// The StoreKit transaction. let transaction: StoreKit.Transaction - /// The raw JWS repesentation of the transaction. + /// The raw JWS representation of the transaction. private let _jwsRepresentation: String? // MARK: Initialization @@ -24,7 +24,7 @@ struct SK2StoreTransaction { /// /// - Parameters: /// - transaction: The StoreKit transaction. - /// - jwsRepresentation: The raw JWS repesentation of the transaction. + /// - jwsRepresentation: The raw JWS representation of the transaction. init(transaction: StoreKit.Transaction, jwsRepresentation: String) { self.transaction = transaction _jwsRepresentation = jwsRepresentation diff --git a/Sources/Flare/Classes/Models/StoreProduct.swift b/Sources/Flare/Classes/Models/StoreProduct.swift index d240cbcde..06255b5a2 100644 --- a/Sources/Flare/Classes/Models/StoreProduct.swift +++ b/Sources/Flare/Classes/Models/StoreProduct.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -28,7 +28,7 @@ public final class StoreProduct: NSObject { } } -// MARK: - Convinience Initializators +// MARK: - Convenience Initializators public extension StoreProduct { /// Creates a new `StoreProduct` instance. diff --git a/Sources/Flare/Classes/Models/StoreTransaction.swift b/Sources/Flare/Classes/Models/StoreTransaction.swift index fa16b2478..0a777b45c 100644 --- a/Sources/Flare/Classes/Models/StoreTransaction.swift +++ b/Sources/Flare/Classes/Models/StoreTransaction.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -25,7 +25,7 @@ public final class StoreTransaction { } } -// MARK: - Convinience Initializators +// MARK: - Convenience Initializators extension StoreTransaction { /// Creates a new `StoreTransaction` instance. diff --git a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift index 50cf3a690..ce26e3de3 100644 --- a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift +++ b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -18,7 +18,7 @@ final class PurchaseProvider { // MARK: Initialization - /// Creates a new `PurchaseProvider` isntance. + /// Creates a new `PurchaseProvider` instance. /// /// - Parameters: /// - paymentProvider: The provider is responsible for purchasing products. diff --git a/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift index b35747c15..ef6acb2e8 100644 --- a/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/RefundRequestProviderTests.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // @testable import Flare @@ -12,7 +12,7 @@ import XCTest @available(iOS 15.0, *) final class RefundRequestProviderTests: XCTestCase { - // MARK: Proeprties + // MARK: Properties private var sut: RefundRequestProvider! From 872e8e3d8c3bb33ede8dc750f83f8e6cc5b87491 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 12 Jan 2024 17:57:16 +0100 Subject: [PATCH 35/44] Add files to comply with community standards (#13) * Add files to comply with community standards - Add `CODE_OF_CONDUCT.md` - Add `CONTRIBUTING.md` - Add `SECURITY.md` - Update templates * Update `CHANGELOG.md` --- .../{bug_template.yml => bug_template.md} | 0 ...ature_template.yml => feature_template.md} | 0 CHANGELOG.md | 3 + CODE_OF_CONDUCT.md | 74 +++++++++++++++++++ CONTRIBUTING.md | 61 +++++++++++++++ SECURITY.md | 7 ++ 6 files changed, 145 insertions(+) rename .github/PULL_REQUEST_TEMPLATE/{bug_template.yml => bug_template.md} (100%) rename .github/PULL_REQUEST_TEMPLATE/{feature_template.yml => feature_template.md} (100%) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md diff --git a/.github/PULL_REQUEST_TEMPLATE/bug_template.yml b/.github/PULL_REQUEST_TEMPLATE/bug_template.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE/bug_template.yml rename to .github/PULL_REQUEST_TEMPLATE/bug_template.md diff --git a/.github/PULL_REQUEST_TEMPLATE/feature_template.yml b/.github/PULL_REQUEST_TEMPLATE/feature_template.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE/feature_template.yml rename to .github/PULL_REQUEST_TEMPLATE/feature_template.md diff --git a/CHANGELOG.md b/CHANGELOG.md index ba76780bf..e0f6bdac3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Add files to comply with community standards + - Added in Pull Request [#13](https://github.com/space-code/flare/pull/13). + - Implement typo checking - Added in Pull Request [#12](https://github.com/space-code/flare/pull/12). diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..56c1661b0 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting one of the project maintainers https://github.com/orgs/space-code/people. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..84871fb4a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,61 @@ +# Contributing Guidelines + +This document contains information and guidelines about contributing to this project. +Please read it before you start participating. + +**Topics** + +* [Reporting Issues](#reporting-issues) +* [Submitting Pull Requests](#submitting-pull-requests) +* [Developers Certificate of Origin](#developers-certificate-of-origin) +* [Code of Conduct](#code-of-conduct) + +## Reporting Issues + +A great way to contribute to the project is to send a detailed issue when you encounter a problem. We always appreciate a well-written, thorough bug report. + +Check that the project issues database doesn't already include that problem or suggestion before submitting an issue. If you find a match, feel free to vote for the issue by adding a reaction. Doing this helps prioritize the most common problems and requests. + +When reporting issues, please fill out our issue template. The information the template asks for will help us review and fix your issue faster. + +## Submitting Pull Requests + +You can contribute by fixing bugs or adding new features. For larger code changes, we recommend first discussing your ideas on our [GitHub Discussions](https://github.com/space-code/flare/discussions). When submitting a pull request, please add relevant tests and ensure your changes don't break any existing tests. + +## Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +- (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +- (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +- (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +- (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +## Code of Conduct + +The Code of Conduct governs how we behave in public or in private +whenever the project will be judged by our actions. +We expect it to be honored by everyone who contributes to this project. + +See [CODE_OF_CONDUCT.md](https://github.com/space-code/flare/blob/master/CODE_OF_CONDUCT.md) for details. + +--- + +*Some of the ideas and wording for the statements above were based on work by the [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) and [Linux](https://elinux.org/Developer_Certificate_Of_Origin) communities. We commend them for their efforts to facilitate collaboration in their projects.* \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..20dffca0b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Reporting Security Vulnerabilities + +This software is built with security and data privacy in mind to ensure your data is safe. We are grateful for security researchers and users reporting a vulnerability to us, first. To ensure that your request is handled in a timely manner and non-disclosure of vulnerabilities can be assured, please follow the below guideline. + +**Please do not report security vulnerabilities directly on GitHub. GitHub Issues can be publicly seen and therefore would result in a direct disclosure.** + +* Please address questions about data privacy, security concepts, and other media requests to the nv3212@gmail.com mailbox. \ No newline at end of file From ae6d0965be4df3be9f946966b8ae2e41dfc088f6 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sat, 13 Jan 2024 18:01:51 +0100 Subject: [PATCH 36/44] Fix typos (#14) * Update `CONTRIBUTING.md` * Update `CHANGELOG.md` --- CHANGELOG.md | 4 ++++ CONTRIBUTING.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0f6bdac3..bfbf645d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,10 @@ All notable changes to this project will be documented in this file. - Added `visionOS` to list of supported platforms - Added in Pull Request [#5](https://github.com/space-code/flare/pull/5). +## Fixed +- Fix typos in `CONTRIBUTING.md` + - Added in Pull Request[#14](https://github.com/space-code/flare/pull/14). + #### 2.x Releases - `2.0.x` Releases - [2.0.0](#200) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 84871fb4a..293fcb589 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -58,4 +58,4 @@ See [CODE_OF_CONDUCT.md](https://github.com/space-code/flare/blob/master/CODE_OF --- -*Some of the ideas and wording for the statements above were based on work by the [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) and [Linux](https://elinux.org/Developer_Certificate_Of_Origin) communities. We commend them for their efforts to facilitate collaboration in their projects.* \ No newline at end of file +*Some of the ideas and wording for the statements above were based on work by the [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) and [Linux](https://elinux.org/Developer_Certificate_Of_Origin) communities. \ No newline at end of file From 7b4db09dee7e55777faa931ddd8371325a680b5d Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sat, 13 Jan 2024 20:22:52 +0100 Subject: [PATCH 37/44] Add additional badges to `README.md` (#15) * Add additional badges to `README.md` * Update `CHANGELOG.md` --- CHANGELOG.md | 3 +++ README.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfbf645d7..93c4c4762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Add additional badges to `README.md` + - Added in Pull Request [#15](https://github.com/space-code/flare/pull/15). + - Add files to comply with community standards - Added in Pull Request [#13](https://github.com/space-code/flare/pull/13). diff --git a/README.md b/README.md index 136ed554b..c1038168d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ CI CodeCov +GitHub release; latest by date +GitHub commit activity

## Description From 65f1cd1711ad26d1dc70456149ed5a9277fbf2a2 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Thu, 18 Jan 2024 17:55:25 +0100 Subject: [PATCH 38/44] [WIP] Implement Promotional Offers (#16) * Implement discount models * Implement `PromotionalOffer` model * Update tests * Implement eligibility checking * Add comments to the `SubscriptionEligibility` enumeration * Implement `presentOfferCodeRedeemSheet(in:)` & `presentCodeRedemptionSheet()` methods * Implement passing a configuration object - Pass an `applicationUsername` property through the `Configuration` object - Refactroing the package's dependencies * Write code comments & fix typos * Rename the `default` property to `shared` * Update `CHANGELOG.md` * Implement unit tests * Implement tests * Increase expectation duration for a test * Update the documentation * Fix flacky tests * Add an integration test * Add code comments --- CHANGELOG.md | 5 +- README.md | 5 +- .../Flare/Classes/DI/FlareDependencies.swift | 70 +++++ .../Flare/Classes/DI/IFlareDependencies.swift | 14 + Sources/Flare/Classes/Flare.swift | 78 ++++-- .../UserDefaults/IUserDefaults.swift | 24 ++ .../UserDefaults/UserDefaults.swift | 19 ++ .../Helpers/PaymentQueue/PaymentQueue.swift | 6 + Sources/Flare/Classes/IFlare.swift | 125 ++++++++- .../Flare/Classes/Models/Configuration.swift | 27 ++ .../Flare/Classes/Models/DiscountType.swift | 53 ++++ Sources/Flare/Classes/Models/IAPError.swift | 10 +- .../Models/Internal/ProductsRequest.swift | 39 +++ .../Internal/Protocols/ISKProduct.swift | 11 +- .../Internal/Protocols/ISKRequest.swift | 12 + .../Protocols/IStoreProductDiscount.swift | 32 +++ .../Models/Internal/SK1StoreProduct.swift | 20 +- .../Internal/SK1StoreProductDiscount.swift | 60 +++++ .../Models/Internal/SK2StoreProduct.swift | 19 +- .../Internal/SK2StoreProductDiscount.swift | 62 +++++ .../Flare/Classes/Models/PaymentMode.swift | 59 +++++ .../Classes/Models/PromotionalOffer.swift | 116 +++++++++ .../Flare/Classes/Models/StoreProduct.swift | 30 ++- .../Classes/Models/StoreProductDiscount.swift | 82 ++++++ .../Models/SubscriptionEligibility.swift | 18 ++ .../Classes/Models/SubscriptionPeriod.swift | 28 +- .../CacheProvider/CacheProvider.swift | 37 +++ .../CacheProvider/ICacheProvider.swift | 23 ++ .../ConfigurationProvider.swift | 44 ++++ .../IConfigurationProvider.swift | 17 ++ .../EligibilityProvider.swift | 33 +++ .../IEligibilityProvider.swift | 17 ++ .../Providers/IAPProvider/IAPProvider.swift | 73 ++++-- .../Providers/IAPProvider/IIAPProvider.swift | 127 ++++++++- .../PaymentProvider/PaymentProvider.swift | 6 +- .../ProductProvider/ProductProvider.swift | 19 +- .../PurchaseProvider/IPurchaseProvider.swift | 40 ++- .../PurchaseProvider/PurchaseProvider.swift | 51 +++- .../ReceiptRefreshProvider.swift | 6 +- .../IRedeemCodeProvider.swift | 24 ++ .../RedeemCodeProvider.swift | 43 ++++ .../Flare.docc/Articles/perform-purchase.md | 14 +- .../Flare.docc/Articles/promotional-offers.md | 86 +++++++ .../Flare.docc/Articles/refund-purchase.md | 2 +- .../Flare.docc/Articles/restore-purchase.md | 4 +- Sources/Flare/Flare.docc/Flare.md | 9 +- Tests/FlareTests/UnitTests/FlareTests.swift | 39 ++- .../Models/PromotionalOfferTests.swift | 56 ++++ .../ConfigurationProviderTests.swift | 67 +++++ .../Providers/IAPProviderTests.swift | 6 +- .../Providers/PurchaseProviderTests.swift | 5 +- .../TestHelpers/Extensions/String+Data.swift | 12 + .../Fakes/Configuration+Fake.swift | 13 + .../TestHelpers/Mocks/CacheProviderMock.swift | 35 +++ .../Mocks/CacheProviderTests.swift | 61 +++++ .../Mocks/ConfigurationProviderMock.swift | 31 +++ .../Mocks/EligibilityProviderMock.swift | 23 ++ .../Mocks/FlareDependenciesMock.swift | 29 +++ .../TestHelpers/Mocks/IAPProviderMock.swift | 96 ++++++- .../Mocks/PurchaseProviderMock.swift | 21 +- .../Mocks/RedeemCodeProvider.swift | 17 ++ .../TestHelpers/Mocks/UserDefaultsMock.swift | 35 +++ Tests/IntegrationTests/Flare.storekit | 243 +++++++++++++++--- .../Helpers/Extensions/AsyncSequence+.swift | 16 ++ .../Providers/ProductProviderHelper.swift | 56 ++++ .../StoreSessionTestCase.swift | 58 ++++- .../Tests/EligibilityProviderTests.swift | 50 ++++ Tests/IntegrationTests/Tests/FlareTests.swift | 50 +++- .../Tests/IAPProviderTests.swift | 151 ----------- .../Tests/ProductProviderHelper.swift | 44 ---- .../Tests/ProductProviderTests.swift | 59 ----- .../Tests/PurchaseProviderTests.swift | 90 ------- .../Tests/StoreProductTests.swift | 173 +++++++++++++ 73 files changed, 2730 insertions(+), 505 deletions(-) create mode 100644 Sources/Flare/Classes/DI/FlareDependencies.swift create mode 100644 Sources/Flare/Classes/DI/IFlareDependencies.swift create mode 100644 Sources/Flare/Classes/Foundation/UserDefaults/IUserDefaults.swift create mode 100644 Sources/Flare/Classes/Foundation/UserDefaults/UserDefaults.swift create mode 100644 Sources/Flare/Classes/Models/Configuration.swift create mode 100644 Sources/Flare/Classes/Models/DiscountType.swift create mode 100644 Sources/Flare/Classes/Models/Internal/ProductsRequest.swift create mode 100644 Sources/Flare/Classes/Models/Internal/Protocols/ISKRequest.swift create mode 100644 Sources/Flare/Classes/Models/Internal/Protocols/IStoreProductDiscount.swift create mode 100644 Sources/Flare/Classes/Models/Internal/SK1StoreProductDiscount.swift create mode 100644 Sources/Flare/Classes/Models/Internal/SK2StoreProductDiscount.swift create mode 100644 Sources/Flare/Classes/Models/PaymentMode.swift create mode 100644 Sources/Flare/Classes/Models/PromotionalOffer.swift create mode 100644 Sources/Flare/Classes/Models/StoreProductDiscount.swift create mode 100644 Sources/Flare/Classes/Models/SubscriptionEligibility.swift create mode 100644 Sources/Flare/Classes/Providers/CacheProvider/CacheProvider.swift create mode 100644 Sources/Flare/Classes/Providers/CacheProvider/ICacheProvider.swift create mode 100644 Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift create mode 100644 Sources/Flare/Classes/Providers/ConfigurationProvider/IConfigurationProvider.swift create mode 100644 Sources/Flare/Classes/Providers/EligibilityProvider/EligibilityProvider.swift create mode 100644 Sources/Flare/Classes/Providers/EligibilityProvider/IEligibilityProvider.swift create mode 100644 Sources/Flare/Classes/Providers/RedeemCodeProvider/IRedeemCodeProvider.swift create mode 100644 Sources/Flare/Classes/Providers/RedeemCodeProvider/RedeemCodeProvider.swift create mode 100644 Sources/Flare/Flare.docc/Articles/promotional-offers.md create mode 100644 Tests/FlareTests/UnitTests/Models/PromotionalOfferTests.swift create mode 100644 Tests/FlareTests/UnitTests/Providers/ConfigurationProviderTests.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Extensions/String+Data.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Fakes/Configuration+Fake.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/CacheProviderMock.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/CacheProviderTests.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/ConfigurationProviderMock.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/EligibilityProviderMock.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/FlareDependenciesMock.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/RedeemCodeProvider.swift create mode 100644 Tests/FlareTests/UnitTests/TestHelpers/Mocks/UserDefaultsMock.swift create mode 100644 Tests/IntegrationTests/Helpers/Extensions/AsyncSequence+.swift create mode 100644 Tests/IntegrationTests/Helpers/Providers/ProductProviderHelper.swift create mode 100644 Tests/IntegrationTests/Tests/EligibilityProviderTests.swift delete mode 100644 Tests/IntegrationTests/Tests/IAPProviderTests.swift delete mode 100644 Tests/IntegrationTests/Tests/ProductProviderHelper.swift delete mode 100644 Tests/IntegrationTests/Tests/ProductProviderTests.swift delete mode 100644 Tests/IntegrationTests/Tests/PurchaseProviderTests.swift create mode 100644 Tests/IntegrationTests/Tests/StoreProductTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 93c4c4762..63760b0ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Implement Support for Promotional Offers + - Added in Pull Request [#16](https://github.com/space-code/flare/pull/16). + - Add additional badges to `README.md` - Added in Pull Request [#15](https://github.com/space-code/flare/pull/15). @@ -55,4 +58,4 @@ Released on 2023-01-20. #### Added - Initial release of Flare. - - Added by [Nikita Vasilev](https://github.com/nik3212). \ No newline at end of file + - Added by [Nikita Vasilev](https://github.com/nik3212). diff --git a/README.md b/README.md index c1038168d..a72bf09c7 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,9 @@ Flare is a framework written in Swift that makes it easy for you to work with in ## Features - [x] Support Consumable & Non-Consumable Purchases - [x] Support Subscription Purchase -- [x] Refresh Receipt -- [x] Complete Unit Test Coverage +- [x] Support Promotional & Introductory Offers +- [x] iOS, tvOS, watchOS, macOS, and visionOS compatible +- [x] Complete Unit & Integration Test Coverage ## Documentation Check out [flare documentation](https://space-code.github.io/flare/documentation/flare/). diff --git a/Sources/Flare/Classes/DI/FlareDependencies.swift b/Sources/Flare/Classes/DI/FlareDependencies.swift new file mode 100644 index 000000000..5f50073af --- /dev/null +++ b/Sources/Flare/Classes/DI/FlareDependencies.swift @@ -0,0 +1,70 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Concurrency +import Foundation +import StoreKit + +/// The package's dependencies. +final class FlareDependencies: IFlareDependencies { + // MARK: Internal + + lazy var iapProvider: IIAPProvider = IAPProvider( + paymentQueue: SKPaymentQueue.default(), + productProvider: productProvider, + purchaseProvider: purchaseProvider, + receiptRefreshProvider: receiptRefreshProvider, + refundProvider: refundProvider, + eligibilityProvider: eligibilityProvider, + redeemCodeProvider: redeemCodeProvider + ) + + lazy var configurationProvider: IConfigurationProvider = ConfigurationProvider() + + // MARK: Private + + private var productProvider: IProductProvider { + ProductProvider( + dispatchQueueFactory: DispatchQueueFactory() + ) + } + + private var purchaseProvider: IPurchaseProvider { + PurchaseProvider( + paymentProvider: paymentProvider, + configurationProvider: configurationProvider + ) + } + + private var paymentProvider: IPaymentProvider { + PaymentProvider( + paymentQueue: SKPaymentQueue.default(), + dispatchQueueFactory: DispatchQueueFactory() + ) + } + + private var receiptRefreshProvider: IReceiptRefreshProvider { + ReceiptRefreshProvider( + dispatchQueueFactory: DispatchQueueFactory(), + receiptRefreshRequestFactory: ReceiptRefreshRequestFactory() + ) + } + + private var refundProvider: IRefundProvider { + RefundProvider( + systemInfoProvider: SystemInfoProvider() + ) + } + + private var eligibilityProvider: IEligibilityProvider { + EligibilityProvider() + } + + private var redeemCodeProvider: IRedeemCodeProvider { + RedeemCodeProvider(systemInfoProvider: systemInfoProvider) + } + + private lazy var systemInfoProvider: ISystemInfoProvider = SystemInfoProvider() +} diff --git a/Sources/Flare/Classes/DI/IFlareDependencies.swift b/Sources/Flare/Classes/DI/IFlareDependencies.swift new file mode 100644 index 000000000..e962f74f3 --- /dev/null +++ b/Sources/Flare/Classes/DI/IFlareDependencies.swift @@ -0,0 +1,14 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// The package's dependencies. +protocol IFlareDependencies { + /// The IAP provider. + var iapProvider: IIAPProvider { get } + /// The configuration provider. + var configurationProvider: IConfigurationProvider { get } +} diff --git a/Sources/Flare/Classes/Flare.swift b/Sources/Flare/Classes/Flare.swift index f27396447..c1db74c81 100644 --- a/Sources/Flare/Classes/Flare.swift +++ b/Sources/Flare/Classes/Flare.swift @@ -13,24 +13,41 @@ import StoreKit /// The class creates and manages in-app purchases. public final class Flare { + // MARK: Properties + + /// The in-app purchase provider. + private let iapProvider: IIAPProvider + + /// The configuration provider. + private let configurationProvider: IConfigurationProvider + + /// The singleton instance. + private static let flare: Flare = .init() + + /// Returns a shared `Flare` object. + public static var shared: IFlare { flare } + // MARK: Initialization /// Creates a new `Flare` instance. /// - /// - Parameter iapProvider: The in-app purchase provider. - init(iapProvider: IIAPProvider = IAPProvider()) { - self.iapProvider = iapProvider + /// - Parameters: + /// - dependencies: The package's dependencies. + /// - configurationProvider: The configuration provider. + init(dependencies: IFlareDependencies = FlareDependencies()) { + iapProvider = dependencies.iapProvider + configurationProvider = dependencies.configurationProvider } // MARK: Public - /// Returns a default `Flare` object. - public static let `default`: IFlare = Flare() - - // MARK: Private - - /// The in-app purchase provider. - private let iapProvider: IIAPProvider + /// Configures the Flare package with the provided configuration. + /// + /// - Parameters: + /// - configuration: The configuration object containing settings for Flare. + public static func configure(with configuration: Configuration) { + flare.configurationProvider.configure(with: configuration) + } } // MARK: IFlare @@ -44,13 +61,17 @@ extension Flare: IFlare { try await iapProvider.fetch(productIDs: productIDs) } - public func purchase(product: StoreProduct, completion: @escaping Closure>) { + public func purchase( + product: StoreProduct, + promotionalOffer: PromotionalOffer?, + completion: @escaping Closure> + ) { guard iapProvider.canMakePayments else { completion(.failure(.paymentNotAllowed)) return } - iapProvider.purchase(product: product) { result in + iapProvider.purchase(product: product, promotionalOffer: promotionalOffer) { result in switch result { case let .success(transaction): completion(.success(transaction)) @@ -60,31 +81,33 @@ extension Flare: IFlare { } } - public func purchase(product: StoreProduct) async throws -> StoreTransaction { + public func purchase(product: StoreProduct, promotionalOffer: PromotionalOffer?) async throws -> StoreTransaction { guard iapProvider.canMakePayments else { throw IAPError.paymentNotAllowed } - return try await iapProvider.purchase(product: product) + return try await iapProvider.purchase(product: product, promotionalOffer: promotionalOffer) } @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) public func purchase( product: StoreProduct, options: Set, + promotionalOffer: PromotionalOffer?, completion: @escaping SendableClosure> ) { guard iapProvider.canMakePayments else { completion(.failure(.paymentNotAllowed)) return } - iapProvider.purchase(product: product, options: options, completion: completion) + iapProvider.purchase(product: product, options: options, promotionalOffer: promotionalOffer, completion: completion) } @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) public func purchase( product: StoreProduct, - options: Set + options: Set, + promotionalOffer: PromotionalOffer? ) async throws -> StoreTransaction { guard iapProvider.canMakePayments else { throw IAPError.paymentNotAllowed } - return try await iapProvider.purchase(product: product, options: options) + return try await iapProvider.purchase(product: product, options: options, promotionalOffer: promotionalOffer) } public func receipt(completion: @escaping Closure>) { @@ -114,6 +137,11 @@ extension Flare: IFlare { iapProvider.removeTransactionObserver() } + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + public func checkEligibility(productIDs: Set) async throws -> [String: SubscriptionEligibility] { + try await iapProvider.checkEligibility(productIDs: productIDs) + } + #if os(iOS) || VISION_OS @available(iOS 15.0, *) @available(macOS, unavailable) @@ -122,5 +150,21 @@ extension Flare: IFlare { public func beginRefundRequest(productID: String) async throws -> RefundRequestStatus { try await iapProvider.beginRefundRequest(productID: productID) } + + @available(iOS 14.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + public func presentCodeRedemptionSheet() { + iapProvider.presentCodeRedemptionSheet() + } + + @available(iOS 16.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + public func presentOfferCodeRedeemSheet() async throws { + try await iapProvider.presentOfferCodeRedeemSheet() + } #endif } diff --git a/Sources/Flare/Classes/Foundation/UserDefaults/IUserDefaults.swift b/Sources/Flare/Classes/Foundation/UserDefaults/IUserDefaults.swift new file mode 100644 index 000000000..dfbd224b4 --- /dev/null +++ b/Sources/Flare/Classes/Foundation/UserDefaults/IUserDefaults.swift @@ -0,0 +1,24 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// Protocol for managing `UserDefaults` operations. +protocol IUserDefaults { + /// Sets a `Codable` value in `UserDefaults` for a given key. + /// + /// - Parameters: + /// - key: The key to associate with the Codable value. + /// + /// - codable: The Codable value to be stored. + func set(key: String, codable: T) + + /// Retrieves a `Codable` value from `UserDefaults` for a given key. + /// + /// - Parameter key: The key associated with the desired Codable value. + /// + /// - Returns: The Codable value stored for the given key, or nil if not found. + func get(key: String) -> T? +} diff --git a/Sources/Flare/Classes/Foundation/UserDefaults/UserDefaults.swift b/Sources/Flare/Classes/Foundation/UserDefaults/UserDefaults.swift new file mode 100644 index 000000000..e280286e2 --- /dev/null +++ b/Sources/Flare/Classes/Foundation/UserDefaults/UserDefaults.swift @@ -0,0 +1,19 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +extension UserDefaults: IUserDefaults { + func set(key: String, codable: T) { + guard let value = try? JSONEncoder().encode(codable) else { return } + set(value, forKey: key) + } + + func get(key: String) -> T? { + let data = object(forKey: key) as? Data + guard let data = data, let value = try? JSONDecoder().decode(T.self, from: data) else { return nil } + return value + } +} diff --git a/Sources/Flare/Classes/Helpers/PaymentQueue/PaymentQueue.swift b/Sources/Flare/Classes/Helpers/PaymentQueue/PaymentQueue.swift index 6bcfe38e6..5b2783f3f 100644 --- a/Sources/Flare/Classes/Helpers/PaymentQueue/PaymentQueue.swift +++ b/Sources/Flare/Classes/Helpers/PaymentQueue/PaymentQueue.swift @@ -35,4 +35,10 @@ public protocol PaymentQueue: AnyObject { /// Remove a finished (i.e. failed or completed) transaction from the queue. /// Attempting to finish a purchasing transaction will throw an exception. func finishTransaction(_ transaction: SKPaymentTransaction) + + #if os(iOS) || VISION_OS + // Call this method to have StoreKit present a sheet enabling the user to redeem codes provided by your app. + @available(iOS 14.0, *) + func presentCodeRedemptionSheet() + #endif } diff --git a/Sources/Flare/Classes/IFlare.swift b/Sources/Flare/Classes/IFlare.swift index 6643cdd14..48e0eef63 100644 --- a/Sources/Flare/Classes/IFlare.swift +++ b/Sources/Flare/Classes/IFlare.swift @@ -6,6 +6,8 @@ import Foundation import StoreKit +// MARK: - IFlare + /// `Flare` creates and manages in-app purchases. public protocol IFlare { /// Retrieves localized information from the App Store about a specified list of products. @@ -32,8 +34,13 @@ public protocol IFlare { /// /// - Parameters: /// - product: The product to be purchased. + /// - promotionalOffer: The promotional offer. /// - completion: The closure to be executed once the purchase is complete. - func purchase(product: StoreProduct, completion: @escaping Closure>) + func purchase( + product: StoreProduct, + promotionalOffer: PromotionalOffer?, + completion: @escaping Closure> + ) /// Purchases a product. /// @@ -41,12 +48,14 @@ public protocol IFlare { /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// - /// - Parameter product: The product to be purchased. + /// - Parameters: + /// - product: The product to be purchased. + /// - promotionalOffer: The promotional offer. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. - func purchase(product: StoreProduct) async throws -> StoreTransaction + func purchase(product: StoreProduct, promotionalOffer: PromotionalOffer?) async throws -> StoreTransaction /// Purchases a product. /// @@ -57,6 +66,7 @@ public protocol IFlare { /// - Parameters: /// - product: The product to be purchased. /// - options: The optional settings for a product purchase. + /// - promotionalOffer: The promotional offer. /// - completion: The closure to be executed once the purchase is complete. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. @@ -66,6 +76,7 @@ public protocol IFlare { func purchase( product: StoreProduct, options: Set, + promotionalOffer: PromotionalOffer?, completion: @escaping SendableClosure> ) @@ -78,12 +89,17 @@ public protocol IFlare { /// - Parameters: /// - product: The product to be purchased. /// - options: The optional settings for a product purchase. + /// - promotionalOffer: The promotional offer. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) - func purchase(product: StoreProduct, options: Set) async throws -> StoreTransaction + func purchase( + product: StoreProduct, + options: Set, + promotionalOffer: PromotionalOffer? + ) async throws -> StoreTransaction /// Refreshes the receipt, representing the user's transactions with your app. /// @@ -116,6 +132,14 @@ public protocol IFlare { /// - Note: This may require that the user authenticate. func removeTransactionObserver() + /// Checks whether products are eligible for promotional offers + /// + /// - Parameter productIDs: The list of product identifiers for which you wish to check eligibility. + /// + /// - Returns: An array that contains information about the eligibility of products. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func checkEligibility(productIDs: Set) async throws -> [String: SubscriptionEligibility] + #if os(iOS) || VISION_OS /// Present the refund request sheet for the specified transaction in a window scene. /// @@ -127,5 +151,98 @@ public protocol IFlare { @available(watchOS, unavailable) @available(tvOS, unavailable) func beginRefundRequest(productID: String) async throws -> RefundRequestStatus + + /// Displays a sheet that enables users to redeem subscription offer codes that you configure in App Store Connect. + @available(iOS 14.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func presentCodeRedemptionSheet() + + /// Displays a sheet in the window scene that enables users to redeem + /// a subscription offer code that you configure in App Store + /// Connect. + @available(iOS 16.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func presentOfferCodeRedeemSheet() async throws #endif } + +public extension IFlare { + /// Performs a purchase of a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - completion: The closure to be executed once the purchase is complete. + func purchase( + product: StoreProduct, + completion: @escaping Closure> + ) { + purchase(product: product, promotionalOffer: nil, completion: completion) + } + + /// Purchases a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameter product: The product to be purchased. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + func purchase(product: StoreProduct) async throws -> StoreTransaction { + try await purchase(product: product, promotionalOffer: nil) + } + + /// Purchases a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// - completion: The closure to be executed once the purchase is complete. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping SendableClosure> + ) { + purchase(product: product, options: options, promotionalOffer: nil, completion: completion) + } + + /// Purchases a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set + ) async throws -> StoreTransaction { + try await purchase(product: product, options: options, promotionalOffer: nil) + } +} diff --git a/Sources/Flare/Classes/Models/Configuration.swift b/Sources/Flare/Classes/Models/Configuration.swift new file mode 100644 index 000000000..d2ece895c --- /dev/null +++ b/Sources/Flare/Classes/Models/Configuration.swift @@ -0,0 +1,27 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +public struct Configuration { + // MARK: Properties + + // swiftlint:disable:next line_length + // https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_promotional_offers_in_your_app + + /// A string that associates the transaction with a user account on your service. + /// + /// - Important: You must set `applicationUsername` to be the same as the one used to generate the signature. + public let applicationUsername: String + + // MARK: Initialization + + /// Creates a `Configuration` instance. + /// + /// - Parameter applicationUsername: A string that associates the transaction with a user account on your service. + public init(applicationUsername: String) { + self.applicationUsername = applicationUsername + } +} diff --git a/Sources/Flare/Classes/Models/DiscountType.swift b/Sources/Flare/Classes/Models/DiscountType.swift new file mode 100644 index 000000000..37f49187f --- /dev/null +++ b/Sources/Flare/Classes/Models/DiscountType.swift @@ -0,0 +1,53 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - DiscountType + +/// The type of discount offer. +public enum DiscountType: Int, Sendable { + /// Introductory offer + case introductory = 0 + /// Promotional offer for subscriptions + case promotional = 1 +} + +extension DiscountType { + /// Creates a ``DiscountType`` instance. + /// + /// - Parameter productDiscount: The details of an introductory offer or a promotional + /// offer for an auto-renewable subscription. + /// + /// - Returns: A discount type. + static func from(productDiscount: SKProductDiscount) -> Self? { + switch productDiscount.type { + case .introductory: + return .introductory + case .subscription: + return .promotional + @unknown default: + return nil + } + } + + /// Creates a ``DiscountType`` instance. + /// + /// - Parameter discount: Information about a subscription offer that you configure in App Store Connect. + /// + /// - Returns: A discount type. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + static func from(discount: Product.SubscriptionOffer) -> Self? { + switch discount.type { + case Product.SubscriptionOffer.OfferType.introductory: + return .introductory + case Product.SubscriptionOffer.OfferType.promotional: + return .promotional + default: + return nil + } + } +} diff --git a/Sources/Flare/Classes/Models/IAPError.swift b/Sources/Flare/Classes/Models/IAPError.swift index 83537685e..80de297b9 100644 --- a/Sources/Flare/Classes/Models/IAPError.swift +++ b/Sources/Flare/Classes/Models/IAPError.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import StoreKit @@ -34,10 +34,14 @@ public enum IAPError: Swift.Error { /// /// - Note: This is only available for StoreKit 2 transactions. case verification(error: VerificationError) - /// + /// The purchase is pending, and requires action from the customer. /// /// - Note: This is only available for StoreKit 2 transactions. case paymentDefferred + /// The decoding signature is failed. + /// + /// - Note: This is only available for StoreKit 2 transactions. + case failedToDecodeSignature(signature: String) /// The unknown error occurred. case unknown } @@ -123,6 +127,8 @@ extension IAPError: Equatable { return lhs == rhs case (.unknown, .unknown): return true + case let (.failedToDecodeSignature(lhs), .failedToDecodeSignature(rhs)): + return lhs == rhs default: return false } diff --git a/Sources/Flare/Classes/Models/Internal/ProductsRequest.swift b/Sources/Flare/Classes/Models/Internal/ProductsRequest.swift new file mode 100644 index 000000000..21be0b315 --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/ProductsRequest.swift @@ -0,0 +1,39 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +/// A class that represents a request to the App Store. +final class ProductsRequest: ISKRequest { + // MARK: Properties + + /// The request. + private let request: SKRequest + + /// The request’s identifier. + var id: String { request.id } + + // MARK: Initialization + + /// Creates a `ProductsRequest` instance. + /// + /// - Parameter request: The request. + init(_ request: SKRequest) { + self.request = request + } + + // MARK: Hashable + + func hash(into hasher: inout Hasher) { + hasher.combine(id) + } + + // MARK: Equatable + + static func == (lhs: ProductsRequest, rhs: ProductsRequest) -> Bool { + lhs.id == rhs.id + } +} diff --git a/Sources/Flare/Classes/Models/Internal/Protocols/ISKProduct.swift b/Sources/Flare/Classes/Models/Internal/Protocols/ISKProduct.swift index 825632ca4..d649481ef 100644 --- a/Sources/Flare/Classes/Models/Internal/Protocols/ISKProduct.swift +++ b/Sources/Flare/Classes/Models/Internal/Protocols/ISKProduct.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -33,4 +33,13 @@ protocol ISKProduct { /// The subscription period for the product, if applicable. var subscriptionPeriod: SubscriptionPeriod? { get } + + /// The details of an introductory offer for an auto-renewable subscription. + var introductoryDiscount: StoreProductDiscount? { get } + + /// The details of promotional offers for an auto-renewable subscription. + var discounts: [StoreProductDiscount] { get } + + /// The subscription group identifier. + var subscriptionGroupIdentifier: String? { get } } diff --git a/Sources/Flare/Classes/Models/Internal/Protocols/ISKRequest.swift b/Sources/Flare/Classes/Models/Internal/Protocols/ISKRequest.swift new file mode 100644 index 000000000..5ec7b4fc1 --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/Protocols/ISKRequest.swift @@ -0,0 +1,12 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// Type that represents a request to the App Store. +protocol ISKRequest: Hashable { + /// The request’s identifier. + var id: String { get } +} diff --git a/Sources/Flare/Classes/Models/Internal/Protocols/IStoreProductDiscount.swift b/Sources/Flare/Classes/Models/Internal/Protocols/IStoreProductDiscount.swift new file mode 100644 index 000000000..903ba0cfa --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/Protocols/IStoreProductDiscount.swift @@ -0,0 +1,32 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +// MARK: - IStoreProductDiscount Protocol + +/// A protocol representing a discount information for a store product. +protocol IStoreProductDiscount: Sendable { + /// A unique identifier for the discount offer. + var offerIdentifier: String? { get } + + /// The currency code for the discount amount. + var currencyCode: String? { get } + + /// The discounted price in the specified currency. + var price: Decimal { get } + + /// The payment mode associated with the discount (e.g., freeTrial, payUpFront, payAsYouGo). + var paymentMode: PaymentMode { get } + + /// The period for which the discount is applicable in a subscription. + var subscriptionPeriod: SubscriptionPeriod { get } + + /// The number of subscription periods for which the discount is applied. + var numberOfPeriods: Int { get } + + /// The type of discount (e.g., introductory, promotional). + var type: DiscountType { get } +} diff --git a/Sources/Flare/Classes/Models/Internal/SK1StoreProduct.swift b/Sources/Flare/Classes/Models/Internal/SK1StoreProduct.swift index 92d48806c..44722d38a 100644 --- a/Sources/Flare/Classes/Models/Internal/SK1StoreProduct.swift +++ b/Sources/Flare/Classes/Models/Internal/SK1StoreProduct.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -56,17 +56,25 @@ extension SK1StoreProduct: ISKProduct { } var productCategory: ProductCategory? { - guard #available(iOS 11.2, macOS 10.13.2, tvOS 11.2, watchOS 6.2, *) else { - return .nonSubscription - } - return subscriptionPeriod == nil ? .nonSubscription : .subscription + subscriptionPeriod == nil ? .nonSubscription : .subscription } - @available(iOS 11.2, macOS 10.13.2, tvOS 11.2, watchOS 6.2, *) var subscriptionPeriod: SubscriptionPeriod? { guard let subscriptionPeriod = product.subscriptionPeriod, subscriptionPeriod.numberOfUnits > 0 else { return nil } return SubscriptionPeriod.from(subscriptionPeriod: subscriptionPeriod) } + + var introductoryDiscount: StoreProductDiscount? { + product.introductoryPrice.flatMap { StoreProductDiscount(skProductDiscount: $0) } + } + + var discounts: [StoreProductDiscount] { + product.discounts.compactMap { StoreProductDiscount(skProductDiscount: $0) } + } + + var subscriptionGroupIdentifier: String? { + product.subscriptionGroupIdentifier + } } diff --git a/Sources/Flare/Classes/Models/Internal/SK1StoreProductDiscount.swift b/Sources/Flare/Classes/Models/Internal/SK1StoreProductDiscount.swift new file mode 100644 index 000000000..263bee9d2 --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/SK1StoreProductDiscount.swift @@ -0,0 +1,60 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +/// The details of an introductory offer or a promotional offer for an auto-renewable subscription. +struct SK1StoreProductDiscount: IStoreProductDiscount { + // MARK: Properties + + private let productDiscount: SKProductDiscount + + /// A unique identifier for the discount offer. + let offerIdentifier: String? + + /// The currency code for the discount amount. + let currencyCode: String? + + /// The discounted price in the specified currency. + let price: Decimal + + /// The payment mode associated with the discount (e.g., freeTrial, payUpFront, payAsYouGo). + let paymentMode: PaymentMode + + /// The period for which the discount is applicable in a subscription. + let subscriptionPeriod: SubscriptionPeriod + + /// The number of subscription periods for which the discount is applied. + let numberOfPeriods: Int + + /// The type of discount (e.g., introductory, promotional). + let type: DiscountType + + // MARK: Initialization + + /// Creates a `SK1StoreProductDiscount` instance. + /// + /// - Parameter productDiscount: The details of an introductory offer or a promotional + /// offer for an auto-renewable subscription. + init?(productDiscount: SKProductDiscount) { + guard let paymentMode = PaymentMode.from(productDiscount: productDiscount), + let discountType = DiscountType.from(productDiscount: productDiscount), + let subscriptionPeriod = SubscriptionPeriod.from(subscriptionPeriod: productDiscount.subscriptionPeriod) + else { + return nil + } + + self.productDiscount = productDiscount + + offerIdentifier = productDiscount.identifier + currencyCode = productDiscount.priceLocale.currencyCodeID + price = productDiscount.price as Decimal + self.paymentMode = paymentMode + self.subscriptionPeriod = subscriptionPeriod + numberOfPeriods = productDiscount.numberOfPeriods + type = discountType + } +} diff --git a/Sources/Flare/Classes/Models/Internal/SK2StoreProduct.swift b/Sources/Flare/Classes/Models/Internal/SK2StoreProduct.swift index c8fa0527d..ad99a8987 100644 --- a/Sources/Flare/Classes/Models/Internal/SK2StoreProduct.swift +++ b/Sources/Flare/Classes/Models/Internal/SK2StoreProduct.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -14,6 +14,7 @@ final class SK2StoreProduct { /// The store kit product. let product: StoreKit.Product + /// The currency format. private var currencyFormat: Decimal.FormatStyle.Currency { product.priceFormatStyle @@ -68,4 +69,20 @@ extension SK2StoreProduct: ISKProduct { } return SubscriptionPeriod.from(subscriptionPeriod: subscriptionPeriod) } + + var introductoryDiscount: StoreProductDiscount? { + product.subscription?.introductoryOffer.flatMap { + StoreProductDiscount(discount: $0, currencyCode: self.currencyCode) + } + } + + var discounts: [StoreProductDiscount] { + product.subscription?.promotionalOffers.compactMap { + StoreProductDiscount(discount: $0, currencyCode: self.currencyCode) + } ?? [] + } + + var subscriptionGroupIdentifier: String? { + product.subscription?.subscriptionGroupID + } } diff --git a/Sources/Flare/Classes/Models/Internal/SK2StoreProductDiscount.swift b/Sources/Flare/Classes/Models/Internal/SK2StoreProductDiscount.swift new file mode 100644 index 000000000..f38ba0cef --- /dev/null +++ b/Sources/Flare/Classes/Models/Internal/SK2StoreProductDiscount.swift @@ -0,0 +1,62 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +/// The details of an introductory offer or a promotional offer for an auto-renewable subscription. +@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) +struct SK2StoreProductDiscount: IStoreProductDiscount, Sendable { + // MARK: Properties + + private let subscriptionOffer: StoreKit.Product.SubscriptionOffer + + /// A unique identifier for the discount offer. + let offerIdentifier: String? + + /// The currency code for the discount amount. + let currencyCode: String? + + /// The discounted price in the specified currency. + let price: Decimal + + /// The payment mode associated with the discount (e.g., freeTrial, payUpFront, payAsYouGo). + let paymentMode: PaymentMode + + /// The period for which the discount is applicable in a subscription. + let subscriptionPeriod: SubscriptionPeriod + + /// The number of subscription periods for which the discount is applied. + let numberOfPeriods: Int + + /// The type of discount (e.g., introductory, promotional). + let type: DiscountType + + // MARK: Initialization + + /// Creates a `SK2StoreProductDiscount` instance. + /// + /// - Parameters: + /// - subscriptionOffer: Information about a subscription offer that you configure in App Store Connect. + /// - currencyCode: The currency code for the discount amount. + init?(subscriptionOffer: StoreKit.Product.SubscriptionOffer, currencyCode: String?) { + guard let paymentMode = PaymentMode.from(discount: subscriptionOffer), + let discountType = DiscountType.from(discount: subscriptionOffer), + let subscriptionPeriod = SubscriptionPeriod.from(subscriptionPeriod: subscriptionOffer.period) + else { + return nil + } + + self.subscriptionOffer = subscriptionOffer + + offerIdentifier = subscriptionOffer.id + self.currencyCode = currencyCode + price = subscriptionOffer.price + self.paymentMode = paymentMode + self.subscriptionPeriod = subscriptionPeriod + numberOfPeriods = subscriptionOffer.periodCount + type = discountType + } +} diff --git a/Sources/Flare/Classes/Models/PaymentMode.swift b/Sources/Flare/Classes/Models/PaymentMode.swift new file mode 100644 index 000000000..963694926 --- /dev/null +++ b/Sources/Flare/Classes/Models/PaymentMode.swift @@ -0,0 +1,59 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - PaymentMode + +/// The offer's payment mode. +public enum PaymentMode: Int, Sendable { + /// Price is charged one or more times + case payAsYouGo = 0 + /// Price is charged once in advance + case payUpFront = 1 + /// No initial charge + case freeTrial = 2 +} + +extension PaymentMode { + /// Creates a ``PaymentMode`` instance. + /// + /// - Parameter productDiscount: The details of an introductory offer or a promotional + /// offer for an auto-renewable subscription. + /// + /// - Returns: A payment mode. + static func from(productDiscount: SKProductDiscount) -> Self? { + switch productDiscount.paymentMode { + case .payAsYouGo: + return .payAsYouGo + case .payUpFront: + return .payUpFront + case .freeTrial: + return .freeTrial + @unknown default: + return nil + } + } + + /// Creates a ``PaymentMode`` instance. + /// + /// - Parameter discount: Information about a subscription offer that you configure in App Store Connect. + /// + /// - Returns: A payment mode. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + static func from(discount: Product.SubscriptionOffer) -> Self? { + switch discount.paymentMode { + case Product.SubscriptionOffer.PaymentMode.freeTrial: + return .freeTrial + case Product.SubscriptionOffer.PaymentMode.payAsYouGo: + return .payAsYouGo + case Product.SubscriptionOffer.PaymentMode.payUpFront: + return .payUpFront + default: + return nil + } + } +} diff --git a/Sources/Flare/Classes/Models/PromotionalOffer.swift b/Sources/Flare/Classes/Models/PromotionalOffer.swift new file mode 100644 index 000000000..c5a279c5c --- /dev/null +++ b/Sources/Flare/Classes/Models/PromotionalOffer.swift @@ -0,0 +1,116 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - PromotionalOffer + +/// A class representing a promotional offer. +public final class PromotionalOffer: NSObject, Sendable { + // MARK: Properties + + /// The details of an introductory offer or a promotional offer for an auto-renewable subscription. + public let discount: StoreProductDiscount + /// The signed discount applied to a payment. + public let signedData: SignedData + + // MARK: Initialization + + /// Creates a `PromotionalOffer` instance. + /// + /// - Parameters: + /// - discount: The details of an introductory offer or a promotional offer for an auto-renewable subscription. + /// - signedData: The signed discount applied to a payment. + public init(discount: StoreProductDiscount, signedData: SignedData) { + self.discount = discount + self.signedData = signedData + } +} + +// MARK: PromotionalOffer.SignedData + +public extension PromotionalOffer { + /// The signed discount applied to a payment. + final class SignedData: NSObject, Sendable { + // MARK: Properties + + /// The identifier agreed upon with the App Store for a discount of your choosing. + public let identifier: String + /// The identifier of the public/private key pair agreed upon with the App Store when the keys were generated. + public let keyIdentifier: String + /// One-time use random entropy-adding value for security. + public let nonce: UUID + /// The cryptographic signature generated by your private key. + public let signature: String + /// Timestamp of when the signature is created. + public let timestamp: Int + + /// Creates a `SignedData` instance. + /// + /// - Parameters: + /// - identifier: The identifier agreed upon with the App Store for a discount of your choosing. + /// - keyIdentifier: The identifier of the public/private key pair agreed upon + /// with the App Store when the keys were generated. + /// - nonce: One-time use random entropy-adding value for security. + /// - signature: The cryptographic signature generated by your private key. + /// - timestamp: Timestamp of when the signature is created. + public init(identifier: String, keyIdentifier: String, nonce: UUID, signature: String, timestamp: Int) { + self.identifier = identifier + self.keyIdentifier = keyIdentifier + self.nonce = nonce + self.signature = signature + self.timestamp = timestamp + } + } +} + +// MARK: - Convenience Initializators + +extension PromotionalOffer.SignedData { + /// Creates a `SignedData` instance. + /// + /// - Parameter paymentDiscount: The signed discount applied to a payment. + convenience init(paymentDiscount: SKPaymentDiscount) { + self.init( + identifier: paymentDiscount.identifier, + keyIdentifier: paymentDiscount.keyIdentifier, + nonce: paymentDiscount.nonce, + signature: paymentDiscount.signature, + timestamp: paymentDiscount.timestamp.intValue + ) + } +} + +// MARK: - Helpers + +extension PromotionalOffer.SignedData { + var skPromotionalOffer: SKPaymentDiscount { + SKPaymentDiscount( + identifier: identifier, + keyIdentifier: keyIdentifier, + nonce: nonce, + signature: signature, + timestamp: .init(integerLiteral: timestamp) + ) + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + var promotionalOffer: Product.PurchaseOption { + get throws { + guard let data = Data(base64Encoded: signature) else { + throw IAPError.failedToDecodeSignature(signature: signature) + } + + return .promotionalOffer( + offerID: identifier, + keyID: keyIdentifier, + nonce: nonce, + signature: data, + timestamp: timestamp + ) + } + } +} diff --git a/Sources/Flare/Classes/Models/StoreProduct.swift b/Sources/Flare/Classes/Models/StoreProduct.swift index 06255b5a2..bfbb34666 100644 --- a/Sources/Flare/Classes/Models/StoreProduct.swift +++ b/Sources/Flare/Classes/Models/StoreProduct.swift @@ -50,39 +50,51 @@ public extension StoreProduct { // MARK: ISKProduct extension StoreProduct: ISKProduct { - var localizedDescription: String { + public var localizedDescription: String { product.localizedDescription } - var localizedTitle: String { + public var localizedTitle: String { product.localizedTitle } - var currencyCode: String? { + public var currencyCode: String? { product.currencyCode } - var price: Decimal { + public var price: Decimal { product.price } - var localizedPriceString: String? { + public var localizedPriceString: String? { product.localizedPriceString } - var productIdentifier: String { + public var productIdentifier: String { product.productIdentifier } - var productType: ProductType? { + public var productType: ProductType? { product.productType } - var productCategory: ProductCategory? { + public var productCategory: ProductCategory? { product.productCategory } - var subscriptionPeriod: SubscriptionPeriod? { + public var subscriptionPeriod: SubscriptionPeriod? { product.subscriptionPeriod } + + public var introductoryDiscount: StoreProductDiscount? { + product.introductoryDiscount + } + + public var discounts: [StoreProductDiscount] { + product.discounts + } + + public var subscriptionGroupIdentifier: String? { + product.subscriptionGroupIdentifier + } } diff --git a/Sources/Flare/Classes/Models/StoreProductDiscount.swift b/Sources/Flare/Classes/Models/StoreProductDiscount.swift new file mode 100644 index 000000000..871755058 --- /dev/null +++ b/Sources/Flare/Classes/Models/StoreProductDiscount.swift @@ -0,0 +1,82 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - StoreProductDiscount + +/// The details of an introductory offer or a promotional offer for an auto-renewable subscription. +public final class StoreProductDiscount { + // MARK: Properties + + /// The details of an introductory offer or a promotional offer for an auto-renewable subscription. + private let discount: IStoreProductDiscount + + // MARK: Initialization + + /// Creates a `StoreProductDiscount` instance. + /// + /// - Parameter discount: The details of an introductory offer or a promotional offer for an auto-renewable subscription. + init(discount: IStoreProductDiscount) { + self.discount = discount + } +} + +// MARK: - Convenience Initializators + +public extension StoreProductDiscount { + /// Creates a new `StoreProductDiscount` instance. + /// + /// - Parameter skProductDiscount: The details of an introductory offer or a promotional + /// offer for an auto-renewable subscription. + convenience init?(skProductDiscount: SKProductDiscount) { + guard let discount = SK1StoreProductDiscount(productDiscount: skProductDiscount) else { return nil } + self.init(discount: discount) + } + + /// Creates a new `StoreProductDiscount` instance. + /// + /// - Parameters: + /// - subscriptionOffer: Information about a subscription offer that you configure in App Store Connect. + /// - currencyCode: The currency code for the discount amount. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + convenience init?(discount: StoreKit.Product.SubscriptionOffer, currencyCode: String?) { + guard let discount = SK2StoreProductDiscount(subscriptionOffer: discount, currencyCode: currencyCode) else { return nil } + self.init(discount: discount) + } +} + +// MARK: IStoreProductDiscount + +extension StoreProductDiscount: IStoreProductDiscount { + public var offerIdentifier: String? { + discount.offerIdentifier + } + + public var currencyCode: String? { + discount.currencyCode + } + + public var price: Decimal { + discount.price + } + + public var paymentMode: PaymentMode { + discount.paymentMode + } + + public var subscriptionPeriod: SubscriptionPeriod { + discount.subscriptionPeriod + } + + public var numberOfPeriods: Int { + discount.numberOfPeriods + } + + public var type: DiscountType { + discount.type + } +} diff --git a/Sources/Flare/Classes/Models/SubscriptionEligibility.swift b/Sources/Flare/Classes/Models/SubscriptionEligibility.swift new file mode 100644 index 000000000..362884ace --- /dev/null +++ b/Sources/Flare/Classes/Models/SubscriptionEligibility.swift @@ -0,0 +1,18 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +// Enumeration defining the eligibility status for a subscription +public enum SubscriptionEligibility: Int, Sendable { + // Represents that the subscription is eligible for an offer + case eligible + + // Represents that the subscription is not eligible for an offer + case nonEligible + + // Represents that there is no offer available for the subscription + case noOffer +} diff --git a/Sources/Flare/Classes/Models/SubscriptionPeriod.swift b/Sources/Flare/Classes/Models/SubscriptionPeriod.swift index 9bf8a2f52..3a8ef32cc 100644 --- a/Sources/Flare/Classes/Models/SubscriptionPeriod.swift +++ b/Sources/Flare/Classes/Models/SubscriptionPeriod.swift @@ -9,10 +9,10 @@ import StoreKit // MARK: - SubscriptionPeriod /// A class representing a subscription period with a specific value and unit. -public final class SubscriptionPeriod: NSObject { +public final class SubscriptionPeriod: NSObject, Sendable { // MARK: Types - public enum Unit: Int { + public enum Unit: Int, Sendable { /// A subscription period unit of a day. case day = 0 /// A subscription period unit of a week. @@ -41,6 +41,19 @@ public final class SubscriptionPeriod: NSObject { self.value = value self.unit = unit } + + override public func isEqual(_ object: Any?) -> Bool { + guard let other = object as? SubscriptionPeriod else { return false } + return value == other.value && unit == other.unit + } + + override public var hash: Int { + var hasher = Hasher() + hasher.combine(value) + hasher.combine(unit) + + return hasher.finalize() + } } // MARK: - Helpers @@ -66,7 +79,11 @@ extension SubscriptionPeriod { // MARK: - Extensions private extension SubscriptionPeriod.Unit { - @available(iOS 11.2, macOS 10.13.2, tvOS 11.2, watchOS 6.2, *) + /// Creates a ``SubscriptionPeriod.Unit`` instance. + /// + /// - Parameter unit: Values representing the duration of an interval, from a day up to a year. + /// + /// - Returns: A subscription unit. static func from(unit: SKProduct.PeriodUnit) -> Self? { switch unit { case .day: @@ -82,6 +99,11 @@ private extension SubscriptionPeriod.Unit { } } + /// Creates a ``SubscriptionPeriod.Unit`` instance. + /// + /// - Parameter unit: Units of time that describe subscription periods. + /// + /// - Returns: A subscription unit. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8, *) static func from(unit: StoreKit.Product.SubscriptionPeriod.Unit) -> Self? { switch unit { diff --git a/Sources/Flare/Classes/Providers/CacheProvider/CacheProvider.swift b/Sources/Flare/Classes/Providers/CacheProvider/CacheProvider.swift new file mode 100644 index 000000000..a28ef627f --- /dev/null +++ b/Sources/Flare/Classes/Providers/CacheProvider/CacheProvider.swift @@ -0,0 +1,37 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +// MARK: - CacheProvider + +/// A class provides caching functionality. +final class CacheProvider { + // MARK: Properties + + /// The user defaults. + private let userDefaults: IUserDefaults + + // MARK: Initialization + + /// Creates a `CacheProvider` instance. + /// + /// - Parameter userDefaults: The user defaults. + init(userDefaults: IUserDefaults = UserDefaults.standard) { + self.userDefaults = userDefaults + } +} + +// MARK: ICacheProvider + +extension CacheProvider: ICacheProvider { + func read(key: String) -> T? { + userDefaults.get(key: key) + } + + func write(key: String, value: T) { + userDefaults.set(key: key, codable: value) + } +} diff --git a/Sources/Flare/Classes/Providers/CacheProvider/ICacheProvider.swift b/Sources/Flare/Classes/Providers/CacheProvider/ICacheProvider.swift new file mode 100644 index 000000000..9c5480dec --- /dev/null +++ b/Sources/Flare/Classes/Providers/CacheProvider/ICacheProvider.swift @@ -0,0 +1,23 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// Type for a cache provider that supports reading and writing Codable values. +protocol ICacheProvider { + /// Reads a Codable value from the cache using the specified key. + /// + /// - Parameters: + /// - key: The key associated with the value in the cache. + /// - Returns: The Codable value associated with the key, or nil if not found. + func read(key: String) -> T? + + /// Writes a Codable value to the cache using the specified key. + /// + /// - Parameters: + /// - key: The key to associate with the value in the cache. + /// - value: The Codable value to be stored in the cache. + func write(key: String, value: T) +} diff --git a/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift b/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift new file mode 100644 index 000000000..08d3e7361 --- /dev/null +++ b/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift @@ -0,0 +1,44 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +// MARK: - ConfigurationProvider + +/// A class responsible for providing configuration settings, utilizing a cache provider. +final class ConfigurationProvider { + // MARK: Properties + + /// The cache provider used to store and retrieve configuration settings. + private let cacheProvider: ICacheProvider + + // MARK: Initialization + + /// Initializes a ConfigurationProvider with a specified cache provider. + /// + /// - Parameter cacheProvider: The cache provider to use. Defaults to an instance of + /// `CacheProvider` with standard UserDefaults. + init(cacheProvider: ICacheProvider = CacheProvider(userDefaults: UserDefaults.standard)) { + self.cacheProvider = cacheProvider + } +} + +// MARK: IConfigurationProvider + +extension ConfigurationProvider: IConfigurationProvider { + var applicationUsername: String? { + cacheProvider.read(key: .applicationUsername) + } + + func configure(with configuration: Configuration) { + cacheProvider.write(key: .applicationUsername, value: configuration.applicationUsername) + } +} + +// MARK: - Constants + +private extension String { + static let applicationUsername = "flare.configuration.application_username" +} diff --git a/Sources/Flare/Classes/Providers/ConfigurationProvider/IConfigurationProvider.swift b/Sources/Flare/Classes/Providers/ConfigurationProvider/IConfigurationProvider.swift new file mode 100644 index 000000000..cae9f7b26 --- /dev/null +++ b/Sources/Flare/Classes/Providers/ConfigurationProvider/IConfigurationProvider.swift @@ -0,0 +1,17 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// Type for providing configuration settings to an application. +protocol IConfigurationProvider { + /// The application username. + var applicationUsername: String? { get } + + /// Configures the provider with the specified configuration settings. + /// + /// - Parameter configuration: The configuration settings to apply. + func configure(with configuration: Configuration) +} diff --git a/Sources/Flare/Classes/Providers/EligibilityProvider/EligibilityProvider.swift b/Sources/Flare/Classes/Providers/EligibilityProvider/EligibilityProvider.swift new file mode 100644 index 000000000..ddaa1be78 --- /dev/null +++ b/Sources/Flare/Classes/Providers/EligibilityProvider/EligibilityProvider.swift @@ -0,0 +1,33 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +// MARK: - EligibilityProvider + +/// A class that provides eligibility checking functionality. +final class EligibilityProvider {} + +// MARK: IEligibilityProvider + +extension EligibilityProvider: IEligibilityProvider { + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func checkEligibility(products: [StoreProduct]) async throws -> [String: SubscriptionEligibility] { + let underlyingProducts = products.compactMap { $0.underlyingProduct as? SK2StoreProduct } + + var result: [String: SubscriptionEligibility] = [:] + + for product in underlyingProducts { + if let subscription = product.product.subscription, subscription.introductoryOffer != nil { + let isEligible = await subscription.isEligibleForIntroOffer + result[product.productIdentifier] = isEligible ? .eligible : .nonEligible + } else { + result[product.productIdentifier] = .noOffer + } + } + + return result + } +} diff --git a/Sources/Flare/Classes/Providers/EligibilityProvider/IEligibilityProvider.swift b/Sources/Flare/Classes/Providers/EligibilityProvider/IEligibilityProvider.swift new file mode 100644 index 000000000..40ad67997 --- /dev/null +++ b/Sources/Flare/Classes/Providers/EligibilityProvider/IEligibilityProvider.swift @@ -0,0 +1,17 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// Type that provides eligibility checking functionality. +protocol IEligibilityProvider { + /// Checks whether products are eligible for promotional offers + /// + /// - Parameter products: The products to be checked. + /// + /// - Returns: An array that contains information about the eligibility of products. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func checkEligibility(products: [StoreProduct]) async throws -> [String: SubscriptionEligibility] +} diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index f2ed8c0a0..8850f3a19 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import StoreKit @@ -19,6 +19,10 @@ final class IAPProvider: IIAPProvider { private let receiptRefreshProvider: IReceiptRefreshProvider /// The provider is responsible for refunding purchases private let refundProvider: IRefundProvider + /// The provider is responsible for eligibility checking. + private let eligibilityProvider: IEligibilityProvider + /// The provider is tasked with handling code redemption. + private let redeemCodeProvider: IRedeemCodeProvider // MARK: Initialization @@ -27,23 +31,27 @@ final class IAPProvider: IIAPProvider { /// - Parameters: /// - paymentQueue: The queue of payment transactions to be processed by the App Store. /// - productProvider: The provider is responsible for fetching StoreKit products. - /// - purchaseProvider: + /// - purchaseProvider: The provider is respinsible for purchasing StoreKit product. /// - receiptRefreshProvider: The provider is responsible for refreshing receipts. /// - refundProvider: The provider is responsible for refunding purchases. + /// - eligibilityProvider: The provider is responsible for eligibility checking. + /// - redeemCodeProvider: The provider is tasked with handling code redemption. init( - paymentQueue: PaymentQueue = SKPaymentQueue.default(), - productProvider: IProductProvider = ProductProvider(), - purchaseProvider: IPurchaseProvider = PurchaseProvider(), - receiptRefreshProvider: IReceiptRefreshProvider = ReceiptRefreshProvider(), - refundProvider: IRefundProvider = RefundProvider( - systemInfoProvider: SystemInfoProvider() - ) + paymentQueue: PaymentQueue, + productProvider: IProductProvider, + purchaseProvider: IPurchaseProvider, + receiptRefreshProvider: IReceiptRefreshProvider, + refundProvider: IRefundProvider, + eligibilityProvider: IEligibilityProvider, + redeemCodeProvider: IRedeemCodeProvider ) { self.paymentQueue = paymentQueue self.productProvider = productProvider self.purchaseProvider = purchaseProvider self.receiptRefreshProvider = receiptRefreshProvider self.refundProvider = refundProvider + self.eligibilityProvider = eligibilityProvider + self.redeemCodeProvider = redeemCodeProvider } // MARK: Internal @@ -55,7 +63,7 @@ final class IAPProvider: IIAPProvider { func fetch(productIDs: Set, completion: @escaping Closure>) { if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) { AsyncHandler.call( - completion: { [weak self] result in + completion: { [weak self] (result: Result<[SK2StoreProduct], Error>) in self?.handleFetchResult(result: result, completion) }, asyncMethod: { @@ -80,8 +88,12 @@ final class IAPProvider: IIAPProvider { } } - func purchase(product: StoreProduct, completion: @escaping Closure>) { - purchaseProvider.purchase(product: product) { result in + func purchase( + product: StoreProduct, + promotionalOffer: PromotionalOffer?, + completion: @escaping Closure> + ) { + purchaseProvider.purchase(product: product, promotionalOffer: promotionalOffer) { result in switch result { case let .success(transaction): completion(.success(transaction)) @@ -91,9 +103,9 @@ final class IAPProvider: IIAPProvider { } } - func purchase(product: StoreProduct) async throws -> StoreTransaction { + func purchase(product: StoreProduct, promotionalOffer: PromotionalOffer?) async throws -> StoreTransaction { try await withCheckedThrowingContinuation { continuation in - self.purchase(product: product) { result in + self.purchase(product: product, promotionalOffer: promotionalOffer) { result in continuation.resume(with: result) } } @@ -103,15 +115,20 @@ final class IAPProvider: IIAPProvider { func purchase( product: StoreProduct, options: Set, + promotionalOffer: PromotionalOffer?, completion: @escaping SendableClosure> ) { - purchaseProvider.purchase(product: product, options: options, completion: completion) + purchaseProvider.purchase(product: product, options: options, promotionalOffer: promotionalOffer, completion: completion) } @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) - func purchase(product: StoreProduct, options: Set) async throws -> StoreTransaction { + func purchase( + product: StoreProduct, + options: Set, + promotionalOffer: PromotionalOffer? + ) async throws -> StoreTransaction { try await withCheckedThrowingContinuation { continuation in - purchase(product: product, options: options) { result in + purchase(product: product, options: options, promotionalOffer: promotionalOffer) { result in continuation.resume(with: result) } } @@ -152,6 +169,12 @@ final class IAPProvider: IIAPProvider { purchaseProvider.removeTransactionObserver() } + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func checkEligibility(productIDs: Set) async throws -> [String: SubscriptionEligibility] { + let products = try await fetch(productIDs: productIDs) + return try await eligibilityProvider.checkEligibility(products: products) + } + #if os(iOS) || VISION_OS @available(iOS 15.0, *) @available(macOS, unavailable) @@ -160,6 +183,22 @@ final class IAPProvider: IIAPProvider { func beginRefundRequest(productID: String) async throws -> RefundRequestStatus { try await refundProvider.beginRefundRequest(productID: productID) } + + @available(iOS 14.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func presentCodeRedemptionSheet() { + paymentQueue.presentCodeRedemptionSheet() + } + + @available(iOS 16.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func presentOfferCodeRedeemSheet() async throws { + try await redeemCodeProvider.presentOfferCodeRedeemSheet() + } #endif // MARK: Private diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift index ac7cf0bac..3e8899936 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift @@ -1,10 +1,12 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import StoreKit +// MARK: - IIAPProvider + /// Type that provides in-app purchase functionality. public protocol IIAPProvider { /// False if this device is not able or allowed to make payments @@ -34,8 +36,13 @@ public protocol IIAPProvider { /// /// - Parameters: /// - product: The product to be purchased. + /// - promotionalOffer: The promotional offer. /// - completion: The closure to be executed once the purchase is complete. - func purchase(product: StoreProduct, completion: @escaping Closure>) + func purchase( + product: StoreProduct, + promotionalOffer: PromotionalOffer?, + completion: @escaping Closure> + ) /// Purchases a product. /// @@ -43,12 +50,14 @@ public protocol IIAPProvider { /// If the user can't make a payment, the method returns an error /// with the type `IAPError.paymentNotAllowed`. /// - /// - Parameter product: The product to be purchased. + /// - Parameters: + /// - product: The product to be purchased. + /// - promotionalOffer: The promotional offer. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. - func purchase(product: StoreProduct) async throws -> StoreTransaction + func purchase(product: StoreProduct, promotionalOffer: PromotionalOffer?) async throws -> StoreTransaction /// Purchases a product with a given ID. /// @@ -59,6 +68,7 @@ public protocol IIAPProvider { /// - Parameters: /// - product: The product to be purchased. /// - options: The optional settings for a product purchase. + /// - promotionalOffer: The promotional offer. /// - completion: The closure to be executed once the purchase is complete. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. @@ -68,6 +78,7 @@ public protocol IIAPProvider { func purchase( product: StoreProduct, options: Set, + promotionalOffer: PromotionalOffer?, completion: @escaping SendableClosure> ) @@ -80,12 +91,17 @@ public protocol IIAPProvider { /// - Parameters: /// - product: The product to be purchased. /// - options: The optional settings for a product purchase. + /// - promotionalOffer: The promotional offer. /// /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. /// /// - Returns: A payment transaction. @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) - func purchase(product: StoreProduct, options: Set) async throws -> StoreTransaction + func purchase( + product: StoreProduct, + options: Set, + promotionalOffer: PromotionalOffer? + ) async throws -> StoreTransaction /// Refreshes the receipt, representing the user's transactions with your app. /// @@ -119,6 +135,14 @@ public protocol IIAPProvider { /// - Note: This may require that the user authenticate. func removeTransactionObserver() + /// Checks whether products are eligible for promotional offers + /// + /// - Parameter productIDs: The list of product identifiers for which you wish to check eligibility. + /// + /// - Returns: An array that contains information about the eligibility of products. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func checkEligibility(productIDs: Set) async throws -> [String: SubscriptionEligibility] + #if os(iOS) || VISION_OS /// Present the refund request sheet for the specified transaction in a window scene. /// @@ -130,5 +154,98 @@ public protocol IIAPProvider { @available(watchOS, unavailable) @available(tvOS, unavailable) func beginRefundRequest(productID: String) async throws -> RefundRequestStatus + + /// Displays a sheet that enables users to redeem subscription offer codes that you configure in App Store Connect. + @available(iOS 14.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func presentCodeRedemptionSheet() + + /// Displays a sheet in the window scene that enables users to redeem + /// a subscription offer code that you configure in App Store + /// Connect. + @available(iOS 16.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func presentOfferCodeRedeemSheet() async throws #endif } + +extension IIAPProvider { + /// Performs a purchase of a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - completion: The closure to be executed once the purchase is complete. + func purchase( + product: StoreProduct, + completion: @escaping Closure> + ) { + purchase(product: product, promotionalOffer: nil, completion: completion) + } + + /// Purchases a product. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameter product: The product to be purchased. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + func purchase(product: StoreProduct) async throws -> StoreTransaction { + try await purchase(product: product, promotionalOffer: nil) + } + + /// Purchases a product with a given ID. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// - completion: The closure to be executed once the purchase is complete. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping SendableClosure> + ) { + purchase(product: product, options: options, promotionalOffer: nil, completion: completion) + } + + /// Purchases a product with a given ID. + /// + /// - Note: The method automatically checks if the user can purchase a product. + /// If the user can't make a payment, the method returns an error + /// with the type `IAPError.paymentNotAllowed`. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// + /// - Throws: `IAPError.paymentNotAllowed` if user can't make payment. + /// + /// - Returns: A payment transaction. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set + ) async throws -> StoreTransaction { + try await purchase(product: product, options: options, promotionalOffer: nil) + } +} diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift index 3261143d0..be3f107a6 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Concurrency @@ -36,8 +36,8 @@ final class PaymentProvider: NSObject { /// - paymentQueue: The queue of payment transactions to be processed by the App Store. /// - dispatchQueueFactory: The dispatch queue factory. init( - paymentQueue: PaymentQueue = SKPaymentQueue.default(), - dispatchQueueFactory: IDispatchQueueFactory = DispatchQueueFactory() + paymentQueue: PaymentQueue, + dispatchQueueFactory: IDispatchQueueFactory ) { self.paymentQueue = paymentQueue self.dispatchQueueFactory = dispatchQueueFactory diff --git a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift index 183741bbb..ce5cbdf30 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Concurrency @@ -50,7 +50,7 @@ final class ProductProvider: NSObject, IProductProvider { // MARK: Private /// Dictionary to store request handlers with their corresponding request IDs. - private var handlers: [String: ProductsHandler] = [:] + private var handlers: [ProductsRequest: ProductsHandler] = [:] /// The dispatch queue factory for handling concurrent tasks. private let dispatchQueueFactory: IDispatchQueueFactory @@ -77,7 +77,7 @@ final class ProductProvider: NSObject, IProductProvider { /// - completion: A closure to be called upon completion with the fetched products. private func fetch(request: SKProductsRequest, completion: @escaping ProductsHandler) { dispatchQueue.async { - self.handlers[request.id] = completion + self.handlers[request.request] = completion self.dispatchQueueFactory.main().async { request.start() } @@ -90,7 +90,8 @@ final class ProductProvider: NSObject, IProductProvider { extension ProductProvider: SKProductsRequestDelegate { func request(_ request: SKRequest, didFailWithError error: Error) { dispatchQueue.async { - let handler = self.handlers.removeValue(forKey: request.id) + let handler = self.handlers.removeValue(forKey: request.request) + self.dispatchQueueFactory.main().async { handler?(.failure(IAPError(error: error))) } @@ -99,7 +100,7 @@ extension ProductProvider: SKProductsRequestDelegate { func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { dispatchQueue.async { - let handler = self.handlers.removeValue(forKey: request.id) + let handler = self.handlers.removeValue(forKey: request.request) guard response.invalidProductIdentifiers.isEmpty else { self.dispatchQueueFactory.main().async { @@ -114,3 +115,11 @@ extension ProductProvider: SKProductsRequestDelegate { } } } + +// MARK: - Helpers + +private extension SKRequest { + var request: ProductsRequest { + ProductsRequest(self) + } +} diff --git a/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift b/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift index a02d3fad4..2fb931923 100644 --- a/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift +++ b/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -35,19 +35,55 @@ protocol IPurchaseProvider { /// /// - Parameters: /// - product: The product to be purchased. + /// - promotionalOffer: The promotional offer. /// - completion: The closure to be executed once the purchase is complete. - func purchase(product: StoreProduct, completion: @escaping PurchaseCompletionHandler) + func purchase( + product: StoreProduct, + promotionalOffer: PromotionalOffer?, + completion: @escaping PurchaseCompletionHandler + ) /// Purchases a product. /// /// - Parameters: /// - product: The product to be purchased. /// - options: The optional settings for a product purchase. + /// - promotionalOffer: The promotional offer. /// - completion: The closure to be executed once the purchase is complete. @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) func purchase( product: StoreProduct, options: Set, + promotionalOffer: PromotionalOffer?, completion: @escaping PurchaseCompletionHandler ) } + +extension IPurchaseProvider { + /// Purchases a product. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - completion: The closure to be executed once the purchase is complete. + func purchase( + product: StoreProduct, + completion: @escaping PurchaseCompletionHandler + ) { + purchase(product: product, promotionalOffer: nil, completion: completion) + } + + /// Purchases a product. + /// + /// - Parameters: + /// - product: The product to be purchased. + /// - options: The optional settings for a product purchase. + /// - completion: The closure to be executed once the purchase is complete. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product: StoreProduct, + options: Set, + completion: @escaping PurchaseCompletionHandler + ) { + purchase(product: product, options: options, promotionalOffer: nil, completion: completion) + } +} diff --git a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift index ce26e3de3..ae5703cad 100644 --- a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift +++ b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift @@ -15,6 +15,8 @@ final class PurchaseProvider { private let paymentProvider: IPaymentProvider /// The transaction listener. private let transactionListener: ITransactionListener? + /// The configuration provider. + private let configurationProvider: IConfigurationProvider // MARK: Initialization @@ -23,11 +25,14 @@ final class PurchaseProvider { /// - Parameters: /// - paymentProvider: The provider is responsible for purchasing products. /// - transactionListener: The transaction listener. + /// - configurationProvider: The configuration provider. init( - paymentProvider: IPaymentProvider = PaymentProvider(), - transactionListener: ITransactionListener? = nil + paymentProvider: IPaymentProvider, + transactionListener: ITransactionListener? = nil, + configurationProvider: IConfigurationProvider ) { self.paymentProvider = paymentProvider + self.configurationProvider = configurationProvider if let transactionListener = transactionListener { self.transactionListener = transactionListener @@ -42,9 +47,12 @@ final class PurchaseProvider { private func purchase( sk1StoreProduct: SK1StoreProduct, + promotionalOffer: PromotionalOffer?, completion: @escaping @MainActor (Result) -> Void ) { - let payment = SKPayment(product: sk1StoreProduct.product) + let payment = SKMutablePayment(product: sk1StoreProduct.product) + payment.applicationUsername = configurationProvider.applicationUsername + payment.paymentDiscount = promotionalOffer?.signedData.skPromotionalOffer paymentProvider.add(payment: payment) { _, result in Task { switch result { @@ -61,9 +69,10 @@ final class PurchaseProvider { private func purchase( sk2StoreProduct: SK2StoreProduct, options: Set? = nil, + promotionalOffer: PromotionalOffer?, completion: @escaping @MainActor (Result) -> Void ) { - AsyncHandler.call(completion: { result in + AsyncHandler.call(completion: { (result: Result) in Task { switch result { case let .success(result): @@ -77,21 +86,39 @@ final class PurchaseProvider { } } }, asyncMethod: { - try await sk2StoreProduct.product.purchase(options: options ?? []) + var options: Set = options ?? [] + try self.configure(options: &options, promotionalOffer: promotionalOffer) + return try await sk2StoreProduct.product.purchase(options: options) }) } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + private func configure(options: inout Set, promotionalOffer: PromotionalOffer?) throws { + if let promotionalOffer { + try options.insert(promotionalOffer.signedData.promotionalOffer) + } + + if let applicationUsername = configurationProvider.applicationUsername, let uuid = UUID(uuidString: applicationUsername) { + // If options contain an app account token, the next line of code doesn't affect it. + options.insert(.appAccountToken(uuid)) + } + } } // MARK: IPurchaseProvider extension PurchaseProvider: IPurchaseProvider { - func purchase(product: StoreProduct, completion: @escaping PurchaseCompletionHandler) { + func purchase( + product: StoreProduct, + promotionalOffer: PromotionalOffer?, + completion: @escaping PurchaseCompletionHandler + ) { if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *), let sk2Product = product.underlyingProduct as? SK2StoreProduct { - self.purchase(sk2StoreProduct: sk2Product, completion: completion) + self.purchase(sk2StoreProduct: sk2Product, promotionalOffer: promotionalOffer, completion: completion) } else if let sk1Product = product.underlyingProduct as? SK1StoreProduct { - purchase(sk1StoreProduct: sk1Product, completion: completion) + purchase(sk1StoreProduct: sk1Product, promotionalOffer: promotionalOffer, completion: completion) } } @@ -99,10 +126,16 @@ extension PurchaseProvider: IPurchaseProvider { func purchase( product: StoreProduct, options: Set, + promotionalOffer: PromotionalOffer?, completion: @escaping PurchaseCompletionHandler ) { if let sk2Product = product.underlyingProduct as? SK2StoreProduct { - purchase(sk2StoreProduct: sk2Product, options: options, completion: completion) + purchase( + sk2StoreProduct: sk2Product, + options: options, + promotionalOffer: promotionalOffer, + completion: completion + ) } else { Task { await completion(.failure(.unknown)) diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift index 5585f0b34..9bf336936 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Concurrency @@ -38,10 +38,10 @@ final class ReceiptRefreshProvider: NSObject { /// - appStoreReceiptProvider: The type that retrieves the App Store receipt URL. /// - receiptRefreshRequestFactory: The receipt refresh request factory. init( - dispatchQueueFactory: IDispatchQueueFactory = DispatchQueueFactory(), + dispatchQueueFactory: IDispatchQueueFactory, fileManager: IFileManager = FileManager.default, appStoreReceiptProvider: IAppStoreReceiptProvider = Bundle.main, - receiptRefreshRequestFactory: IReceiptRefreshRequestFactory = ReceiptRefreshRequestFactory() + receiptRefreshRequestFactory: IReceiptRefreshRequestFactory ) { self.dispatchQueueFactory = dispatchQueueFactory self.fileManager = fileManager diff --git a/Sources/Flare/Classes/Providers/RedeemCodeProvider/IRedeemCodeProvider.swift b/Sources/Flare/Classes/Providers/RedeemCodeProvider/IRedeemCodeProvider.swift new file mode 100644 index 000000000..03981bec2 --- /dev/null +++ b/Sources/Flare/Classes/Providers/RedeemCodeProvider/IRedeemCodeProvider.swift @@ -0,0 +1,24 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// Protocol defining the requirements for a redeem code provider. +protocol IRedeemCodeProvider { + #if os(iOS) || VISION_OS + /// Displays a sheet in the window scene that enables users to redeem + /// a subscription offer code configured in App Store Connect. + /// + /// - Important: This method is available starting from iOS 16.0. + /// - Note: This method is not available on macOS, watchOS, or tvOS. + /// + /// - Throws: An error if there is an issue with presenting the redeem code sheet. + @available(iOS 16.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + func presentOfferCodeRedeemSheet() async throws + #endif +} diff --git a/Sources/Flare/Classes/Providers/RedeemCodeProvider/RedeemCodeProvider.swift b/Sources/Flare/Classes/Providers/RedeemCodeProvider/RedeemCodeProvider.swift new file mode 100644 index 000000000..a4301be86 --- /dev/null +++ b/Sources/Flare/Classes/Providers/RedeemCodeProvider/RedeemCodeProvider.swift @@ -0,0 +1,43 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import StoreKit + +// MARK: - RedeemCodeProvider + +/// A final class responsible for providing functionality related to redeeming offer codes. +final class RedeemCodeProvider { + // MARK: Properties + + /// An instance of a system information provider conforming to the `ISystemInfoProvider` + private let systemInfoProvider: ISystemInfoProvider + + // MARK: Initialization + + /// Initializes a `RedeemCodeProvider` instance with an optional system information provider. + /// + /// - Parameter systemInfoProvider: An instance of a system information provider. + /// Defaults to a new instance of `SystemInfoProvider` if not provided. + init(systemInfoProvider: ISystemInfoProvider = SystemInfoProvider()) { + self.systemInfoProvider = systemInfoProvider + } +} + +// MARK: IRedeemCodeProvider + +extension RedeemCodeProvider: IRedeemCodeProvider { + #if os(iOS) || VISION_OS + @available(iOS 16.0, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(tvOS, unavailable) + @MainActor + func presentOfferCodeRedeemSheet() async throws { + let windowScene = try systemInfoProvider.currentScene + try await AppStore.presentOfferCodeRedeemSheet(in: windowScene) + } + #endif +} diff --git a/Sources/Flare/Flare.docc/Articles/perform-purchase.md b/Sources/Flare/Flare.docc/Articles/perform-purchase.md index 55d439082..65f127781 100644 --- a/Sources/Flare/Flare.docc/Articles/perform-purchase.md +++ b/Sources/Flare/Flare.docc/Articles/perform-purchase.md @@ -10,7 +10,7 @@ The transactions array will only be synchronized with the server while the queue ```swift // Adds transaction observer to the payment queue and handles payment transactions. -Flare.default.addTransactionObserver { result in +Flare.shared.addTransactionObserver { result in switch result { case let .success(transaction): debugPrint("A transaction was received: \(transaction)") @@ -22,7 +22,7 @@ Flare.default.addTransactionObserver { result in ```swift // Removes transaction observer from the payment queue. -Flare.default.removeTransactionObserver() +Flare.shared.removeTransactionObserver() ``` ## Getting Products @@ -32,7 +32,7 @@ The fetch method sends a request to the App Store, which retrieves the products > important: Before attempting to add a payment always check if the user can actually make payments. The Flare does it under the hood, if a user cannot make payments, you will get an ``IAPError`` with the value ``IAPError/paymentNotAllowed``. ```swift -Flare.default.fetch(productIDs: ["product_id"]) { result in +Flare.shared.fetch(productIDs: ["product_id"]) { result in switch result { case let .success(products): debugPrint("Fetched products: \(products)") @@ -46,7 +46,7 @@ Additionally, there are versions of both fetch that provide an `async` method, a ```swift do { - let products = try await Flare.default.fetch(productIDs: Set(arrayLiteral: ["product_id"])) + let products = try await Flare.shared.fetch(productIDs: Set(arrayLiteral: ["product_id"])) } catch { debugPrint("An error occurred while fetching products: \(error.localizedDescription)") } @@ -64,7 +64,7 @@ Flare provides a few methods to perform a purchase: The method accepts a product parameter which represents a product: ```swift -Flare.default.purchase(product: product) { result in +Flare.shared.purchase(product: product) { result in switch result { case let .success(transaction): debugPrint("A transaction was received: \(transaction)") @@ -77,7 +77,7 @@ Flare.default.purchase(product: product) { result in If your app has a deployment target higher than iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, you can pass a set of [`options`](https://developer.apple.com/documentation/storekit/product/purchaseoption) along with a purchase request. ```swift -let transaction = try await Flare.default.purchase(product: product, options: [.appAccountToken(UUID())]) +let transaction = try await Flare.shared.purchase(product: product, options: [.appAccountToken(UUID())]) ``` ## Finishing Transaction @@ -87,7 +87,7 @@ Finishing a transaction tells StoreKit that your app completed its workflow to m To finish the transaction, call the ``IFlare/finish(transaction:completion:)`` method. ```swift -Flare.default.finish(transaction: transaction, completion: nil) +Flare.shared.finish(transaction: transaction, completion: nil) ``` > important: Don’t call the ``IFlare/finish(transaction:completion:)`` method before the transaction is actually complete and attempt to use some other mechanism in your app to track the transaction as unfinished. StoreKit doesn’t function that way, and doing that prevents your app from downloading Apple-hosted content and can lead to other issues. diff --git a/Sources/Flare/Flare.docc/Articles/promotional-offers.md b/Sources/Flare/Flare.docc/Articles/promotional-offers.md new file mode 100644 index 000000000..bdb9015c1 --- /dev/null +++ b/Sources/Flare/Flare.docc/Articles/promotional-offers.md @@ -0,0 +1,86 @@ +# Promotional Offers + +Learn how to use promotional offers. + +## Overview + +[Promotional offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_promotional_offers_in_your_app) can be effective in winning back lapsed subscribers or retaining current subscribers. You can provide lapsed or current subscribers a limited-time offer of a discounted or free period of service for auto-renewable subscriptions on macOS, iOS, and tvOS. + +[Introductory offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_introductory_offers_in_your_app#2940726) can offer a discounted introductory price, including a free trial, to eligible users. You can make introductory offers to customers who haven’t previously received an introductory offer for the given product, or for any products in the same subscription group. + +> note: To implement the offers, first complete the setup on App Store Connect, including generating a private key. See [Setting up promotional offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/setting_up_promotional_offers) for more details. + +## Introductory Offers + +> important: Do not show a subscription offer to users if they are not eligible for it. It’s very important to check this beforehand. + +First, check if the user is eligible for an introductory offer. + +> tip For this purpose can be used ``IFlare/checkEligibility(productIDs:)`` method. This method requires iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0. Otherwise, see [Determine Eligibility](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_introductory_offers_in_your_app#2940726). + +```swift +func isEligibleForIntroductoryOffer(productID: String) async -> Bool { + let dict = await Flare.shared.checkEligibility(productIDs: [productID]) + return dict[productID] == .eligible +} +``` + +Second, proceed with the purchase as usual. See [Perform Purchase]() + +## Promotional Offers + +First, you need to fetch the signature from your server. See [Generation a signature for promotional offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/generating_a_signature_for_promotional_offers) for more information. + +Second, configure ``IFlare`` with a ``Configuration``. + +```swift +Flare.configure(configuration: Configuration(applicationUsername: "username")) +``` + +Third, request a signature from your server and prepare the discount offer. + +```swift +func prepareOffer(username: String, productID: String, offerID: String, completion: @escaping (PromotionalOffer.SignedData) -> Void) { + YourServer.fetchOfferDetails( + username: username, + productIdentifier: productID, + offerIdentifier: offerID, + completion: { (nonce: UUID, timestamp: NSNumber, keyIdentifier: String, signature: String) in + let signedData = PromotionalOffer.SignedData( + identifier: offerID, + keyIdentifier: keyIdentifier, + nonce: nonce, + signature: signature, + timestamp: timestamp + ) + + completion(signedData) + } +} +``` + +Fourth, complete the purchase with the promotional offer. + +```swift +func purchase(product: StoreProduct, discount: StoreProductDiscount, signedData: SignedData) { + let promotionalOffer = PromotionalOffer(discount: discount, signedData: signedData) + + Flare.default.purchase(product: product, promotionalOffer: promotionalOffer) { result in + switch result { + case let .success(transaction): + break + case let .failure(error): + break + } + } + + // Or using async/await + let transaction = Flare.shared.purchase(product: product, promotionalOffer: promotionalOffer) +} +``` + +Fifth, complete the transaction. + +```swift +Flare.default.finish(transaction: transaction) +``` diff --git a/Sources/Flare/Flare.docc/Articles/refund-purchase.md b/Sources/Flare/Flare.docc/Articles/refund-purchase.md index f4f551738..46ab24f6d 100644 --- a/Sources/Flare/Flare.docc/Articles/refund-purchase.md +++ b/Sources/Flare/Flare.docc/Articles/refund-purchase.md @@ -9,7 +9,7 @@ Starting with iOS 15, Flare now includes support for refunding purchases as part Flare suggest to use ``IFlare/beginRefundRequest(productID:)`` for refunding purchase. ```swift -let status = try await Flare.default.beginRefundRequest(productID: "product_id") +let status = try await Flare.shared.beginRefundRequest(productID: "product_id") ``` > important: If an issue occurs during the refund process, this method throws an ``IAPError/refund(error:)`` error. diff --git a/Sources/Flare/Flare.docc/Articles/restore-purchase.md b/Sources/Flare/Flare.docc/Articles/restore-purchase.md index 18dae9f76..1164954b4 100644 --- a/Sources/Flare/Flare.docc/Articles/restore-purchase.md +++ b/Sources/Flare/Flare.docc/Articles/restore-purchase.md @@ -17,7 +17,7 @@ Use this API to request a new app receipt from the App Store if the receipt is i > important: The receipt refresh request displays a system prompt that asks users to authenticate with their App Store credentials. For a better user experience, initiate the request after an explicit user action, like tapping or clicking a button. ```swift -Flare.default.receipt { result in +Flare.shared.receipt { result in switch result { case let .success(receipt): // Handle a receipt @@ -32,5 +32,5 @@ Flare.default.receipt { result in There is an ``IFlare/receipt()`` method for obtaining a receipt using async/await. ```swift -let receipt = try await Flare.default.receipt() +let receipt = try await Flare.shared.receipt() ``` diff --git a/Sources/Flare/Flare.docc/Flare.md b/Sources/Flare/Flare.docc/Flare.md index 0682d736d..847fb53fa 100644 --- a/Sources/Flare/Flare.docc/Flare.md +++ b/Sources/Flare/Flare.docc/Flare.md @@ -10,11 +10,11 @@ Flare provides a clear and convenient API for making in-app purchases. import Flare /// Fetch a product with the given id -guard let product = try await Flare.default.products(productIDs: ["product_identifier"]) else { return } +guard let product = try await Flare.shared.products(productIDs: ["product_identifier"]) else { return } /// Purchase a product -let transaction = try await Flare.default.purchase(product: product) +let transaction = try await Flare.shared.purchase(product: product) /// Finish a transaction -Flare.default.finish(transaction: transaction, completion: nil) +Flare.shared.finish(transaction: transaction, completion: nil) ``` Flare supports both StoreKit and StoreKit2; it decides which one to use under the hood based on the operating system version. Flare provides two ways to work with in-app purchases (IAP): it supports the traditional closure-based syntax and the modern async/await approach. @@ -23,7 +23,7 @@ Flare supports both StoreKit and StoreKit2; it decides which one to use under th import Flare /// Fetch a product with the given id -Flare.default.products(productIDs: ["product_identifier"]) { result in +Flare.shared.products(productIDs: ["product_identifier"]) { result in switch result { case let .success(products): // Purchase a product @@ -64,3 +64,4 @@ flare is available under the MIT license. See the LICENSE file for more info. - - - +- diff --git a/Tests/FlareTests/UnitTests/FlareTests.swift b/Tests/FlareTests/UnitTests/FlareTests.swift index 33cc4debc..6998e78bf 100644 --- a/Tests/FlareTests/UnitTests/FlareTests.swift +++ b/Tests/FlareTests/UnitTests/FlareTests.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // @testable import Flare @@ -12,7 +12,9 @@ import XCTest class FlareTests: XCTestCase { // MARK: - Properties + private var dependenciesMock: FlareDependenciesMock! private var iapProviderMock: IAPProviderMock! + private var configurationProviderMock: ConfigurationProviderMock! private var sut: Flare! @@ -21,10 +23,16 @@ class FlareTests: XCTestCase { override func setUp() { super.setUp() iapProviderMock = IAPProviderMock() - sut = Flare(iapProvider: iapProviderMock) + dependenciesMock = FlareDependenciesMock() + configurationProviderMock = ConfigurationProviderMock() + dependenciesMock.stubbedIapProvider = iapProviderMock + dependenciesMock.stubbedConfigurationProvider = configurationProviderMock + sut = Flare(dependencies: dependenciesMock) } override func tearDown() { + configurationProviderMock = nil + dependenciesMock = nil iapProviderMock = nil sut = nil super.tearDown() @@ -64,8 +72,8 @@ class FlareTests: XCTestCase { sut.purchase(product: .fake(skProduct: .fake(id: .productID)), completion: { _ in }) // then - XCTAssertTrue(iapProviderMock.invokedPurchase) - XCTAssertEqual(iapProviderMock.invokedPurchaseParameters?.product.productIdentifier, .productID) + XCTAssertTrue(iapProviderMock.invokedPurchaseWithPromotionalOffer) + XCTAssertEqual(iapProviderMock.invokedPurchaseWithPromotionalOfferParameters?.product.productIdentifier, .productID) } func test_thatFlareThrowsAnError_whenUserCannotMakePayments() { @@ -83,6 +91,7 @@ class FlareTests: XCTestCase { // given let paymentTransaction = StoreTransaction(storeTransaction: StoreTransactionStub()) iapProviderMock.stubbedCanMakePayments = true + iapProviderMock.stubbedPurchaseWithPromotionalOffer = .success(paymentTransaction) // when var transaction: IStoreTransaction? @@ -92,7 +101,7 @@ class FlareTests: XCTestCase { iapProviderMock.invokedPurchaseParameters?.completion(.success(paymentTransaction)) // then - XCTAssertTrue(iapProviderMock.invokedPurchase) + XCTAssertTrue(iapProviderMock.invokedPurchaseWithPromotionalOffer) XCTAssertEqual(transaction?.productIdentifier, paymentTransaction.productIdentifier) } @@ -100,6 +109,7 @@ class FlareTests: XCTestCase { // given let errorMock = IAPError.paymentNotAllowed iapProviderMock.stubbedCanMakePayments = true + iapProviderMock.stubbedPurchaseWithPromotionalOffer = .failure(errorMock) // when var error: IAPError? @@ -109,7 +119,7 @@ class FlareTests: XCTestCase { iapProviderMock.invokedPurchaseParameters?.completion(.failure(errorMock)) // then - XCTAssertTrue(iapProviderMock.invokedPurchase) + XCTAssertTrue(iapProviderMock.invokedPurchaseWithPromotionalOffer) XCTAssertEqual(error, errorMock) } @@ -131,13 +141,13 @@ class FlareTests: XCTestCase { let transactionMock = StoreTransaction(storeTransaction: StoreTransactionStub()) iapProviderMock.stubbedCanMakePayments = true - iapProviderMock.stubbedAsyncPurchase = transactionMock + iapProviderMock.stubbedPurchaseAsyncWithPromotionalOffer = transactionMock // when let transaction = await value(for: { try await sut.purchase(product: .fake(skProduct: .fake(id: .productID))) }) // then - XCTAssertTrue(iapProviderMock.invokedAsyncPurchase) + XCTAssertTrue(iapProviderMock.invokedPurchaseAsyncWithPromotionalOffer) XCTAssertEqual(transaction?.productIdentifier, transactionMock.productIdentifier) } @@ -213,6 +223,19 @@ class FlareTests: XCTestCase { // then XCTAssertTrue(iapProviderMock.invokedAddTransactionObserver) } + + @available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) + func test_thatFlareChecksEligibility() async throws { + // given + iapProviderMock.stubbedCheckEligibility = [.productID: .eligible] + + // when + let _ = try await sut.checkEligibility(productIDs: [.productID]) + + // then + XCTAssertEqual(iapProviderMock.invokedCheckEligibilityCount, 1) + XCTAssertEqual(iapProviderMock.invokedCheckEligibilityParameters?.productIDs, [.productID]) + } } // MARK: - Constants diff --git a/Tests/FlareTests/UnitTests/Models/PromotionalOfferTests.swift b/Tests/FlareTests/UnitTests/Models/PromotionalOfferTests.swift new file mode 100644 index 000000000..e172dc4ab --- /dev/null +++ b/Tests/FlareTests/UnitTests/Models/PromotionalOfferTests.swift @@ -0,0 +1,56 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import StoreKit +import XCTest + +// MARK: - PromotionalOfferTests + +final class PromotionalOfferTests: XCTestCase { + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func test_purchaseOptions() throws { + let option = try PromotionalOffer.SignedData.randomOffer.promotionalOffer + let expected: Product.PurchaseOption = .promotionalOffer( + offerID: PromotionalOffer.SignedData.randomOffer.identifier, + keyID: PromotionalOffer.SignedData.randomOffer.keyIdentifier, + nonce: PromotionalOffer.SignedData.randomOffer.nonce, + signature: Data(), + timestamp: PromotionalOffer.SignedData.randomOffer.timestamp + ) + + XCTAssertEqual(expected, option) + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func test_purchaseOptionWithInvalidSignatureThrows() throws { + do { + _ = try PromotionalOffer.SignedData.invalidOffer.promotionalOffer + } catch { + let error = try XCTUnwrap(error as? IAPError) + XCTAssertEqual(error, IAPError.failedToDecodeSignature(signature: PromotionalOffer.SignedData.invalidOffer.signature)) + } + } +} + +// MARK: - Constants + +private extension PromotionalOffer.SignedData { + static let randomOffer: PromotionalOffer.SignedData = .init( + identifier: "identifier \(Int.random(in: 0 ..< 1000))", + keyIdentifier: "key identifier \(Int.random(in: 0 ..< 1000))", + nonce: .init(), + signature: "signature \(Int.random(in: 0 ..< 1000))".asData.base64EncodedString(), + timestamp: Int.random(in: 0 ..< 1000) + ) + + static let invalidOffer: PromotionalOffer.SignedData = .init( + identifier: "identifier \(Int.random(in: 0 ..< 1000))", + keyIdentifier: "key identifier \(Int.random(in: 0 ..< 1000))", + nonce: .init(), + signature: "signature \(Int.random(in: 0 ..< 1000))", + timestamp: Int.random(in: 0 ..< 1000) + ) +} diff --git a/Tests/FlareTests/UnitTests/Providers/ConfigurationProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ConfigurationProviderTests.swift new file mode 100644 index 000000000..634f230be --- /dev/null +++ b/Tests/FlareTests/UnitTests/Providers/ConfigurationProviderTests.swift @@ -0,0 +1,67 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import XCTest + +// MARK: - ConfigurationProviderTests + +final class ConfigurationProviderTests: XCTestCase { + // MARK: Properties + + private var cacheProviderMock: CacheProviderMock! + + private var sut: ConfigurationProvider! + + // MARK: Initialization + + override func setUp() { + super.setUp() + cacheProviderMock = CacheProviderMock() + sut = ConfigurationProvider( + cacheProvider: cacheProviderMock + ) + } + + override func tearDown() { + cacheProviderMock = nil + sut = nil + super.tearDown() + } + + // MARK: Tests + + func test_thatCacheProviderReturnsApplicationUsername_whenUsernameExists() { + // given + cacheProviderMock.stubbedReadResult = String.applicationUsername + + // when + let applicationUsername = sut.applicationUsername + + // then + XCTAssertEqual(cacheProviderMock.invokedReadParameters?.key, .applicationUsernameKey) + XCTAssertEqual(applicationUsername, .applicationUsername) + } + + func test_thatCacheProviderConfigures() { + // given + let configurationFake = Configuration.fake() + + // when + sut.configure(with: configurationFake) + + // then + XCTAssertEqual(cacheProviderMock.invokedWriteParameters?.key, .applicationUsernameKey) + XCTAssertEqual(cacheProviderMock.invokedWriteParameters?.value as? String, configurationFake.applicationUsername) + } +} + +// MARK: - Constants + +private extension String { + static let applicationUsername = "application_username" + + static let applicationUsernameKey = "flare.configuration.application_username" +} diff --git a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift index 319d97f15..a9793760c 100644 --- a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // @testable import Flare @@ -34,7 +34,9 @@ class IAPProviderTests: XCTestCase { productProvider: productProviderMock, purchaseProvider: purchaseProvider, receiptRefreshProvider: receiptRefreshProviderMock, - refundProvider: refundProviderMock + refundProvider: refundProviderMock, + eligibilityProvider: EligibilityProviderMock(), + redeemCodeProvider: RedeemCodeProviderMock() ) } diff --git a/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift index af4b7a49a..abc7c95e9 100644 --- a/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // @testable import Flare @@ -25,7 +25,8 @@ final class PurchaseProviderTests: XCTestCase { paymentQueueMock = PaymentQueueMock() paymentProviderMock = PaymentProviderMock() sut = PurchaseProvider( - paymentProvider: paymentProviderMock + paymentProvider: paymentProviderMock, + configurationProvider: ConfigurationProviderMock() ) } diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Extensions/String+Data.swift b/Tests/FlareTests/UnitTests/TestHelpers/Extensions/String+Data.swift new file mode 100644 index 000000000..50643fa69 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Extensions/String+Data.swift @@ -0,0 +1,12 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +extension String { + var asData: Data { + Data(utf8) + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Fakes/Configuration+Fake.swift b/Tests/FlareTests/UnitTests/TestHelpers/Fakes/Configuration+Fake.swift new file mode 100644 index 000000000..7ffdd13d5 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Fakes/Configuration+Fake.swift @@ -0,0 +1,13 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +extension Configuration { + static func fake(applicationUsername: String = "username") -> Configuration { + Configuration(applicationUsername: applicationUsername) + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/CacheProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/CacheProviderMock.swift new file mode 100644 index 000000000..413504174 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/CacheProviderMock.swift @@ -0,0 +1,35 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class CacheProviderMock: ICacheProvider { + var invokedRead = false + var invokedReadCount = 0 + var invokedReadParameters: (key: String, Void)? + var invokedReadParametersList = [(key: String, Void)]() + var stubbedReadResult: Any! + + func read(key: String) -> T? { + invokedRead = true + invokedReadCount += 1 + invokedReadParameters = (key, ()) + invokedReadParametersList.append((key, ())) + return stubbedReadResult as? T + } + + var invokedWrite = false + var invokedWriteCount = 0 + var invokedWriteParameters: (key: String, value: Any)? + var invokedWriteParametersList = [(key: String, value: Any)]() + + func write(key: String, value: T) { + invokedWrite = true + invokedWriteCount += 1 + invokedWriteParameters = (key, value) + invokedWriteParametersList.append((key, value)) + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/CacheProviderTests.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/CacheProviderTests.swift new file mode 100644 index 000000000..55ae8c599 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/CacheProviderTests.swift @@ -0,0 +1,61 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import XCTest + +// MARK: - CacheProviderTests + +final class CacheProviderTests: XCTestCase { + // MARK: Properties + + private var userDefaultsMock: UserDefaultsMock! + + private var sut: CacheProvider! + + // MARK: XCTestCase + + override func setUp() { + super.setUp() + userDefaultsMock = UserDefaultsMock() + sut = CacheProvider(userDefaults: userDefaultsMock) + } + + override func tearDown() { + userDefaultsMock = nil + sut = nil + super.tearDown() + } + + // MARK: Tests + + func test_write() { + // when + sut.write(key: .key, value: String.value) + + // then + XCTAssertEqual(userDefaultsMock.invokedSetParameters?.key, .key) + XCTAssertEqual(userDefaultsMock.invokedSetParameters?.codable as? String, String.value) + } + + func test_read() { + // given + userDefaultsMock.stubbedGetResult = String.value + + // when + let value: String? = sut.read(key: .key) + + // then + XCTAssertEqual(userDefaultsMock.invokedGetParameters?.key, .key) + XCTAssertEqual(value, String.value) + } +} + +// MARK: - Constants + +private extension String { + static let key = "key" + static let value = "value" +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ConfigurationProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ConfigurationProviderMock.swift new file mode 100644 index 000000000..0f460b5c0 --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ConfigurationProviderMock.swift @@ -0,0 +1,31 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class ConfigurationProviderMock: IConfigurationProvider { + var invokedApplicationUsernameGetter = false + var invokedApplicationUsernameGetterCount = 0 + var stubbedApplicationUsername: String! + + var applicationUsername: String? { + invokedApplicationUsernameGetter = true + invokedApplicationUsernameGetterCount += 1 + return stubbedApplicationUsername + } + + var invokedConfigure = false + var invokedConfigureCount = 0 + var invokedConfigureParameters: (configuration: Configuration, Void)? + var invokedConfigureParametersList = [(configuration: Configuration, Void)]() + + func configure(with configuration: Configuration) { + invokedConfigure = true + invokedConfigureCount += 1 + invokedConfigureParameters = (configuration, ()) + invokedConfigureParametersList.append((configuration, ())) + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/EligibilityProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/EligibilityProviderMock.swift new file mode 100644 index 000000000..94578e24b --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/EligibilityProviderMock.swift @@ -0,0 +1,23 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class EligibilityProviderMock: IEligibilityProvider { + var invokedCheckEligibility = false + var invokedCheckEligibilityCount = 0 + var invokedCheckEligibilityParameters: (products: [StoreProduct], Void)? + var invokedCheckEligibilityParametersList = [(products: [StoreProduct], Void)]() + var stubbedCheckEligibility: [String: SubscriptionEligibility] = [:] + + func checkEligibility(products: [StoreProduct]) async throws -> [String: SubscriptionEligibility] { + invokedCheckEligibility = true + invokedCheckEligibilityCount += 1 + invokedCheckEligibilityParameters = (products, ()) + invokedCheckEligibilityParametersList.append((products, ())) + return stubbedCheckEligibility + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/FlareDependenciesMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/FlareDependenciesMock.swift new file mode 100644 index 000000000..ac2886dba --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/FlareDependenciesMock.swift @@ -0,0 +1,29 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class FlareDependenciesMock: IFlareDependencies { + var invokedIapProviderGetter = false + var invokedIapProviderGetterCount = 0 + var stubbedIapProvider: IIAPProvider! + + var iapProvider: IIAPProvider { + invokedIapProviderGetter = true + invokedIapProviderGetterCount += 1 + return stubbedIapProvider + } + + var invokedConfigurationProviderGetter = false + var invokedConfigurationProviderGetterCount = 0 + var stubbedConfigurationProvider: IConfigurationProvider! + + var configurationProvider: IConfigurationProvider { + invokedConfigurationProviderGetter = true + invokedConfigurationProviderGetterCount += 1 + return stubbedConfigurationProvider + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift index e6a194485..1d05ea36c 100644 --- a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // @testable import Flare @@ -190,4 +190,98 @@ final class IAPProviderMock: IIAPProvider { invokedAsyncPurchaseWithOptionsParametersList.append((product, options)) return stubbedAsyncPurchaseWithOptions } + + var invokedPurchaseWithPromotionalOffer = false + var invokedPurchaseWithPromotionalOfferCount = 0 + var invokedPurchaseWithPromotionalOfferParameters: (product: StoreProduct, promotionalOffer: PromotionalOffer?)? + var invokedPurchaseWithPromotionalOfferParametersList = [(product: StoreProduct, VpromotionalOffer: PromotionalOffer?)]() + var stubbedPurchaseWithPromotionalOffer: Result? + + func purchase( + product: StoreProduct, + promotionalOffer: PromotionalOffer?, + completion: @escaping Closure> + ) { + invokedPurchaseWithPromotionalOffer = true + invokedPurchaseWithPromotionalOfferCount += 1 + invokedPurchaseWithPromotionalOfferParameters = (product, promotionalOffer) + invokedPurchaseWithPromotionalOfferParametersList.append((product, promotionalOffer)) + + if let result = stubbedPurchaseWithPromotionalOffer { + completion(result) + } + } + + var invokedPurchaseAsyncWithPromotionalOffer = false + var invokedPurchaseAsyncWithPromotionalOfferCount = 0 + var invokedPurchaseAsyncWithPromotionalOfferParameters: (product: StoreProduct, promotionalOffer: PromotionalOffer?)? + var invokedPurchaseAsyncWithPromotionalOfferParametersList = [(product: StoreProduct, VpromotionalOffer: PromotionalOffer?)]() + var stubbedPurchaseAsyncWithPromotionalOffer: StoreTransaction! + + func purchase( + product: StoreProduct, + promotionalOffer: PromotionalOffer? + ) async throws -> StoreTransaction { + invokedPurchaseAsyncWithPromotionalOffer = true + invokedPurchaseAsyncWithPromotionalOfferCount += 1 + invokedPurchaseAsyncWithPromotionalOfferParameters = (product, promotionalOffer) + invokedPurchaseAsyncWithPromotionalOfferParametersList.append((product, promotionalOffer)) + return stubbedPurchaseAsyncWithPromotionalOffer + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product _: StoreProduct, + options _: Set, + promotionalOffer _: PromotionalOffer?, + completion _: @escaping SendableClosure> + ) {} + + var invokedPurchaseWithOptionsAndPromotionalOffer = false + var invokedPurchaseWithOptionsAndPromotionalOfferCount = 0 + var stubbedPurchaseWithOptionsAndPromotionalOffer: StoreTransaction! + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func purchase( + product _: StoreProduct, + options _: Set, + promotionalOffer _: PromotionalOffer? + ) async throws -> StoreTransaction { + invokedPurchaseWithOptionsAndPromotionalOffer = true + invokedPurchaseWithOptionsAndPromotionalOfferCount += 1 + return stubbedPurchaseWithOptionsAndPromotionalOffer + } + + var invokedCheckEligibility = false + var invokedCheckEligibilityCount = 0 + var invokedCheckEligibilityParameters: (productIDs: Set, Void)? + var invokedCheckEligibilityParametersList = [(productIDs: Set, Void)]() + var stubbedCheckEligibility: [String: SubscriptionEligibility] = [:] + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func checkEligibility(productIDs: Set) async throws -> [String: SubscriptionEligibility] { + invokedCheckEligibility = true + invokedCheckEligibilityCount += 1 + invokedCheckEligibilityParameters = (productIDs, ()) + invokedCheckEligibilityParametersList = [(productIDs, ())] + return stubbedCheckEligibility + } + + var invokedPresentCodeRedemptionSheet = false + var invokedPresentCodeRedemptionSheetCount = 0 + + @available(iOS 14.0, *) + func presentCodeRedemptionSheet() { + invokedPresentCodeRedemptionSheet = true + invokedPresentCodeRedemptionSheetCount += 1 + } + + var invokedPresentOfferCodeRedeemSheet = false + var invokedPresentOfferCodeRedeemSheetCount = 0 + + @available(iOS 16.0, *) + func presentOfferCodeRedeemSheet() async throws { + invokedPresentOfferCodeRedeemSheet = true + invokedPresentOfferCodeRedeemSheetCount += 1 + } } diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift index b24200266..7ccf9b076 100644 --- a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // @testable import Flare @@ -41,16 +41,16 @@ final class PurchaseProviderMock: IPurchaseProvider { var invokedPurchase = false var invokedPurchaseCount = 0 - var invokedPurchaseParameters: (product: StoreProduct, Void)? - var invokedPurchaseParametersList = [(product: StoreProduct, Void)]() + var invokedPurchaseParameters: (product: StoreProduct, promotionalOffer: PromotionalOffer?)? + var invokedPurchaseParametersList = [(product: StoreProduct, promotionalOffer: PromotionalOffer?)]() var stubbedPurchaseCompletionResult: (Result, Void)? @MainActor - func purchase(product: StoreProduct, completion: @escaping PurchaseCompletionHandler) { + func purchase(product: StoreProduct, promotionalOffer: PromotionalOffer?, completion: @escaping PurchaseCompletionHandler) { invokedPurchase = true invokedPurchaseCount += 1 - invokedPurchaseParameters = (product, ()) - invokedPurchaseParametersList.append((product, ())) + invokedPurchaseParameters = (product, promotionalOffer) + invokedPurchaseParametersList.append((product, promotionalOffer)) if let result = stubbedPurchaseCompletionResult { completion(result.0) } @@ -58,8 +58,8 @@ final class PurchaseProviderMock: IPurchaseProvider { var invokedPurchaseWithOptions = false var invokedPurchaseWithOptionsCount = 0 - var invokedPurchaseWithOptionsParameters: (product: StoreProduct, Any)? - var invokedPurchaseWithOptionsParametersList = [(product: StoreProduct, Any)]() + var invokedPurchaseWithOptionsParameters: (product: StoreProduct, Any, promotionalOffer: PromotionalOffer?)? + var invokedPurchaseWithOptionsParametersList = [(product: StoreProduct, Any, promotionalOffer: PromotionalOffer?)]() var stubbedinvokedPurchaseWithOptionsCompletionResult: (Result, Void)? @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) @@ -67,12 +67,13 @@ final class PurchaseProviderMock: IPurchaseProvider { func purchase( product: StoreProduct, options: Set, + promotionalOffer: PromotionalOffer?, completion: @escaping PurchaseCompletionHandler ) { invokedPurchaseWithOptions = true invokedPurchaseWithOptionsCount += 1 - invokedPurchaseWithOptionsParameters = (product, options) - invokedPurchaseWithOptionsParametersList.append((product, options)) + invokedPurchaseWithOptionsParameters = (product, options, promotionalOffer) + invokedPurchaseWithOptionsParametersList.append((product, options, promotionalOffer)) if let result = stubbedinvokedPurchaseWithOptionsCompletionResult { completion(result.0) diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/RedeemCodeProvider.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/RedeemCodeProvider.swift new file mode 100644 index 000000000..0f3f03a5f --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/RedeemCodeProvider.swift @@ -0,0 +1,17 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class RedeemCodeProviderMock: IRedeemCodeProvider { + var invokedPresentOfferCodeRedeemSheet = false + var invokedPresentOfferCodeRedeemSheetCount = 0 + + func presentOfferCodeRedeemSheet() async { + invokedPresentOfferCodeRedeemSheet = true + invokedPresentOfferCodeRedeemSheetCount += 1 + } +} diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/UserDefaultsMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/UserDefaultsMock.swift new file mode 100644 index 000000000..f1a341fec --- /dev/null +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/UserDefaultsMock.swift @@ -0,0 +1,35 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import Foundation + +final class UserDefaultsMock: IUserDefaults { + var invokedSet = false + var invokedSetCount = 0 + var invokedSetParameters: (key: String, codable: Any)? + var invokedSetParametersList = [(key: String, codable: Any)]() + + func set(key: String, codable: T) { + invokedSet = true + invokedSetCount += 1 + invokedSetParameters = (key, codable) + invokedSetParametersList.append((key, codable)) + } + + var invokedGet = false + var invokedGetCount = 0 + var invokedGetParameters: (key: String, Void)? + var invokedGetParametersList = [(key: String, Void)]() + var stubbedGetResult: Any! + + func get(key: String) -> T? { + invokedGet = true + invokedGetCount += 1 + invokedGetParameters = (key, ()) + invokedGetParametersList.append((key, ())) + return stubbedGetResult as? T + } +} diff --git a/Tests/IntegrationTests/Flare.storekit b/Tests/IntegrationTests/Flare.storekit index 102d022b8..23d0dd415 100644 --- a/Tests/IntegrationTests/Flare.storekit +++ b/Tests/IntegrationTests/Flare.storekit @@ -4,36 +4,6 @@ ], "products" : [ - { - "displayPrice" : "0.99", - "familyShareable" : false, - "internalID" : "169432A7", - "localizations" : [ - { - "description" : "com.flare.test_purchase_1", - "displayName" : "com.flare.test_purchase_1", - "locale" : "en_US" - } - ], - "productID" : "com.flare.test_purchase_1", - "referenceName" : "com.flare.test_purchase_1", - "type" : "Consumable" - }, - { - "displayPrice" : "0.99", - "familyShareable" : false, - "internalID" : "33E61322", - "localizations" : [ - { - "description" : "com.flare.test_purchase_2", - "displayName" : "com.flare.test_purchase_2", - "locale" : "en_US" - } - ], - "productID" : "com.flare.test_purchase_2", - "referenceName" : "com.flare.test_purchase_2", - "type" : "Consumable" - }, { "displayPrice" : "0.99", "familyShareable" : false, @@ -51,13 +21,222 @@ } ], "settings" : { - + "_failTransactionsEnabled" : false, + "_locale" : "en_US", + "_storefront" : "USA", + "_storeKitErrors" : [ + { + "current" : null, + "enabled" : false, + "name" : "Load Products" + }, + { + "current" : null, + "enabled" : false, + "name" : "Purchase" + }, + { + "current" : null, + "enabled" : false, + "name" : "Verification" + }, + { + "current" : null, + "enabled" : false, + "name" : "App Store Sync" + }, + { + "current" : null, + "enabled" : false, + "name" : "Subscription Status" + }, + { + "current" : null, + "enabled" : false, + "name" : "App Transaction" + }, + { + "current" : null, + "enabled" : false, + "name" : "Manage Subscriptions Sheet" + }, + { + "current" : null, + "enabled" : false, + "name" : "Refund Request Sheet" + }, + { + "current" : null, + "enabled" : false, + "name" : "Offer Code Redeem Sheet" + } + ] }, "subscriptionGroups" : [ + { + "id" : "C3C61FEC", + "localizations" : [ + + ], + "name" : "subscription_group", + "subscriptions" : [ + { + "adHocOffers" : [ + ], + "codeOffers" : [ + + ], + "displayPrice" : "1.99", + "familyShareable" : false, + "groupNumber" : 1, + "internalID" : "138CEE33", + "introductoryOffer" : { + "displayPrice" : "0.99", + "internalID" : "970CA16D", + "numberOfPeriods" : 1, + "paymentMode" : "payAsYouGo", + "subscriptionPeriod" : "P1M" + }, + "localizations" : [ + { + "description" : "", + "displayName" : "", + "locale" : "en_US" + } + ], + "productID" : "com.flare.monthly_1.99_week_intro", + "recurringSubscriptionPeriod" : "P1M", + "referenceName" : "Subscription with Introductory Offer", + "subscriptionGroupID" : "C3C61FEC", + "type" : "RecurringSubscription" + }, + { + "adHocOffers" : [ + + ], + "codeOffers" : [ + + ], + "displayPrice" : "0.99", + "familyShareable" : false, + "groupNumber" : 1, + "internalID" : "9CB5F7A9", + "introductoryOffer" : null, + "localizations" : [ + { + "description" : "", + "displayName" : "", + "locale" : "en_US" + } + ], + "productID" : "com.flare.monthly_0.99", + "recurringSubscriptionPeriod" : "P1M", + "referenceName" : "Subscription Without Offers", + "subscriptionGroupID" : "C3C61FEC", + "type" : "RecurringSubscription" + }, + { + "adHocOffers" : [ + { + "internalID" : "479390B8", + "offerID" : "subscription_3_offer", + "paymentMode" : "free", + "referenceName" : "subscription_3_offer", + "subscriptionPeriod" : "P2W" + } + ], + "codeOffers" : [ + + ], + "displayPrice" : "0.99", + "familyShareable" : false, + "groupNumber" : 1, + "internalID" : "8D29D6BD", + "introductoryOffer" : null, + "localizations" : [ + { + "description" : "", + "displayName" : "", + "locale" : "en_US" + } + ], + "productID" : "com.flare.monthly_1.99_two_weeks_offer.free", + "recurringSubscriptionPeriod" : "P1M", + "referenceName" : "Subscription with Promotional Offer", + "subscriptionGroupID" : "C3C61FEC", + "type" : "RecurringSubscription" + }, + { + "adHocOffers" : [ + { + "displayPrice" : "0.99", + "internalID" : "A05B39A3", + "numberOfPeriods" : 1, + "offerID" : "com.flare.monthly_0.99.1_week_intro", + "paymentMode" : "payAsYouGo", + "referenceName" : "com.flare.monthly_0.99.1_week_intro", + "subscriptionPeriod" : "P1M" + }, + { + "displayPrice" : "1.99", + "internalID" : "79BD229A", + "offerID" : "com.flare.monthly_0.99.1_week_intro", + "paymentMode" : "payUpFront", + "referenceName" : "com.flare.monthly_0.99.1_week_intro", + "subscriptionPeriod" : "P1M" + }, + { + "internalID" : "C181C3BF", + "offerID" : "com.flare.monthly_0.99.1_week_intro", + "paymentMode" : "free", + "referenceName" : "com.flare.monthly_0.99.1_week_intro", + "subscriptionPeriod" : "P1W" + } + ], + "codeOffers" : [ + { + "displayPrice" : "0.99", + "eligibility" : [ + "existing", + "expired", + "new" + ], + "internalID" : "A9D00827", + "isStackable" : true, + "paymentMode" : "payUpFront", + "referenceName" : "offer", + "subscriptionPeriod" : "P1M" + } + ], + "displayPrice" : "0.99", + "familyShareable" : false, + "groupNumber" : 1, + "internalID" : "7867CD16", + "introductoryOffer" : { + "displayPrice" : "0.99", + "internalID" : "0A94C45A", + "paymentMode" : "payUpFront", + "subscriptionPeriod" : "P1M" + }, + "localizations" : [ + { + "description" : "Subscription", + "displayName" : "Subscription", + "locale" : "en_US" + } + ], + "productID" : "com.flare.monthly_0.99.1_week_intro", + "recurringSubscriptionPeriod" : "P1M", + "referenceName" : "Subscription Full", + "subscriptionGroupID" : "C3C61FEC", + "type" : "RecurringSubscription" + } + ] + } ], "version" : { - "major" : 2, + "major" : 3, "minor" : 0 } } diff --git a/Tests/IntegrationTests/Helpers/Extensions/AsyncSequence+.swift b/Tests/IntegrationTests/Helpers/Extensions/AsyncSequence+.swift new file mode 100644 index 000000000..b16130182 --- /dev/null +++ b/Tests/IntegrationTests/Helpers/Extensions/AsyncSequence+.swift @@ -0,0 +1,16 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.2, *) +extension AsyncSequence { + /// Returns the elements of the asynchronous sequence. + func extractValues() async rethrows -> [Element] { + try await reduce(into: []) { + $0.append($1) + } + } +} diff --git a/Tests/IntegrationTests/Helpers/Providers/ProductProviderHelper.swift b/Tests/IntegrationTests/Helpers/Providers/ProductProviderHelper.swift new file mode 100644 index 000000000..4e35afd6d --- /dev/null +++ b/Tests/IntegrationTests/Helpers/Providers/ProductProviderHelper.swift @@ -0,0 +1,56 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import StoreKit + +// MARK: - ProductProviderHelper + +@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) +enum ProductProviderHelper { + static var purchases: [StoreKit.Product] { + get async throws { + try await StoreKit.Product.products(for: [.testNonConsumableID]) + } + } + + static var subscriptions: [StoreKit.Product] { + get async throws { + try await subscriptionsWithIntroductoryOffer + subscriptionsWithoutOffers + subscriptonsWithOffers + } + } + + static var subscriptionsWithIntroductoryOffer: [StoreKit.Product] { + get async throws { + try await StoreKit.Product.products(for: [.subscription1ID]) + } + } + + static var subscriptionsWithoutOffers: [StoreKit.Product] { + get async throws { + try await StoreKit.Product.products(for: [.subscription2ID]) + } + } + + static var subscriptonsWithOffers: [StoreKit.Product] { + get async throws { + try await StoreKit.Product.products(for: [.subscription3ID]) + } + } +} + +// MARK: - Constants + +private extension String { + static let testNonConsumableID = "com.flare.test_non_consumable_purchase_1" + + /// The subscription's id with introductory offer + static let subscription1ID = "com.flare.monthly_1.99_week_intro" + + /// The subscription's id without introductory offer + static let subscription2ID = "com.flare.monthly_0.99" + + /// The subscription's id with promotional offer + static let subscription3ID = "com.flare.monthly_1.99_two_weeks_offer.free" +} diff --git a/Tests/IntegrationTests/Helpers/StoreSessionTestCase/StoreSessionTestCase.swift b/Tests/IntegrationTests/Helpers/StoreSessionTestCase/StoreSessionTestCase.swift index 4e33a5234..d0923294a 100644 --- a/Tests/IntegrationTests/Helpers/StoreSessionTestCase/StoreSessionTestCase.swift +++ b/Tests/IntegrationTests/Helpers/StoreSessionTestCase/StoreSessionTestCase.swift @@ -1,11 +1,14 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // +import Flare import StoreKitTest import XCTest +// MARK: - StoreSessionTestCase + @available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 7.0, *) class StoreSessionTestCase: XCTestCase { // MARK: Properties @@ -29,3 +32,56 @@ class StoreSessionTestCase: XCTestCase { super.tearDown() } } + +@available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 7.0, *) +extension StoreSessionTestCase { + func expireSubscription(product: StoreProduct) { + do { + try session?.expireSubscription(productIdentifier: product.productIdentifier) + } catch { + debugPrint(error.localizedDescription) + } + } + + @available(iOS 15.2, tvOS 15.2, macOS 12.1, watchOS 8.3, *) + func findTransaction(for productID: String) async throws -> Transaction { + let transactions: [Transaction] = await Transaction.currentEntitlements + .compactMap { result in + switch result { + case let .verified(transaction): + return transaction + case .unverified: + return nil + } + } + .filter { (transaction: Transaction) in + transaction.productID == productID + } + .extractValues() + + return try XCTUnwrap(transactions.first) + } + + @available(iOS 15.2, tvOS 15.2, macOS 12.1, watchOS 8.3, *) + func latestTransaction(for productID: String) async throws -> Transaction { + let result: Transaction? = await Transaction.latest(for: productID) + .flatMap { result -> Transaction? in + switch result { + case let .verified(transaction): + return transaction + case .unverified: + return nil + } + } + + return try XCTUnwrap(result) + } + + func clearTransactions() { + session?.clearTransactions() + } + + func forceRenewalOfSubscription(for productIdentifier: String) throws { + try session?.forceRenewalOfSubscription(productIdentifier: productIdentifier) + } +} diff --git a/Tests/IntegrationTests/Tests/EligibilityProviderTests.swift b/Tests/IntegrationTests/Tests/EligibilityProviderTests.swift new file mode 100644 index 000000000..ec7e48152 --- /dev/null +++ b/Tests/IntegrationTests/Tests/EligibilityProviderTests.swift @@ -0,0 +1,50 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import XCTest + +@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) +final class EligibilityProviderTests: StoreSessionTestCase { + // MARK: Properties + + private var sut: EligibilityProvider! + + // MARK: XCTestCase + + override func setUp() { + super.setUp() + sut = EligibilityProvider() + } + + override func tearDown() { + sut = nil + super.tearDown() + } + + // MARK: Tests + + func test_thatProviderReturnsNoOffer_whenProductDoesNotHaveIntroductoryOffer() async throws { + // given + let product = try await ProductProviderHelper.subscriptionsWithoutOffers.randomElement()! + + // when + let result = try await sut.checkEligibility(products: [StoreProduct(product: product)]) + + // then + XCTAssertEqual(result[product.id], .noOffer) + } + + func test_thatProviderReturnsEligible_whenProductHasIntroductoryOffer() async throws { + // given + let product = try await ProductProviderHelper.subscriptionsWithIntroductoryOffer.randomElement()! + + // when + let result = try await sut.checkEligibility(products: [StoreProduct(product: product)]) + + // then + XCTAssertEqual(result[product.id], .eligible) + } +} diff --git a/Tests/IntegrationTests/Tests/FlareTests.swift b/Tests/IntegrationTests/Tests/FlareTests.swift index c3ff08793..1fc5b9b87 100644 --- a/Tests/IntegrationTests/Tests/FlareTests.swift +++ b/Tests/IntegrationTests/Tests/FlareTests.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // @testable import Flare @@ -82,6 +82,54 @@ final class FlareTests: StoreSessionTestCase { ) } + @available(iOS 15.2, tvOS 15.2, macOS 12.1, watchOS 8.3, *) + func test_thatPurchaseIntorudctoryOffer() async throws { + // 1. Fetch a product + let product = try await ProductProviderHelper.subscriptionsWithIntroductoryOffer.randomElement()! + let storeProduct = StoreProduct(product: product) + + // 2. Checking eligibility for a product + var eligibleResult = try await Flare.shared.checkEligibility(productIDs: [product.id])[product.id] + XCTAssertEqual(eligibleResult, .eligible) + + // 3. Purchase the product + let purchaseTransaction = try await sut.purchase(product: storeProduct) + + // 5. Retrieve a transaction + var transaction = try await findTransaction(for: product.id) + + // 6. Checking transaction + XCTAssertEqual(transaction.productID, product.id) + XCTAssertEqual(transaction.offerType, .introductory) + + // 7. Finish the transaction + let expectation = XCTestExpectation(description: "Finishing the transaction") + sut.finish(transaction: purchaseTransaction) { expectation.fulfill() } + + #if swift(>=5.9) + await fulfillment(of: [expectation]) + #else + wait(for: [expectation], timeout: .second) + #endif + + // 8. Checking eligibility for the purchased product + eligibleResult = try await Flare.shared.checkEligibility(productIDs: [product.id])[product.id] + XCTAssertEqual(eligibleResult, .nonEligible) + + // 9. Expire subscription + expireSubscription(product: storeProduct) + + // 10. Purchase the same product again + _ = try await sut.purchase(product: storeProduct) + + // 11. Retrieve a transaction + transaction = try await latestTransaction(for: product.id) + + // 12. Checking the transaction + XCTAssertEqual(transaction.productID, product.id) + XCTAssertEqual(transaction.offerType, nil) + } + // MARK: Private private func test_purchaseWithOptionsAndCompletion( diff --git a/Tests/IntegrationTests/Tests/IAPProviderTests.swift b/Tests/IntegrationTests/Tests/IAPProviderTests.swift deleted file mode 100644 index d1c0d99d4..000000000 --- a/Tests/IntegrationTests/Tests/IAPProviderTests.swift +++ /dev/null @@ -1,151 +0,0 @@ -// -// Flare -// Copyright © 2023 Space Code. All rights reserved. -// - -////// -////// Flare -////// Copyright © 2023 Space Code. All rights reserved. -////// -// -// @testable import Flare -// import XCTest -// -//// MARK: - IAPProviderStoreKit2Tests -// -// @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) -// final class IAPProviderStoreKit2Tests: StoreSessionTestCase { -// // MARK: - Properties -// -// private var productProviderMock: ProductProviderMock! -// private var purchaseProvider: PurchaseProviderMock! -// private var refundProviderMock: RefundProviderMock! -// -// private var sut: IIAPProvider! -// -// // MARK: - XCTestCase -// -// override func setUp() { -// super.setUp() -// productProviderMock = ProductProviderMock() -// purchaseProvider = PurchaseProviderMock() -// refundProviderMock = RefundProviderMock() -// sut = IAPProvider( -// paymentQueue: PaymentQueueMock(), -// productProvider: productProviderMock, -// purchaseProvider: purchaseProvider, -// receiptRefreshProvider: ReceiptRefreshProviderMock(), -// refundProvider: refundProviderMock -// ) -// } -// -// override func tearDown() { -// productProviderMock = nil -// purchaseProvider = nil -// refundProviderMock = nil -// sut = nil -// super.tearDown() -// } -// -// // MARK: Tests -// -// func test_thatIAPProviderFetchesSK2Products_whenProductsAreAvailable() async throws { -// let productsMock = try await ProductProviderHelper.purchases.map(SK2StoreProduct.init) -// productProviderMock.stubbedAsyncFetchResult = .success(productsMock) -// -// // when -// let products = try await sut.fetch(productIDs: [.productID]) -// -// // then -// XCTAssertFalse(products.isEmpty) -// XCTAssertEqual(productsMock.count, products.count) -// } -// -// func test_thatIAPProviderThrowsAnIAPError_whenFetchingProductsFailed() async { -// productProviderMock.stubbedAsyncFetchResult = .failure(IAPError.unknown) -// -// // when -// let error: IAPError? = await error(for: { try await sut.fetch(productIDs: [.productID]) }) -// -// // then -// XCTAssertEqual(error, .unknown) -// } -// -// func test_thatIAPProviderThrowsAPlainError_whenFetchingProductsFailed() async { -// productProviderMock.stubbedAsyncFetchResult = .failure(URLError(.unknown)) -// -// // when -// let error: IAPError? = await error(for: { try await sut.fetch(productIDs: [.productID]) }) -// -// // then -// XCTAssertEqual(error, .with(error: URLError(.unknown))) -// } -// -// #if os(iOS) || VISION_OS -// func test_thatIAPProviderRefundsPurchase() async throws { -// // given -// refundProviderMock.stubbedBeginRefundRequest = .success -// -// // when -// let state = try await sut.beginRefundRequest(productID: .productID) -// -// // then -// if case .success = state {} -// else { XCTFail("state must be `success`") } -// } -// -// func test_thatFlareThrowsAnError_whenBeginRefundRequestFailed() async throws { -// // given -// refundProviderMock.stubbedBeginRefundRequest = .failed(error: IAPError.unknown) -// -// // when -// let state = try await sut.beginRefundRequest(productID: .productID) -// -// // then -// if case let .failed(error) = state { XCTAssertEqual(error as NSError, IAPError.unknown as NSError) } -// else { XCTFail("state must be `failed`") } -// } -// #endif -// -// func test_thatIAPProviderPurchasesAProduct() async throws { -// // given -// let transactionMock = StoreTransactionMock() -// transactionMock.stubbedTransactionIdentifier = .transactionID -// -// let storeTransaction = StoreTransaction(storeTransaction: transactionMock) -// purchaseProvider.stubbedPurchaseCompletionResult = (.success(storeTransaction), ()) -// -// let product = try await ProductProviderHelper.purchases[0] -// -// // when -// let transaction = try await sut.purchase(product: StoreProduct(product: product)) -// -// // then -// XCTAssertEqual(transaction.transactionIdentifier, .transactionID) -// } -// -// func test_thatIAPProviderPurchasesAProductWithOptions() async throws { -// // given -// let transactionMock = StoreTransactionMock() -// transactionMock.stubbedTransactionIdentifier = .transactionID -// -// let storeTransaction = StoreTransaction(storeTransaction: transactionMock) -// purchaseProvider.stubbedinvokedPurchaseWithOptionsCompletionResult = (.success(storeTransaction), ()) -// -// let product = try await ProductProviderHelper.purchases[0] -// -// // when -// let transaction = try await sut.purchase(product: StoreProduct(product: product), options: []) -// -// // then -// XCTAssertEqual(transaction.transactionIdentifier, .transactionID) -// } -// } -// -//// MARK: - Constants -// -// private extension String { -//// static let receipt = "receipt" -// static let productID = "product_identifier" -// static let transactionID = "transaction_identifier" -// } diff --git a/Tests/IntegrationTests/Tests/ProductProviderHelper.swift b/Tests/IntegrationTests/Tests/ProductProviderHelper.swift deleted file mode 100644 index 2deb3d05b..000000000 --- a/Tests/IntegrationTests/Tests/ProductProviderHelper.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// Flare -// Copyright © 2023 Space Code. All rights reserved. -// - -import StoreKit - -// MARK: - ProductProviderHelper - -@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) -enum ProductProviderHelper { - static var purchases: [StoreKit.Product] { - get async throws { - try await StoreKit.Product.products(for: [.testNonConsumableID]) - } - } - -// static var subscriptions: [StoreKit.Product] { -// get async throws { -// try await StoreKit.Product.products(for: [.testSubscription1ID, .testSubscription2ID]) -// } -// } -// -// static var all: [StoreKit.Product] { -// get async throws { -// let purchases = try await self.purchases -// let subscriptions = try await self.subscriptions -// -// return purchases + subscriptions -// } -// } -} - -// MARK: - Constants - -private extension String { - static let testPurchase1ID = "com.flare.test_purchase_1" - static let testPurchase2ID = "com.flare.test_purchase_2" - - static let testNonConsumableID = "com.flare.test_non_consumable_purchase_1" - -// static let testSubscription1ID = "com.flare.test_subscription_1" -// static let testSubscription2ID = "com.flare.test_subscription_2" -} diff --git a/Tests/IntegrationTests/Tests/ProductProviderTests.swift b/Tests/IntegrationTests/Tests/ProductProviderTests.swift deleted file mode 100644 index 3edf243fb..000000000 --- a/Tests/IntegrationTests/Tests/ProductProviderTests.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// Flare -// Copyright © 2023 Space Code. All rights reserved. -// - -//// -//// Flare -//// Copyright © 2023 Space Code. All rights reserved. -//// -// -// import Concurrency -// @testable import Flare -// import TestConcurrency -// import XCTest -// -//// MARK: - ProductProviderStoreKit2Tests -// -// @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) -// final class ProductProviderStoreKit2Tests: StoreSessionTestCase { -// // MARK: - Properties -// -// private var testDispatchQueue: TestDispatchQueue! -// private var dispatchQueueFactory: IDispatchQueueFactory! -// -// private var sut: ProductProvider! -// -// // MARK: - XCTestCase -// -// override func setUp() { -// super.setUp() -// testDispatchQueue = TestDispatchQueue() -// dispatchQueueFactory = TestDispatchQueueFactory(testQueue: testDispatchQueue) -// sut = ProductProvider(dispatchQueueFactory: dispatchQueueFactory) -// } -// -// override func tearDown() { -// testDispatchQueue = nil -// dispatchQueueFactory = nil -// sut = nil -// super.tearDown() -// } -// -// // MARK: - Tests -// -// func test_thatProductProviderFetchesProductsWithIDs() async throws { -// // when -// let products = try await sut.fetch(productIDs: [.productID]) -// -// // then -// XCTAssertEqual(products.count, 1) -// XCTAssertEqual(products.first?.productIdentifier, .productID) -// } -// } -// -//// MARK: - Constants -// -// private extension String { -// static let productID = "com.flare.test_purchase_1" -// } diff --git a/Tests/IntegrationTests/Tests/PurchaseProviderTests.swift b/Tests/IntegrationTests/Tests/PurchaseProviderTests.swift deleted file mode 100644 index 31170ffb3..000000000 --- a/Tests/IntegrationTests/Tests/PurchaseProviderTests.swift +++ /dev/null @@ -1,90 +0,0 @@ -// -// Flare -// Copyright © 2023 Space Code. All rights reserved. -// - -//// -//// Flare -//// Copyright © 2023 Space Code. All rights reserved. -//// -// -// @testable import Flare -// import XCTest -// -//// MARK: - PurchaseProviderStoreKit2Tests -// -// @available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) -// final class PurchaseProviderStoreKit2Tests: StoreSessionTestCase { -// // MARK: Properties -// -// private var paymentProviderMock: PaymentProviderMock! -// -// private var sut: PurchaseProvider! -// -// // MARK: XCTestCase -// -// override func setUp() { -// super.setUp() -// paymentProviderMock = PaymentProviderMock() -// sut = PurchaseProvider( -// paymentProvider: paymentProviderMock -// ) -// } -// -// override func tearDown() { -// sut = nil -// super.tearDown() -// } -// -// // MARK: Tests -// -// func test_thatPurchaseProviderReturnsPaymentTransaction_whenPurchasesAProductWithOptions() async throws { -// let expectation = XCTestExpectation(description: "Purchase a product") -// let productMock = try StoreProduct(product: await ProductProviderHelper.purchases.randomElement()!) -// -// // when -// sut.purchase(product: productMock, options: [.simulatesAskToBuyInSandbox(false)]) { result in -// switch result { -// case let .success(transaction): -// XCTAssertEqual(transaction.productIdentifier, productMock.productIdentifier) -// expectation.fulfill() -// case let .failure(error): -// XCTFail(error.localizedDescription) -// } -// } -// -// #if swift(>=5.9) -// await fulfillment(of: [expectation]) -// #else -// wait(for: [expectation], timeout: .second) -// #endif -// } -// -// func test_thatPurchaseProviderReturnsPaymentTransaction_whenSK2ProductExist() async throws { -// let expectation = XCTestExpectation(description: "Purchase a product") -// let productMock = try StoreProduct(product: await ProductProviderHelper.purchases.randomElement()!) -// -// // when -// sut.purchase(product: productMock) { result in -// switch result { -// case let .success(transaction): -// XCTAssertEqual(transaction.productIdentifier, productMock.productIdentifier) -// expectation.fulfill() -// case let .failure(error): -// XCTFail(error.localizedDescription) -// } -// } -// -// #if swift(>=5.9) -// await fulfillment(of: [expectation]) -// #else -// wait(for: [expectation], timeout: .second) -// #endif -// } -// } -// -//// MARK: - Constants -// -// private extension TimeInterval { -// static let second: TimeInterval = 1.0 -// } diff --git a/Tests/IntegrationTests/Tests/StoreProductTests.swift b/Tests/IntegrationTests/Tests/StoreProductTests.swift new file mode 100644 index 000000000..91432b7e2 --- /dev/null +++ b/Tests/IntegrationTests/Tests/StoreProductTests.swift @@ -0,0 +1,173 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import StoreKit +import XCTest + +// MARK: - StoreProductTests + +@available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 7.0, *) +final class StoreProductTests: StoreSessionTestCase { + // MARK: Private + + private var provider: IProductProvider! + + // MARK: XCTestCase + + override func setUp() { + super.setUp() + provider = ProductProvider() + } + + override func tearDown() { + provider = nil + super.tearDown() + } + + // MARK: - Tests + + func test_sk1ProductWrapsCorrectly() async throws { + // given + let expectation = XCTestExpectation(description: "Purchase a product") + + // when + var products: [StoreProduct] = [] + provider.fetch(productIDs: [String.productID], requestID: UUID().uuidString) { result in + switch result { + case let .success(skProducts): + products = skProducts.map { StoreProduct($0) } + case .failure: + break + } + expectation.fulfill() + } + + #if swift(>=5.9) + await fulfillment(of: [expectation]) + #else + wait(for: [expectation], timeout: .seconds) + #endif + + // then + let storeProduct = try XCTUnwrap(products.first) + + // then + XCTAssertEqual(storeProduct.productIdentifier, .productID) + XCTAssertEqual(storeProduct.productCategory, .subscription) + XCTAssertEqual(storeProduct.productType, nil) + XCTAssertEqual(storeProduct.localizedDescription, "Subscription") + XCTAssertEqual(storeProduct.localizedTitle, "Subscription") + XCTAssertEqual(storeProduct.currencyCode, "USD") + XCTAssertEqual(storeProduct.price.description, "0.99") + XCTAssertEqual(storeProduct.localizedPriceString, "$0.99") + XCTAssertEqual(storeProduct.subscriptionGroupIdentifier, "C3C61FEC") + + XCTAssertEqual(storeProduct.subscriptionPeriod?.unit, .month) + XCTAssertEqual(storeProduct.subscriptionPeriod?.value, 1) + + let intro = try XCTUnwrap(storeProduct.introductoryDiscount) + + XCTAssertEqual(intro.price, 0.99) + XCTAssertEqual(intro.paymentMode, .payUpFront) + XCTAssertEqual(intro.type, .introductory) + XCTAssertEqual(intro.offerIdentifier, nil) + XCTAssertEqual(intro.subscriptionPeriod, SubscriptionPeriod(value: 1, unit: .month)) + + let offers = try XCTUnwrap(storeProduct.discounts) + XCTAssertEqual(offers.count, 3) + + XCTAssertEqual(offers[0].price, 0.99) + XCTAssertEqual(offers[0].paymentMode, .payAsYouGo) + XCTAssertEqual(offers[0].type, .promotional) + XCTAssertEqual(offers[0].offerIdentifier, "com.flare.monthly_0.99.1_week_intro") + XCTAssertEqual(offers[0].subscriptionPeriod, SubscriptionPeriod(value: 1, unit: .month)) + XCTAssertEqual(offers[0].numberOfPeriods, 1) + XCTAssertEqual(offers[0].currencyCode, "USD") + + XCTAssertEqual(offers[1].price, 1.99) + XCTAssertEqual(offers[1].paymentMode, .payUpFront) + XCTAssertEqual(offers[1].type, .promotional) + XCTAssertEqual(offers[1].offerIdentifier, "com.flare.monthly_0.99.1_week_intro") + XCTAssertEqual(offers[1].subscriptionPeriod, SubscriptionPeriod(value: 1, unit: .month)) + XCTAssertEqual(offers[1].numberOfPeriods, 1) + XCTAssertEqual(offers[1].currencyCode, "USD") + + XCTAssertEqual(offers[2].price, 0) + XCTAssertEqual(offers[2].paymentMode, .freeTrial) + XCTAssertEqual(offers[2].type, .promotional) + XCTAssertEqual(offers[2].offerIdentifier, "com.flare.monthly_0.99.1_week_intro") + XCTAssertEqual(offers[2].subscriptionPeriod, SubscriptionPeriod(value: 1, unit: .week)) + XCTAssertEqual(offers[2].numberOfPeriods, 1) + XCTAssertEqual(offers[2].currencyCode, "USD") + } + + @available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) + func test_sk2ProductWrapsCorrectly() async throws { + // given + let products = try await StoreKit.Product.products(for: [String.productID]) + let product = try XCTUnwrap(products.first) + let storeProduct = StoreProduct(product: product) + + // then + XCTAssertEqual(storeProduct.productIdentifier, .productID) + XCTAssertEqual(storeProduct.productCategory, .subscription) + XCTAssertEqual(storeProduct.productType, .autoRenewableSubscription) + XCTAssertEqual(storeProduct.localizedDescription, "Subscription") + XCTAssertEqual(storeProduct.localizedTitle, "Subscription") + XCTAssertEqual(storeProduct.currencyCode, "USD") + XCTAssertEqual(storeProduct.price.description, "0.99") + XCTAssertEqual(storeProduct.localizedPriceString, "$0.99") + XCTAssertEqual(storeProduct.subscriptionGroupIdentifier, "C3C61FEC") + + XCTAssertEqual(storeProduct.subscriptionPeriod?.unit, .month) + XCTAssertEqual(storeProduct.subscriptionPeriod?.value, 1) + + let intro = try XCTUnwrap(storeProduct.introductoryDiscount) + + XCTAssertEqual(intro.price, 0.99) + XCTAssertEqual(intro.paymentMode, .payUpFront) + XCTAssertEqual(intro.type, .introductory) + XCTAssertEqual(intro.offerIdentifier, nil) + XCTAssertEqual(intro.subscriptionPeriod, SubscriptionPeriod(value: 1, unit: .month)) + + let offers = try XCTUnwrap(storeProduct.discounts) + XCTAssertEqual(offers.count, 3) + + XCTAssertEqual(offers[0].price, 0.99) + XCTAssertEqual(offers[0].paymentMode, .payAsYouGo) + XCTAssertEqual(offers[0].type, .promotional) + XCTAssertEqual(offers[0].offerIdentifier, "com.flare.monthly_0.99.1_week_intro") + XCTAssertEqual(offers[0].subscriptionPeriod, SubscriptionPeriod(value: 1, unit: .month)) + XCTAssertEqual(offers[0].numberOfPeriods, 1) + XCTAssertEqual(offers[0].currencyCode, "USD") + + XCTAssertEqual(offers[1].price, 1.99) + XCTAssertEqual(offers[1].paymentMode, .payUpFront) + XCTAssertEqual(offers[1].type, .promotional) + XCTAssertEqual(offers[1].offerIdentifier, "com.flare.monthly_0.99.1_week_intro") + XCTAssertEqual(offers[1].subscriptionPeriod, SubscriptionPeriod(value: 1, unit: .month)) + XCTAssertEqual(offers[1].numberOfPeriods, 1) + XCTAssertEqual(offers[1].currencyCode, "USD") + + XCTAssertEqual(offers[2].price, 0) + XCTAssertEqual(offers[2].paymentMode, .freeTrial) + XCTAssertEqual(offers[2].type, .promotional) + XCTAssertEqual(offers[2].offerIdentifier, "com.flare.monthly_0.99.1_week_intro") + XCTAssertEqual(offers[2].subscriptionPeriod, SubscriptionPeriod(value: 1, unit: .week)) + XCTAssertEqual(offers[2].numberOfPeriods, 1) + XCTAssertEqual(offers[2].currencyCode, "USD") + } +} + +// MARK: - Constants + +private extension String { + static let productID = "com.flare.monthly_0.99.1_week_intro" +} + +private extension TimeInterval { + static let seconds: CGFloat = 60.0 +} From 33804c90ec9783c77839dd7fa6ea667aea432f40 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Sun, 21 Jan 2024 18:06:23 +0100 Subject: [PATCH 39/44] Implement Logging (#17) * Implement logging - Integrate the `log` package - Write a wrapper for logging - Implement a few events to be logged * Implement a few events to be logged * Add localization to all types of errors * Update `Makefile` * Update `CHANGELOG.md` * Implement a few events to be logged --- .swiftlint.yml | 1 + CHANGELOG.md | 3 + Makefile | 11 +- Package.resolved | 9 + Package.swift | 3 + Package@swift-5.7.swift | 5 +- Package@swift-5.8.swift | 5 +- Sources/Flare/Classes/Common/Logger.swift | 78 +++++++ Sources/Flare/Classes/Flare.swift | 25 +- Sources/Flare/Classes/Generated/Strings.swift | 213 ++++++++++++++++++ Sources/Flare/Classes/IFlare.swift | 4 + .../ITransactionListener.swift | 11 +- .../TransactionListener.swift | 11 +- Sources/Flare/Classes/Models/IAPError.swift | 66 +++++- .../Flare/Classes/Models/RefundError.swift | 15 ++ .../Classes/Models/VerificationError.swift | 13 ++ .../ConfigurationProvider.swift | 1 + .../Providers/IAPProvider/IAPProvider.swift | 1 + .../PaymentProvider/PaymentProvider.swift | 14 ++ .../ProductProvider/ProductProvider.swift | 5 +- .../PurchaseProvider/PurchaseProvider.swift | 30 +++ .../ReceiptRefreshProvider.swift | 6 + .../RedeemCodeProvider.swift | 8 +- .../RefundRequestProvider.swift | 4 + Sources/Flare/Resources/Localizable.strings | 77 +++++++ .../UnitTests/Models/IAPErrorTests.swift | 11 - .../Providers/ProductProviderTests.swift | 4 +- project.yml | 5 + swiftgen.yml | 10 + 29 files changed, 612 insertions(+), 37 deletions(-) create mode 100644 Sources/Flare/Classes/Common/Logger.swift create mode 100644 Sources/Flare/Classes/Generated/Strings.swift create mode 100644 Sources/Flare/Resources/Localizable.strings create mode 100644 swiftgen.yml diff --git a/.swiftlint.yml b/.swiftlint.yml index 66d17c089..530b2f63f 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -3,6 +3,7 @@ excluded: - Package.swift - Package@swift-5.7.swift - Package@swift-5.8.swift + - Sources/Flare/Classes/Generated/Strings.swift - .build # Rules diff --git a/CHANGELOG.md b/CHANGELOG.md index 63760b0ae..908bfc4f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Implement Logging Functionality + - Added in Pull Request [#17](https://github.com/space-code/flare/pull/17). + - Implement Support for Promotional Offers - Added in Pull Request [#16](https://github.com/space-code/flare/pull/16). diff --git a/Makefile b/Makefile index f11937816..37e687ede 100644 --- a/Makefile +++ b/Makefile @@ -16,10 +16,19 @@ lint: fmt: mint run swiftformat Sources Tests +strings: + swiftgen + generate: xcodegen generate setup_build_tools: sh scripts/setup_build_tools.sh -.PHONY: all bootstrap hook mint lint fmt generate setup_build_tools \ No newline at end of file +build: + swift build -c release --target Flare + +test: + xcodebuild test -scheme "Flare" -destination "$(destination)" -testPlan AllTests clean -enableCodeCoverage YES + +.PHONY: all bootstrap hook mint lint fmt generate setup_build_tools strings build test \ No newline at end of file diff --git a/Package.resolved b/Package.resolved index df6a8652a..a1bfb4096 100644 --- a/Package.resolved +++ b/Package.resolved @@ -9,6 +9,15 @@ "version" : "0.0.1" } }, + { + "identity" : "log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/space-code/log", + "state" : { + "revision" : "d99fff5656c31ef7e604965b90a50ec10539c98f", + "version" : "1.1.0" + } + }, { "identity" : "swift-docc-plugin", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 8953275aa..036ddab79 100644 --- a/Package.swift +++ b/Package.swift @@ -21,13 +21,16 @@ let package = Package( dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), + .package(url: "https://github.com/space-code/log.git", .upToNextMajor(from: "1.1.0")), ], targets: [ .target( name: "Flare", dependencies: [ .product(name: "Concurrency", package: "concurrency"), + .product(name: "Log", package: "log"), ], + resources: [.process("Resources")], swiftSettings: [visionOSSetting] ), .testTarget( diff --git a/Package@swift-5.7.swift b/Package@swift-5.7.swift index 4a19d4f04..167c85790 100644 --- a/Package@swift-5.7.swift +++ b/Package@swift-5.7.swift @@ -18,13 +18,16 @@ let package = Package( dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), + .package(url: "https://github.com/space-code/log.git", .upToNextMajor(from: "1.1.0")), ], targets: [ .target( name: "Flare", dependencies: [ .product(name: "Concurrency", package: "concurrency"), - ] + .product(name: "Log", package: "log"), + ], + resources: [.process("Resources")] ), .testTarget( name: "FlareTests", diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift index 5c077121e..9dbb5ffa9 100644 --- a/Package@swift-5.8.swift +++ b/Package@swift-5.8.swift @@ -18,13 +18,16 @@ let package = Package( dependencies: [ .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), + .package(url: "https://github.com/space-code/log.git", .upToNextMajor(from: "1.1.0")), ], targets: [ .target( name: "Flare", dependencies: [ .product(name: "Concurrency", package: "concurrency"), - ] + .product(name: "Log", package: "log"), + ], + resources: [.process("Resources")] ), .testTarget( name: "FlareTests", diff --git a/Sources/Flare/Classes/Common/Logger.swift b/Sources/Flare/Classes/Common/Logger.swift new file mode 100644 index 000000000..9fa71ee7a --- /dev/null +++ b/Sources/Flare/Classes/Common/Logger.swift @@ -0,0 +1,78 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation +import Log + +// MARK: - Logger + +enum Logger { + // MARK: Properties + + private static var defaultLogLevel: LogLevel { + #if DEBUG + return .debug + #endif + return .info + } + + private static let `default`: Log.Logger = .init( + printers: [ + ConsolePrinter(formatters: Self.formatters), + OSPrinter(subsystem: .subsystem, category: .category, formatters: Self.formatters), + ], + logLevel: Self.defaultLogLevel + ) + + private static var formatters: [ILogFormatter] { + [ + PrefixLogFormatter(name: .subsystem), + TimestampLogFormatter(dateFormat: "dd.MM.yyyy hh:mm:ss"), + ] + } + + static var logLevel: LogLevel { + get { Self.default.logLevel } + set { Self.default.logLevel = newValue } + } + + // MARK: Static Public Methods + + static func debug(message: @autoclosure () -> String) { + log(level: .debug, message: message()) + } + + static func info(message: @autoclosure () -> String) { + log(level: .info, message: message()) + } + + static func error(message: @autoclosure () -> String) { + log(level: .fault, message: message()) + } + + // MARK: Private + + private static func log(level: LogLevel, message: @autoclosure () -> String) { + switch level { + case .debug: + Self.default.debug(message: message()) + case .info: + Self.default.info(message: message()) + case .fault: + Self.default.fault(message: message()) + case .error: + Self.default.error(message: message()) + default: + break + } + } +} + +// MARK: - Constants + +private extension String { + static let subsystem = "Flare" + static let category = "iap" +} diff --git a/Sources/Flare/Classes/Flare.swift b/Sources/Flare/Classes/Flare.swift index c1db74c81..9ea74d1f4 100644 --- a/Sources/Flare/Classes/Flare.swift +++ b/Sources/Flare/Classes/Flare.swift @@ -3,6 +3,7 @@ // Copyright © 2024 Space Code. All rights reserved. // +import struct Log.LogLevel import StoreKit #if os(iOS) || VISION_OS @@ -27,6 +28,12 @@ public final class Flare { /// Returns a shared `Flare` object. public static var shared: IFlare { flare } + /// The log level. + public var logLevel: LogLevel { + get { Logger.logLevel } + set { Logger.logLevel = newValue } + } + // MARK: Initialization /// Creates a new `Flare` instance. @@ -66,7 +73,7 @@ extension Flare: IFlare { promotionalOffer: PromotionalOffer?, completion: @escaping Closure> ) { - guard iapProvider.canMakePayments else { + guard checkIfUserCanMakePayments() else { completion(.failure(.paymentNotAllowed)) return } @@ -82,7 +89,7 @@ extension Flare: IFlare { } public func purchase(product: StoreProduct, promotionalOffer: PromotionalOffer?) async throws -> StoreTransaction { - guard iapProvider.canMakePayments else { throw IAPError.paymentNotAllowed } + guard checkIfUserCanMakePayments() else { throw IAPError.paymentNotAllowed } return try await iapProvider.purchase(product: product, promotionalOffer: promotionalOffer) } @@ -93,7 +100,7 @@ extension Flare: IFlare { promotionalOffer: PromotionalOffer?, completion: @escaping SendableClosure> ) { - guard iapProvider.canMakePayments else { + guard checkIfUserCanMakePayments() else { completion(.failure(.paymentNotAllowed)) return } @@ -106,7 +113,7 @@ extension Flare: IFlare { options: Set, promotionalOffer: PromotionalOffer? ) async throws -> StoreTransaction { - guard iapProvider.canMakePayments else { throw IAPError.paymentNotAllowed } + guard checkIfUserCanMakePayments() else { throw IAPError.paymentNotAllowed } return try await iapProvider.purchase(product: product, options: options, promotionalOffer: promotionalOffer) } @@ -167,4 +174,14 @@ extension Flare: IFlare { try await iapProvider.presentOfferCodeRedeemSheet() } #endif + + // MARK: Private + + private func checkIfUserCanMakePayments() -> Bool { + guard iapProvider.canMakePayments else { + Logger.error(message: L10n.Purchase.cannotPurcaseProduct) + return false + } + return true + } } diff --git a/Sources/Flare/Classes/Generated/Strings.swift b/Sources/Flare/Classes/Generated/Strings.swift new file mode 100644 index 000000000..5d56fbcbe --- /dev/null +++ b/Sources/Flare/Classes/Generated/Strings.swift @@ -0,0 +1,213 @@ +// swiftlint:disable all +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen + +import Foundation + +// swiftlint:disable superfluous_disable_command file_length implicit_return prefer_self_in_static_references + +// MARK: - Strings + +// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length +// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces +internal enum L10n { + internal enum Error { + internal enum FailedToDecodeSignature { + /// Decoding the signature has failed. The signature: %s + internal static func description(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "error.failed_to_decode_signature.description", p1, fallback: "Decoding the signature has failed. The signature: %s") + } + } + internal enum InvalidProductIds { + /// Invalid product IDs: %@ + internal static func description(_ p1: Any) -> String { + return L10n.tr("Localizable", "error.invalid_product_ids.description", String(describing: p1), fallback: "Invalid product IDs: %@") + } + } + internal enum PaymentCancelled { + /// The payment was canceled by the user. + internal static let description = L10n.tr("Localizable", "error.payment_cancelled.description", fallback: "The payment was canceled by the user.") + } + internal enum PaymentDefferred { + /// The purchase is pending, and requires action from the customer. + internal static let description = L10n.tr("Localizable", "error.payment_defferred.description", fallback: "The purchase is pending, and requires action from the customer.") + } + internal enum PaymentNotAllowed { + /// The current user is not eligible to make payments. + internal static let description = L10n.tr("Localizable", "error.payment_not_allowed.description", fallback: "The current user is not eligible to make payments.") + /// The payment card may have purchase restrictions, such as set limits or unavailability for online shopping. + internal static let failureReason = L10n.tr("Localizable", "error.payment_not_allowed.failure_reason", fallback: "The payment card may have purchase restrictions, such as set limits or unavailability for online shopping.") + /// Please check the payment card purchase restrictions. + internal static let recoverySuggestion = L10n.tr("Localizable", "error.payment_not_allowed.recovery_suggestion", fallback: "Please check the payment card purchase restrictions.") + } + internal enum Receipt { + /// The receipt could not be found. + internal static let description = L10n.tr("Localizable", "error.receipt.description", fallback: "The receipt could not be found.") + } + internal enum Refund { + /// The error occurred during the refund: %s + internal static func description(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "error.refund.description", p1, fallback: "The error occurred during the refund: %s") + } + } + internal enum StoreProductNotAvailable { + /// The store product is currently unavailable. + internal static let description = L10n.tr("Localizable", "error.store_product_not_available.description", fallback: "The store product is currently unavailable.") + /// Make sure to create a product with the given identifier in App Store Connect. + internal static let recoverySuggestion = L10n.tr("Localizable", "error.store_product_not_available.recovery_suggestion", fallback: "Make sure to create a product with the given identifier in App Store Connect.") + } + internal enum TransactionNotFound { + /// Transaction for productID: %s couldn't be found. + internal static func description(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "error.transaction_not_found.description", p1, fallback: "Transaction for productID: %s couldn't be found.") + } + } + internal enum Unknown { + /// The SKPayment returned unknown error. + internal static let description = L10n.tr("Localizable", "error.unknown.description", fallback: "The SKPayment returned unknown error.") + } + internal enum Verification { + /// The verification has failed with the following error: %s + internal static func description(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "error.verification.description", p1, fallback: "The verification has failed with the following error: %s") + } + } + internal enum With { + /// The error occurred: %s + internal static func description(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "error.with.description", p1, fallback: "The error occurred: %s") + } + } + } + internal enum Flare { + /// Flare configured with configuration: + /// %@ + internal static func initWithConfiguration(_ p1: Any) -> String { + return L10n.tr("Localizable", "flare.init_with_configuration", String(describing: p1), fallback: "Flare configured with configuration:\n%@") + } + } + internal enum Payment { + /// Adding payment for product: %s. %i transactions already in the queue + internal static func paymentQueueAddingPayment(_ p1: UnsafePointer, _ p2: Int) -> String { + return L10n.tr("Localizable", "payment.payment_queue_adding_payment", p1, p2, fallback: "Adding payment for product: %s. %i transactions already in the queue") + } + } + internal enum Products { + /// Requested products %@ not found. + internal static func requestedProductsNotFound(_ p1: Any) -> String { + return L10n.tr("Localizable", "products.requested_products_not_found", String(describing: p1), fallback: "Requested products %@ not found.") + } + /// Requested products %@ have been received + internal static func requestedProductsReceived(_ p1: Any) -> String { + return L10n.tr("Localizable", "products.requested_products_received", String(describing: p1), fallback: "Requested products %@ have been received") + } + } + internal enum Purchase { + /// This device is not able or allowed to make payments. + internal static let cannotPurcaseProduct = L10n.tr("Localizable", "purchase.cannot_purcase_product", fallback: "This device is not able or allowed to make payments.") + /// An error occurred while listening for transactions: %s + internal static func errorUpdatingTransaction(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "purchase.error_updating_transaction", p1, fallback: "An error occurred while listening for transactions: %s") + } + /// Finishing transaction %s for product identifier: %s + internal static func finishingTransaction(_ p1: UnsafePointer, _ p2: UnsafePointer) -> String { + return L10n.tr("Localizable", "purchase.finishing_transaction", p1, p2, fallback: "Finishing transaction %s for product identifier: %s") + } + /// Product purchase for %s failed with error: %s + internal static func productPurchaseFailed(_ p1: UnsafePointer, _ p2: UnsafePointer) -> String { + return L10n.tr("Localizable", "purchase.product_purchase_failed", p1, p2, fallback: "Product purchase for %s failed with error: %s") + } + /// Purchased product: %s + internal static func purchasedProduct(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "purchase.purchased_product", p1, fallback: "Purchased product: %s") + } + /// Purchasing product: %s + internal static func purchasingProduct(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "purchase.purchasing_product", p1, fallback: "Purchasing product: %s") + } + /// Purchasing product %s with offer %s + internal static func purchasingProductWithOffer(_ p1: UnsafePointer, _ p2: UnsafePointer) -> String { + return L10n.tr("Localizable", "purchase.purchasing_product_with_offer", p1, p2, fallback: "Purchasing product %s with offer %s") + } + /// Transaction for productID: %s not found. + internal static func transactionNotFound(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "purchase.transaction_not_found", p1, fallback: "Transaction for productID: %s not found.") + } + /// Transaction for productID: %s is unverified by the App Store. Verification error: %s. + internal static func transactionUnverified(_ p1: UnsafePointer, _ p2: UnsafePointer) -> String { + return L10n.tr("Localizable", "purchase.transaction_unverified", p1, p2, fallback: "Transaction for productID: %s is unverified by the App Store. Verification error: %s.") + } + } + internal enum Receipt { + /// Refreshed receipt. Request id: %s. + internal static func refreshedReceipt(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "receipt.refreshed_receipt", p1, fallback: "Refreshed receipt. Request id: %s.") + } + /// Refreshing receipt. Request id: %s. + internal static func refreshingReceipt(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "receipt.refreshing_receipt", p1, fallback: "Refreshing receipt. Request id: %s.") + } + /// Refreshing receipt failed with error: %s. Request id: %s. + internal static func refreshingReceiptFailed(_ p1: UnsafePointer, _ p2: UnsafePointer) -> String { + return L10n.tr("Localizable", "receipt.refreshing_receipt_failed", p1, p2, fallback: "Refreshing receipt failed with error: %s. Request id: %s.") + } + } + internal enum Redeem { + /// Presenting code redemption sheet. + internal static let presentingCodeRedemptionSheet = L10n.tr("Localizable", "redeem.presenting_code_redemption_sheet", fallback: "Presenting code redemption sheet.") + /// Presenting offer code redeem sheet + internal static let presentingOfferCodeRedeemSheet = L10n.tr("Localizable", "redeem.presenting_offer_code_redeem_sheet", fallback: "Presenting offer code redeem sheet") + /// Unable to present offer code redeem sheet due to unexpected error: %s + internal static func unableToPresentOfferCodeRedeemSheet(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "redeem.unable_to_present_offer_code_redeem_sheet", p1, fallback: "Unable to present offer code redeem sheet due to unexpected error: %s") + } + } + internal enum Refund { + /// Refund has already requested for this product: %s + internal static func duplicateRefundRequest(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "refund.duplicate_refund_request", p1, fallback: "Refund has already requested for this product: %s") + } + /// Refund request submission failed: %s + internal static func failedRefundRequest(_ p1: UnsafePointer) -> String { + return L10n.tr("Localizable", "refund.failed_refund_request", p1, fallback: "Refund request submission failed: %s") + } + } + internal enum RefundError { + internal enum DuplicateRequest { + /// The request has been duplicated. + internal static let description = L10n.tr("Localizable", "refund_error.duplicate_request.description", fallback: "The request has been duplicated.") + } + internal enum Failed { + /// The refund request failed. + internal static let description = L10n.tr("Localizable", "refund_error.failed.description", fallback: "The refund request failed.") + } + } + internal enum VerificationError { + /// Transaction for productID: %s is unverified by the App Store. Verification error: %s. + internal static func unverified(_ p1: UnsafePointer, _ p2: UnsafePointer) -> String { + return L10n.tr("Localizable", "verification_error.unverified", p1, p2, fallback: "Transaction for productID: %s is unverified by the App Store. Verification error: %s.") + } + } +} +// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length +// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces + +// MARK: - Implementation Details + +extension L10n { + private static func tr(_ table: String, _ key: String, _ args: CVarArg..., fallback value: String) -> String { + let format = BundleToken.bundle.localizedString(forKey: key, value: value, table: table) + return String(format: format, locale: Locale.current, arguments: args) + } +} + +// swiftlint:disable convenience_type +private final class BundleToken { + static let bundle: Bundle = { + #if SWIFT_PACKAGE + return Bundle.module + #else + return Bundle(for: BundleToken.self) + #endif + }() +} +// swiftlint:enable convenience_type diff --git a/Sources/Flare/Classes/IFlare.swift b/Sources/Flare/Classes/IFlare.swift index 48e0eef63..21856a111 100644 --- a/Sources/Flare/Classes/IFlare.swift +++ b/Sources/Flare/Classes/IFlare.swift @@ -4,12 +4,16 @@ // import Foundation +import struct Log.LogLevel import StoreKit // MARK: - IFlare /// `Flare` creates and manages in-app purchases. public protocol IFlare { + /// The log level. + var logLevel: Log.LogLevel { get set } + /// Retrieves localized information from the App Store about a specified list of products. /// /// - Parameters: diff --git a/Sources/Flare/Classes/Listeners/TransactionListener/ITransactionListener.swift b/Sources/Flare/Classes/Listeners/TransactionListener/ITransactionListener.swift index faefa7cb8..095c12af9 100644 --- a/Sources/Flare/Classes/Listeners/TransactionListener/ITransactionListener.swift +++ b/Sources/Flare/Classes/Listeners/TransactionListener/ITransactionListener.swift @@ -1,14 +1,23 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation import StoreKit +/// Protocol for objects that listen for transactions. protocol ITransactionListener: Sendable { + /// Listen for incoming transactions asynchronously. func listenForTransaction() async + /// Handle the purchase result asynchronously. + /// + /// - Parameters: + /// - purchaseResult: The result of a StoreKit product purchase. + /// - Returns: An optional `StoreTransaction` if handling is successful. + /// + /// - Note: Available on iOS 15.0+, tvOS 15.0+, macOS 12.0+, watchOS 8.0+. @available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) func handle(purchaseResult: StoreKit.Product.PurchaseResult) async throws -> StoreTransaction? } diff --git a/Sources/Flare/Classes/Listeners/TransactionListener/TransactionListener.swift b/Sources/Flare/Classes/Listeners/TransactionListener/TransactionListener.swift index 1078ed1c3..1edd3e410 100644 --- a/Sources/Flare/Classes/Listeners/TransactionListener/TransactionListener.swift +++ b/Sources/Flare/Classes/Listeners/TransactionListener/TransactionListener.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -38,6 +38,13 @@ actor TransactionListener { jwtRepresentation: transactionResult.jwsRepresentation ) case let .unverified(transaction, verificationError): + Logger.info( + message: L10n.Purchase.transactionUnverified( + transaction.productID, + verificationError.localizedDescription + ) + ) + throw IAPError.verification( error: .unverified(productID: transaction.productID, error: verificationError) ) @@ -59,7 +66,7 @@ extension TransactionListener: ITransactionListener { do { _ = try await self.handle(transactionResult: update, fromTransactionUpdate: true) } catch { - debugPrint("[TransactionListener] Error occurred: \(error.localizedDescription)") + Logger.error(message: L10n.Purchase.errorUpdatingTransaction(error.localizedDescription)) } } } diff --git a/Sources/Flare/Classes/Models/IAPError.swift b/Sources/Flare/Classes/Models/IAPError.swift index 80de297b9..0de5a9262 100644 --- a/Sources/Flare/Classes/Models/IAPError.swift +++ b/Sources/Flare/Classes/Models/IAPError.swift @@ -10,18 +10,14 @@ import StoreKit /// `IAPError` is the error type returned by Flare. /// It encompasses a few different types of errors, each with their own associated reasons. public enum IAPError: Swift.Error { - /// The empty array of products were fetched. - case emptyProducts /// The attempt to fetch products with invalid identifiers. - case invalid(productIds: [String]) + case invalid(productIDs: [String]) /// The attempt to purchase a product when payments are not allowed. case paymentNotAllowed /// The payment was cancelled. case paymentCancelled /// The attempt to fetch a product that doesn't available. case storeProductNotAvailable - /// The `SKPayment` returned unknown error. - case storeTrouble /// The operation failed with an underlying error. case with(error: Swift.Error) /// The App Store receipt wasn't found. @@ -80,7 +76,7 @@ extension IAPError { case .storeProductNotAvailable: self = .storeProductNotAvailable case .unknown: - self = .storeTrouble + self = .unknown default: if let error = error { self = .with(error: error) @@ -103,12 +99,9 @@ extension IAPError { // MARK: Equatable -// swiftlint:disable cyclomatic_complexity extension IAPError: Equatable { public static func == (lhs: IAPError, rhs: IAPError) -> Bool { switch (lhs, rhs) { - case (.emptyProducts, .emptyProducts): - return true case let (.invalid(lhs), .invalid(rhs)): return lhs == rhs case (.paymentNotAllowed, .paymentNotAllowed): @@ -117,8 +110,6 @@ extension IAPError: Equatable { return true case (.storeProductNotAvailable, .storeProductNotAvailable): return true - case (.storeTrouble, .storeTrouble): - return true case let (.with(lhs), .with(rhs)): return (lhs as NSError) == (rhs as NSError) case (.receiptNotFound, .receiptNotFound): @@ -135,4 +126,55 @@ extension IAPError: Equatable { } } -// swiftlint:enable cyclomatic_complexity +// MARK: LocalizedError + +extension IAPError: LocalizedError { + public var errorDescription: String? { + switch self { + case let .invalid(productIDs): + return L10n.Error.InvalidProductIds.description(productIDs) + case .paymentNotAllowed: + return L10n.Error.PaymentNotAllowed.description + case .paymentCancelled: + return L10n.Error.PaymentCancelled.description + case .storeProductNotAvailable: + return L10n.Error.StoreProductNotAvailable.description + case let .with(error): + return L10n.Error.With.description(error.localizedDescription) + case .receiptNotFound: + return L10n.Error.Receipt.description + case let .transactionNotFound(productID): + return L10n.Error.TransactionNotFound.description(productID) + case let .refund(error): + return L10n.Error.Refund.description(error.localizedDescription) + case let .verification(error): + return L10n.Error.Verification.description(error.localizedDescription) + case .paymentDefferred: + return L10n.Error.PaymentDefferred.description + case let .failedToDecodeSignature(signature): + return L10n.Error.FailedToDecodeSignature.description(signature) + case .unknown: + return L10n.Error.Unknown.description + } + } + + public var failureReason: String? { + switch self { + case .paymentNotAllowed: + return L10n.Error.PaymentNotAllowed.failureReason + default: + return nil + } + } + + public var recoverySuggestion: String? { + switch self { + case .paymentNotAllowed: + return L10n.Error.PaymentNotAllowed.recoverySuggestion + case .storeProductNotAvailable: + return L10n.Error.StoreProductNotAvailable.recoverySuggestion + default: + return nil + } + } +} diff --git a/Sources/Flare/Classes/Models/RefundError.swift b/Sources/Flare/Classes/Models/RefundError.swift index b7577599a..1db81dfc7 100644 --- a/Sources/Flare/Classes/Models/RefundError.swift +++ b/Sources/Flare/Classes/Models/RefundError.swift @@ -5,6 +5,8 @@ import Foundation +// MARK: - RefundError + /// It encompasses all types of refund errors. public enum RefundError: Error, Equatable { /// The duplicate refund request. @@ -12,3 +14,16 @@ public enum RefundError: Error, Equatable { /// The refund request failed. case failed } + +// MARK: LocalizedError + +extension RefundError: LocalizedError { + public var errorDescription: String? { + switch self { + case .duplicateRequest: + return L10n.RefundError.DuplicateRequest.description + case .failed: + return L10n.RefundError.Failed.description + } + } +} diff --git a/Sources/Flare/Classes/Models/VerificationError.swift b/Sources/Flare/Classes/Models/VerificationError.swift index 8f098d05e..fc661b2fa 100644 --- a/Sources/Flare/Classes/Models/VerificationError.swift +++ b/Sources/Flare/Classes/Models/VerificationError.swift @@ -5,8 +5,21 @@ import Foundation +// MARK: - VerificationError + /// Enumeration representing errors that can occur during verification. public enum VerificationError: Error { // Case for unverified product with associated productID and error details. case unverified(productID: String, error: Error) } + +// MARK: LocalizedError + +extension VerificationError: LocalizedError { + public var errorDescription: String? { + switch self { + case let .unverified(productID, error): + return L10n.VerificationError.unverified(productID, error.localizedDescription) + } + } +} diff --git a/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift b/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift index 08d3e7361..f517705bd 100644 --- a/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift +++ b/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift @@ -34,6 +34,7 @@ extension ConfigurationProvider: IConfigurationProvider { func configure(with configuration: Configuration) { cacheProvider.write(key: .applicationUsername, value: configuration.applicationUsername) + Logger.debug(message: L10n.Flare.initWithConfiguration(configuration)) } } diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index 8850f3a19..9cf523d95 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -189,6 +189,7 @@ final class IAPProvider: IIAPProvider { @available(watchOS, unavailable) @available(tvOS, unavailable) func presentCodeRedemptionSheet() { + Logger.debug(message: L10n.Redeem.presentingCodeRedemptionSheet) paymentQueue.presentCodeRedemptionSheet() } diff --git a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift index be3f107a6..0d681238e 100644 --- a/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift +++ b/Sources/Flare/Classes/Providers/PaymentProvider/PaymentProvider.swift @@ -63,6 +63,13 @@ extension PaymentProvider: IPaymentProvider { addPaymentHandler(productID: payment.productIdentifier, handler: handler) dispatchQueueFactory.main().async { self.paymentQueue.add(payment) + + Logger.info( + message: L10n.Payment.paymentQueueAddingPayment( + payment.productIdentifier, + self.paymentQueue.transactions.count + ) + ) } } @@ -157,6 +164,13 @@ extension PaymentProvider: SKPaymentTransactionObserver { #endif func finish(transaction: PaymentTransaction) { + Logger.info( + message: L10n.Purchase.finishingTransaction( + transaction.transactionIdentifier ?? "", + transaction.productIdentifier + ) + ) + paymentQueue.finishTransaction(transaction.skTransaction) } diff --git a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift index ce5cbdf30..f7666169c 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift @@ -104,11 +104,14 @@ extension ProductProvider: SKProductsRequestDelegate { guard response.invalidProductIdentifiers.isEmpty else { self.dispatchQueueFactory.main().async { - handler?(.failure(.invalid(productIds: response.invalidProductIdentifiers))) + handler?(.failure(.invalid(productIDs: response.invalidProductIdentifiers))) + Logger.error(message: L10n.Products.requestedProductsNotFound(response.invalidProductIdentifiers)) } return } + Logger.debug(message: L10n.Products.requestedProductsReceived(response.products.map(\.productIdentifier))) + self.dispatchQueueFactory.main().async { handler?(.success(response.products.map { SK1StoreProduct($0) })) } diff --git a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift index ae5703cad..b78680ba9 100644 --- a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift +++ b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift @@ -58,8 +58,10 @@ final class PurchaseProvider { switch result { case let .success(transaction): await completion(.success(StoreTransaction(paymentTransaction: PaymentTransaction(transaction)))) + Logger.info(message: L10n.Purchase.purchasedProduct(sk1StoreProduct.productIdentifier)) case let .failure(error): await completion(.failure(error)) + self.log(error: error, productID: sk1StoreProduct.productIdentifier) } } } @@ -78,8 +80,10 @@ final class PurchaseProvider { case let .success(result): if let transaction = try await self.transactionListener?.handle(purchaseResult: result) { await completion(.success(transaction)) + Logger.info(message: L10n.Purchase.purchasedProduct(sk2StoreProduct.productIdentifier)) } else { await completion(.failure(IAPError.unknown)) + self.log(error: IAPError.unknown, productID: sk2StoreProduct.productIdentifier) } case let .failure(error): await completion(.failure(IAPError(error: error))) @@ -103,6 +107,20 @@ final class PurchaseProvider { options.insert(.appAccountToken(uuid)) } } + + private func log(error: Error, productID: String) { + Logger.error(message: L10n.Purchase.productPurchaseFailed(productID, error.localizedDescription)) + } + + private func logPurchase(productID: String, promotionalOffer: PromotionalOffer?) { + if let offerID = promotionalOffer?.discount.offerIdentifier { + Logger.info( + message: L10n.Purchase.purchasingProductWithOffer(productID, offerID) + ) + } else { + Logger.info(message: L10n.Purchase.purchasingProduct(productID)) + } + } } // MARK: IPurchaseProvider @@ -113,6 +131,8 @@ extension PurchaseProvider: IPurchaseProvider { promotionalOffer: PromotionalOffer?, completion: @escaping PurchaseCompletionHandler ) { + logPurchase(productID: product.productIdentifier, promotionalOffer: promotionalOffer) + if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *), let sk2Product = product.underlyingProduct as? SK2StoreProduct { @@ -129,6 +149,8 @@ extension PurchaseProvider: IPurchaseProvider { promotionalOffer: PromotionalOffer?, completion: @escaping PurchaseCompletionHandler ) { + logPurchase(productID: product.productIdentifier, promotionalOffer: promotionalOffer) + if let sk2Product = product.underlyingProduct as? SK2StoreProduct { purchase( sk2StoreProduct: sk2Product, @@ -139,6 +161,7 @@ extension PurchaseProvider: IPurchaseProvider { } else { Task { await completion(.failure(.unknown)) + self.log(error: IAPError.unknown, productID: product.productIdentifier) } } } @@ -153,6 +176,13 @@ extension PurchaseProvider: IPurchaseProvider { }, asyncMethod: { await sk2Transaction.transaction.finish() + + Logger.info( + message: L10n.Purchase.finishingTransaction( + sk2Transaction.transactionIdentifier, + sk2Transaction.productIdentifier + ) + ) } ) } else if let sk1Transaction = transaction.storeTransaction as? SK1StoreTransaction { diff --git a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift index 9bf336936..f5ec09957 100644 --- a/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift +++ b/Sources/Flare/Classes/Providers/ReceiptRefreshProvider/ReceiptRefreshProvider.swift @@ -93,6 +93,8 @@ final class ReceiptRefreshProvider: NSObject { extension ReceiptRefreshProvider: IReceiptRefreshProvider { func refresh(requestID: String, handler: @escaping ReceiptRefreshHandler) { + Logger.info(message: L10n.Receipt.refreshingReceipt(requestID)) + let request = makeRequest(id: requestID) fetch(request: request, handler: handler) } @@ -110,6 +112,8 @@ extension ReceiptRefreshProvider: IReceiptRefreshProvider { extension ReceiptRefreshProvider: SKRequestDelegate { func request(_ request: SKRequest, didFailWithError error: Error) { + Logger.error(message: L10n.Receipt.refreshingReceiptFailed(request.id, error.localizedDescription)) + dispatchQueue.async { let handler = self.handlers.removeValue(forKey: request.id) self.dispatchQueueFactory.main().async { @@ -119,6 +123,8 @@ extension ReceiptRefreshProvider: SKRequestDelegate { } func requestDidFinish(_ request: SKRequest) { + Logger.info(message: L10n.Receipt.refreshedReceipt(request.id)) + dispatchQueue.async { let handler = self.handlers.removeValue(forKey: request.id) self.dispatchQueueFactory.main().async { diff --git a/Sources/Flare/Classes/Providers/RedeemCodeProvider/RedeemCodeProvider.swift b/Sources/Flare/Classes/Providers/RedeemCodeProvider/RedeemCodeProvider.swift index a4301be86..6358aeb69 100644 --- a/Sources/Flare/Classes/Providers/RedeemCodeProvider/RedeemCodeProvider.swift +++ b/Sources/Flare/Classes/Providers/RedeemCodeProvider/RedeemCodeProvider.swift @@ -37,7 +37,13 @@ extension RedeemCodeProvider: IRedeemCodeProvider { @MainActor func presentOfferCodeRedeemSheet() async throws { let windowScene = try systemInfoProvider.currentScene - try await AppStore.presentOfferCodeRedeemSheet(in: windowScene) + do { + Logger.debug(message: L10n.Redeem.presentingOfferCodeRedeemSheet) + try await AppStore.presentOfferCodeRedeemSheet(in: windowScene) + } catch { + Logger.error(message: L10n.Redeem.unableToPresentOfferCodeRedeemSheet(error.localizedDescription)) + throw error + } } #endif } diff --git a/Sources/Flare/Classes/Providers/RefundRequestProvider/RefundRequestProvider.swift b/Sources/Flare/Classes/Providers/RefundRequestProvider/RefundRequestProvider.swift index 360b62ef2..bdc650a6d 100644 --- a/Sources/Flare/Classes/Providers/RefundRequestProvider/RefundRequestProvider.swift +++ b/Sources/Flare/Classes/Providers/RefundRequestProvider/RefundRequestProvider.swift @@ -39,6 +39,7 @@ extension RefundRequestProvider: IRefundRequestProvider { @available(tvOS, unavailable) func verifyTransaction(productID: String) async throws -> UInt64 { guard let state = await StoreKit.Transaction.latest(for: productID) else { + Logger.error(message: L10n.Purchase.transactionNotFound(productID)) throw IAPError.transactionNotFound(productID: productID) } @@ -46,6 +47,7 @@ extension RefundRequestProvider: IRefundRequestProvider { case let .verified(transaction): return transaction.id case let .unverified(_, result): + Logger.error(message: L10n.Purchase.transactionUnverified(productID, result.localizedDescription)) throw result } } @@ -58,8 +60,10 @@ extension RefundRequestProvider: IRefundRequestProvider { if let skError = error as? StoreKit.Transaction.RefundRequestError { switch skError { case .duplicateRequest: + Logger.error(message: L10n.Refund.duplicateRefundRequest(skError.localizedDescription)) return .refund(error: .duplicateRequest) case .failed: + Logger.error(message: L10n.Refund.failedRefundRequest(skError.localizedDescription)) return .refund(error: .failed) @unknown default: return .unknown diff --git a/Sources/Flare/Resources/Localizable.strings b/Sources/Flare/Resources/Localizable.strings new file mode 100644 index 000000000..127895aa8 --- /dev/null +++ b/Sources/Flare/Resources/Localizable.strings @@ -0,0 +1,77 @@ +"purchase.transaction_unverified" = "Transaction for productID: %s is unverified by the App Store. Verification error: %s."; + +"purchase.finishing_transaction" = "Finishing transaction %s for product identifier: %s"; + +"purchase.cannot_purcase_product" = "This device is not able or allowed to make payments."; + +"purchase.transaction_not_found" = "Transaction for productID: %s not found."; + +"purchase.error_updating_transaction" = "An error occurred while listening for transactions: %s"; + +"flare.init_with_configuration" = "Flare configured with configuration:\n%@"; + +"payment.payment_queue_adding_payment" = "Adding payment for product: %s. %i transactions already in the queue"; + +"purchase.purchased_product" = "Purchased product: %s"; + +"purchase.purchasing_product" = "Purchasing product: %s"; + +"purchase.purchasing_product_with_offer" = "Purchasing product %s with offer %s"; + +"purchase.product_purchase_failed" = "Product purchase for %s failed with error: %s"; + +"refund.failed_refund_request" = "Refund request submission failed: %s"; + +"refund.duplicate_refund_request" = "Refund has already requested for this product: %s"; + +"redeem.presenting_code_redemption_sheet" = "Presenting code redemption sheet."; + +"redeem.presenting_offer_code_redeem_sheet" = "Presenting offer code redeem sheet"; + +"redeem.unable_to_present_offer_code_redeem_sheet" = "Unable to present offer code redeem sheet due to unexpected error: %s"; + +"products.requested_products_not_found" = "Requested products %@ not found."; + +"products.requested_products_received" = "Requested products %@ have been received"; + +"receipt.refreshing_receipt" = "Refreshing receipt. Request id: %s."; + +"receipt.refreshed_receipt" = "Refreshed receipt. Request id: %s."; + +"receipt.refreshing_receipt_failed" = "Refreshing receipt failed with error: %s. Request id: %s."; + +"error.invalid_product_ids.description" = "Invalid product IDs: %@"; + +"error.payment_not_allowed.description" = "The current user is not eligible to make payments."; + +"error.payment_not_allowed.failure_reason" = "The payment card may have purchase restrictions, such as set limits or unavailability for online shopping."; + +"error.payment_not_allowed.recovery_suggestion" = "Please check the payment card purchase restrictions."; + +"error.payment_cancelled.description" = "The payment was canceled by the user."; + +"error.store_product_not_available.description" = "The store product is currently unavailable."; + +"error.store_product_not_available.recovery_suggestion" = "Make sure to create a product with the given identifier in App Store Connect."; + +"error.unknown.description" = "The SKPayment returned unknown error."; + +"error.with.description" = "The error occurred: %s"; + +"error.receipt.description" = "The receipt could not be found."; + +"error.transaction_not_found.description" = "Transaction for productID: %s couldn't be found."; + +"error.refund.description" = "The error occurred during the refund: %s"; + +"error.verification.description" = "The verification has failed with the following error: %s"; + +"error.failed_to_decode_signature.description" = "Decoding the signature has failed. The signature: %s"; + +"error.payment_defferred.description" = "The purchase is pending, and requires action from the customer."; + +"refund_error.duplicate_request.description" = "The request has been duplicated."; + +"refund_error.failed.description" = "The refund request failed."; + +"verification_error.unverified" = "Transaction for productID: %s is unverified by the App Store. Verification error: %s."; diff --git a/Tests/FlareTests/UnitTests/Models/IAPErrorTests.swift b/Tests/FlareTests/UnitTests/Models/IAPErrorTests.swift index d1d1fa183..e46c73d32 100644 --- a/Tests/FlareTests/UnitTests/Models/IAPErrorTests.swift +++ b/Tests/FlareTests/UnitTests/Models/IAPErrorTests.swift @@ -41,17 +41,6 @@ final class IAPErrorTests: XCTestCase { XCTAssertEqual(error, IAPError.storeProductNotAvailable) } - func test_thatIAPErrorInstantiatesANewInstanceFromSkError_whenCodeIsEqualToUnknown() { - // given - let skError = SKError(SKError.Code.unknown) - - // when - let error = IAPError(error: skError) - - // then - XCTAssertEqual(error, IAPError.storeTrouble) - } - func test_thatIAPErrorInstantiatesANewInstanceFromSkError_whenErrorIsNil() { // when let error = IAPError(error: nil) diff --git a/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift index fc0a2edf1..ee9cb4d8e 100644 --- a/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Concurrency @@ -78,7 +78,7 @@ final class ProductProviderTests: XCTestCase { var error: IAPError? let completionHandler: IProductProvider.ProductsHandler = { error = $0.error } let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) - let errorStub = IAPError.emptyProducts + let errorStub = IAPError.unknown // when sut.fetch(productIDs: .productIDs, requestID: .requestID, completion: completionHandler) diff --git a/project.yml b/project.yml index 59e13d92d..5ba453420 100644 --- a/project.yml +++ b/project.yml @@ -11,6 +11,9 @@ packages: Concurrency: url: https://github.com/space-code/concurrency.git from: 0.0.1 + Log: + url: https://github.com/space-code/log.git + from: 1.1.0 targets: UnitTestHostApp: type: application @@ -31,6 +34,8 @@ targets: dependencies: - package: Concurrency product: Concurrency + - package: Log + product: Log settings: base: GENERATE_INFOPLIST_FILE: YES diff --git a/swiftgen.yml b/swiftgen.yml new file mode 100644 index 000000000..d54965973 --- /dev/null +++ b/swiftgen.yml @@ -0,0 +1,10 @@ +input_dir: Sources/Flare/Resources +output_dir: Sources/Flare/Classes/Generated +strings: + inputs: + - Localizable.strings + outputs: + templateName: structured-swift5 + output: Strings.swift + params: + publicAccess: false \ No newline at end of file From 1f56285da76648535fff02d1073cc27315b2a783 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 22 Jan 2024 16:13:22 +0100 Subject: [PATCH 40/44] Update the Documentation Page for Promotional Offers (#18) * Update the documentation * Update `CHANGELOG.md` --- CHANGELOG.md | 4 ++++ README.md | 2 +- Sources/Flare/Flare.docc/Articles/logging.md | 19 ++++++++++++++++++ .../Flare.docc/Articles/promotional-offers.md | 20 +++++++++++++------ Sources/Flare/Flare.docc/Flare.md | 1 + 5 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 Sources/Flare/Flare.docc/Articles/logging.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 908bfc4f9..9353e8576 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ All notable changes to this project will be documented in this file. - Added `visionOS` to list of supported platforms - Added in Pull Request [#5](https://github.com/space-code/flare/pull/5). +## Updated +- Update the documentation page for Promotional Offer + - Updated in Pull Request [#18](https://github.com/space-code/flare/pull/18). + ## Fixed - Fix typos in `CONTRIBUTING.md` - Added in Pull Request[#14](https://github.com/space-code/flare/pull/14). diff --git a/README.md b/README.md index a72bf09c7..63b899b10 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Flare is a framework written in Swift that makes it easy for you to work with in - [x] Complete Unit & Integration Test Coverage ## Documentation -Check out [flare documentation](https://space-code.github.io/flare/documentation/flare/). +Check out the [flare documentation](https://space-code.github.io/flare/documentation/flare/). ## Requirements - iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 7.0+ / visionOS 1.0+ diff --git a/Sources/Flare/Flare.docc/Articles/logging.md b/Sources/Flare/Flare.docc/Articles/logging.md new file mode 100644 index 000000000..6df6914d4 --- /dev/null +++ b/Sources/Flare/Flare.docc/Articles/logging.md @@ -0,0 +1,19 @@ +# logging + +Learn how to log important events. + +## Overview + +The `Flare` supports logging out of the box. It has a set of methods to facilitate logging, each accompanied by a detailed description. + +### Enabling Logging + +> important: `Flare` uses the `log` package for logging functionality. See [Log Package](https://github.com/space-code/log) for more info. + +By default, `Flare` logs only `debug` or `info` events based on the package building scheme. The special logging level can be forced by setting ``IFlare/logLevel`` to Flare. + +```swift +Flare.shared.logLevel = .all +``` + +The logging can be turned off by setting ``IFlare/logLevel`` to `off`. diff --git a/Sources/Flare/Flare.docc/Articles/promotional-offers.md b/Sources/Flare/Flare.docc/Articles/promotional-offers.md index bdb9015c1..fd5641f41 100644 --- a/Sources/Flare/Flare.docc/Articles/promotional-offers.md +++ b/Sources/Flare/Flare.docc/Articles/promotional-offers.md @@ -16,7 +16,7 @@ Learn how to use promotional offers. First, check if the user is eligible for an introductory offer. -> tip For this purpose can be used ``IFlare/checkEligibility(productIDs:)`` method. This method requires iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0. Otherwise, see [Determine Eligibility](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_introductory_offers_in_your_app#2940726). +> tip: For this purpose can be used ``IFlare/checkEligibility(productIDs:)`` method. This method requires iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0. Otherwise, see [Determine Eligibility](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_introductory_offers_in_your_app#2940726). ```swift func isEligibleForIntroductoryOffer(productID: String) async -> Bool { @@ -29,15 +29,19 @@ Second, proceed with the purchase as usual. See [Perform Purchase]( important: You need to fetch the signature from your server. See [Generation a signature for promotional offers](https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/generating_a_signature_for_promotional_offers) for more information. + +Request a signature from your server and prepare the discount offer. ```swift func prepareOffer(username: String, productID: String, offerID: String, completion: @escaping (PromotionalOffer.SignedData) -> Void) { @@ -59,7 +63,9 @@ func prepareOffer(username: String, productID: String, offerID: String, completi } ``` -Fourth, complete the purchase with the promotional offer. +### Perform a Purchase with the Promotional Offer + +Complete the purchase with the promotional offer. ```swift func purchase(product: StoreProduct, discount: StoreProductDiscount, signedData: SignedData) { @@ -79,7 +85,9 @@ func purchase(product: StoreProduct, discount: StoreProductDiscount, signedData: } ``` -Fifth, complete the transaction. +### Finish the Transaction + +Complete the transaction after purchasing. ```swift Flare.default.finish(transaction: transaction) diff --git a/Sources/Flare/Flare.docc/Flare.md b/Sources/Flare/Flare.docc/Flare.md index 847fb53fa..196c2ac5f 100644 --- a/Sources/Flare/Flare.docc/Flare.md +++ b/Sources/Flare/Flare.docc/Flare.md @@ -65,3 +65,4 @@ flare is available under the MIT license. See the LICENSE file for more info. - - - +- From 26fe805dbde5a298abd5607387b0294a0d878e05 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Thu, 25 Jan 2024 18:56:35 +0100 Subject: [PATCH 41/44] Implement Products Caching Mechanism (#19) * Implement products caching mechanism - Create a decorator object that implements caching functionality * Update `CHANGELOG.md` * Implement a cache policy for fetching products * Update docs --- CHANGELOG.md | 3 + Package.resolved | 9 + Package.swift | 2 + Package@swift-5.7.swift | 2 + Package@swift-5.8.swift | 2 + .../Flare/Classes/DI/FlareDependencies.swift | 9 +- .../Flare/Classes/Models/Configuration.swift | 15 +- .../Classes/Models/FetchCachePolicy.swift | 18 ++ .../Flare/Classes/Models/StoreProduct.swift | 2 +- .../ConfigurationProvider.swift | 5 + .../IConfigurationProvider.swift | 3 + .../Providers/IAPProvider/IAPProvider.swift | 34 ++-- .../CachingProductsProviderDecorator.swift | 160 ++++++++++++++++++ .../ICachingProductsProviderDecorator.swift | 9 + .../ProductProvider/IProductProvider.swift | 6 +- .../ProductProvider/ProductProvider.swift | 23 ++- .../Flare.docc/Articles/perform-purchase.md | 2 + ...achingProductsProviderDecoratorTests.swift | 83 +++++++++ .../Providers/IAPProviderTests.swift | 4 +- .../Providers/ProductProviderTests.swift | 6 +- .../Providers/PurchaseProviderTests.swift | 6 +- .../Mocks/ConfigurationProviderMock.swift | 10 ++ .../TestHelpers/Mocks/ProductMock.swift | 4 +- .../Mocks/ProductProviderMock.swift | 14 +- project.yml | 7 +- 25 files changed, 384 insertions(+), 54 deletions(-) create mode 100644 Sources/Flare/Classes/Models/FetchCachePolicy.swift create mode 100644 Sources/Flare/Classes/Providers/ProductProvider/Decorators/ProductsCacheProviderDecorator/CachingProductsProviderDecorator.swift create mode 100644 Sources/Flare/Classes/Providers/ProductProvider/Decorators/ProductsCacheProviderDecorator/ICachingProductsProviderDecorator.swift create mode 100644 Tests/FlareTests/UnitTests/Providers/CachingProductsProviderDecoratorTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 9353e8576..c6dba55b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ## Added +- Implement products caching mechanism + - Added in Pull Request [#19](https://github.com/space-code/flare/pull/19). + - Implement Logging Functionality - Added in Pull Request [#17](https://github.com/space-code/flare/pull/17). diff --git a/Package.resolved b/Package.resolved index a1bfb4096..83938f378 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,14 @@ { "pins" : [ + { + "identity" : "atomic", + "kind" : "remoteSourceControl", + "location" : "https://github.com/space-code/atomic.git", + "state" : { + "revision" : "53fae2fc8216bb5c27c87b245f893176d0d290eb", + "version" : "1.0.0" + } + }, { "identity" : "concurrency", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 036ddab79..0291e2f6c 100644 --- a/Package.swift +++ b/Package.swift @@ -22,11 +22,13 @@ let package = Package( .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), .package(url: "https://github.com/space-code/log.git", .upToNextMajor(from: "1.1.0")), + .package(url: "https://github.com/space-code/atomic.git", .upToNextMajor(from: "1.0.0")), ], targets: [ .target( name: "Flare", dependencies: [ + .product(name: "Atomic", package: "atomic"), .product(name: "Concurrency", package: "concurrency"), .product(name: "Log", package: "log"), ], diff --git a/Package@swift-5.7.swift b/Package@swift-5.7.swift index 167c85790..693b183aa 100644 --- a/Package@swift-5.7.swift +++ b/Package@swift-5.7.swift @@ -19,11 +19,13 @@ let package = Package( .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), .package(url: "https://github.com/space-code/log.git", .upToNextMajor(from: "1.1.0")), + .package(url: "https://github.com/space-code/atomic.git", .upToNextMajor(from: "1.0.0")), ], targets: [ .target( name: "Flare", dependencies: [ + .product(name: "Atomic", package: "atomic"), .product(name: "Concurrency", package: "concurrency"), .product(name: "Log", package: "log"), ], diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift index 9dbb5ffa9..87183860a 100644 --- a/Package@swift-5.8.swift +++ b/Package@swift-5.8.swift @@ -19,11 +19,13 @@ let package = Package( .package(url: "https://github.com/space-code/concurrency.git", .upToNextMajor(from: "0.0.1")), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"), .package(url: "https://github.com/space-code/log.git", .upToNextMajor(from: "1.1.0")), + .package(url: "https://github.com/space-code/atomic.git", .upToNextMajor(from: "1.0.0")), ], targets: [ .target( name: "Flare", dependencies: [ + .product(name: "Atomic", package: "atomic"), .product(name: "Concurrency", package: "concurrency"), .product(name: "Log", package: "log"), ], diff --git a/Sources/Flare/Classes/DI/FlareDependencies.swift b/Sources/Flare/Classes/DI/FlareDependencies.swift index 5f50073af..f97ae841c 100644 --- a/Sources/Flare/Classes/DI/FlareDependencies.swift +++ b/Sources/Flare/Classes/DI/FlareDependencies.swift @@ -13,7 +13,7 @@ final class FlareDependencies: IFlareDependencies { lazy var iapProvider: IIAPProvider = IAPProvider( paymentQueue: SKPaymentQueue.default(), - productProvider: productProvider, + productProvider: cachingProductProviderDecorator, purchaseProvider: purchaseProvider, receiptRefreshProvider: receiptRefreshProvider, refundProvider: refundProvider, @@ -25,6 +25,13 @@ final class FlareDependencies: IFlareDependencies { // MARK: Private + private var cachingProductProviderDecorator: ICachingProductsProviderDecorator { + CachingProductsProviderDecorator( + productProvider: productProvider, + configurationProvider: configurationProvider + ) + } + private var productProvider: IProductProvider { ProductProvider( dispatchQueueFactory: DispatchQueueFactory() diff --git a/Sources/Flare/Classes/Models/Configuration.swift b/Sources/Flare/Classes/Models/Configuration.swift index d2ece895c..ea7ab1da2 100644 --- a/Sources/Flare/Classes/Models/Configuration.swift +++ b/Sources/Flare/Classes/Models/Configuration.swift @@ -5,7 +5,7 @@ import Foundation -public struct Configuration { +public struct Configuration: Sendable { // MARK: Properties // swiftlint:disable:next line_length @@ -16,12 +16,21 @@ public struct Configuration { /// - Important: You must set `applicationUsername` to be the same as the one used to generate the signature. public let applicationUsername: String + /// The cache policy for fetching products. + public let fetchCachePolicy: FetchCachePolicy + // MARK: Initialization /// Creates a `Configuration` instance. /// - /// - Parameter applicationUsername: A string that associates the transaction with a user account on your service. - public init(applicationUsername: String) { + /// - Parameters: + /// - applicationUsername: A string that associates the transaction with a user account on your service. + /// - fetchCachePolicy: The cache policy for fetching products. + public init( + applicationUsername: String, + fetchCachePolicy: FetchCachePolicy = .cachedOrFetch + ) { self.applicationUsername = applicationUsername + self.fetchCachePolicy = fetchCachePolicy } } diff --git a/Sources/Flare/Classes/Models/FetchCachePolicy.swift b/Sources/Flare/Classes/Models/FetchCachePolicy.swift new file mode 100644 index 000000000..bfb267c2e --- /dev/null +++ b/Sources/Flare/Classes/Models/FetchCachePolicy.swift @@ -0,0 +1,18 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// Enum representing different cache policies for fetching data. +public enum FetchCachePolicy: Sendable, Codable { + /// Fetch the current data without using the cache. + case fetch + + /// Use the cached data if available; otherwise, fetch the data. + case cachedOrFetch + + /// The default cache policy, set to use cached data if available; otherwise, fetch the data. + static let `default`: FetchCachePolicy = .cachedOrFetch +} diff --git a/Sources/Flare/Classes/Models/StoreProduct.swift b/Sources/Flare/Classes/Models/StoreProduct.swift index bfbb34666..3a2c4a7d8 100644 --- a/Sources/Flare/Classes/Models/StoreProduct.swift +++ b/Sources/Flare/Classes/Models/StoreProduct.swift @@ -13,7 +13,7 @@ public final class StoreProduct: NSObject { // MARK: Properties /// Protocol representing a Store Kit product. - private let product: ISKProduct + let product: ISKProduct /// <#Description#> var underlyingProduct: ISKProduct { product } diff --git a/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift b/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift index f517705bd..66ae0d47e 100644 --- a/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift +++ b/Sources/Flare/Classes/Providers/ConfigurationProvider/ConfigurationProvider.swift @@ -14,6 +14,9 @@ final class ConfigurationProvider { /// The cache provider used to store and retrieve configuration settings. private let cacheProvider: ICacheProvider + /// The cache policy for fetching products. + private(set) var fetchCachePolicy: FetchCachePolicy = .default + // MARK: Initialization /// Initializes a ConfigurationProvider with a specified cache provider. @@ -34,6 +37,7 @@ extension ConfigurationProvider: IConfigurationProvider { func configure(with configuration: Configuration) { cacheProvider.write(key: .applicationUsername, value: configuration.applicationUsername) + fetchCachePolicy = configuration.fetchCachePolicy Logger.debug(message: L10n.Flare.initWithConfiguration(configuration)) } } @@ -42,4 +46,5 @@ extension ConfigurationProvider: IConfigurationProvider { private extension String { static let applicationUsername = "flare.configuration.application_username" + static let fetchCachePolicy = "flare.configuration.fetch_cache_policy" } diff --git a/Sources/Flare/Classes/Providers/ConfigurationProvider/IConfigurationProvider.swift b/Sources/Flare/Classes/Providers/ConfigurationProvider/IConfigurationProvider.swift index cae9f7b26..e5e2649b2 100644 --- a/Sources/Flare/Classes/Providers/ConfigurationProvider/IConfigurationProvider.swift +++ b/Sources/Flare/Classes/Providers/ConfigurationProvider/IConfigurationProvider.swift @@ -10,6 +10,9 @@ protocol IConfigurationProvider { /// The application username. var applicationUsername: String? { get } + /// <#Description#> + var fetchCachePolicy: FetchCachePolicy { get } + /// Configures the provider with the specified configuration settings. /// /// - Parameter configuration: The configuration settings to apply. diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index 9cf523d95..bb386a7bf 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -63,8 +63,13 @@ final class IAPProvider: IIAPProvider { func fetch(productIDs: Set, completion: @escaping Closure>) { if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) { AsyncHandler.call( - completion: { [weak self] (result: Result<[SK2StoreProduct], Error>) in - self?.handleFetchResult(result: result, completion) + completion: { (result: Result<[StoreProduct], Error>) in + switch result { + case let .success(products): + completion(.success(products)) + case let .failure(error): + completion(.failure(.with(error: error))) + } }, asyncMethod: { try await self.productProvider.fetch(productIDs: productIDs) @@ -73,10 +78,9 @@ final class IAPProvider: IIAPProvider { } else { productProvider.fetch( productIDs: productIDs, - requestID: UUID().uuidString - ) { [weak self] result in - self?.handleFetchResult(result: result, completion) - } + requestID: UUID().uuidString, + completion: completion + ) } } @@ -201,22 +205,4 @@ final class IAPProvider: IIAPProvider { try await redeemCodeProvider.presentOfferCodeRedeemSheet() } #endif - - // MARK: Private - - private func handleFetchResult( - result: Result<[T], E>, - _ completion: @escaping (Result<[StoreProduct], IAPError>) -> Void - ) { - switch result { - case let .success(products): - completion(.success(products.map { StoreProduct($0) })) - case let .failure(error): - if let iapError = error as? IAPError { - completion(.failure(iapError)) - } else { - completion(.failure(IAPError(error: error))) - } - } - } } diff --git a/Sources/Flare/Classes/Providers/ProductProvider/Decorators/ProductsCacheProviderDecorator/CachingProductsProviderDecorator.swift b/Sources/Flare/Classes/Providers/ProductProvider/Decorators/ProductsCacheProviderDecorator/CachingProductsProviderDecorator.swift new file mode 100644 index 000000000..d2a865962 --- /dev/null +++ b/Sources/Flare/Classes/Providers/ProductProvider/Decorators/ProductsCacheProviderDecorator/CachingProductsProviderDecorator.swift @@ -0,0 +1,160 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Atomic +import Foundation + +// MARK: - CachingProductsProviderDecorator + +/// `CachingProductsProviderDecorator` is a decorator class that adds caching functionality to an `IProductProvider`. +final class CachingProductsProviderDecorator { + // MARK: Properties + + /// Atomic property for thread-safe access to the cache dictionary. + @Atomic + private var cache: [String: StoreProduct] = [:] + + /// The product provider. + private let productProvider: IProductProvider + + /// The configuration provider. + private let configurationProvider: IConfigurationProvider + + // MARK: Initialization + + /// Creates a `CachingProductsProviderDecorator`instance. + /// + /// - Parameter productProvider: The product provider. + init(productProvider: IProductProvider, configurationProvider: IConfigurationProvider) { + self.productProvider = productProvider + self.configurationProvider = configurationProvider + } + + // MARK: Private + + /// Caches the provided array of products. + /// + /// - Parameter products: The array of products to be cached. + private func cache(products: [StoreProduct]) { + products.forEach { _cache.wrappedValue[$0.productIdentifier] = $0 } + } + + /// Retrieves cached products for the given set of product IDs. + /// + /// - Parameter ids: The set of product IDs to retrieve cached products for. + /// + /// - Returns: A dictionary containing cached products for the specified IDs. + private func cachedProducts(ids: Set) -> [String: StoreProduct] { + let cachedProducts = _cache.wrappedValue.filter { ids.contains($0.key) } + return cachedProducts + } + + /// Checks the cache for specified product IDs and fetches missing products from the product provider. + /// + /// - Parameters: + /// - productIDs: The set of product IDs to check the cache for. + /// - fetcher: A closure to fetch missing products from the product provider. + /// - completion: A closure to be called with the fetched products or an error. + private func fetch( + productIDs: Set, + fetcher: (Set, @escaping (Result<[StoreProduct], IAPError>) -> Void) -> Void, + completion: @escaping ProductsHandler + ) { + let cachedProducts = cachedProducts(ids: productIDs) + let missingProducts = productIDs.subtracting(cachedProducts.keys) + + if missingProducts.isEmpty { + completion(.success(Array(cachedProducts.values))) + } else { + fetcher(missingProducts) { [weak self] result in + switch result { + case let .success(products): + self?.cache(products: products) + completion(.success(products)) + case let .failure(error): + completion(.failure(error)) + } + } + } + } + + /// Retrieves localized information from the App Store about a specified list of products. + /// + /// - Parameters: + /// - fetchPolicy: The cache policy for fetching products. + /// - productIDs: The set of product IDs to check the cache for. + /// - fetcher: A closure to fetch missing products from the product provider. + /// - completion: A closure to be called with the fetched products or an error. + private func fetch( + fetchPolicy: FetchCachePolicy, + productIDs: Set, + fetcher: (Set, @escaping (Result<[StoreProduct], IAPError>) -> Void) -> Void, + completion: @escaping ProductsHandler + ) { + switch fetchPolicy { + case .fetch: + fetcher(productIDs, completion) + case .cachedOrFetch: + fetch(productIDs: productIDs, fetcher: fetcher, completion: completion) + } + } + + /// Retrieves localized information from the App Store about a specified list of products. + /// + /// - Parameters: + /// - productIDs: The set of product IDs to check the cache for. + /// - completion: A closure to be called with the fetched products or an error. + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + private func fetchSK2Products(productIDs: Set, completion: @escaping ProductsHandler) { + AsyncHandler.call( + completion: { result in + switch result { + case let .success(products): + completion(.success(products)) + case let .failure(error): + completion(.failure(IAPError.with(error: error))) + } + }, + asyncMethod: { + try await self.productProvider.fetch(productIDs: productIDs) + } + ) + } +} + +// MARK: ICachingProductsProviderDecorator + +extension CachingProductsProviderDecorator: ICachingProductsProviderDecorator { + func fetch(productIDs: Set, requestID: String, completion: @escaping ProductsHandler) { + fetch( + fetchPolicy: configurationProvider.fetchCachePolicy, + productIDs: productIDs, + fetcher: { [weak self] ids, completion in + self?.productProvider.fetch(productIDs: ids, requestID: requestID, completion: completion) + }, completion: completion + ) + } + + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + func fetch(productIDs: Set) async throws -> [StoreProduct] { + try await withCheckedThrowingContinuation { [weak self] continuation in + guard let self = self else { + continuation.resume(throwing: IAPError.unknown) + return + } + + self.fetch( + fetchPolicy: self.configurationProvider.fetchCachePolicy, + productIDs: productIDs, + fetcher: { [weak self] _, completion in + self?.fetchSK2Products(productIDs: productIDs, completion: completion) + }, + completion: { result in + continuation.resume(with: result) + } + ) + } + } +} diff --git a/Sources/Flare/Classes/Providers/ProductProvider/Decorators/ProductsCacheProviderDecorator/ICachingProductsProviderDecorator.swift b/Sources/Flare/Classes/Providers/ProductProvider/Decorators/ProductsCacheProviderDecorator/ICachingProductsProviderDecorator.swift new file mode 100644 index 000000000..b53e6d4d7 --- /dev/null +++ b/Sources/Flare/Classes/Providers/ProductProvider/Decorators/ProductsCacheProviderDecorator/ICachingProductsProviderDecorator.swift @@ -0,0 +1,9 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +/// Type that caches retrieved products. +protocol ICachingProductsProviderDecorator: IProductProvider {} diff --git a/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift index 156263321..1e82f3158 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/IProductProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import StoreKit @@ -14,7 +14,7 @@ typealias ReceiptRefreshHandler = (Result) -> Void /// A type that is responsible for retrieving StoreKit products. protocol IProductProvider { - typealias ProductsHandler = Closure> + typealias ProductsHandler = Closure> /// Retrieves localized information from the App Store about a specified list of products. /// @@ -32,5 +32,5 @@ protocol IProductProvider { /// /// - Returns: The requested products. @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) - func fetch(productIDs: Set) async throws -> [SK2StoreProduct] + func fetch(productIDs: Set) async throws -> [StoreProduct] } diff --git a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift index f7666169c..57a6ad833 100644 --- a/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift +++ b/Sources/Flare/Classes/Providers/ProductProvider/ProductProvider.swift @@ -3,6 +3,7 @@ // Copyright © 2024 Space Code. All rights reserved. // +import Atomic import Concurrency import StoreKit @@ -43,8 +44,8 @@ final class ProductProvider: NSObject, IProductProvider { } @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) - func fetch(productIDs ids: Set) async throws -> [SK2StoreProduct] { - try await StoreKit.Product.products(for: ids).map(SK2StoreProduct.init) + func fetch(productIDs ids: Set) async throws -> [StoreProduct] { + try await StoreKit.Product.products(for: ids).map { StoreProduct(product: $0) } } // MARK: Private @@ -83,6 +84,22 @@ final class ProductProvider: NSObject, IProductProvider { } } } + + private func handleFetchResult( + result: Result<[T], E>, + _ completion: @escaping (Result<[StoreProduct], IAPError>) -> Void + ) { + switch result { + case let .success(products): + completion(.success(products.map { StoreProduct($0) })) + case let .failure(error): + if let iapError = error as? IAPError { + completion(.failure(iapError)) + } else { + completion(.failure(IAPError(error: error))) + } + } + } } // MARK: SKProductsRequestDelegate @@ -113,7 +130,7 @@ extension ProductProvider: SKProductsRequestDelegate { Logger.debug(message: L10n.Products.requestedProductsReceived(response.products.map(\.productIdentifier))) self.dispatchQueueFactory.main().async { - handler?(.success(response.products.map { SK1StoreProduct($0) })) + handler?(.success(response.products.map { StoreProduct(skProduct: $0) })) } } } diff --git a/Sources/Flare/Flare.docc/Articles/perform-purchase.md b/Sources/Flare/Flare.docc/Articles/perform-purchase.md index 65f127781..87dd4ea88 100644 --- a/Sources/Flare/Flare.docc/Articles/perform-purchase.md +++ b/Sources/Flare/Flare.docc/Articles/perform-purchase.md @@ -52,6 +52,8 @@ do { } ``` +> note: Products are cached by default. If caching is not possible for specific usecases, set ``Configuration/fetchCachePolicy`` to ``FetchCachePolicy/fetch``. + ## Purchasing Product Flare provides a few methods to perform a purchase: diff --git a/Tests/FlareTests/UnitTests/Providers/CachingProductsProviderDecoratorTests.swift b/Tests/FlareTests/UnitTests/Providers/CachingProductsProviderDecoratorTests.swift new file mode 100644 index 000000000..c3c779602 --- /dev/null +++ b/Tests/FlareTests/UnitTests/Providers/CachingProductsProviderDecoratorTests.swift @@ -0,0 +1,83 @@ +// +// Flare +// Copyright © 2024 Space Code. All rights reserved. +// + +@testable import Flare +import XCTest + +// MARK: - CachingProductsProviderDecoratorTests + +final class CachingProductsProviderDecoratorTests: XCTestCase { + // MARK: Properties + + private var productProviderMock: ProductProviderMock! + private var configurationProviderMock: ConfigurationProviderMock! + + private var sut: CachingProductsProviderDecorator! + + // MARK: XCTestCase + + override func setUp() { + super.setUp() + productProviderMock = ProductProviderMock() + configurationProviderMock = ConfigurationProviderMock() + sut = CachingProductsProviderDecorator( + productProvider: productProviderMock, + configurationProvider: configurationProviderMock + ) + } + + override func tearDown() { + productProviderMock = nil + configurationProviderMock = nil + sut = nil + super.tearDown() + } + + // MARK: Tests + + func test_thatProviderFetchesCachedProducts_whenFetchCachePolicyIsCachedOrFetch() { + // given + configurationProviderMock.stubbedFetchCachePolicy = .cachedOrFetch + productProviderMock.stubbedFetchResult = .success([StoreProduct.fake()]) + + // when + sut.fetch(productIDs: [.productID], requestID: "", completion: { _ in }) + sut.fetch(productIDs: [.productID], requestID: "", completion: { _ in }) + + // then + XCTAssertEqual(productProviderMock.invokedFetchCount, 1) + } + + func test_thatProviderFetchesProducts_whenFetchCachePolicyIsFetch() { + // given + configurationProviderMock.stubbedFetchCachePolicy = .fetch + productProviderMock.stubbedFetchResult = .success([StoreProduct.fake()]) + + // when + sut.fetch(productIDs: [.productID], requestID: "", completion: { _ in }) + sut.fetch(productIDs: [.productID], requestID: "", completion: { _ in }) + + // then + XCTAssertEqual(productProviderMock.invokedFetchCount, 2) + } + + func test_thatProviderThrowsAnError_whenFetchDidFail() { + // given + configurationProviderMock.stubbedFetchCachePolicy = .cachedOrFetch + productProviderMock.stubbedFetchResult = .failure(.unknown) + + // when + sut.fetch(productIDs: [.productID], requestID: "", completion: { XCTAssertEqual($0.error, .unknown) }) + + // then + XCTAssertEqual(productProviderMock.invokedFetchCount, 1) + } +} + +// MARK: - Constants + +private extension String { + static let productID = "product_id" +} diff --git a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift index a9793760c..ace7cd0e8 100644 --- a/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/IAPProviderTests.swift @@ -120,7 +120,7 @@ class IAPProviderTests: XCTestCase { try AvailabilityChecker.iOS15APINotAvailableOrSkipTest() // given - let productsMock = [0 ... 2].map { _ in SK1StoreProduct(ProductMock()) } + let productsMock = [0 ... 2].map { _ in StoreProduct(SK1StoreProduct(ProductMock())) } productProviderMock.stubbedFetchResult = .success(productsMock) // when @@ -145,7 +145,7 @@ class IAPProviderTests: XCTestCase { func test_thatIAPProviderReturnsError_whenAddingPaymentFailed() { // given - productProviderMock.stubbedFetchResult = .success([SK1StoreProduct(ProductMock())]) + productProviderMock.stubbedFetchResult = .success([StoreProduct(SK1StoreProduct(ProductMock()))]) purchaseProvider.stubbedPurchaseCompletionResult = (.failure(.unknown), ()) // when diff --git a/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift index ee9cb4d8e..497601be2 100644 --- a/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/ProductProviderTests.swift @@ -39,7 +39,7 @@ final class ProductProviderTests: XCTestCase { func test_thatProductProviderReturnsInvalidProductIDs_whenRequestProductsAreFetchedWithInvalidIDs() { // given - var fetchResult: Result<[SK1StoreProduct], IAPError>? + var fetchResult: Result<[StoreProduct], IAPError>? let completionHandler: IProductProvider.ProductsHandler = { result in fetchResult = result } let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let response = ProductResponseMock() @@ -60,7 +60,7 @@ final class ProductProviderTests: XCTestCase { func test_thatProductProviderReturnsProducts_whenRequestProductsAreFetchedWithValidProductIDs() { // given - var products: [SK1StoreProduct]? = [] + var products: [StoreProduct]? = [] let completionHandler: IProductProvider.ProductsHandler = { products = $0.success } let request = PurchaseManagerTestHelper.makeRequest(with: .requestID) let response = ProductResponseMock() @@ -70,7 +70,7 @@ final class ProductProviderTests: XCTestCase { sut.productsRequest(request, didReceive: response) // then - XCTAssertEqual(products?.map(\.product), response.products) + XCTAssertEqual(products?.compactMap { $0.product as? SK1StoreProduct }.map(\.product), response.products) } func test_thatProductProviderHandlesError_whenRequestDidFailWithError() { diff --git a/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift b/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift index abc7c95e9..dee0878b7 100644 --- a/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift +++ b/Tests/FlareTests/UnitTests/Providers/PurchaseProviderTests.swift @@ -42,13 +42,15 @@ final class PurchaseProviderTests: XCTestCase { func test_thatPurchaseProviderReturnsPaymentTransaction_whenSK1ProductExist() { // given let productMock = StoreProduct(skProduct: ProductMock()) + let paymentTransaction = SKPaymentTransaction() + let storeTransaction = StoreTransaction(paymentTransaction: PaymentTransaction(paymentTransaction)) - paymentProviderMock.stubbedAddResult = (paymentQueueMock, .success(SKPaymentTransaction())) + paymentProviderMock.stubbedAddResult = (paymentQueueMock, .success(paymentTransaction)) // when sut.purchase(product: productMock) { result in if case let .success(transaction) = result { - XCTAssertEqual(transaction.productIdentifier, productMock.productIdentifier) + XCTAssertEqual(transaction, storeTransaction) } else { XCTFail("The products' ids must be equal") } diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ConfigurationProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ConfigurationProviderMock.swift index 0f460b5c0..679845da5 100644 --- a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ConfigurationProviderMock.swift +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ConfigurationProviderMock.swift @@ -17,6 +17,16 @@ final class ConfigurationProviderMock: IConfigurationProvider { return stubbedApplicationUsername } + var invokedFetchCachePolicyGetter = false + var invokedFetchCachePolicyGetterCount = 0 + var stubbedFetchCachePolicy: FetchCachePolicy! + + var fetchCachePolicy: FetchCachePolicy { + invokedFetchCachePolicyGetter = true + invokedFetchCachePolicyGetterCount += 1 + return stubbedFetchCachePolicy + } + var invokedConfigure = false var invokedConfigureCount = 0 var invokedConfigureParameters: (configuration: Configuration, Void)? diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductMock.swift index e15937e91..9d765f02e 100644 --- a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductMock.swift +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductMock.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import StoreKit @@ -8,7 +8,7 @@ import StoreKit final class ProductMock: SKProduct { var invokedProductIdentifier = false var invokedProductIdentifierCount = 0 - var stubbedProductIdentifier: String = "" + var stubbedProductIdentifier: String = "product_id" override var productIdentifier: String { invokedProductIdentifier = true diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductProviderMock.swift index 38a26470a..489118ce7 100644 --- a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductProviderMock.swift +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/ProductProviderMock.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // @testable import Flare @@ -11,7 +11,7 @@ final class ProductProviderMock: IProductProvider { var invokedFetchCount = 0 var invokedFetchParameters: (productIDs: Set, requestID: String, completion: ProductsHandler)? var invokedFetchParamtersList = [(productIDs: Set, requestID: String, completion: ProductsHandler)]() - var stubbedFetchResult: Result<[SK1StoreProduct], IAPError>? + var stubbedFetchResult: Result<[StoreProduct], IAPError>? func fetch(productIDs: Set, requestID: String, completion: @escaping ProductsHandler) { invokedFetch = true @@ -28,10 +28,10 @@ final class ProductProviderMock: IProductProvider { var invokedAsyncFetchCount = 0 var invokedAsyncFetchParameters: (productIDs: Set, Void)? var invokedAsyncFetchParamtersList = [(productIDs: Set, Void)]() - var stubbedAsyncFetchResult: Result<[ISKProduct], Error>? + var stubbedAsyncFetchResult: Result<[StoreProduct], Error>? @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) - func fetch(productIDs: Set) async throws -> [SK2StoreProduct] { + func fetch(productIDs: Set) async throws -> [StoreProduct] { invokedAsyncFetch = true invokedAsyncFetchCount += 1 invokedAsyncFetchParameters = (productIDs, ()) @@ -39,11 +39,7 @@ final class ProductProviderMock: IProductProvider { switch stubbedAsyncFetchResult { case let .success(products): - if let products = products as? [SK2StoreProduct] { - return products - } else { - return [] - } + return products case let .failure(error): throw error default: diff --git a/project.yml b/project.yml index 5ba453420..9f43f179d 100644 --- a/project.yml +++ b/project.yml @@ -14,6 +14,9 @@ packages: Log: url: https://github.com/space-code/log.git from: 1.1.0 + Atomic: + url: https://github.com/space-code/atomic.git + from: 1.0.0 targets: UnitTestHostApp: type: application @@ -36,6 +39,8 @@ targets: product: Concurrency - package: Log product: Log + - package: Atomic + package: Atomic settings: base: GENERATE_INFOPLIST_FILE: YES @@ -82,4 +87,4 @@ targets: TEST_HOST: $(BUILT_PRODUCTS_DIR)/UnitTestHostApp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/UnitTestHostApp PRODUCT_BUNDLE_IDENTIFIER: com.spacecode.flare.storekit-unit-tests sources: - - Tests/IntegrationTests \ No newline at end of file + - Tests/IntegrationTests From e290ca151c0bd476be3b043f82dc1afbd2021868 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 07:49:59 +0100 Subject: [PATCH 42/44] Bump `atomic` from 1.0.0 to 1.0.1 (#20) Bumps [github.com/space-code/atomic](https://github.com/space-code/atomic) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/space-code/atomic/releases) - [Commits](https://github.com/space-code/atomic/compare/1.0.0...1.0.1) --- updated-dependencies: - dependency-name: github.com/space-code/atomic dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index 83938f378..afc089a5b 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/space-code/atomic.git", "state" : { - "revision" : "53fae2fc8216bb5c27c87b245f893176d0d290eb", - "version" : "1.0.0" + "revision" : "6a1473440c31c6debf1de2404265949ed7892b14", + "version" : "1.0.1" } }, { From fa5bfbfd0bcfaca12111ed3a49c06e59c49c8dad Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 12 Feb 2024 15:34:05 +0100 Subject: [PATCH 43/44] Fix Branch (#21) * Fix conflicts From a120b99c04d2a10cf36ca0e60074de4bb711004d Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Mon, 12 Feb 2024 15:42:55 +0100 Subject: [PATCH 44/44] Update `CHANGELOG.md` --- CHANGELOG.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6dba55b1..c2c2d4c03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,17 @@ # Change Log All notable changes to this project will be documented in this file. -## [Unreleased] +#### 3.x Releases +- `3.0.0` Release Candidates - [`3.0.0-rc.1`](#300-rc1) + +#### 2.x Releases +- `2.0.x` Releases - [2.0.0](#200) + +#### 1.x Releases +- `1.0.x` Releases - [1.0.0](#100) + +## [3.0.0-rc.1](https://github.com/space-code/flare/releases/tag/3.0.0-rc.1) +Released on 2024-02-12. ## Added - Implement products caching mechanism @@ -48,9 +58,6 @@ All notable changes to this project will be documented in this file. - Fix typos in `CONTRIBUTING.md` - Added in Pull Request[#14](https://github.com/space-code/flare/pull/14). -#### 2.x Releases -- `2.0.x` Releases - [2.0.0](#200) - ## [2.0.0](https://github.com/space-code/flare/releases/tag/2.0.0) Released on 2023-09-13. @@ -60,9 +67,6 @@ Released on 2023-09-13. #### Updated - Rename public methods and parameters to increase readability. -#### 1.x Releases -- `1.0.x` Releases - [1.0.0](#100) - ## [1.0.0](https://github.com/space-code/flare/releases/tag/1.0.0) Released on 2023-01-20.