11import Foundation
22import Testing
33@testable import Yosemite
4- import Storage
4+ @ testable import Storage
55
66struct POSCatalogSyncCoordinatorTests {
77 private let mockSyncService : MockPOSCatalogFullSyncService
88 private let mockSettingsStore : MockSiteSpecificAppSettingsStoreMethods
9+ private let grdbManager : GRDBManager
910 private let sut : POSCatalogSyncCoordinator
1011 private let sampleSiteID : Int64 = 134
1112
12- init ( ) {
13+ init ( ) throws {
1314 self . mockSyncService = MockPOSCatalogFullSyncService ( )
1415 self . mockSettingsStore = MockSiteSpecificAppSettingsStoreMethods ( )
16+ self . grdbManager = try GRDBManager ( )
1517 self . sut = POSCatalogSyncCoordinator (
1618 fullSyncService: mockSyncService,
17- settingsStore: mockSettingsStore
19+ settingsStore: mockSettingsStore,
20+ grdbManager: grdbManager
1821 )
1922 }
2023
@@ -72,9 +75,23 @@ struct POSCatalogSyncCoordinatorTests {
7275
7376 // MARK: - Should Sync Decision Tests
7477
75- @Test func shouldPerformFullSync_returns_true_when_no_previous_sync ( ) {
76- // Given - no previous sync date stored
78+ @Test func shouldPerformFullSync_returns_true_when_site_is_not_in_database_with_no_sync_history ( ) {
79+ // Given - site doesn't exist in database AND has no sync history
7780 mockSettingsStore. storedDates = [ : ]
81+ // Note: NOT creating site in database
82+
83+ // When
84+ let shouldSync = sut. shouldPerformFullSync ( for: sampleSiteID, maxAge: 60 * 60 )
85+
86+ // Then - should sync because site doesn't exist in database
87+ #expect( shouldSync == true )
88+ }
89+
90+ @Test func shouldPerformFullSync_returns_true_when_site_is_in_database_with_no_previous_sync( ) throws {
91+ // Given - no previous sync date stored, but site exists in database
92+ // This is much less likely to happen, but could help at a migration point
93+ mockSettingsStore. storedDates = [ : ]
94+ try createSiteInDatabase ( siteID: sampleSiteID)
7895
7996 // When
8097 let shouldSync = sut. shouldPerformFullSync ( for: sampleSiteID, maxAge: 3600 )
@@ -84,10 +101,11 @@ struct POSCatalogSyncCoordinatorTests {
84101 #expect( mockSettingsStore. getPOSLastFullSyncDateCallCount == 1 )
85102 }
86103
87- @Test func shouldPerformFullSync_returns_true_when_sync_is_stale( ) {
88- // Given - previous sync was 2 hours ago
104+ @Test func shouldPerformFullSync_returns_true_when_sync_is_stale( ) throws {
105+ // Given - previous sync was 2 hours ago, and site exists in database
89106 let twoHoursAgo = Date ( ) . addingTimeInterval ( - 2 * 60 * 60 )
90107 mockSettingsStore. storedDates [ sampleSiteID] = twoHoursAgo
108+ try createSiteInDatabase ( siteID: sampleSiteID)
91109
92110 // When - max age is 1 hour
93111 let shouldSync = sut. shouldPerformFullSync ( for: sampleSiteID, maxAge: 60 * 60 )
@@ -96,10 +114,11 @@ struct POSCatalogSyncCoordinatorTests {
96114 #expect( shouldSync == true )
97115 }
98116
99- @Test func shouldPerformFullSync_returns_false_when_sync_is_fresh( ) {
100- // Given - previous sync was 30 minutes ago
117+ @Test func shouldPerformFullSync_returns_false_when_sync_is_fresh( ) throws {
118+ // Given - previous sync was 30 minutes ago, and site exists in database
101119 let thirtyMinutesAgo = Date ( ) . addingTimeInterval ( - 30 * 60 )
102120 mockSettingsStore. storedDates [ sampleSiteID] = thirtyMinutesAgo
121+ try createSiteInDatabase ( siteID: sampleSiteID)
103122
104123 // When - max age is 1 hour
105124 let shouldSync = sut. shouldPerformFullSync ( for: sampleSiteID, maxAge: 60 * 60 )
@@ -108,7 +127,7 @@ struct POSCatalogSyncCoordinatorTests {
108127 #expect( shouldSync == false )
109128 }
110129
111- @Test func shouldPerformFullSync_handles_different_sites_independently( ) {
130+ @Test func shouldPerformFullSync_handles_different_sites_independently( ) throws {
112131 // Given
113132 let siteA : Int64 = 123
114133 let siteB : Int64 = 456
@@ -117,6 +136,10 @@ struct POSCatalogSyncCoordinatorTests {
117136 mockSettingsStore. storedDates [ siteA] = oneHourAgo // Has previous sync
118137 // siteB has no previous sync
119138
139+ // Create both sites in database to test timing logic
140+ try createSiteInDatabase ( siteID: siteA)
141+ try createSiteInDatabase ( siteID: siteB)
142+
120143 // When
121144 let shouldSyncA = sut. shouldPerformFullSync ( for: siteA, maxAge: 2 * 60 * 60 ) // 2 hours
122145 let shouldSyncB = sut. shouldPerformFullSync ( for: siteB, maxAge: 2 * 60 * 60 ) // 2 hours
@@ -126,17 +149,55 @@ struct POSCatalogSyncCoordinatorTests {
126149 #expect( shouldSyncB == true ) // No previous sync
127150 }
128151
129- @Test func shouldPerformFullSync_with_zero_maxAge_always_returns_true( ) {
130- // Given - previous sync was just now
152+ @Test func shouldPerformFullSync_with_zero_maxAge_always_returns_true( ) throws {
153+ // Given - previous sync was just now, and site exists in database
131154 let justNow = Date ( )
132155 mockSettingsStore. storedDates [ sampleSiteID] = justNow
156+ try createSiteInDatabase ( siteID: sampleSiteID)
133157
134158 // When - max age is 0 (always sync)
135159 let shouldSync = sut. shouldPerformFullSync ( for: sampleSiteID, maxAge: 0 )
136160
137161 // Then
138162 #expect( shouldSync == true )
139163 }
164+
165+ // MARK: - Database Check Tests
166+
167+ @Test func shouldPerformFullSync_returns_true_when_site_not_in_database( ) {
168+ // Given - site does not exist in database, but has recent sync date
169+ let recentSyncDate = Date ( ) . addingTimeInterval ( - 30 * 60 ) // 30 minutes ago
170+ mockSettingsStore. storedDates [ sampleSiteID] = recentSyncDate
171+ // Note: not creating site in database so it won't exist
172+
173+ // When - max age is 1 hour (normally wouldn't sync)
174+ let shouldSync = sut. shouldPerformFullSync ( for: sampleSiteID, maxAge: 60 * 60 )
175+
176+ // Then - should sync because site doesn't exist in database
177+ #expect( shouldSync == true )
178+ }
179+
180+ @Test func shouldPerformFullSync_respects_time_when_site_exists_in_database( ) throws {
181+ // Given - site exists in database with recent sync date
182+ let recentSyncDate = Date ( ) . addingTimeInterval ( - 30 * 60 ) // 30 minutes ago
183+ mockSettingsStore. storedDates [ sampleSiteID] = recentSyncDate
184+ try createSiteInDatabase ( siteID: sampleSiteID)
185+
186+ // When - max age is 1 hour
187+ let shouldSync = sut. shouldPerformFullSync ( for: sampleSiteID, maxAge: 60 * 60 )
188+
189+ // Then - should not sync because site exists and time hasn't passed
190+ #expect( shouldSync == false )
191+ }
192+
193+ // MARK: - Helper Methods
194+
195+ private func createSiteInDatabase( siteID: Int64 ) throws {
196+ try grdbManager. databaseConnection. write { db in
197+ let site = PersistedSite ( id: siteID)
198+ try site. insert ( db)
199+ }
200+ }
140201}
141202
142203// MARK: - Mock Services
0 commit comments