@@ -11,6 +11,7 @@ final class ProductSelectorViewModelTests: XCTestCase {
1111 storageManager. viewStorage
1212 }
1313 private let stores = MockStoresManager ( sessionManager: . testingInstance)
14+ private let searchDebounceTime : UInt64 = 600_000_000 // 500 milliseconds with buffer
1415
1516 override func setUp( ) {
1617 super. setUp ( )
@@ -472,26 +473,29 @@ final class ProductSelectorViewModelTests: XCTestCase {
472473 XCTAssertEqual ( selectedItems, [ simpleProduct. productID, 12 ] )
473474 }
474475
475- func test_filter_button_title_shows_correct_number_of_active_filters( ) {
476+ func test_filter_button_title_shows_correct_number_of_active_filters( ) async throws {
476477 // Given
477478 let viewModel = ProductSelectorViewModel ( siteID: sampleSiteID)
479+ let defaultTitle = NSLocalizedString ( " Filter " , comment: " " )
478480 // confidence check
479- XCTAssertEqual ( viewModel. filterButtonTitle, NSLocalizedString ( " Filter " , comment : " " ) )
481+ XCTAssertEqual ( viewModel. filterButtonTitle, defaultTitle )
480482
481483 // When
484+ viewModel. searchTerm = " "
482485 viewModel. filters = FilterProductListViewModel . Filters (
483486 stockStatus: ProductStockStatus . outOfStock,
484487 productStatus: ProductStatus . draft,
485488 productType: ProductType . simple,
486489 productCategory: nil ,
487490 numberOfActiveFilters: 3
488491 )
492+ try await Task . sleep ( nanoseconds: searchDebounceTime)
489493
490494 // Then
491495 XCTAssertEqual ( viewModel. filterButtonTitle, String . localizedStringWithFormat ( NSLocalizedString ( " Filter (%ld) " , comment: " " ) , 3 ) )
492496 }
493497
494- func test_productRows_are_updated_correctly_when_filters_are_applied( ) {
498+ func test_productRows_are_updated_correctly_when_filters_are_applied( ) async throws {
495499 // Given
496500 let simpleProduct = Product . fake ( ) . copy ( siteID: sampleSiteID, productID: 1 , productTypeKey: ProductType . simple. rawValue, purchasable: true )
497501 let variableProduct = Product . fake ( ) . copy ( siteID: sampleSiteID, productID: 10 , productTypeKey: ProductType . variable. rawValue, purchasable: true )
@@ -507,6 +511,8 @@ final class ProductSelectorViewModelTests: XCTestCase {
507511 productCategory: nil ,
508512 numberOfActiveFilters: 1
509513 )
514+ viewModel. searchTerm = " "
515+ try await Task . sleep ( nanoseconds: searchDebounceTime)
510516
511517 // Then
512518 XCTAssertEqual ( viewModel. productRows. count, 1 )
@@ -552,7 +558,7 @@ final class ProductSelectorViewModelTests: XCTestCase {
552558 XCTAssertEqual ( variableProductRow? . selectedState, . notSelected)
553559 }
554560
555- func test_synchronizeProducts_are_triggered_with_correct_filters( ) {
561+ func test_synchronizeProducts_are_triggered_with_correct_filters( ) async throws {
556562 // Given
557563 let viewModel = ProductSelectorViewModel ( siteID: sampleSiteID, stores: stores)
558564 var filteredStockStatus : ProductStockStatus ?
@@ -581,6 +587,8 @@ final class ProductSelectorViewModelTests: XCTestCase {
581587
582588 // When
583589 viewModel. filters = filters
590+ viewModel. searchTerm = " "
591+ try await Task . sleep ( nanoseconds: searchDebounceTime)
584592
585593 // Then
586594 assertEqual ( filteredStockStatus, filters. stockStatus)
@@ -589,7 +597,7 @@ final class ProductSelectorViewModelTests: XCTestCase {
589597 assertEqual ( filteredProductCategory, filters. productCategory)
590598 }
591599
592- func test_searchProducts_are_triggered_with_correct_filters( ) {
600+ func test_searchProducts_are_triggered_with_correct_filters( ) async throws {
593601 // Given
594602 let viewModel = ProductSelectorViewModel ( siteID: sampleSiteID, stores: stores)
595603 var filteredStockStatus : ProductStockStatus ?
@@ -617,15 +625,60 @@ final class ProductSelectorViewModelTests: XCTestCase {
617625 }
618626
619627 // When
620- viewModel. searchTerm = " hiii "
621628 viewModel. filters = filters
629+ viewModel. searchTerm = " hiii "
630+ try await Task . sleep ( nanoseconds: searchDebounceTime)
622631
623632 // Then
624633 assertEqual ( filteredStockStatus, filters. stockStatus)
625634 assertEqual ( filteredProductType, filters. productType)
626635 assertEqual ( filteredProductStatus, filters. productStatus)
627636 assertEqual ( filteredProductCategory, filters. productCategory)
628637 }
638+
639+ func test_search_term_and_filters_are_combined_to_get_correct_results( ) {
640+ // Given
641+ let bolognese = Product . fake ( ) . copy ( siteID: sampleSiteID, productID: 1 , name: " Bolognese spaghetti " , productTypeKey: ProductType . simple. rawValue)
642+ let carbonara = Product . fake ( ) . copy ( siteID: sampleSiteID, productID: 23 , name: " Carbonara spaghetti " , productTypeKey: ProductType . simple. rawValue)
643+ let pizza = Product . fake ( ) . copy ( siteID: sampleSiteID, productID: 11 , name: " Pizza " , productTypeKey: ProductType . variable. rawValue)
644+ insert ( pizza)
645+ insert ( bolognese, withSearchTerm: " spa " )
646+ insert ( carbonara, withSearchTerm: " spa " )
647+
648+ let viewModel = ProductSelectorViewModel ( siteID: sampleSiteID, storageManager: storageManager)
649+ XCTAssertEqual ( viewModel. productRows. count, 3 ) // Confidence check
650+
651+ // When
652+ viewModel. searchTerm = " spa "
653+ waitUntil {
654+ viewModel. productRows. count != 3
655+ }
656+
657+ // Then
658+ XCTAssertEqual ( viewModel. productRows. count, 2 ) // 2 spaghetti
659+
660+ // When
661+ let updatedFilters = FilterProductListViewModel . Filters (
662+ stockStatus: nil ,
663+ productStatus: nil ,
664+ productType: ProductType . variable,
665+ productCategory: nil ,
666+ numberOfActiveFilters: 1
667+ )
668+ viewModel. filters = updatedFilters
669+
670+ // Then
671+ XCTAssertEqual ( viewModel. productRows. count, 0 ) // no product matches the filter and search term
672+
673+ // When
674+ viewModel. searchTerm = " "
675+ waitUntil {
676+ viewModel. productRows. isNotEmpty
677+ }
678+
679+ // Then
680+ XCTAssertEqual ( viewModel. productRows. count, 1 ) // only 1 variable product "Pizza"
681+ }
629682}
630683
631684// MARK: - Utils
0 commit comments