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
6 changes: 2 additions & 4 deletions WooCommerce/Classes/POS/TabBar/POSTabCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,14 @@ final class POSTabCoordinator {
}

func onTabSelected() {
schedulePOSSurveyNotificationIfNeeded()
setPOSHasBeenOpened()
presentPOSView(siteID: siteID)
}
}

private extension POSTabCoordinator {
func schedulePOSSurveyNotificationIfNeeded() {
func setPOSHasBeenOpened() {
Task { @MainActor in
await POSNotificationScheduler().scheduleLocalNotificationIfEligible(for: .currentMerchant)

let action = AppSettingsAction.setHasPOSBeenOpenedAtLeastOnce { _ in }
storesManager.dispatch(action)
}
Expand Down
10 changes: 10 additions & 0 deletions WooCommerce/Classes/ViewRelated/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ final class AppCoordinator {

// Configures authenticator first in case `WordPressAuthenticator` is used in other `AppDelegate` launch events.
configureAuthenticator()

schedulePOSSurveyNotificationIfNeeded()
}

func start() {
Expand Down Expand Up @@ -101,6 +103,14 @@ final class AppCoordinator {
}
}

private extension AppCoordinator {
func schedulePOSSurveyNotificationIfNeeded() {
Task { @MainActor in
await POSNotificationScheduler(stores: stores).scheduleLocalNotificationIfEligible(for: .currentMerchant)
}
}
}

private extension AppCoordinator {
// Fetch latest site properties and update the default store if anything has changed:
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ final class EditableOrderViewModel: ObservableObject {
private let currencyFormatter: CurrencyFormatter
private let featureFlagService: FeatureFlagService
private let permissionChecker: CaptureDevicePermissionChecker
private let posNotificationScheduler: POSNotificationScheduling

@Published var syncRequired: Bool = false

Expand Down Expand Up @@ -460,6 +461,7 @@ final class EditableOrderViewModel: ObservableObject {
featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService,
orderDurationRecorder: OrderDurationRecorderProtocol = OrderDurationRecorder.shared,
permissionChecker: CaptureDevicePermissionChecker = AVCaptureDevicePermissionChecker(),
posNotificationScheduler: POSNotificationScheduling = POSNotificationScheduler(),
initialItem: OrderBaseItem? = nil,
initialCustomer: (id: Int64, billing: Address?, shipping: Address?)? = nil,
quantityDebounceDuration: Double = Constants.quantityDebounceDuration) {
Expand All @@ -473,6 +475,7 @@ final class EditableOrderViewModel: ObservableObject {
self.featureFlagService = featureFlagService
self.orderDurationRecorder = orderDurationRecorder
self.permissionChecker = permissionChecker
self.posNotificationScheduler = posNotificationScheduler
self.initialItem = initialItem
self.initialCustomer = initialCustomer
self.barcodeScannerItemFinder = BarcodeScannerItemFinder(stores: stores)
Expand Down Expand Up @@ -1026,7 +1029,7 @@ final class EditableOrderViewModel: ObservableObject {
self.onFinished(order)
self.trackCreateOrderSuccess(usesGiftCard: usesGiftCard)
Task {
await POSNotificationScheduler().scheduleLocalNotificationIfEligible(for: .potentialMerchant)
await self.posNotificationScheduler.scheduleLocalNotificationIfEligible(for: .potentialMerchant)
}
} onFailure: { [weak self] error, usesGiftCard in
guard let self else { return }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3362,6 +3362,56 @@ final class EditableOrderViewModelTests: XCTestCase {
// Then
XCTAssertTrue(viewModel.canBeDismissed)
}

func test_onCreateOrderTapped_schedules_potential_merchant_notification() {
// Given
let mockScheduler = MockPOSNotificationScheduler()
let viewModel = EditableOrderViewModel(siteID: sampleSiteID,
stores: stores,
posNotificationScheduler: mockScheduler)

// When
stores.whenReceivingAction(ofType: OrderAction.self) { action in
switch action {
case let .createOrder(_, order, _, onCompletion):
onCompletion(.success(order))
default:
XCTFail("Received unsupported action: \(action)")
}
}
viewModel.onCreateOrderTapped()

// Then
waitUntil {
mockScheduler.scheduleCallCount > 0
}
XCTAssertEqual(mockScheduler.scheduleCallCount, 1)
XCTAssertEqual(mockScheduler.lastMerchantType, .potentialMerchant)
}

func test_onCreateOrderTapped_does_not_schedule_notification_on_failure() {
// Given
let mockScheduler = MockPOSNotificationScheduler()
let viewModel = EditableOrderViewModel(siteID: sampleSiteID,
stores: stores,
posNotificationScheduler: mockScheduler)
let error = NSError(domain: "Error", code: 0)

// When
stores.whenReceivingAction(ofType: OrderAction.self) { action in
switch action {
case let .createOrder(_, _, _, onCompletion):
onCompletion(.failure(error))
default:
XCTFail("Received unsupported action: \(action)")
}
}
viewModel.onCreateOrderTapped()

// Then
XCTAssertEqual(mockScheduler.scheduleCallCount, 0)
XCTAssertNil(mockScheduler.lastMerchantType)
}
}

private extension EditableOrderViewModelTests {
Expand Down Expand Up @@ -3458,3 +3508,16 @@ private extension EditableOrderViewModelTests {
email: "")
}
}

// MARK: - POS Notification Tests & MockPOSNotificationScheduler
private extension EditableOrderViewModelTests {
final class MockPOSNotificationScheduler: POSNotificationScheduling {
private(set) var scheduleCallCount = 0
private(set) var lastMerchantType: POSNotificationScheduler.MerchantType?

func scheduleLocalNotificationIfEligible(for merchantType: POSNotificationScheduler.MerchantType) async {
scheduleCallCount += 1
lastMerchantType = merchantType
}
}
}