-
Notifications
You must be signed in to change notification settings - Fork 330
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
As suggested by @aboedo in #3164 (comment)
- Loading branch information
Showing
9 changed files
with
296 additions
and
133 deletions.
There are no files selected for viewing
File renamed without changes.
49 changes: 49 additions & 0 deletions
49
RevenueCatUI/Data/IntroEligibility/TrialOrIntroEligibilityChecker+TestData.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// | ||
// Copyright RevenueCat Inc. All Rights Reserved. | ||
// | ||
// Licensed under the MIT License (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// TrialOrIntroEligibilityChecker+TestData.swift | ||
// | ||
// Created by Nacho Soto on 9/12/23. | ||
|
||
import Foundation | ||
import RevenueCat | ||
|
||
#if DEBUG | ||
|
||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, *) | ||
extension TrialOrIntroEligibilityChecker { | ||
|
||
/// Creates a mock `TrialOrIntroEligibilityChecker` with a constant result. | ||
static func producing(eligibility: @autoclosure @escaping () -> IntroEligibilityStatus) -> Self { | ||
return .init { packages in | ||
return Dictionary( | ||
uniqueKeysWithValues: Set(packages) | ||
.map { package in | ||
let result = package.storeProduct.hasIntroDiscount | ||
? eligibility() | ||
: .noIntroOfferExists | ||
|
||
return (package, result) | ||
} | ||
) | ||
} | ||
} | ||
|
||
/// Creates a copy of this `TrialOrIntroEligibilityChecker` with a delay. | ||
func with(delay seconds: TimeInterval) -> Self { | ||
return .init { [checker = self.checker] in | ||
await Task.sleep(seconds: seconds) | ||
|
||
return await checker($0) | ||
} | ||
} | ||
|
||
} | ||
|
||
#endif |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// | ||
// Copyright RevenueCat Inc. All Rights Reserved. | ||
// | ||
// Licensed under the MIT License (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// MockPurchasesType.swift | ||
// | ||
// Created by Nacho Soto on 9/12/23. | ||
|
||
import RevenueCat | ||
|
||
#if DEBUG | ||
|
||
/// An implementation of `PaywallPurchasesType` that allows creating custom blocks. | ||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, *) | ||
final class MockPurchases: PaywallPurchasesType { | ||
|
||
typealias PurchaseBlock = @Sendable (Package) async throws -> PurchaseResultData | ||
typealias RestoreBlock = @Sendable () async throws -> CustomerInfo | ||
typealias TrackEventBlock = @Sendable (PaywallEvent) async -> Void | ||
|
||
private let purchaseBlock: PurchaseBlock | ||
private let restoreBlock: RestoreBlock | ||
private let trackEventBlock: TrackEventBlock | ||
|
||
init( | ||
purchase: @escaping PurchaseBlock, | ||
restorePurchases: @escaping RestoreBlock, | ||
trackEvent: @escaping TrackEventBlock | ||
) { | ||
self.purchaseBlock = purchase | ||
self.restoreBlock = restorePurchases | ||
self.trackEventBlock = trackEvent | ||
} | ||
|
||
func purchase(package: Package) async throws -> PurchaseResultData { | ||
return try await self.purchaseBlock(package) | ||
} | ||
|
||
func restorePurchases() async throws -> CustomerInfo { | ||
return try await self.restoreBlock() | ||
} | ||
|
||
func track(paywallEvent: PaywallEvent) async { | ||
await self.trackEventBlock(paywallEvent) | ||
} | ||
|
||
} | ||
|
||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, *) | ||
extension PaywallPurchasesType { | ||
|
||
/// Creates a copy of this `PaywallPurchasesType` wrapping `purchase` and `restore`. | ||
func map( | ||
purchase: @escaping (@escaping MockPurchases.PurchaseBlock) -> MockPurchases.PurchaseBlock, | ||
restore: @escaping (@escaping MockPurchases.RestoreBlock) -> MockPurchases.RestoreBlock | ||
) -> PaywallPurchasesType { | ||
return MockPurchases { package in | ||
try await purchase(self.purchase(package:))(package) | ||
} restorePurchases: { | ||
try await restore(self.restorePurchases)() | ||
} trackEvent: { event in | ||
await self.track(paywallEvent: event) | ||
} | ||
} | ||
|
||
/// Creates a copy of this `PaywallPurchasesType` wrapping `trackEvent`. | ||
func map( | ||
trackEvent: @escaping (@escaping MockPurchases.TrackEventBlock) -> MockPurchases.TrackEventBlock | ||
) -> PaywallPurchasesType { | ||
return MockPurchases { package in | ||
try await self.purchase(package: package) | ||
} restorePurchases: { | ||
try await self.restorePurchases() | ||
} trackEvent: { event in | ||
await trackEvent(self.track(paywallEvent:))(event) | ||
} | ||
} | ||
|
||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// | ||
// Copyright RevenueCat Inc. All Rights Reserved. | ||
// | ||
// Licensed under the MIT License (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// PaywallPurchasesType.swift | ||
// | ||
// Created by Nacho Soto on 9/12/23. | ||
|
||
import RevenueCat | ||
|
||
/// A simplified protocol for the subset of `PurchasesType` needed for `RevenueCatUI`. | ||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, *) | ||
protocol PaywallPurchasesType: Sendable { | ||
|
||
@Sendable | ||
func purchase(package: Package) async throws -> PurchaseResultData | ||
|
||
@Sendable | ||
func restorePurchases() async throws -> CustomerInfo | ||
|
||
@Sendable | ||
func track(paywallEvent: PaywallEvent) async | ||
|
||
} | ||
|
||
extension Purchases: PaywallPurchasesType {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// | ||
// Copyright RevenueCat Inc. All Rights Reserved. | ||
// | ||
// Licensed under the MIT License (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// PurchaseHandler+TestData.swift | ||
// | ||
// Created by Nacho Soto on 9/12/23. | ||
|
||
import Foundation | ||
import RevenueCat | ||
|
||
#if DEBUG | ||
|
||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, *) | ||
extension PurchaseHandler { | ||
|
||
static func mock() -> Self { | ||
return self.init( | ||
purchases: MockPurchases { _ in | ||
return ( | ||
transaction: nil, | ||
customerInfo: TestData.customerInfo, | ||
userCancelled: false | ||
) | ||
} restorePurchases: { | ||
return TestData.customerInfo | ||
} trackEvent: { event in | ||
Logger.debug("Tracking event: \(event)") | ||
} | ||
) | ||
} | ||
|
||
static func cancelling() -> Self { | ||
return .mock() | ||
.map { block in { | ||
var result = try await block($0) | ||
result.userCancelled = true | ||
return result | ||
} | ||
} restore: { $0 } | ||
} | ||
|
||
/// Creates a copy of this `PurchaseHandler` with a delay. | ||
func with(delay seconds: TimeInterval) -> Self { | ||
return self.map { purchaseBlock in { | ||
await Task.sleep(seconds: seconds) | ||
|
||
return try await purchaseBlock($0) | ||
} | ||
} restore: { restoreBlock in { | ||
await Task.sleep(seconds: seconds) | ||
|
||
return try await restoreBlock() | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) | ||
extension Task where Success == Never, Failure == Never { | ||
|
||
static func sleep(seconds: TimeInterval) async { | ||
try? await Self.sleep(nanoseconds: UInt64(seconds * 1_000_000_000)) | ||
} | ||
|
||
} | ||
|
||
#endif |
Oops, something went wrong.