Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,76 @@ final class ReceiptEligibilityUseCase: ReceiptEligibilityUseCaseProtocol {
return onCompletion(false)
}
// 2. If WooCommerce version is any of the specific API development branches, mark as eligible
if Constants.wcPluginDevVersion.contains(wcPlugin.version) {
if Constants.BackendReceipt.wcPluginDevVersion.contains(wcPlugin.version) {
onCompletion(true)
} else {
// 3. Else, if WooCommerce version is higher than minimum required version, mark as eligible
let isSupported = VersionHelpers.isVersionSupported(version: wcPlugin.version,
minimumRequired: Constants.wcPluginMinimumVersion)
minimumRequired: Constants.BackendReceipt.wcPluginMinimumVersion)
onCompletion(isSupported)
}
}
stores.dispatch(action)
}

func isEligibleSendingReceiptAfterPayment(onCompletion: @escaping (Bool) -> Void) {
// TODO: WooCommerce 9.5.0
onCompletion(featureFlagService.isFeatureFlagEnabled(.sendReceiptAfterPayment))
guard featureFlagService.isFeatureFlagEnabled(.sendReceiptAfterPayment) else {
return onCompletion(false)
}

Task { @MainActor in
async let isWooCommerceSupported = isPluginSupported(Constants.wcPluginName,
minimumVersion: Constants.ReceiptAfterPayment.wcPluginMinimumVersion)
async let isWooPaymentsSupported = isPluginSupported(Constants.wcPayPluginName,
minimumVersion: Constants.ReceiptAfterPayment.wcPayPluginMinimumVersion)
let wooCommerceResult = await isWooCommerceSupported
let wooPaymentsResult = await isWooPaymentsSupported
let isSupported = wooCommerceResult && wooPaymentsResult

onCompletion(isSupported)
}
}
}

private extension ReceiptEligibilityUseCase {
@MainActor
func isPluginSupported(_ pluginName: String, minimumVersion: String) async -> Bool {
await withCheckedContinuation { continuation in
let action = SystemStatusAction.fetchSystemPlugin(siteID: siteID, systemPluginName: pluginName) { plugin in
// Plugin must be installed and active
guard let plugin, plugin.active else {
return continuation.resume(returning: false)
}

// Checking for concrete versions to cover dev and beta versions
if plugin.version.contains(minimumVersion) {
return continuation.resume(returning: true)
}

// If plugin version is higher than minimum required version, mark as eligible
let isSupported = VersionHelpers.isVersionSupported(version: plugin.version,
minimumRequired: minimumVersion)
continuation.resume(returning: isSupported)
}
stores.dispatch(action)
}
}
}

private extension ReceiptEligibilityUseCase {
enum Constants {
static let wcPluginName = "WooCommerce"
static let wcPluginMinimumVersion = "8.7.0"
static let wcPluginDevVersion: [String] = ["8.7.0-dev", "8.6.0-dev"]
static let wcPayPluginName = "WooPayments"

enum BackendReceipt {
static let wcPluginMinimumVersion = "8.7.0"
static let wcPluginDevVersion: [String] = ["8.7.0-dev", "8.6.0-dev"]
}

enum ReceiptAfterPayment {
static let wcPluginMinimumVersion = "9.5.0"
static let wcPayPluginMinimumVersion = "8.6.0"
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct MockFeatureFlagService: FeatureFlagService {
private let favoriteProducts: Bool
private let paymentsOnboardingInPointOfSale: Bool
private let isProductGlobalUniqueIdentifierSupported: Bool
private let isSendReceiptAfterPaymentEnabled: Bool

init(isInboxOn: Bool = false,
isShowInboxCTAEnabled: Bool = false,
Expand All @@ -46,7 +47,8 @@ struct MockFeatureFlagService: FeatureFlagService {
viewEditCustomFieldsInProductsAndOrders: Bool = false,
favoriteProducts: Bool = false,
paymentsOnboardingInPointOfSale: Bool = false,
isProductGlobalUniqueIdentifierSupported: Bool = false) {
isProductGlobalUniqueIdentifierSupported: Bool = false,
isSendReceiptAfterPaymentEnabled: Bool = false) {
self.isInboxOn = isInboxOn
self.isShowInboxCTAEnabled = isShowInboxCTAEnabled
self.isUpdateOrderOptimisticallyOn = isUpdateOrderOptimisticallyOn
Expand All @@ -69,6 +71,7 @@ struct MockFeatureFlagService: FeatureFlagService {
self.favoriteProducts = favoriteProducts
self.paymentsOnboardingInPointOfSale = paymentsOnboardingInPointOfSale
self.isProductGlobalUniqueIdentifierSupported = isProductGlobalUniqueIdentifierSupported
self.isSendReceiptAfterPaymentEnabled = isSendReceiptAfterPaymentEnabled
}

func isFeatureFlagEnabled(_ featureFlag: FeatureFlag) -> Bool {
Expand Down Expand Up @@ -117,6 +120,8 @@ struct MockFeatureFlagService: FeatureFlagService {
return paymentsOnboardingInPointOfSale
case .productGlobalUniqueIdentifierSupport:
return isProductGlobalUniqueIdentifierSupported
case .sendReceiptAfterPayment:
return isSendReceiptAfterPaymentEnabled
default:
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,155 @@ final class ReceiptEligibilityUseCaseTests: XCTestCase {
// Then
XCTAssertTrue(isEligible)
}

// MARK: - Send Receipt After Payment

func test_isEligibleSendingReceiptAfterPayment_when_feature_flag_is_disabled_then_returns_false() {
// Given
let featureFlag = MockFeatureFlagService(isSendReceiptAfterPaymentEnabled: false)
let stores = MockStoresManager(sessionManager: .makeForTesting())
let sut = ReceiptEligibilityUseCase(stores: stores, featureFlagService: featureFlag)

// When
let isEligible: Bool = waitFor { promise in
sut.isEligibleSendingReceiptAfterPayment(onCompletion: { result in
promise(result)
})
}

// Then
XCTAssertFalse(isEligible)
}

func test_isEligibleSendingReceiptAfterPayment_when_plugins_are_inactive_then_returns_false() {
// Given
let featureFlag = MockFeatureFlagService(isSendReceiptAfterPaymentEnabled: true)
let stores = MockStoresManager(sessionManager: .makeForTesting())
let wooCommercePlugin = SystemPlugin.fake().copy(name: "WooCommerce", version: "9.6.0", active: false)
let wooPaymentsPlugin = SystemPlugin.fake().copy(name: "WooPayments", version: "8.9.0", active: false)

stores.whenReceivingAction(ofType: SystemStatusAction.self) { action in
switch action {
case let .fetchSystemPlugin(_, systemPluginName, onCompletion):
if systemPluginName == "WooCommerce" {
onCompletion(wooCommercePlugin)
} else if systemPluginName == "WooPayments" {
onCompletion(wooPaymentsPlugin)
}
default:
XCTFail("Unexpected action")
}
}

let sut = ReceiptEligibilityUseCase(stores: stores, featureFlagService: featureFlag)

// When
let isEligible: Bool = waitFor { promise in
sut.isEligibleSendingReceiptAfterPayment(onCompletion: { result in
promise(result)
})
}

// Then
XCTAssertFalse(isEligible)
}

func test_isEligibleSendingReceiptAfterPayment_when_plugins_are_supported_then_returns_true() {
// Given
let featureFlag = MockFeatureFlagService(isSendReceiptAfterPaymentEnabled: true)
let stores = MockStoresManager(sessionManager: .makeForTesting())
let wooCommercePlugin = SystemPlugin.fake().copy(name: "WooCommerce", version: "9.5.0", active: true)
let wooPaymentsPlugin = SystemPlugin.fake().copy(name: "WooPayments", version: "8.6.0", active: true)

stores.whenReceivingAction(ofType: SystemStatusAction.self) { action in
switch action {
case let .fetchSystemPlugin(_, systemPluginName, onCompletion):
if systemPluginName == "WooCommerce" {
onCompletion(wooCommercePlugin)
} else if systemPluginName == "WooPayments" {
onCompletion(wooPaymentsPlugin)
}
default:
XCTFail("Unexpected action")
}
}

let sut = ReceiptEligibilityUseCase(stores: stores, featureFlagService: featureFlag)

// When
let isEligible: Bool = waitFor { promise in
sut.isEligibleSendingReceiptAfterPayment(onCompletion: { result in
promise(result)
})
}

// Then
XCTAssertTrue(isEligible)
}

func test_isEligibleSendingReceiptAfterPayment_when_plugins_are_supported_dev_then_returns_true() {
// Given
let featureFlag = MockFeatureFlagService(isSendReceiptAfterPaymentEnabled: true)
let stores = MockStoresManager(sessionManager: .makeForTesting())
let wooCommercePlugin = SystemPlugin.fake().copy(name: "WooCommerce", version: "9.6.0-dev-1181231238", active: true)
let wooPaymentsPlugin = SystemPlugin.fake().copy(name: "WooPayments", version: "8.6.0-test-1", active: true)

stores.whenReceivingAction(ofType: SystemStatusAction.self) { action in
switch action {
case let .fetchSystemPlugin(_, systemPluginName, onCompletion):
if systemPluginName == "WooCommerce" {
onCompletion(wooCommercePlugin)
} else if systemPluginName == "WooPayments" {
onCompletion(wooPaymentsPlugin)
}
default:
XCTFail("Unexpected action")
}
}

let sut = ReceiptEligibilityUseCase(stores: stores, featureFlagService: featureFlag)

// When
let isEligible: Bool = waitFor { promise in
sut.isEligibleSendingReceiptAfterPayment(onCompletion: { result in
promise(result)
})
}

// Then
XCTAssertTrue(isEligible)
}

func test_isEligibleSendingReceiptAfterPayment_when_woopayments_version_is_incorrect_then_returns_false() {
// Given
let featureFlag = MockFeatureFlagService(isSendReceiptAfterPaymentEnabled: true)
let stores = MockStoresManager(sessionManager: .makeForTesting())
let wooCommercePlugin = SystemPlugin.fake().copy(name: "WooCommerce", version: "9.5.0", active: true)
let wooPaymentsPlugin = SystemPlugin.fake().copy(name: "WooPayments", version: "5.0.0-dev", active: true)

stores.whenReceivingAction(ofType: SystemStatusAction.self) { action in
switch action {
case let .fetchSystemPlugin(_, systemPluginName, onCompletion):
if systemPluginName == "WooCommerce" {
onCompletion(wooCommercePlugin)
} else if systemPluginName == "WooPayments" {
onCompletion(wooPaymentsPlugin)
}
default:
XCTFail("Unexpected action")
}
}

let sut = ReceiptEligibilityUseCase(stores: stores, featureFlagService: featureFlag)

// When
let isEligible: Bool = waitFor { promise in
sut.isEligibleSendingReceiptAfterPayment(onCompletion: { result in
promise(result)
})
}

// Then
XCTAssertFalse(isEligible)
}
}
Loading