@@ -416,4 +416,178 @@ struct POSCatalogSyncRemoteTests {
416416 #expect( fieldNames. contains ( " stock_quantity " ) )
417417 #expect( fieldNames. contains ( " stock_status " ) )
418418 }
419+
420+ // MARK: - Count Endpoints Tests
421+
422+ @Test func getProductCount_uses_correct_path( ) async throws {
423+ // Given
424+ let remote = POSCatalogSyncRemote ( network: network)
425+ network. responseHeaders = [ " X-WP-Total " : " 150 " ]
426+
427+ // When
428+ _ = try ? await remote. getProductCount ( siteID: sampleSiteID)
429+
430+ // Then - verify correct path was used
431+ let request = try #require( network. requestsForResponseData. last as? JetpackRequest )
432+ #expect( request. path. contains ( " products " ) )
433+ }
434+
435+ @Test func getProductCount_returns_count_from_total_header( ) async throws {
436+ // Given
437+ let remote = POSCatalogSyncRemote ( network: network)
438+ let expectedCount = 500
439+ network. responseHeaders = [ " X-WP-Total " : " \( expectedCount) " ]
440+ network. simulateResponse ( requestUrlSuffix: " products " , filename: " empty-data-array " )
441+
442+ // When
443+ let count = try await remote. getProductCount ( siteID: sampleSiteID)
444+
445+ // Then
446+ #expect( count == expectedCount)
447+ }
448+
449+ @Test func getProductCount_returns_zero_when_header_missing( ) async throws {
450+ // Given
451+ let remote = POSCatalogSyncRemote ( network: network)
452+ network. responseHeaders = nil
453+ network. simulateResponse ( requestUrlSuffix: " products " , filename: " empty-data-array " )
454+
455+ // When
456+ let count = try await remote. getProductCount ( siteID: sampleSiteID)
457+
458+ // Then
459+ #expect( count == 0 )
460+ }
461+
462+ @Test func getProductCount_returns_zero_when_header_invalid( ) async throws {
463+ // Given
464+ let remote = POSCatalogSyncRemote ( network: network)
465+ network. responseHeaders = [ " X-WP-Total " : " invalid-number " ]
466+ network. simulateResponse ( requestUrlSuffix: " products " , filename: " empty-data-array " )
467+
468+ // When
469+ let count = try await remote. getProductCount ( siteID: sampleSiteID)
470+
471+ // Then
472+ #expect( count == 0 )
473+ }
474+
475+ @Test func getProductCount_relays_networking_error( ) async throws {
476+ // Given
477+ let remote = POSCatalogSyncRemote ( network: network)
478+
479+ // When/Then
480+ await #expect( throws: NetworkError . notFound ( ) ) {
481+ try await remote. getProductCount ( siteID: sampleSiteID)
482+ }
483+ }
484+
485+ @Test func getProductVariationCount_uses_correct_path( ) async throws {
486+ // Given
487+ let remote = POSCatalogSyncRemote ( network: network)
488+ network. responseHeaders = [ " X-WP-Total " : " 75 " ]
489+ network. simulateResponse ( requestUrlSuffix: " variations " , filename: " empty-data-array " )
490+
491+ // When
492+ _ = try ? await remote. getProductVariationCount ( siteID: sampleSiteID)
493+
494+ // Then - verify correct path was used
495+ let request = try #require( network. requestsForResponseData. last as? JetpackRequest )
496+ #expect( request. path. contains ( " variations " ) )
497+ }
498+
499+ @Test func getProductVariationCount_returns_count_from_total_header( ) async throws {
500+ // Given
501+ let remote = POSCatalogSyncRemote ( network: network)
502+ let expectedCount = 250
503+ network. responseHeaders = [ " X-WP-Total " : " \( expectedCount) " ]
504+ network. simulateResponse ( requestUrlSuffix: " variations " , filename: " empty-data-array " )
505+
506+ // When
507+ let count = try await remote. getProductVariationCount ( siteID: sampleSiteID)
508+
509+ // Then
510+ #expect( count == expectedCount)
511+ }
512+
513+ @Test func getProductVariationCount_returns_zero_when_header_missing( ) async throws {
514+ // Given
515+ let remote = POSCatalogSyncRemote ( network: network)
516+ network. responseHeaders = nil
517+ network. simulateResponse ( requestUrlSuffix: " variations " , filename: " empty-data-array " )
518+
519+ // When
520+ let count = try await remote. getProductVariationCount ( siteID: sampleSiteID)
521+
522+ // Then
523+ #expect( count == 0 )
524+ }
525+
526+ @Test func getProductVariationCount_returns_zero_when_header_invalid( ) async throws {
527+ // Given
528+ let remote = POSCatalogSyncRemote ( network: network)
529+ network. responseHeaders = [ " X-WP-Total " : " not-a-number " ]
530+ network. simulateResponse ( requestUrlSuffix: " variations " , filename: " empty-data-array " )
531+
532+ // When
533+ let count = try await remote. getProductVariationCount ( siteID: sampleSiteID)
534+
535+ // Then
536+ #expect( count == 0 )
537+ }
538+
539+ @Test func getProductVariationCount_relays_networking_error( ) async throws {
540+ // Given
541+ let remote = POSCatalogSyncRemote ( network: network)
542+
543+ // When/Then
544+ await #expect( throws: NetworkError . notFound ( ) ) {
545+ try await remote. getProductVariationCount ( siteID: sampleSiteID)
546+ }
547+ }
548+
549+ @Test func getProductCount_handles_very_large_counts( ) async throws {
550+ // Given
551+ let remote = POSCatalogSyncRemote ( network: network)
552+ let largeCount = 999999
553+ network. responseHeaders = [ " X-WP-Total " : " \( largeCount) " ]
554+ network. simulateResponse ( requestUrlSuffix: " products " , filename: " empty-data-array " )
555+
556+ // When
557+ let count = try await remote. getProductCount ( siteID: sampleSiteID)
558+
559+ // Then
560+ #expect( count == largeCount)
561+ }
562+
563+ @Test func getProductVariationCount_handles_very_large_counts( ) async throws {
564+ // Given
565+ let remote = POSCatalogSyncRemote ( network: network)
566+ let largeCount = 888888
567+ network. responseHeaders = [ " X-WP-Total " : " \( largeCount) " ]
568+ network. simulateResponse ( requestUrlSuffix: " variations " , filename: " empty-data-array " )
569+
570+ // When
571+ let count = try await remote. getProductVariationCount ( siteID: sampleSiteID)
572+
573+ // Then
574+ #expect( count == largeCount)
575+ }
576+
577+ @Test func count_endpoints_use_correct_api_versions( ) async throws {
578+ // Given
579+ let remote = POSCatalogSyncRemote ( network: network)
580+ network. responseHeaders = [ " X-WP-Total " : " 10 " ]
581+
582+ // When - make both count calls
583+ _ = try ? await remote. getProductCount ( siteID: sampleSiteID)
584+ _ = try ? await remote. getProductVariationCount ( siteID: sampleSiteID)
585+
586+ // Then - verify API versions match the data endpoints
587+ // Products should use .mark3, variations should use .wcAnalytics (based on the load endpoints)
588+ // This is verified by checking that the correct paths are called
589+ let requests = network. requestsForResponseData. compactMap { $0 as? JetpackRequest }
590+ #expect( requests. contains { $0. path. contains ( " products " ) } )
591+ #expect( requests. contains { $0. path. contains ( " variations " ) } )
592+ }
419593}
0 commit comments