@@ -1331,6 +1331,7 @@ extension POSCatalogSyncCoordinatorTests {
13311331 let syncSkipped = mockAnalytics. trackedEvents. first { $0. eventName == " local_catalog_sync_skipped " }
13321332 #expect( syncSkipped != nil )
13331333 #expect( syncSkipped? . properties ? [ " reason " ] as? String == " no_full_sync " )
1334+ #expect( syncSkipped? . properties ? [ " sync_type " ] as? String == " incremental " )
13341335 }
13351336
13361337 @Test func performFullSyncIfApplicable_tracks_sync_skipped_when_not_stale( ) async throws {
@@ -1354,6 +1355,87 @@ extension POSCatalogSyncCoordinatorTests {
13541355 let syncSkipped = mockAnalytics. trackedEvents. first { $0. eventName == " local_catalog_sync_skipped " }
13551356 #expect( syncSkipped != nil )
13561357 #expect( syncSkipped? . properties ? [ " reason " ] as? String == " catalog_not_stale " )
1358+ #expect( syncSkipped? . properties ? [ " sync_type " ] as? String == " full " )
1359+ }
1360+
1361+ // MARK: - Sync Type Analytics
1362+
1363+ @Test ( " POSCatalogSyncType enum has correct raw values " )
1364+ func testPOSCatalogSyncTypeRawValues( ) {
1365+ #expect( POSCatalogSyncType . full. rawValue == " full " )
1366+ #expect( POSCatalogSyncType . incremental. rawValue == " incremental " )
1367+ }
1368+
1369+ // MARK: - POS Not Opened 30 Days Skip Reason Tests
1370+
1371+ @Test func performFullSyncIfApplicable_tracks_pos_not_opened_30_days_when_not_opened_recently( ) async throws {
1372+ // Given - Store with first sync > 30 days ago and last opened > 30 days ago
1373+ let mockAnalytics = MockAnalytics ( )
1374+ let mockSiteSettings = MockSiteSpecificAppSettingsStoreMethods ( )
1375+
1376+ // Set first sync date to 40 days ago
1377+ let firstSyncDate = Calendar . current. date ( byAdding: . day, value: - 40 , to: Date ( ) ) !
1378+ mockSiteSettings. setFirstPOSCatalogSyncDate ( siteID: sampleSiteID, date: firstSyncDate)
1379+
1380+ // Set last opened date to 35 days ago (more than 30 days)
1381+ let lastOpenedDate = Calendar . current. date ( byAdding: . day, value: - 35 , to: Date ( ) ) !
1382+ mockSiteSettings. setPOSLastOpenedDate ( siteID: sampleSiteID, date: lastOpenedDate)
1383+
1384+ // Create site in database with full sync date
1385+ try createSiteInDatabase ( siteID: sampleSiteID, lastFullSyncDate: firstSyncDate)
1386+
1387+ let sut = POSCatalogSyncCoordinator (
1388+ fullSyncService: mockSyncService,
1389+ incrementalSyncService: mockIncrementalSyncService,
1390+ grdbManager: grdbManager,
1391+ catalogEligibilityChecker: mockEligibilityChecker,
1392+ siteSettings: mockSiteSettings,
1393+ analytics: mockAnalytics,
1394+ connectivityObserver: nil
1395+ )
1396+
1397+ // When - Try to perform sync
1398+ try ? await sut. performFullSyncIfApplicable ( for: sampleSiteID, maxAge: . zero)
1399+
1400+ // Then - Should track pos_not_opened_30_days
1401+ let syncSkipped = mockAnalytics. trackedEvents. first { $0. eventName == " local_catalog_sync_skipped " }
1402+ #expect( syncSkipped != nil )
1403+ #expect( syncSkipped? . properties ? [ " reason " ] as? String == " pos_not_opened_30_days " )
1404+ #expect( syncSkipped? . properties ? [ " sync_type " ] as? String == " full " )
1405+ }
1406+
1407+ @Test func performIncrementalSyncIfApplicable_tracks_pos_not_opened_30_days_when_never_opened_and_past_grace_period( ) async throws {
1408+ // Given - Store with first sync > 30 days ago and never opened POS
1409+ let mockAnalytics = MockAnalytics ( )
1410+ let mockSiteSettings = MockSiteSpecificAppSettingsStoreMethods ( )
1411+
1412+ // Set first sync date to 40 days ago
1413+ let firstSyncDate = Calendar . current. date ( byAdding: . day, value: - 40 , to: Date ( ) ) !
1414+ mockSiteSettings. setFirstPOSCatalogSyncDate ( siteID: sampleSiteID, date: firstSyncDate)
1415+
1416+ // Don't set last opened date (nil = never opened)
1417+
1418+ // Create site in database with full sync date
1419+ try createSiteInDatabase ( siteID: sampleSiteID, lastFullSyncDate: firstSyncDate)
1420+
1421+ let sut = POSCatalogSyncCoordinator (
1422+ fullSyncService: mockSyncService,
1423+ incrementalSyncService: mockIncrementalSyncService,
1424+ grdbManager: grdbManager,
1425+ catalogEligibilityChecker: mockEligibilityChecker,
1426+ siteSettings: mockSiteSettings,
1427+ analytics: mockAnalytics,
1428+ connectivityObserver: nil
1429+ )
1430+
1431+ // When - Try to perform incremental sync
1432+ try await sut. performIncrementalSyncIfApplicable ( for: sampleSiteID, maxAge: . zero)
1433+
1434+ // Then - Should track pos_not_opened_30_days
1435+ let syncSkipped = mockAnalytics. trackedEvents. first { $0. eventName == " local_catalog_sync_skipped " }
1436+ #expect( syncSkipped != nil )
1437+ #expect( syncSkipped? . properties ? [ " reason " ] as? String == " pos_not_opened_30_days " )
1438+ #expect( syncSkipped? . properties ? [ " sync_type " ] as? String == " incremental " )
13571439 }
13581440}
13591441
0 commit comments