@@ -56,7 +56,6 @@ final class ResultsControllerTests: XCTestCase {
5656 ///
5757 func testResultsControllerPicksUpEntitiesAvailablePriorToInstantiation( ) {
5858 storageManager. insertSampleAccount ( )
59- viewStorage. saveIfNeeded ( )
6059
6160 let resultsController = ResultsController < StorageAccount > ( viewStorage: viewStorage, sortedBy: [ sampleSortDescriptor] )
6261 try ? resultsController. performFetch ( )
@@ -70,12 +69,11 @@ final class ResultsControllerTests: XCTestCase {
7069 /// Verifies that ResultsController does pick up entities inserted after being instantiated.
7170 ///
7271 func testResultsControllerPicksUpEntitiesInsertedAfterInstantiation( ) {
72+ storageManager. insertSampleAccount ( )
73+
7374 let resultsController = ResultsController < StorageAccount > ( viewStorage: viewStorage, sortedBy: [ sampleSortDescriptor] )
7475 try ? resultsController. performFetch ( )
7576
76- storageManager. insertSampleAccount ( )
77- viewStorage. saveIfNeeded ( )
78-
7977 XCTAssertEqual ( resultsController. sections. count, 1 )
8078 XCTAssertEqual ( resultsController. sections. first? . objects. count, 1 )
8179 XCTAssertEqual ( resultsController. sections. first? . numberOfObjects, 1 )
@@ -85,18 +83,16 @@ final class ResultsControllerTests: XCTestCase {
8583 /// Verifies that `sectionNameKeyPath` effectively causes the ResultsController to produce multiple sections, based on the grouping parameter.
8684 ///
8785 func testResultsControllerGroupSectionsBySectionNameKeypath( ) {
88- let sectionNameKeyPath = " userID "
89- let resultsController = ResultsController < StorageAccount > ( viewStorage: viewStorage,
90- sectionNameKeyPath: sectionNameKeyPath,
91- sortedBy: [ sampleSortDescriptor] )
92- try ? resultsController. performFetch ( )
93-
9486 let numberOfAccounts = 100
9587 for _ in 0 ..< numberOfAccounts {
9688 storageManager. insertSampleAccount ( )
9789 }
9890
99- viewStorage. saveIfNeeded ( )
91+ let sectionNameKeyPath = " userID "
92+ let resultsController = ResultsController < StorageAccount > ( viewStorage: viewStorage,
93+ sectionNameKeyPath: sectionNameKeyPath,
94+ sortedBy: [ sampleSortDescriptor] )
95+ try ? resultsController. performFetch ( )
10096
10197 XCTAssertEqual ( resultsController. sections. count, numberOfAccounts)
10298
@@ -109,15 +105,13 @@ final class ResultsControllerTests: XCTestCase {
109105 /// Verifies that `object(at indexPath:)` effectively returns the expected (ReadOnly) Entity.
110106 ///
111107 func testObjectAtIndexPathReturnsExpectedEntity( ) {
108+ let mutableAccount = storageManager. insertSampleAccount ( )
112109 let sectionNameKeyPath = " userID "
113110 let resultsController = ResultsController < StorageAccount > ( viewStorage: viewStorage,
114111 sectionNameKeyPath: sectionNameKeyPath,
115112 sortedBy: [ sampleSortDescriptor] )
116113 try ? resultsController. performFetch ( )
117114
118- let mutableAccount = storageManager. insertSampleAccount ( )
119- viewStorage. saveIfNeeded ( )
120-
121115 let indexPath = IndexPath ( row: 0 , section: 0 )
122116 let readOnlyAccount = resultsController. object ( at: indexPath)
123117
@@ -144,7 +138,6 @@ final class ResultsControllerTests: XCTestCase {
144138 }
145139
146140 storageManager. insertSampleAccount ( )
147- viewStorage. saveIfNeeded ( )
148141
149142 waitForExpectations ( timeout: Constants . expectationTimeout, handler: nil )
150143 }
@@ -167,7 +160,6 @@ final class ResultsControllerTests: XCTestCase {
167160 }
168161
169162 storageManager. insertSampleAccount ( )
170- viewStorage. saveIfNeeded ( )
171163
172164 waitForExpectations ( timeout: Constants . expectationTimeout, handler: nil )
173165 }
@@ -189,7 +181,6 @@ final class ResultsControllerTests: XCTestCase {
189181 }
190182
191183 storageManager. insertSampleAccount ( )
192- viewStorage. saveIfNeeded ( )
193184
194185 waitForExpectations ( timeout: Constants . expectationTimeout, handler: nil )
195186 }
@@ -211,7 +202,6 @@ final class ResultsControllerTests: XCTestCase {
211202 }
212203
213204 storageManager. insertSampleAccount ( )
214- viewStorage. saveIfNeeded ( )
215205
216206 waitForExpectations ( timeout: Constants . expectationTimeout, handler: nil )
217207 }
@@ -228,7 +218,6 @@ final class ResultsControllerTests: XCTestCase {
228218 let second = storageManager. insertSampleAccount ( ) . toReadOnly ( )
229219 let expected = [ first. userID: first, second. userID: second]
230220
231- viewStorage. saveIfNeeded ( )
232221
233222 for retrieved in resultsController. fetchedObjects {
234223 XCTAssertEqual ( retrieved. username, expected [ retrieved. userID] ? . username)
@@ -239,14 +228,13 @@ final class ResultsControllerTests: XCTestCase {
239228 /// Verifies that `fetchedObjects` effectively returns all of the (readOnly) objects that are expected to be available.
240229 ///
241230 func testResettingStorageIsMappedIntoOnResetClosure( ) {
231+ storageManager. insertSampleAccount ( )
232+ storageManager. insertSampleAccount ( )
233+
242234 let sortDescriptor = NSSortDescriptor ( key: #selector( getter: StorageAccount . userID) . description, ascending: true )
243235 let resultsController = ResultsController < StorageAccount > ( viewStorage: viewStorage, sortedBy: [ sortDescriptor] )
244236 try ? resultsController. performFetch ( )
245237
246- storageManager. insertSampleAccount ( )
247- storageManager. insertSampleAccount ( )
248-
249- viewStorage. saveIfNeeded ( )
250238 XCTAssertEqual ( resultsController. fetchedObjects. count, 2 )
251239
252240 let expectation = self . expectation ( description: " OnDidReset " )
@@ -296,8 +284,6 @@ final class ResultsControllerTests: XCTestCase {
296284 }
297285 }
298286
299- viewStorage. saveIfNeeded ( )
300-
301287 for (sectionNumber, sectionObject) in resultsController. sections. enumerated ( ) {
302288 for (row, object) in sectionObject. objects. enumerated ( ) {
303289 let indexPath = IndexPath ( row: row, section: sectionNumber)
@@ -464,6 +450,124 @@ final class ResultsControllerTests: XCTestCase {
464450 // Then
465451 XCTAssertNil ( resultsController. indexPath ( forObjectMatching: { $0. displayName == " B " } ) )
466452 }
453+
454+ // MARK: - List Item Tests
455+
456+ func test_listItemObjects_returns_empty_array_when_no_products( ) throws {
457+ // Given
458+ let sortDescriptor = NSSortDescriptor ( key: #keyPath( StorageProduct . productID) , ascending: true )
459+ let resultsController = ResultsController < StorageProduct > ( viewStorage: viewStorage, sortedBy: [ sortDescriptor] )
460+ try resultsController. performFetch ( )
461+
462+ // When
463+ let listItems = resultsController. listItemObjects
464+
465+ // Then
466+ XCTAssertTrue ( listItems. isEmpty)
467+ }
468+
469+ func test_listItemObjects_returns_all_list_items_from_fetched_products( ) throws {
470+ // Given
471+ let product1 = createSampleProductListItem ( productID: 1 , name: " Product 1 " , price: " 10.00 " )
472+ let product2 = createSampleProductListItem ( productID: 2 , name: " Product 2 " , price: " 20.00 " )
473+ let product3 = createSampleProductListItem ( productID: 3 , name: " Product 3 " , price: " 30.00 " )
474+
475+ storageManager. insertSampleProductListItem ( item: product1)
476+ storageManager. insertSampleProductListItem ( item: product2)
477+ storageManager. insertSampleProductListItem ( item: product3)
478+
479+ let sortDescriptor = NSSortDescriptor ( key: #keyPath( StorageProduct . productID) , ascending: true )
480+ let resultsController = ResultsController < StorageProduct > ( viewStorage: viewStorage, sortedBy: [ sortDescriptor] )
481+ try resultsController. performFetch ( )
482+
483+ // When
484+ let listItems = resultsController. listItemObjects
485+
486+ // Then
487+ XCTAssertEqual ( listItems. count, 3 )
488+ XCTAssertEqual ( listItems [ 0 ] . productID, 1 )
489+ XCTAssertEqual ( listItems [ 0 ] . name, " Product 1 " )
490+ XCTAssertEqual ( listItems [ 0 ] . price, " 10.00 " )
491+ XCTAssertEqual ( listItems [ 1 ] . productID, 2 )
492+ XCTAssertEqual ( listItems [ 1 ] . name, " Product 2 " )
493+ XCTAssertEqual ( listItems [ 1 ] . price, " 20.00 " )
494+ XCTAssertEqual ( listItems [ 2 ] . productID, 3 )
495+ XCTAssertEqual ( listItems [ 2 ] . name, " Product 3 " )
496+ XCTAssertEqual ( listItems [ 2 ] . price, " 30.00 " )
497+ }
498+
499+ func test_listItem_at_indexPath_returns_expected_list_item( ) throws {
500+ // Given
501+ let product1 = createSampleProductListItem ( productID: 1 , name: " Product 1 " , price: " 10.00 " )
502+ let product2 = createSampleProductListItem ( productID: 2 , name: " Product 2 " , price: " 20.00 " )
503+
504+ storageManager. insertSampleProductListItem ( item: product1)
505+ storageManager. insertSampleProductListItem ( item: product2)
506+
507+ let sortDescriptor = NSSortDescriptor ( key: #keyPath( StorageProduct . productID) , ascending: true )
508+ let resultsController = ResultsController < StorageProduct > ( viewStorage: viewStorage, sortedBy: [ sortDescriptor] )
509+ try resultsController. performFetch ( )
510+
511+ // When
512+ let listItem = resultsController. listItem ( at: IndexPath ( row: 1 , section: 0 ) )
513+
514+ // Then
515+ XCTAssertEqual ( listItem. productID, 2 )
516+ XCTAssertEqual ( listItem. name, " Product 2 " )
517+ XCTAssertEqual ( listItem. price, " 20.00 " )
518+ }
519+
520+ func test_listItemObjects_in_section_returns_list_items_for_specified_section( ) throws {
521+ // Given
522+ let categoryA = createSampleProductListItem ( productID: 1 , name: " Product A1 " , price: " 10.00 " )
523+ let categoryA2 = createSampleProductListItem ( productID: 2 , name: " Product A2 " , price: " 15.00 " )
524+ let categoryB = createSampleProductListItem ( productID: 3 , name: " Product B1 " , price: " 20.00 " )
525+
526+ // Insert products and manually set product type for section grouping
527+ let storageProductA = storageManager. insertSampleProductListItem ( item: categoryA)
528+ storageProductA. productTypeKey = " simple "
529+ let storageProductA2 = storageManager. insertSampleProductListItem ( item: categoryA2)
530+ storageProductA2. productTypeKey = " simple "
531+ let storageProductB = storageManager. insertSampleProductListItem ( item: categoryB)
532+ storageProductB. productTypeKey = " variable "
533+
534+ let sortDescriptor = NSSortDescriptor ( key: #keyPath( StorageProduct . productID) , ascending: true )
535+ let resultsController = ResultsController < StorageProduct > ( viewStorage: viewStorage,
536+ sectionNameKeyPath: #keyPath( StorageProduct . productTypeKey) ,
537+ sortedBy: [ sortDescriptor] )
538+ try resultsController. performFetch ( )
539+
540+ // When
541+ let section0Items = resultsController. listItemObjects ( in: 0 )
542+ let section1Items = resultsController. listItemObjects ( in: 1 )
543+
544+ // Then
545+ XCTAssertEqual ( section0Items. count, 2 )
546+ XCTAssertEqual ( section0Items [ 0 ] . productID, 1 )
547+ XCTAssertEqual ( section0Items [ 0 ] . name, " Product A1 " )
548+ XCTAssertEqual ( section0Items [ 1 ] . productID, 2 )
549+ XCTAssertEqual ( section0Items [ 1 ] . name, " Product A2 " )
550+
551+ XCTAssertEqual ( section1Items. count, 1 )
552+ XCTAssertEqual ( section1Items [ 0 ] . productID, 3 )
553+ XCTAssertEqual ( section1Items [ 0 ] . name, " Product B1 " )
554+ }
555+
556+ func test_listItemObjects_in_section_returns_empty_array_for_nonexistent_section( ) throws {
557+ // Given
558+ let product = createSampleProductListItem ( productID: 1 , name: " Product 1 " , price: " 10.00 " )
559+ storageManager. insertSampleProductListItem ( item: product)
560+
561+ let sortDescriptor = NSSortDescriptor ( key: #keyPath( StorageProduct . productID) , ascending: true )
562+ let resultsController = ResultsController < StorageProduct > ( viewStorage: viewStorage, sortedBy: [ sortDescriptor] )
563+ try resultsController. performFetch ( )
564+
565+ // When
566+ let items = resultsController. listItemObjects ( in: 5 )
567+
568+ // Then
569+ XCTAssertTrue ( items. isEmpty)
570+ }
467571}
468572
469573// MARK: - Utils
@@ -476,4 +580,23 @@ private extension ResultsControllerTests {
476580 account. username = username
477581 return account
478582 }
583+
584+ func createSampleProductListItem( siteID: Int64 = 123 , productID: Int64 , name: String , price: String ) -> ProductListItem {
585+ return ProductListItem . fake ( ) . copy (
586+ siteID: siteID,
587+ productID: productID,
588+ name: name,
589+ productTypeKey: " simple " ,
590+ statusKey: " publish " ,
591+ sku: nil ,
592+ price: price,
593+ virtual: false ,
594+ manageStock: false ,
595+ stockQuantity: nil ,
596+ stockStatusKey: " instock " ,
597+ reviewsAllowed: true ,
598+ averageRating: " 0 " ,
599+ ratingCount: 0
600+ )
601+ }
479602}
0 commit comments