@@ -53,52 +53,57 @@ struct PointOfSaleOrderControllerTests {
5353 #expect( mockOrderService. syncOrderWasCalled == false )
5454 }
5555
56- @Test func syncOrder_when_already_syncing_doesnt_call_orderService( ) async throws {
56+ @Test @ MainActor func syncOrder_when_already_syncing_doesnt_call_orderService( ) async throws {
5757 // Given
5858 let sut = PointOfSaleOrderController ( orderService: mockOrderService,
5959 receiptSender: mockReceiptSender,
6060 currencySettingsProvider: MockCurrencySettingsProvider ( ) ,
6161 analytics: MockPOSAnalytics ( ) )
62- mockOrderService. simulateSyncing = true
6362
64- // Use a continuation to wait until the first sync has definitely started
63+ // Block the sync so it doesn't complete until we manually resume it
64+ mockOrderService. blockNextSync ( )
65+
66+ // Start the first sync in a detached task so it runs concurrently
67+ let firstSyncTask = Task . detached {
68+ await sut. syncOrder ( for: Cart ( purchasableItems: [ makeItem ( quantity: 1 ) ] ) , retryHandler: { } )
69+ }
70+
71+ // Wait for the order state to actually become syncing
6572 await withCheckedContinuation { ( continuation: CheckedContinuation < Void , Never > ) in
66- Task { @MainActor in
67- // Start observing state changes
68- @Sendable func observeOrderState( ) {
69- withObservationTracking {
70- _ = sut. orderState
71- } onChange: {
72- Task { @MainActor in
73- if sut. orderState. isSyncing {
74- // State is now syncing, resume the test
75- continuation. resume ( )
76- } else {
77- // Keep observing
78- observeOrderState ( )
79- }
73+ @Sendable func observeOrderState( ) {
74+ withObservationTracking {
75+ _ = sut. orderState
76+ } onChange: {
77+ Task { @MainActor in
78+ if sut. orderState. isSyncing {
79+ continuation. resume ( )
80+ } else {
81+ observeOrderState ( )
8082 }
8183 }
8284 }
83- observeOrderState ( )
84-
85- // Start the first sync in a background task
86- Task {
87- await sut. syncOrder ( for: Cart ( purchasableItems: [ makeItem ( quantity: 1 ) ] ) , retryHandler: { } )
88- }
8985 }
86+ observeOrderState ( )
9087 }
9188
89+ // Verify the state is actually syncing
90+ #expect( sut. orderState. isSyncing == true )
91+ #expect( mockOrderService. syncOrderWasCalled == true )
92+
9293 // Reset the flag after confirming the sync has started
9394 mockOrderService. syncOrderWasCalled = false
9495
95- // When - try to sync while already syncing
96+ // When - try to sync while the first sync is still in progress
9697 await sut. syncOrder ( for: Cart ( purchasableItems: [ makeItem ( quantity: 2 ) ,
9798 makeItem ( quantity: 5 ) ] ) ,
9899 retryHandler: { } )
99100
100101 // Then - the second sync should have been skipped
101102 #expect( mockOrderService. syncOrderWasCalled == false )
103+
104+ // Cleanup - allow the first sync to complete
105+ mockOrderService. resumeBlockedSync ( )
106+ _ = await firstSyncTask. result
102107 }
103108
104109 @Test func syncOrder_with_no_previous_order_calls_orderService( ) async throws {
0 commit comments