Skip to content

Commit

Permalink
More tests in StoreSubscriptionAdvancedTests
Browse files Browse the repository at this point in the history
  • Loading branch information
jimisaacs committed Apr 8, 2024
1 parent 4e56f16 commit b7f04f6
Showing 1 changed file with 175 additions and 3 deletions.
178 changes: 175 additions & 3 deletions Tests/ApolloTests/Cache/StoreSubscriptionTests.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import Nimble
import XCTest
@testable import Apollo
//@testable import ApolloSQLite

open class StoreSubscriptionTests: XCTestCase {
static let defaultWaitTimeout: TimeInterval = 1

var cache: NormalizedCache!
var store: ApolloStore!

open override func setUpWithError() throws {
try super.setUpWithError()
store = ApolloStore()
cache = InMemoryNormalizedCache()
//cache = try! SQLiteNormalizedCache(fileURL: URL(fileURLWithPath: "/tmp/test.sqlite"))
store = ApolloStore(cache: cache)
}

open override func tearDownWithError() throws {
cache = nil
store = nil
try super.tearDownWithError()
}
Expand Down Expand Up @@ -107,7 +112,43 @@ final class StoreSubscriptionAdvancedTests: StoreSubscriptionTests {

// MARK: - Tests

func testSubscriberIsNotifiedOfStoreUpdate() throws {
func testSubscriberIsNotifiedOfStoreRead() throws {
let keys = Set(["QUERY_ROOT"])
let records: RecordSet = [
"QUERY_ROOT": [
"__typename": "Hero",
"name": "Han Solo"
]
]
let _ = try cache.merge(records: records)
XCTAssertEqual(try cache.loadRecords(forKeys: Set(["QUERY_ROOT"]))["QUERY_ROOT"], records.storage["QUERY_ROOT"]!)

let cacheSubscriberExpectation = XCTestExpectation(description: "Subscriber is notified of all expected activities")
let expectedActivitiesSet: Set<ApolloStore.Activity> = [
.will(perform: .loadRecords(forKeys: keys)),
.did(perform: .loadRecords(forKeys: keys), outcome: .records(records.storage))
]
let subscriber = AdvancedSubscriber(cacheSubscriberExpectation, expectedActivitiesSet)

store.subscribe(subscriber)
addTeardownBlock { self.store.unsubscribe(subscriber) }

store.withinReadTransaction { transaction in
try transaction.loadObject(forKey: "QUERY_ROOT").get()
} completion: { result in
switch result {
case .success(let record):
XCTAssertEqual(record, records.storage["QUERY_ROOT"])
case .failure(let error):
XCTFail(String(describing: error))
}
}

wait(for: [cacheSubscriberExpectation], timeout: Self.defaultWaitTimeout)
}

func testSubscriberIsNotifiedOfStorePublish() throws {
let keys = Set(["QUERY_ROOT.__typename", "QUERY_ROOT.name"])
let records: RecordSet = [
"QUERY_ROOT": [
"__typename": "Hero",
Expand All @@ -117,7 +158,7 @@ final class StoreSubscriptionAdvancedTests: StoreSubscriptionTests {
let cacheSubscriberExpectation = XCTestExpectation(description: "Subscriber is notified of all expected activities")
let expectedActivitiesSet: Set<ApolloStore.Activity> = [
.will(perform: .merge(records: records)),
.did(perform: .merge(records: records), outcome: .changedKeys(["QUERY_ROOT.__typename", "QUERY_ROOT.name"]))
.did(perform: .merge(records: records), outcome: .changedKeys(keys)),
]
let subscriber = AdvancedSubscriber(cacheSubscriberExpectation, expectedActivitiesSet)

Expand All @@ -129,6 +170,137 @@ final class StoreSubscriptionAdvancedTests: StoreSubscriptionTests {
wait(for: [cacheSubscriberExpectation], timeout: Self.defaultWaitTimeout)
}

func testSubscriberIsNotifiedOfStoreRemoveForKey() throws {
let key = "QUERY_ROOT"
let records: RecordSet = [
"QUERY_ROOT": [
"__typename": "Hero",
"name": "Han Solo"
]
]
let _ = try cache.merge(records: records)
XCTAssertEqual(try cache.loadRecords(forKeys: Set(["QUERY_ROOT"]))["QUERY_ROOT"], records.storage["QUERY_ROOT"]!)

let cacheSubscriberExpectation = XCTestExpectation(description: "Subscriber is notified of all expected activities")
let transactionSuccessExpectation = XCTestExpectation(description: "transaction completed successfully")
let expectedActivitiesSet: Set<ApolloStore.Activity> = [
.will(perform: .removeRecord(for: key)),
.did(perform: .removeRecord(for: key), outcome: .success),
]
let subscriber = AdvancedSubscriber(cacheSubscriberExpectation, expectedActivitiesSet)

store.subscribe(subscriber)
addTeardownBlock { self.store.unsubscribe(subscriber) }

store.withinReadWriteTransaction { transaction in
try transaction.removeObject(for: key)
} completion: { result in
switch result {
case .success:
transactionSuccessExpectation.fulfill()
case .failure(let error):
XCTFail(String(describing: error))
}
}

wait(for: [cacheSubscriberExpectation, transactionSuccessExpectation], timeout: Self.defaultWaitTimeout)

XCTAssertNil(try cache.loadRecords(forKeys: Set(["QUERY_ROOT"]))["QUERY_ROOT"])
}

func testSubscriberIsNotifiedOfStoreRemoveMatchingPattern() throws {
let pattern = "_ROOT"
let records: RecordSet = [
"QUERY_ROOT": [
"__typename": "Hero",
"name": "Han Solo"
],
"MUTATION_ROOT": [
"__typename": "Hero",
"name": "Han Solo"
]
]
let _ = try cache.merge(records: records)
XCTAssertEqual(try cache.loadRecords(forKeys: Set(["QUERY_ROOT"]))["QUERY_ROOT"], records.storage["QUERY_ROOT"]!)
XCTAssertEqual(try cache.loadRecords(forKeys: Set(["MUTATION_ROOT"]))["MUTATION_ROOT"], records.storage["MUTATION_ROOT"]!)

let cacheSubscriberExpectation = XCTestExpectation(description: "Subscriber is notified of all expected activities")
let transactionSuccessExpectation = XCTestExpectation(description: "transaction completed successfully")
let expectedActivitiesSet: Set<ApolloStore.Activity> = [
.will(perform: .removeRecords(matching: "NADA")),
.did(perform: .removeRecords(matching: "NADA"), outcome: .success),
.will(perform: .removeRecords(matching: pattern)),
.did(perform: .removeRecords(matching: pattern), outcome: .success),
]
let subscriber = AdvancedSubscriber(cacheSubscriberExpectation, expectedActivitiesSet)

store.subscribe(subscriber)
addTeardownBlock { self.store.unsubscribe(subscriber) }

store.withinReadWriteTransaction { transaction in
try transaction.removeObjects(matching: "NADA")
}
XCTAssertEqual(try cache.loadRecords(forKeys: Set(["QUERY_ROOT"]))["QUERY_ROOT"], records.storage["QUERY_ROOT"]!)
XCTAssertEqual(try cache.loadRecords(forKeys: Set(["MUTATION_ROOT"]))["MUTATION_ROOT"], records.storage["MUTATION_ROOT"]!)

store.withinReadWriteTransaction { transaction in
try transaction.removeObjects(matching: pattern)
} completion: { result in
switch result {
case .success:
transactionSuccessExpectation.fulfill()
case .failure(let error):
XCTFail(String(describing: error))
}
}

wait(for: [cacheSubscriberExpectation, transactionSuccessExpectation], timeout: Self.defaultWaitTimeout, enforceOrder: true)

XCTAssertNil(try cache.loadRecords(forKeys: Set(["QUERY_ROOT"]))["QUERY_ROOT"])
XCTAssertNil(try cache.loadRecords(forKeys: Set(["MUTATION_ROOT"]))["MUTATION_ROOT"])
}

func testSubscriberIsNotifiedOfStoreClear() throws {
let records: RecordSet = [
"QUERY_ROOT": [
"__typename": "Hero",
"name": "Han Solo"
],
"MUTATION_ROOT": [
"__typename": "Hero",
"name": "Han Solo"
]
]
let _ = try cache.merge(records: records)
XCTAssertEqual(try cache.loadRecords(forKeys: Set(["QUERY_ROOT"]))["QUERY_ROOT"], records.storage["QUERY_ROOT"]!)
XCTAssertEqual(try cache.loadRecords(forKeys: Set(["MUTATION_ROOT"]))["MUTATION_ROOT"], records.storage["MUTATION_ROOT"]!)

let cacheSubscriberExpectation = XCTestExpectation(description: "Subscriber is notified of all expected activities")
let cacheClearExpectation = XCTestExpectation(description: "clear cache completed")
let expectedActivitiesSet: Set<ApolloStore.Activity> = [
.will(perform: .clear),
.did(perform: .clear, outcome: .success),
]
let subscriber = AdvancedSubscriber(cacheSubscriberExpectation, expectedActivitiesSet)

store.subscribe(subscriber)
addTeardownBlock { self.store.unsubscribe(subscriber) }

store.clearCache { result in
switch result {
case .success:
cacheClearExpectation.fulfill()
case .failure(let error):
XCTFail(String(describing: error))
}
}

wait(for: [cacheSubscriberExpectation, cacheClearExpectation], timeout: Self.defaultWaitTimeout, enforceOrder: true)

XCTAssertNil(try cache.loadRecords(forKeys: Set(["QUERY_ROOT"]))["QUERY_ROOT"])
XCTAssertNil(try cache.loadRecords(forKeys: Set(["MUTATION_ROOT"]))["MUTATION_ROOT"])
}

/// Fufills the provided expectation when all expected keys have been observed.
internal class AdvancedSubscriber: ApolloStoreSubscriber {
private let expectation: XCTestExpectation
Expand Down

0 comments on commit b7f04f6

Please sign in to comment.