diff --git a/WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift b/WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift index d90d1028c07..fa4b287648f 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift @@ -179,9 +179,9 @@ where TapToPayAlertProvider.AlertDetails == AlertPresenter.AlertDetails, alertProvider: paymentAlertProvider, onCompleted: onCompleted) } + onPaymentCompletion() } } - onPaymentCompletion() }) case .canceled(let cancellationSource, _): self.handlePaymentCancellation(from: cancellationSource) diff --git a/WooCommerce/WooCommerceTests/Mocks/MockReceiptEligibilityUseCase.swift b/WooCommerce/WooCommerceTests/Mocks/MockReceiptEligibilityUseCase.swift index 615e27f925c..89bcc56b64b 100644 --- a/WooCommerce/WooCommerceTests/Mocks/MockReceiptEligibilityUseCase.swift +++ b/WooCommerce/WooCommerceTests/Mocks/MockReceiptEligibilityUseCase.swift @@ -7,8 +7,14 @@ final class MockReceiptEligibilityUseCase: ReceiptEligibilityUseCaseProtocol { var isEligibleForFailedPaymentEmailReceipts: Bool = false var isEligibleForReceipt: Bool = true + var mockIsEligibleForBackendReceiptsHandler: ((@escaping (Bool) -> Void) -> Void)? + func isEligibleForBackendReceipts(onCompletion: @escaping (Bool) -> Void) { - onCompletion(isEligibleForBackendReceipts) + if let handler = mockIsEligibleForBackendReceiptsHandler { + handler(onCompletion) + } else { + onCompletion(isEligibleForBackendReceipts) + } } func isEligibleForSuccessfulPaymentEmailReceipts(onCompletion: @escaping (Bool) -> Void) { diff --git a/WooCommerce/WooCommerceTests/ViewModels/CardPresentPayments/CollectOrderPaymentUseCaseTests.swift b/WooCommerce/WooCommerceTests/ViewModels/CardPresentPayments/CollectOrderPaymentUseCaseTests.swift index 34847076f63..b36f69c5e29 100644 --- a/WooCommerce/WooCommerceTests/ViewModels/CardPresentPayments/CollectOrderPaymentUseCaseTests.swift +++ b/WooCommerce/WooCommerceTests/ViewModels/CardPresentPayments/CollectOrderPaymentUseCaseTests.swift @@ -361,6 +361,55 @@ final class CollectOrderPaymentUseCaseTests: XCTestCase { // Then XCTAssertEqual(mockPaymentOrchestrator.spyChannel, .pos) } + + func test_completion_called_after_alert_presentation() throws { + receiptEligibilityUseCase.isEligibleForBackendReceipts = true + let paymentMethod = PaymentMethod.cardPresent(details: .fake()) + let intent = PaymentIntent.fake().copy(charges: [.fake().copy(paymentMethod: paymentMethod)]) + let capturedPaymentData = CardPresentCapturedPaymentData(paymentMethod: paymentMethod, receiptParameters: .fake()) + mockSuccessfulCardPresentPaymentActions(intent: intent, capturedPaymentData: capturedPaymentData) + enum Event { + case receiptEligibilityCheck + case alertPresented + case paymentCompletion + } + var eventOrder: [Event] = [] + + receiptEligibilityUseCase.mockIsEligibleForBackendReceiptsHandler = { completion in + // Force receiptEligibilityCheck completion delay + DispatchQueue.main.async { + eventOrder.append(.receiptEligibilityCheck) + completion(true) + } + } + + // Track when receipt alert is presented + alertsPresenter.onPresentCalled = { viewModel in + if viewModel is CardPresentModalSuccessWithoutEmail || + viewModel is CardPresentModalSuccessEmailSent { + eventOrder.append(.alertPresented) + } + } + + // When payment succeeds + waitFor { promise in + self.useCase.collectPayment( + using: .bluetoothScan, + channel: .storeManagement, + onFailure: { _ in }, + onCancel: {}, + onPaymentCompletion: { + eventOrder.append(.paymentCompletion) + promise(()) + }, + onCompleted: {} + ) + self.mockPreflightController.completeConnection(reader: MockCardReader.wisePad3(), gatewayID: Mocks.paymentGatewayAccount) + } + + // Then ensure payment completion happens after alert presentation to avoid CollectOrderPaymentUseCase deinit before alert presentation + XCTAssertEqual(eventOrder, [.receiptEligibilityCheck, .alertPresented, .paymentCompletion]) + } } private extension CollectOrderPaymentUseCaseTests {