Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow toggle of cache policy used in 'perform' method #1521

Merged
merged 4 commits into from
Nov 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Apollo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@
C35D43C622DDE28D00BCBABE /* a.txt in Resources */ = {isa = PBXBuildFile; fileRef = C304EBD322DDC7B200748F72 /* a.txt */; };
C377CCA922D798BD00572E03 /* GraphQLFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C377CCA822D798BD00572E03 /* GraphQLFile.swift */; };
C377CCAB22D7992E00572E03 /* MultipartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C377CCAA22D7992E00572E03 /* MultipartFormData.swift */; };
D87AC09F2564D60B0079FAA5 /* ApolloClientOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87AC09E2564D60B0079FAA5 /* ApolloClientOperationTests.swift */; };
D90F1AFB2479E57A007A1534 /* WebSocketTransportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90F1AF92479DEE5007A1534 /* WebSocketTransportTests.swift */; };
E86D8E05214B32FD0028EFE1 /* JSONTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E86D8E03214B32DA0028EFE1 /* JSONTests.swift */; };
F16D083C21EF6F7300C458B8 /* QueryFromJSONBuildingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F16D083B21EF6F7300C458B8 /* QueryFromJSONBuildingTests.swift */; };
Expand Down Expand Up @@ -802,6 +803,7 @@
C35D43BF22DDD3C100BCBABE /* c.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = c.txt; sourceTree = "<group>"; };
C377CCA822D798BD00572E03 /* GraphQLFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLFile.swift; sourceTree = "<group>"; };
C377CCAA22D7992E00572E03 /* MultipartFormData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipartFormData.swift; sourceTree = "<group>"; };
D87AC09E2564D60B0079FAA5 /* ApolloClientOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApolloClientOperationTests.swift; sourceTree = "<group>"; };
D90F1AF92479DEE5007A1534 /* WebSocketTransportTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebSocketTransportTests.swift; sourceTree = "<group>"; };
E86D8E03214B32DA0028EFE1 /* JSONTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONTests.swift; sourceTree = "<group>"; };
F16D083B21EF6F7300C458B8 /* QueryFromJSONBuildingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryFromJSONBuildingTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1580,6 +1582,7 @@
children = (
9B0417812390320A00C9EC4E /* TestHelpers */,
9FC750551D2A532D00458D91 /* Info.plist */,
D87AC09E2564D60B0079FAA5 /* ApolloClientOperationTests.swift */,
F82E62E022BCD223000C311B /* AutomaticPersistedQueriesTests.swift */,
9F438D0B1E6C494C007BDC1A /* BatchedLoadTests.swift */,
9FC9A9C71E2EFE6E0023C4D5 /* CacheKeyForFieldTests.swift */,
Expand Down Expand Up @@ -2653,6 +2656,7 @@
C3279FC72345234D00224790 /* TestCustomRequestBodyCreator.swift in Sources */,
9B95EDC022CAA0B000702BB2 /* GETTransformerTests.swift in Sources */,
9FF90A6F1DDDEB420034C3B6 /* InputValueEncodingTests.swift in Sources */,
D87AC09F2564D60B0079FAA5 /* ApolloClientOperationTests.swift in Sources */,
9FE1C6E71E634C8D00C02284 /* PromiseTests.swift in Sources */,
9B64F6762354D219002D1BB5 /* URL+QueryDict.swift in Sources */,
9FADC8541E6B86D900C677E6 /* DataLoaderTests.swift in Sources */,
Expand Down
16 changes: 10 additions & 6 deletions Sources/Apollo/ApolloClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,18 @@ extension ApolloClient: ApolloClientProtocol {

@discardableResult
public func perform<Mutation: GraphQLMutation>(mutation: Mutation,
publishResultToStore: Bool = true,
queue: DispatchQueue = .main,
resultHandler: GraphQLResultHandler<Mutation.Data>? = nil) -> Cancellable {
return self.networkTransport.send(operation: mutation,
cachePolicy: .default,
contextIdentifier: nil,
callbackQueue: queue) { result in
resultHandler?(result)
}
return self.networkTransport.send(
operation: mutation,
cachePolicy: publishResultToStore ? .default : .fetchIgnoringCacheCompletely,
contextIdentifier: nil,
callbackQueue: queue,
completionHandler: { result in
resultHandler?(result)
}
)
}

@discardableResult
Expand Down
2 changes: 2 additions & 0 deletions Sources/Apollo/ApolloClientProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ public protocol ApolloClientProtocol: class {
///
/// - Parameters:
/// - mutation: The mutation to perform.
/// - publishResultToStore: If `true`, this will publish the result returned from the operation to the cache store. Default is `true`.
/// - queue: A dispatch queue on which the result handler will be called. Defaults to the main queue.
/// - resultHandler: An optional closure that is called when mutation results are available or when an error occurs.
/// - Returns: An object that can be used to cancel an in progress mutation.
func perform<Mutation: GraphQLMutation>(mutation: Mutation,
publishResultToStore: Bool,
queue: DispatchQueue,
resultHandler: GraphQLResultHandler<Mutation.Data>?) -> Cancellable

Expand Down
7 changes: 6 additions & 1 deletion Sources/ApolloTestSupport/XCTestCase+Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ public protocol StoreLoading {
}

extension StoreLoading where Self: XCTestCase {
public func loadFromStore<Query: GraphQLQuery>(query: Query, file: StaticString = #filePath, line: UInt = #line, resultHandler: @escaping AsyncResultObserver<GraphQLResult<Query.Data>, Error>.ResultHandler) {
public func loadFromStore<Operation: GraphQLOperation>(
query: Operation,
file: StaticString = #filePath,
line: UInt = #line,
resultHandler: @escaping AsyncResultObserver<GraphQLResult<Operation.Data>, Error>.ResultHandler
) {
let resultObserver = makeResultObserver(for: query, file: file, line: line)

let expectation = resultObserver.expectation(description: "Loaded query from store", file: file, line: line, resultHandler: resultHandler)
Expand Down
74 changes: 74 additions & 0 deletions Tests/ApolloTests/ApolloClientOperationTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Apollo
import ApolloTestSupport
import StarWarsAPI
import XCTest

final class ApolloClientOperationTests: XCTestCase, CacheDependentTesting, StoreLoading {
var cacheType: TestCacheProvider.Type { InMemoryTestCacheProvider.self }

var defaultWaitTimeout: TimeInterval { 1 }

var cache: NormalizedCache!
var store: ApolloStore!
var server: MockGraphQLServer!
var client: ApolloClient!

override func setUpWithError() throws {
try super.setUpWithError()

self.cache = try self.makeNormalizedCache()
self.store = ApolloStore(cache: cache)
self.server = MockGraphQLServer()
self.client = ApolloClient(
networkTransport: MockNetworkTransport(server: self.server, store: self.store),
store: self.store
)
}

override func tearDownWithError() throws {
self.cache = nil
self.server = nil
self.client = nil

try super.tearDownWithError()
}

func testPerformMutationRespectsPublishResultToStoreBoolean() throws {
let mutation = CreateReviewForEpisodeMutation(episode: .newhope, review: .init(stars: 3))
let resultObserver = self.makeResultObserver(for: mutation)

let serverRequestExpectation = self.server.expect(CreateReviewForEpisodeMutation.self) { _ in
[
"data": [
"createReview": [
"__typename": "Review",
"stars": 3,
"commentary": ""
]
]
]
}
let performResultFromServerExpectation = resultObserver.expectation(description: "Mutation was successful") { _ in }

self.client.perform(mutation: mutation, publishResultToStore: false, resultHandler: resultObserver.handler)

self.loadFromStore(query: mutation) {
try XCTAssertFailureResult($0) { error in
switch error as? JSONDecodingError {
// expected case, nothing to do
case .missingValue:
break

// unexpected error, rethrow
case .none:
throw error

default:
XCTFail("Unexpected json error: \(error)")
}
}
}

self.wait(for: [serverRequestExpectation, performResultFromServerExpectation], timeout: self.defaultWaitTimeout)
}
}