Implemented some more tests to the FetcherTests test cases.
This commit is contained in:
parent
a96c762b85
commit
62a07ff873
@ -24,7 +24,7 @@ public class Fetcher<Model: NSManagedObject>: NSObject, NSFetchedResultsControll
|
||||
fetchedResultsController.sections?.count ?? 0
|
||||
}
|
||||
|
||||
private var inProgressChanges: [Change] = []
|
||||
private var changesToNotify: [Change] = []
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
@ -87,11 +87,11 @@ public class Fetcher<Model: NSManagedObject>: NSObject, NSFetchedResultsControll
|
||||
// MARK: NSFetchedResultsControllerDelegate
|
||||
|
||||
public func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
inProgressChanges.removeAll()
|
||||
changesToNotify.removeAll()
|
||||
}
|
||||
|
||||
public func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
didChangePublisher.send(inProgressChanges)
|
||||
didChangePublisher.send(changesToNotify)
|
||||
}
|
||||
|
||||
public func controller(
|
||||
@ -101,9 +101,9 @@ public class Fetcher<Model: NSManagedObject>: NSObject, NSFetchedResultsControll
|
||||
for type: NSFetchedResultsChangeType
|
||||
) {
|
||||
if type == .insert {
|
||||
inProgressChanges.append(.section(.inserted(sectionIndex)))
|
||||
changesToNotify.append(.section(.inserted(sectionIndex)))
|
||||
} else if type == .delete {
|
||||
inProgressChanges.append(.section(.deleted(sectionIndex)))
|
||||
changesToNotify.append(.section(.deleted(sectionIndex)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,19 +118,19 @@ public class Fetcher<Model: NSManagedObject>: NSObject, NSFetchedResultsControll
|
||||
case .insert:
|
||||
guard let newIndexPath else { return }
|
||||
|
||||
inProgressChanges.append(.object(.inserted(at: newIndexPath)))
|
||||
changesToNotify.append(.object(.inserted(at: newIndexPath)))
|
||||
case .delete:
|
||||
guard let indexPath else { return }
|
||||
|
||||
inProgressChanges.append(.object(.deleted(from: indexPath)))
|
||||
changesToNotify.append(.object(.deleted(from: indexPath)))
|
||||
case .move:
|
||||
guard let indexPath, let newIndexPath else { return }
|
||||
|
||||
inProgressChanges.append(.object(.moved(from: indexPath, to: newIndexPath)))
|
||||
changesToNotify.append(.object(.moved(from: indexPath, to: newIndexPath)))
|
||||
case .update:
|
||||
guard let indexPath else { return }
|
||||
|
||||
inProgressChanges.append(.object(.updated(at: indexPath)))
|
||||
changesToNotify.append(.object(.updated(at: indexPath)))
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
// Copyright © 2023 Röck+Cöde. All rights reserved.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import Persistence
|
||||
import XCTest
|
||||
|
||||
@ -13,21 +14,16 @@ final class FetcherTests: XCTestCase {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let persistence = TestPersistenceService.shared
|
||||
|
||||
private var fetcher: Fetcher<TestEntity>!
|
||||
private lazy var persistence: TestPersistenceService = .shared
|
||||
private lazy var fetcher: Fetcher<TestEntity> = .init(
|
||||
fetchRequest: .allTestEntities(),
|
||||
managedObjectContext: persistence.viewContext
|
||||
)
|
||||
|
||||
// MARK: Setup
|
||||
|
||||
override func setUpWithError() throws {
|
||||
fetcher = .init(
|
||||
fetchRequest: .allTestEntities(),
|
||||
managedObjectContext: persistence.viewContext
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
fetcher = nil
|
||||
try persistence.clean()
|
||||
}
|
||||
|
||||
// MARK: Number of sections tests
|
||||
@ -132,7 +128,7 @@ final class FetcherTests: XCTestCase {
|
||||
try fetcher.fetch()
|
||||
|
||||
// WHEN & THEN
|
||||
let indexPath = IndexPath(
|
||||
let _ = IndexPath(
|
||||
item: 0,
|
||||
section: fetcher.numberOfSections - 1
|
||||
)
|
||||
@ -169,7 +165,7 @@ final class FetcherTests: XCTestCase {
|
||||
try fetcher.fetch()
|
||||
|
||||
// WHEN & THEN
|
||||
let indexPath = IndexPath(
|
||||
let _ = IndexPath(
|
||||
item: entities.count,
|
||||
section: fetcher.numberOfSections
|
||||
)
|
||||
@ -191,4 +187,133 @@ final class FetcherTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Did change publisher tests
|
||||
|
||||
func test_didChangePublisher_whenModelIsEmpty() throws {
|
||||
let expectation = self.expectation(description: "didChangePublisher when model is filled.")
|
||||
|
||||
var result: [Change]?
|
||||
|
||||
// GIVEN
|
||||
let cancellable = fetcher
|
||||
.didChangePublisher
|
||||
.sink(receiveValue: { value in
|
||||
result = value
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
// WHEN
|
||||
try fetcher.fetch()
|
||||
|
||||
// THEN
|
||||
let waiter = XCTWaiter.wait(for: [expectation], timeout: 1.0)
|
||||
|
||||
guard waiter == .timedOut else {
|
||||
XCTFail("Waiter expected to time out.")
|
||||
return
|
||||
}
|
||||
|
||||
cancellable.cancel()
|
||||
|
||||
XCTAssertNil(result)
|
||||
}
|
||||
|
||||
func test_didChangePublisher_whenModelIsFilled() throws {
|
||||
let expectation = self.expectation(description: "didChangePublisher when model is filled.")
|
||||
|
||||
var result: [Change]?
|
||||
|
||||
// GIVEN
|
||||
let context = persistence.makeChildContext()
|
||||
let _ = [
|
||||
TestEntity(context: context),
|
||||
TestEntity(context: context),
|
||||
TestEntity(context: context)
|
||||
]
|
||||
|
||||
let cancellable = fetcher
|
||||
.didChangePublisher
|
||||
.sink(receiveValue: { value in
|
||||
result = value
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
// WHEN
|
||||
try persistence.save(childContext: context)
|
||||
try fetcher.fetch()
|
||||
|
||||
// THEN
|
||||
let waiter = XCTWaiter.wait(for: [expectation], timeout: 1.0)
|
||||
|
||||
guard waiter == .timedOut else {
|
||||
XCTFail("Waiter expected to time out.")
|
||||
return
|
||||
}
|
||||
|
||||
cancellable.cancel()
|
||||
|
||||
XCTAssertNil(result)
|
||||
}
|
||||
|
||||
func test_didChangePublisher_whenModelIsUpdated() throws {
|
||||
let expectation = self.expectation(description: "didChangePublisher when model is updated.")
|
||||
|
||||
var result: [Change]?
|
||||
|
||||
// GIVEN
|
||||
let context = persistence.makeChildContext()
|
||||
let entities = [
|
||||
TestEntity(context: context),
|
||||
TestEntity(context: context),
|
||||
TestEntity(context: context)
|
||||
]
|
||||
|
||||
let cancellable = fetcher
|
||||
.didChangePublisher
|
||||
.sink(receiveValue: { value in
|
||||
result = value
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
// WHEN
|
||||
try fetcher.fetch()
|
||||
try persistence.save(childContext: context)
|
||||
|
||||
// THEN
|
||||
waitForExpectations(timeout: 1.0)
|
||||
|
||||
cancellable.cancel()
|
||||
|
||||
XCTAssertNotNil(result)
|
||||
XCTAssertEqual(result?.count, entities.count)
|
||||
XCTAssertEqual(result, [
|
||||
.object(.inserted(at: .init(item: 2, section: 0))),
|
||||
.object(.inserted(at: .init(item: 1, section: 0))),
|
||||
.object(.inserted(at: .init(item: 0, section: 0))),
|
||||
])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - TestPersistenceService+Functions
|
||||
|
||||
private extension TestPersistenceService {
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
func clean() throws {
|
||||
let context = makeChildContext()
|
||||
|
||||
try context.performAndWait {
|
||||
try context
|
||||
.fetch(.allTestEntities())
|
||||
.forEach(context.delete)
|
||||
}
|
||||
|
||||
try save(childContext: context)
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user