mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-13 13:55:58 +01:00
Merge branch 'develop' into prototype/propertyWrappers
# Conflicts: # CoreStoreTests/DynamicModelTests.swift
This commit is contained in:
@@ -67,11 +67,11 @@ class BaseTestCase: XCTestCase {
|
||||
@nonobjc
|
||||
func expectLogger<T>(_ expectations: [TestLogger.Expectation], closure: () throws -> T) rethrows -> T {
|
||||
|
||||
Shared.logger = TestLogger(self.prepareLoggerExpectations(expectations))
|
||||
CoreStoreDefaults.logger = TestLogger(self.prepareLoggerExpectations(expectations))
|
||||
defer {
|
||||
|
||||
self.checkExpectationsImmediately()
|
||||
Shared.logger = TestLogger([:])
|
||||
CoreStoreDefaults.logger = TestLogger([:])
|
||||
}
|
||||
return try closure()
|
||||
}
|
||||
@@ -79,17 +79,17 @@ class BaseTestCase: XCTestCase {
|
||||
@nonobjc
|
||||
func expectLogger(_ expectations: [TestLogger.Expectation: XCTestExpectation]) {
|
||||
|
||||
Shared.logger = TestLogger(expectations)
|
||||
CoreStoreDefaults.logger = TestLogger(expectations)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
func expectError<T>(code: CoreStoreErrorCode, closure: () throws -> T) {
|
||||
|
||||
Shared.logger = TestLogger(self.prepareLoggerExpectations([.logError]))
|
||||
CoreStoreDefaults.logger = TestLogger(self.prepareLoggerExpectations([.logError]))
|
||||
defer {
|
||||
|
||||
self.checkExpectationsImmediately()
|
||||
Shared.logger = TestLogger([:])
|
||||
CoreStoreDefaults.logger = TestLogger([:])
|
||||
}
|
||||
do {
|
||||
|
||||
@@ -138,12 +138,12 @@ class BaseTestCase: XCTestCase {
|
||||
|
||||
super.setUp()
|
||||
self.deleteStores()
|
||||
Shared.logger = TestLogger([:])
|
||||
CoreStoreDefaults.logger = TestLogger([:])
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
|
||||
Shared.logger = DefaultLogger()
|
||||
CoreStoreDefaults.logger = DefaultLogger()
|
||||
self.deleteStores()
|
||||
super.tearDown()
|
||||
}
|
||||
@@ -171,20 +171,72 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
|
||||
animal.color .= .yellow
|
||||
XCTAssertEqual(animal.color.value, Color.yellow)
|
||||
|
||||
for property in Animal.metaProperties(includeSuperclasses: true) {
|
||||
|
||||
switch property.keyPath {
|
||||
|
||||
case String(keyPath: \Animal.species):
|
||||
XCTAssertTrue(property is ValueContainer<Animal>.Required<String>)
|
||||
|
||||
case String(keyPath: \Animal.master):
|
||||
XCTAssertTrue(property is RelationshipContainer<Animal>.ToOne<Person>)
|
||||
|
||||
case String(keyPath: \Animal.color):
|
||||
XCTAssertTrue(property is TransformableContainer<Animal>.Optional<Color>)
|
||||
|
||||
default:
|
||||
XCTFail("Unknown KeyPath: \"\(property.keyPath)\"")
|
||||
}
|
||||
}
|
||||
|
||||
let dog = transaction.create(Into<Dog>())
|
||||
XCTAssertEqual(dog.species.value, "Swift")
|
||||
XCTAssertEqual(dog.nickname.value, nil)
|
||||
XCTAssertEqual(dog.age, 1)
|
||||
|
||||
#if swift(>=5.1)
|
||||
for property in Dog.metaProperties(includeSuperclasses: true) {
|
||||
|
||||
let dogKeyPathBuilder = Dog.keyPathBuilder()
|
||||
XCTAssertEqual(dogKeyPathBuilder.species.keyPathString, "SELF.species")
|
||||
XCTAssertEqual(dogKeyPathBuilder.master.title.keyPathString, "SELF.master.title")
|
||||
XCTAssertEqual(dogKeyPathBuilder.master.spouse.pets.color.keyPathString, "SELF.master.spouse.pets.color")
|
||||
switch property.keyPath {
|
||||
|
||||
#endif
|
||||
case String(keyPath: \Dog.species):
|
||||
XCTAssertTrue(property is ValueContainer<Animal>.Required<String>)
|
||||
|
||||
case String(keyPath: \Dog.master):
|
||||
XCTAssertTrue(property is RelationshipContainer<Animal>.ToOne<Person>)
|
||||
|
||||
case String(keyPath: \Dog.color):
|
||||
XCTAssertTrue(property is TransformableContainer<Animal>.Optional<Color>)
|
||||
|
||||
case String(keyPath: \Dog.nickname):
|
||||
XCTAssertTrue(property is ValueContainer<Dog>.Optional<String>)
|
||||
|
||||
case String(keyPath: \Dog.age):
|
||||
XCTAssertTrue(property is ValueContainer<Dog>.Required<Int>)
|
||||
|
||||
case String(keyPath: \Dog.friends):
|
||||
XCTAssertTrue(property is RelationshipContainer<Dog>.ToManyOrdered<Dog>)
|
||||
|
||||
case String(keyPath: \Dog.friendedBy):
|
||||
XCTAssertTrue(property is RelationshipContainer<Dog>.ToManyUnordered<Dog>)
|
||||
|
||||
default:
|
||||
XCTFail("Unknown KeyPath: \"\(property.keyPath)\"")
|
||||
}
|
||||
}
|
||||
|
||||
// #if swift(>=5.1)
|
||||
//
|
||||
// let dogKeyPathBuilder = Dog.keyPathBuilder()
|
||||
// XCTAssertEqual(dogKeyPathBuilder.species.keyPathString, "SELF.species")
|
||||
// XCTAssertEqual(dogKeyPathBuilder.master.title.keyPathString, "SELF.master.title")
|
||||
// let a = dogKeyPathBuilder.master
|
||||
// let b = dogKeyPathBuilder.master.spouse
|
||||
// let c = dogKeyPathBuilder.master.spouse.pets
|
||||
// let d = dogKeyPathBuilder.master.spouse.pets.color
|
||||
// XCTAssertEqual(dogKeyPathBuilder.master.spouse.pets.color.keyPathString, "SELF.master.spouse.pets.color")
|
||||
//
|
||||
// #endif
|
||||
|
||||
let didSetObserver = dog.species.observe(options: [.new, .old]) { (object, change) in
|
||||
|
||||
@@ -247,7 +299,7 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
XCTAssertEqual(person.name.value, "John")
|
||||
XCTAssertEqual(person.displayName.value, "Mr. John") // Custom getter
|
||||
|
||||
let personSnapshot1 = person.createSnapshot()
|
||||
let personSnapshot1 = person.asSnapshot(in: transaction)!
|
||||
XCTAssertEqual(person.name.value, personSnapshot1.name)
|
||||
XCTAssertEqual(person.title.value, personSnapshot1.title)
|
||||
XCTAssertEqual(person.displayName.value, personSnapshot1.displayName)
|
||||
@@ -259,10 +311,20 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
XCTAssertEqual(personSnapshot1.title, "Mr.")
|
||||
XCTAssertEqual(personSnapshot1.displayName, "Mr. John")
|
||||
|
||||
let personSnapshot2 = person.createSnapshot()
|
||||
let personSnapshot2 = person.asSnapshot(in: transaction)!
|
||||
XCTAssertEqual(person.name.value, personSnapshot2.name)
|
||||
XCTAssertEqual(person.title.value, personSnapshot2.title)
|
||||
XCTAssertEqual(person.displayName.value, personSnapshot2.displayName)
|
||||
|
||||
var personSnapshot3 = personSnapshot2
|
||||
personSnapshot3.name = "James"
|
||||
XCTAssertEqual(personSnapshot1.name, "John")
|
||||
XCTAssertEqual(personSnapshot1.displayName, "Mr. John")
|
||||
XCTAssertEqual(personSnapshot2.name, "John")
|
||||
XCTAssertEqual(personSnapshot2.displayName, "Sir John")
|
||||
XCTAssertEqual(personSnapshot3.name, "James")
|
||||
XCTAssertEqual(personSnapshot3.displayName, "Sir John")
|
||||
|
||||
|
||||
person.pets.value.insert(dog)
|
||||
XCTAssertEqual(person.pets.count, 1)
|
||||
|
||||
304
CoreStoreTests/ListPublisherTests.swift
Normal file
304
CoreStoreTests/ListPublisherTests.swift
Normal file
@@ -0,0 +1,304 @@
|
||||
//
|
||||
// ListPublisherTests.swift
|
||||
// CoreStore iOS
|
||||
//
|
||||
// Copyright © 2018 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
#if canImport(UIKit) || canImport(AppKit)
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable
|
||||
import CoreStore
|
||||
|
||||
|
||||
// MARK: - ListPublisherTests
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
class ListPublisherTests: BaseTestDataTestCase {
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatListPublishers_CanReceiveInsertNotifications() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
let observer = NSObject()
|
||||
let listPublisher = stack.publishList(
|
||||
From<TestEntity1>(),
|
||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||
)
|
||||
XCTAssertFalse(listPublisher.snapshot.hasSections())
|
||||
XCTAssertFalse(listPublisher.snapshot.hasItems())
|
||||
XCTAssertTrue(listPublisher.snapshot.itemIDs.isEmpty)
|
||||
|
||||
let didChangeExpectation = self.expectation(description: "didChange")
|
||||
listPublisher.addObserver(observer) { listPublisher in
|
||||
|
||||
XCTAssertTrue(listPublisher.snapshot.hasSections())
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems())
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 1)
|
||||
|
||||
didChangeExpectation.fulfill()
|
||||
}
|
||||
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
let object = transaction.create(Into<TestEntity1>())
|
||||
object.testBoolean = NSNumber(value: true)
|
||||
object.testNumber = NSNumber(value: 1)
|
||||
object.testDecimal = NSDecimalNumber(string: "1")
|
||||
object.testString = "nil:TestEntity1:1"
|
||||
object.testData = ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!
|
||||
object.testDate = self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!
|
||||
|
||||
return transaction.hasChanges
|
||||
},
|
||||
success: { (hasChanges) in
|
||||
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
|
||||
withExtendedLifetime(listPublisher, {})
|
||||
withExtendedLifetime(observer, {})
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatListPublishers_CanReceiveUpdateNotifications() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack)
|
||||
|
||||
let observer = NSObject()
|
||||
let listPublisher = stack.publishList(
|
||||
From<TestEntity1>(),
|
||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||
)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasSections())
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems())
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 2)
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 3)
|
||||
|
||||
let didChangeExpectation = self.expectation(description: "didChange")
|
||||
listPublisher.addObserver(observer) { listPublisher in
|
||||
|
||||
XCTAssertTrue(listPublisher.snapshot.hasSections())
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems())
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 2)
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 3)
|
||||
|
||||
didChangeExpectation.fulfill()
|
||||
}
|
||||
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
if let object = try transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
|
||||
|
||||
object.testNumber = NSNumber(value: 11)
|
||||
object.testDecimal = NSDecimalNumber(string: "11")
|
||||
object.testString = "nil:TestEntity1:11"
|
||||
object.testData = ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!
|
||||
object.testDate = self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!
|
||||
}
|
||||
else {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
if let object = try transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
|
||||
|
||||
object.testNumber = NSNumber(value: 22)
|
||||
object.testDecimal = NSDecimalNumber(string: "22")
|
||||
object.testString = "nil:TestEntity1:22"
|
||||
object.testData = ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!
|
||||
object.testDate = self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!
|
||||
}
|
||||
else {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
return transaction.hasChanges
|
||||
},
|
||||
success: { (hasChanges) in
|
||||
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
|
||||
withExtendedLifetime(listPublisher, {})
|
||||
withExtendedLifetime(observer, {})
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatListPublishers_CanReceiveMoveNotifications() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack)
|
||||
|
||||
let observer = NSObject()
|
||||
let listPublisher = stack.publishList(
|
||||
From<TestEntity1>(),
|
||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||
)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasSections())
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems())
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 2)
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 3)
|
||||
|
||||
let didChangeExpectation = self.expectation(description: "didChange")
|
||||
listPublisher.addObserver(observer) { listPublisher in
|
||||
|
||||
XCTAssertTrue(listPublisher.snapshot.hasSections())
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems())
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 1)
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 4)
|
||||
|
||||
didChangeExpectation.fulfill()
|
||||
}
|
||||
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
if let object = try transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
|
||||
|
||||
object.testBoolean = NSNumber(value: true)
|
||||
}
|
||||
else {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
return transaction.hasChanges
|
||||
},
|
||||
success: { (hasChanges) in
|
||||
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
|
||||
withExtendedLifetime(listPublisher, {})
|
||||
withExtendedLifetime(observer, {})
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatListPublishers_CanReceiveDeleteNotifications() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack)
|
||||
|
||||
let observer = NSObject()
|
||||
let listPublisher = stack.publishList(
|
||||
From<TestEntity1>(),
|
||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||
)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasSections())
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems())
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 2)
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 3)
|
||||
|
||||
let didChangeExpectation = self.expectation(description: "didChange")
|
||||
listPublisher.addObserver(observer) { listPublisher in
|
||||
|
||||
XCTAssertTrue(listPublisher.snapshot.hasSections())
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 1)
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems())
|
||||
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
|
||||
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 3)
|
||||
|
||||
didChangeExpectation.fulfill()
|
||||
}
|
||||
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
let count = try transaction.deleteAll(
|
||||
From<TestEntity1>(),
|
||||
Where<TestEntity1>(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
|
||||
)
|
||||
XCTAssertEqual(count, 2)
|
||||
return transaction.hasChanges
|
||||
},
|
||||
success: { (hasChanges) in
|
||||
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
154
CoreStoreTests/ObjectPublisherTests.swift
Normal file
154
CoreStoreTests/ObjectPublisherTests.swift
Normal file
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// ObjectPublisherTests.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2018 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable
|
||||
import CoreStore
|
||||
|
||||
|
||||
// MARK: - ObjectPublisherTests
|
||||
|
||||
@available(macOS 10.12, *)
|
||||
class ObjectPublisherTests: BaseTestDataTestCase {
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatObjectPublishers_CanReceiveUpdateNotifications() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack)
|
||||
|
||||
guard let object = try stack.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
|
||||
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
let observer = NSObject()
|
||||
let objectPublisher = stack.publishObject(object)
|
||||
XCTAssertEqual(objectPublisher.object, object)
|
||||
XCTAssertNotNil(objectPublisher.snapshot)
|
||||
|
||||
let didChangeExpectation = self.expectation(description: "didChange")
|
||||
objectPublisher.addObserver(observer) { objectPublisher in
|
||||
|
||||
XCTAssertEqual(objectPublisher.object?.testNumber, NSNumber(value: 10))
|
||||
XCTAssertEqual(objectPublisher.object?.testString, "nil:TestEntity1:10")
|
||||
|
||||
didChangeExpectation.fulfill()
|
||||
}
|
||||
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
guard let object = transaction.edit(object) else {
|
||||
|
||||
XCTFail()
|
||||
try transaction.cancel()
|
||||
}
|
||||
object.testNumber = NSNumber(value: 10)
|
||||
object.testString = "nil:TestEntity1:10"
|
||||
|
||||
return transaction.hasChanges
|
||||
},
|
||||
success: { (hasChanges) in
|
||||
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
|
||||
withExtendedLifetime(objectPublisher, {})
|
||||
withExtendedLifetime(observer, {})
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatObjectPublishers_CanReceiveDeleteNotifications() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack)
|
||||
|
||||
guard let object = try stack.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
|
||||
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
let observer = NSObject()
|
||||
let objectPublisher = stack.publishObject(object)
|
||||
XCTAssertEqual(objectPublisher.object, object)
|
||||
XCTAssertNotNil(objectPublisher.snapshot)
|
||||
|
||||
let didChangeExpectation = self.expectation(description: "didChange")
|
||||
objectPublisher.addObserver(observer) { objectPublisher in
|
||||
|
||||
XCTAssertNil(objectPublisher.object)
|
||||
XCTAssertNil(objectPublisher.snapshot)
|
||||
|
||||
didChangeExpectation.fulfill()
|
||||
}
|
||||
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
guard let object = transaction.edit(object) else {
|
||||
|
||||
XCTFail()
|
||||
try transaction.cancel()
|
||||
}
|
||||
transaction.delete(object)
|
||||
|
||||
return transaction.hasChanges
|
||||
},
|
||||
success: { (hasChanges) in
|
||||
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
|
||||
withExtendedLifetime(objectPublisher, {})
|
||||
withExtendedLifetime(observer, {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ import CoreStore
|
||||
|
||||
// MARK: - XCTAssertAllEqual
|
||||
|
||||
private func XCTAssertAllEqual<D>(_ whereClauses: Where<D>...) {
|
||||
private func XCTAssertAllEqual<O>(_ whereClauses: Where<O>...) {
|
||||
|
||||
XCTAssertAllEqual(whereClauses)
|
||||
}
|
||||
|
||||
private func XCTAssertAllEqual<D>(_ whereClauses: [Where<D>]) {
|
||||
private func XCTAssertAllEqual<O>(_ whereClauses: [Where<O>]) {
|
||||
|
||||
for i in whereClauses.indices {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user