aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/Example/Tests
diff options
context:
space:
mode:
authorGravatar rsgowman <rgowman@google.com>2018-04-18 10:30:37 -0400
committerGravatar GitHub <noreply@github.com>2018-04-18 10:30:37 -0400
commita5b3185ed372fc16b5430c230c197e3dbd34f953 (patch)
tree8f77610cf27ee35f5cccad825b6a33e74d7be8ef /Firestore/Example/Tests
parent6a39c71be83f589550c7dfa3c6d89d8b6145887c (diff)
Add GetOptions for controlling offline get behaviour (#655)
Add option to allow the user to control where DocumentReference.getDocument() and CollectionReference.getDocuments() fetches from. By default, it fetches from the server (if possible) and falls back to the local cache. It's now possible to alternatively fetch from the local cache only, or to fetch from the server only (though in the server only case, latency compensation is still enabled).
Diffstat (limited to 'Firestore/Example/Tests')
-rw-r--r--Firestore/Example/Tests/Integration/API/FIRFirestoreSourceTests.mm648
-rw-r--r--Firestore/Example/Tests/Util/FSTIntegrationTestCase.h11
-rw-r--r--Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm43
3 files changed, 692 insertions, 10 deletions
diff --git a/Firestore/Example/Tests/Integration/API/FIRFirestoreSourceTests.mm b/Firestore/Example/Tests/Integration/API/FIRFirestoreSourceTests.mm
new file mode 100644
index 0000000..0f844c6
--- /dev/null
+++ b/Firestore/Example/Tests/Integration/API/FIRFirestoreSourceTests.mm
@@ -0,0 +1,648 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <FirebaseFirestore/FirebaseFirestore.h>
+
+#import <XCTest/XCTest.h>
+
+#import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h"
+#import "Firestore/Source/API/FIRFirestore+Internal.h"
+#import "Firestore/Source/Core/FSTFirestoreClient.h"
+
+@interface FIRFirestoreSourceTests : FSTIntegrationTestCase
+@end
+
+@implementation FIRFirestoreSourceTests
+
+- (void)testGetDocumentWhileOnlineWithDefaultSource {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // set document to a known value
+ NSDictionary<NSString *, id> *initialData = @{@"key" : @"value"};
+ [self writeDocumentRef:doc data:initialData];
+
+ // get doc and ensure that it exists, is *not* from the cache, and matches
+ // the initialData.
+ FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
+ XCTAssertTrue(result.exists);
+ XCTAssertFalse(result.metadata.fromCache);
+ XCTAssertFalse(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(result.data, initialData);
+}
+
+- (void)testGetCollectionWhileOnlineWithDefaultSource {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // set a few documents to known values
+ NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
+ @"doc1" : @{@"key1" : @"value1"},
+ @"doc2" : @{@"key2" : @"value2"},
+ @"doc3" : @{@"key3" : @"value3"}
+ };
+ [self writeAllDocuments:initialDocs toCollection:col];
+
+ // get docs and ensure they are *not* from the cache, and match the
+ // initialDocs.
+ FIRQuerySnapshot *result = [self readDocumentSetForRef:col];
+ XCTAssertFalse(result.metadata.fromCache);
+ XCTAssertFalse(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(
+ FIRQuerySnapshotGetData(result),
+ (@[ @{@"key1" : @"value1"}, @{@"key2" : @"value2"}, @{@"key3" : @"value3"} ]));
+ XCTAssertEqualObjects(FIRQuerySnapshotGetDocChangesData(result), (@[
+ @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3" : @"value3"} ]
+ ]));
+}
+
+- (void)testGetDocumentWhileOfflineWithDefaultSource {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // set document to a known value
+ NSDictionary<NSString *, id> *initialData = @{@"key1" : @"value1"};
+ [self writeDocumentRef:doc data:initialData];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // update the doc (though don't wait for a server response. We're offline; so
+ // that ain't happening!). This allows us to further distinguished cached vs
+ // server responses below.
+ NSDictionary<NSString *, id> *newData = @{@"key2" : @"value2"};
+ [doc setData:newData
+ completion:^(NSError *_Nullable error) {
+ XCTAssertTrue(false, "Because we're offline, this should never occur.");
+ }];
+
+ // get doc and ensure it exists, *is* from the cache, and matches the
+ // newData.
+ FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
+ XCTAssertTrue(result.exists);
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertTrue(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(result.data, newData);
+}
+
+- (void)testGetCollectionWhileOfflineWithDefaultSource {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // set a few documents to known values
+ NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
+ @"doc1" : @{@"key1" : @"value1"},
+ @"doc2" : @{@"key2" : @"value2"},
+ @"doc3" : @{@"key3" : @"value3"}
+ };
+ [self writeAllDocuments:initialDocs toCollection:col];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // update the docs (though don't wait for a server response. We're offline; so
+ // that ain't happening!). This allows us to further distinguished cached vs
+ // server responses below.
+ [[col documentWithPath:@"doc2"] setData:@{@"key2b" : @"value2b"} options:FIRSetOptions.merge];
+ [[col documentWithPath:@"doc3"] setData:@{@"key3b" : @"value3b"}];
+ [[col documentWithPath:@"doc4"] setData:@{@"key4" : @"value4"}];
+
+ // get docs and ensure they *are* from the cache, and matches the updated data.
+ FIRQuerySnapshot *result = [self readDocumentSetForRef:col];
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertTrue(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
+ @{@"key1" : @"value1"}, @{@"key2" : @"value2", @"key2b" : @"value2b"},
+ @{@"key3b" : @"value3b"}, @{@"key4" : @"value4"}
+ ]));
+ XCTAssertEqualObjects(
+ FIRQuerySnapshotGetDocChangesData(result), (@[
+ @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2", @"key2b" : @"value2b"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3b" : @"value3b"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc4", @{@"key4" : @"value4"} ]
+ ]));
+}
+
+- (void)testGetDocumentWhileOnlineCacheOnly {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // set document to a known value
+ NSDictionary<NSString *, id> *initialData = @{@"key" : @"value"};
+ [self writeDocumentRef:doc data:initialData];
+
+ // get doc and ensure that it exists, *is* from the cache, and matches
+ // the initialData.
+ FIRDocumentSnapshot *result = [self readDocumentForRef:doc source:FIRFirestoreSourceCache];
+ XCTAssertTrue(result.exists);
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertFalse(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(result.data, initialData);
+}
+
+- (void)testGetCollectionWhileOnlineCacheOnly {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // set a few documents to a known value
+ NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
+ @"doc1" : @{@"key1" : @"value1"},
+ @"doc2" : @{@"key2" : @"value2"},
+ @"doc3" : @{@"key3" : @"value3"},
+ };
+ [self writeAllDocuments:initialDocs toCollection:col];
+
+ // get docs and ensure they *are* from the cache, and matches the
+ // initialDocs.
+ FIRQuerySnapshot *result = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertFalse(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
+ @{@"key1" : @"value1"},
+ @{@"key2" : @"value2"},
+ @{@"key3" : @"value3"},
+ ]));
+ XCTAssertEqualObjects(FIRQuerySnapshotGetDocChangesData(result), (@[
+ @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3" : @"value3"} ]
+ ]));
+}
+
+- (void)testGetDocumentWhileOfflineCacheOnly {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // set document to a known value
+ NSDictionary<NSString *, id> *initialData = @{@"key1" : @"value1"};
+ [self writeDocumentRef:doc data:initialData];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // update the doc (though don't wait for a server response. We're offline; so
+ // that ain't happening!). This allows us to further distinguished cached vs
+ // server responses below.
+ NSDictionary<NSString *, id> *newData = @{@"key2" : @"value2"};
+ [doc setData:newData
+ completion:^(NSError *_Nullable error) {
+ XCTFail("Because we're offline, this should never occur.");
+ }];
+
+ // get doc and ensure it exists, *is* from the cache, and matches the
+ // newData.
+ FIRDocumentSnapshot *result = [self readDocumentForRef:doc source:FIRFirestoreSourceCache];
+ XCTAssertTrue(result.exists);
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertTrue(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(result.data, newData);
+}
+
+- (void)testGetCollectionWhileOfflineCacheOnly {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // set a few documents to a known value
+ NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
+ @"doc1" : @{@"key1" : @"value1"},
+ @"doc2" : @{@"key2" : @"value2"},
+ @"doc3" : @{@"key3" : @"value3"},
+ };
+ [self writeAllDocuments:initialDocs toCollection:col];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // update the docs (though don't wait for a server response. We're offline; so
+ // that ain't happening!). This allows us to further distinguished cached vs
+ // server responses below.
+ [[col documentWithPath:@"doc2"] setData:@{@"key2b" : @"value2b"} options:FIRSetOptions.merge];
+ [[col documentWithPath:@"doc3"] setData:@{@"key3b" : @"value3b"}];
+ [[col documentWithPath:@"doc4"] setData:@{@"key4" : @"value4"}];
+
+ // get docs and ensure they *are* from the cache, and matches the updated
+ // data.
+ FIRQuerySnapshot *result = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertTrue(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
+ @{@"key1" : @"value1"}, @{@"key2" : @"value2", @"key2b" : @"value2b"},
+ @{@"key3b" : @"value3b"}, @{@"key4" : @"value4"}
+ ]));
+ XCTAssertEqualObjects(
+ FIRQuerySnapshotGetDocChangesData(result), (@[
+ @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2", @"key2b" : @"value2b"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3b" : @"value3b"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc4", @{@"key4" : @"value4"} ]
+ ]));
+}
+
+- (void)testGetDocumentWhileOnlineServerOnly {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // set document to a known value
+ NSDictionary<NSString *, id> *initialData = @{@"key" : @"value"};
+ [self writeDocumentRef:doc data:initialData];
+
+ // get doc and ensure that it exists, is *not* from the cache, and matches
+ // the initialData.
+ FIRDocumentSnapshot *result = [self readDocumentForRef:doc source:FIRFirestoreSourceServer];
+ XCTAssertTrue(result.exists);
+ XCTAssertFalse(result.metadata.fromCache);
+ XCTAssertFalse(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(result.data, initialData);
+}
+
+- (void)testGetCollectionWhileOnlineServerOnly {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // set a few documents to a known value
+ NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
+ @"doc1" : @{@"key1" : @"value1"},
+ @"doc2" : @{@"key2" : @"value2"},
+ @"doc3" : @{@"key3" : @"value3"},
+ };
+ [self writeAllDocuments:initialDocs toCollection:col];
+
+ // get docs and ensure they are *not* from the cache, and matches the
+ // initialData.
+ FIRQuerySnapshot *result = [self readDocumentSetForRef:col source:FIRFirestoreSourceServer];
+ XCTAssertFalse(result.metadata.fromCache);
+ XCTAssertFalse(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
+ @{@"key1" : @"value1"},
+ @{@"key2" : @"value2"},
+ @{@"key3" : @"value3"},
+ ]));
+ XCTAssertEqualObjects(FIRQuerySnapshotGetDocChangesData(result), (@[
+ @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3" : @"value3"} ]
+ ]));
+}
+
+- (void)testGetDocumentWhileOfflineServerOnly {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // set document to a known value
+ NSDictionary<NSString *, id> *initialData = @{@"key1" : @"value1"};
+ [self writeDocumentRef:doc data:initialData];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // attempt to get doc and ensure it cannot be retreived
+ XCTestExpectation *failedGetDocCompletion = [self expectationWithDescription:@"failedGetDoc"];
+ [doc getDocumentWithSource:FIRFirestoreSourceServer
+ completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [failedGetDocCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+- (void)testGetCollectionWhileOfflineServerOnly {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // set a few documents to a known value
+ NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
+ @"doc1" : @{@"key1" : @"value1"},
+ @"doc2" : @{@"key2" : @"value2"},
+ @"doc3" : @{@"key3" : @"value3"},
+ };
+ [self writeAllDocuments:initialDocs toCollection:col];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // attempt to get docs and ensure they cannot be retreived
+ XCTestExpectation *failedGetDocsCompletion = [self expectationWithDescription:@"failedGetDocs"];
+ [col getDocumentsWithSource:FIRFirestoreSourceServer
+ completion:^(FIRQuerySnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [failedGetDocsCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+- (void)testGetDocumentWhileOfflineWithDifferentSource {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // set document to a known value
+ NSDictionary<NSString *, id> *initialData = @{@"key1" : @"value1"};
+ [self writeDocumentRef:doc data:initialData];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // update the doc (though don't wait for a server response. We're offline; so
+ // that ain't happening!). This allows us to further distinguished cached vs
+ // server responses below.
+ NSDictionary<NSString *, id> *newData = @{@"key2" : @"value2"};
+ [doc setData:newData
+ completion:^(NSError *_Nullable error) {
+ XCTAssertTrue(false, "Because we're offline, this should never occur.");
+ }];
+
+ // Create an initial listener for this query (to attempt to disrupt the gets below) and wait for
+ // the listener to deliver its initial snapshot before continuing.
+ XCTestExpectation *listenerReady = [self expectationWithDescription:@"listenerReady"];
+ [doc addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) {
+ [listenerReady fulfill];
+ }];
+ [self awaitExpectations];
+
+ // get doc (from cache) and ensure it exists, *is* from the cache, and
+ // matches the newData.
+ FIRDocumentSnapshot *result = [self readDocumentForRef:doc source:FIRFirestoreSourceCache];
+ XCTAssertTrue(result.exists);
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertTrue(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(result.data, newData);
+
+ // attempt to get doc (with default get source)
+ result = [self readDocumentForRef:doc source:FIRFirestoreSourceDefault];
+ XCTAssertTrue(result.exists);
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertTrue(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(result.data, newData);
+
+ // attempt to get doc (from the server) and ensure it cannot be retreived
+ XCTestExpectation *failedGetDocCompletion = [self expectationWithDescription:@"failedGetDoc"];
+ [doc getDocumentWithSource:FIRFirestoreSourceServer
+ completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [failedGetDocCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+- (void)testGetCollectionWhileOfflineWithDifferentSource {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // set a few documents to a known value
+ NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
+ @"doc1" : @{@"key1" : @"value1"},
+ @"doc2" : @{@"key2" : @"value2"},
+ @"doc3" : @{@"key3" : @"value3"},
+ };
+ [self writeAllDocuments:initialDocs toCollection:col];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // update the docs (though don't wait for a server response. We're offline; so
+ // that ain't happening!). This allows us to further distinguished cached vs
+ // server responses below.
+ [[col documentWithPath:@"doc2"] setData:@{@"key2b" : @"value2b"} options:FIRSetOptions.merge];
+ [[col documentWithPath:@"doc3"] setData:@{@"key3b" : @"value3b"}];
+ [[col documentWithPath:@"doc4"] setData:@{@"key4" : @"value4"}];
+
+ // Create an initial listener for this query (to attempt to disrupt the gets
+ // below) and wait for the listener to deliver its initial snapshot before
+ // continuing.
+ XCTestExpectation *listenerReady = [self expectationWithDescription:@"listenerReady"];
+ [col addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) {
+ [listenerReady fulfill];
+ }];
+ [self awaitExpectations];
+
+ // get docs (from cache) and ensure they *are* from the cache, and
+ // matches the updated data.
+ FIRQuerySnapshot *result = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertTrue(result.metadata.hasPendingWrites);
+ XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
+ @{@"key1" : @"value1"}, @{@"key2" : @"value2", @"key2b" : @"value2b"},
+ @{@"key3b" : @"value3b"}, @{@"key4" : @"value4"}
+ ]));
+ XCTAssertEqualObjects(
+ FIRQuerySnapshotGetDocChangesData(result), (@[
+ @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2", @"key2b" : @"value2b"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3b" : @"value3b"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc4", @{@"key4" : @"value4"} ]
+ ]));
+
+ // attempt to get docs (with default get source)
+ result = [self readDocumentSetForRef:col source:FIRFirestoreSourceDefault];
+ XCTAssertTrue(result.metadata.fromCache);
+ XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
+ @{@"key1" : @"value1"}, @{@"key2" : @"value2", @"key2b" : @"value2b"},
+ @{@"key3b" : @"value3b"}, @{@"key4" : @"value4"}
+ ]));
+ XCTAssertEqualObjects(
+ FIRQuerySnapshotGetDocChangesData(result), (@[
+ @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2", @"key2b" : @"value2b"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3b" : @"value3b"} ],
+ @[ @(FIRDocumentChangeTypeAdded), @"doc4", @{@"key4" : @"value4"} ]
+ ]));
+
+ // attempt to get docs (from the server) and ensure they cannot be retreived
+ XCTestExpectation *failedGetDocsCompletion = [self expectationWithDescription:@"failedGetDocs"];
+ [col getDocumentsWithSource:FIRFirestoreSourceServer
+ completion:^(FIRQuerySnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [failedGetDocsCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+- (void)testGetNonExistingDocWhileOnlineWithDefaultSource {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // get doc and ensure that it does not exist and is *not* from the cache.
+ FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc];
+ XCTAssertFalse(snapshot.exists);
+ XCTAssertFalse(snapshot.metadata.fromCache);
+ XCTAssertFalse(snapshot.metadata.hasPendingWrites);
+}
+
+- (void)testGetNonExistingCollectionWhileOnlineWithDefaultSource {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // get collection and ensure it's empty and that it's *not* from the cache.
+ FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col];
+ XCTAssertEqual(snapshot.count, 0);
+ XCTAssertEqual(snapshot.documentChanges.count, 0);
+ XCTAssertFalse(snapshot.metadata.fromCache);
+ XCTAssertFalse(snapshot.metadata.hasPendingWrites);
+}
+
+- (void)testGetNonExistingDocWhileOfflineWithDefaultSource {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // attempt to get doc. Currently, this is expected to fail. In the future, we
+ // might consider adding support for negative cache hits so that we know
+ // certain documents *don't* exist.
+ XCTestExpectation *getNonExistingDocCompletion =
+ [self expectationWithDescription:@"getNonExistingDoc"];
+ [doc getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [getNonExistingDocCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+- (void)testGetNonExistingCollectionWhileOfflineWithDefaultSource {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // get collection and ensure it's empty and that it *is* from the cache.
+ FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col];
+ XCTAssertEqual(snapshot.count, 0);
+ XCTAssertEqual(snapshot.documentChanges.count, 0);
+ XCTAssertTrue(snapshot.metadata.fromCache);
+ XCTAssertFalse(snapshot.metadata.hasPendingWrites);
+}
+
+- (void)testGetNonExistingDocWhileOnlineCacheOnly {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // attempt to get doc. Currently, this is expected to fail. In the future, we
+ // might consider adding support for negative cache hits so that we know
+ // certain documents *don't* exist.
+ XCTestExpectation *getNonExistingDocCompletion =
+ [self expectationWithDescription:@"getNonExistingDoc"];
+ [doc getDocumentWithSource:FIRFirestoreSourceCache
+ completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [getNonExistingDocCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+- (void)testGetNonExistingCollectionWhileOnlineCacheOnly {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // get collection and ensure it's empty and that it *is* from the cache.
+ FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
+ XCTAssertEqual(snapshot.count, 0);
+ XCTAssertEqual(snapshot.documentChanges.count, 0);
+ XCTAssertTrue(snapshot.metadata.fromCache);
+ XCTAssertFalse(snapshot.metadata.hasPendingWrites);
+}
+
+- (void)testGetNonExistingDocWhileOfflineCacheOnly {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // attempt to get doc. Currently, this is expected to fail. In the future, we
+ // might consider adding support for negative cache hits so that we know
+ // certain documents *don't* exist.
+ XCTestExpectation *getNonExistingDocCompletion =
+ [self expectationWithDescription:@"getNonExistingDoc"];
+ [doc getDocumentWithSource:FIRFirestoreSourceCache
+ completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [getNonExistingDocCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+- (void)testGetNonExistingCollectionWhileOfflineCacheOnly {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // get collection and ensure it's empty and that it *is* from the cache.
+ FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
+ XCTAssertEqual(snapshot.count, 0);
+ XCTAssertEqual(snapshot.documentChanges.count, 0);
+ XCTAssertTrue(snapshot.metadata.fromCache);
+ XCTAssertFalse(snapshot.metadata.hasPendingWrites);
+}
+
+- (void)testGetNonExistingDocWhileOnlineServerOnly {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // get doc and ensure that it does not exist and is *not* from the cache.
+ FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc source:FIRFirestoreSourceServer];
+ XCTAssertFalse(snapshot.exists);
+ XCTAssertFalse(snapshot.metadata.fromCache);
+ XCTAssertFalse(snapshot.metadata.hasPendingWrites);
+}
+
+- (void)testGetNonExistingCollectionWhileOnlineServerOnly {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // get collection and ensure that it's empty and that it's *not* from the cache.
+ FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col source:FIRFirestoreSourceServer];
+ XCTAssertEqual(snapshot.count, 0);
+ XCTAssertEqual(snapshot.documentChanges.count, 0);
+ XCTAssertFalse(snapshot.metadata.fromCache);
+ XCTAssertFalse(snapshot.metadata.hasPendingWrites);
+}
+
+- (void)testGetNonExistingDocWhileOfflineServerOnly {
+ FIRDocumentReference *doc = [self documentRef];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // attempt to get doc. Currently, this is expected to fail. In the future, we
+ // might consider adding support for negative cache hits so that we know
+ // certain documents *don't* exist.
+ XCTestExpectation *getNonExistingDocCompletion =
+ [self expectationWithDescription:@"getNonExistingDoc"];
+ [doc getDocumentWithSource:FIRFirestoreSourceServer
+ completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [getNonExistingDocCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+- (void)testGetNonExistingCollectionWhileOfflineServerOnly {
+ FIRCollectionReference *col = [self collectionRef];
+
+ // go offline for the rest of this test
+ [self disableNetwork];
+
+ // attempt to get collection and ensure that it cannot be retreived
+ XCTestExpectation *failedGetDocsCompletion = [self expectationWithDescription:@"failedGetDocs"];
+ [col getDocumentsWithSource:FIRFirestoreSourceServer
+ completion:^(FIRQuerySnapshot *snapshot, NSError *error) {
+ XCTAssertNotNil(error);
+ XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
+ XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
+ [failedGetDocsCompletion fulfill];
+ }];
+ [self awaitExpectations];
+}
+
+@end
diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h
index e27491b..585d99a 100644
--- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h
+++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h
@@ -20,6 +20,8 @@
#import "Firestore/Example/Tests/Util/XCTestCase+Await.h"
#import "Firestore/Source/Core/FSTTypes.h"
+#import "FIRFirestoreSource.h"
+
@class FIRCollectionReference;
@class FIRDocumentSnapshot;
@class FIRDocumentReference;
@@ -71,8 +73,13 @@ extern "C" {
- (FIRDocumentSnapshot *)readDocumentForRef:(FIRDocumentReference *)ref;
+- (FIRDocumentSnapshot *)readDocumentForRef:(FIRDocumentReference *)ref
+ source:(FIRFirestoreSource)source;
+
- (FIRQuerySnapshot *)readDocumentSetForRef:(FIRQuery *)query;
+- (FIRQuerySnapshot *)readDocumentSetForRef:(FIRQuery *)query source:(FIRFirestoreSource)source;
+
- (FIRDocumentSnapshot *)readSnapshotForRef:(FIRDocumentReference *)query
requireOnline:(BOOL)online;
@@ -108,6 +115,10 @@ NSArray<NSDictionary<NSString *, id> *> *FIRQuerySnapshotGetData(FIRQuerySnapsho
/** Converts the FIRQuerySnapshot to an NSArray containing the document IDs in order. */
NSArray<NSString *> *FIRQuerySnapshotGetIDs(FIRQuerySnapshot *docs);
+/** Converts the FIRQuerySnapshot to an NSArray containing an NSArray containing the doc change data
+ * in order of { type, doc title, doc data }. */
+NSArray<NSArray<id> *> *FIRQuerySnapshotGetDocChangesData(FIRQuerySnapshot *docs);
+
#if __cplusplus
} // extern "C"
#endif
diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
index 9bfdb3b..1817015 100644
--- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
+++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
@@ -212,28 +212,39 @@ NS_ASSUME_NONNULL_BEGIN
}
- (FIRDocumentSnapshot *)readDocumentForRef:(FIRDocumentReference *)ref {
+ return [self readDocumentForRef:ref source:FIRFirestoreSourceDefault];
+}
+
+- (FIRDocumentSnapshot *)readDocumentForRef:(FIRDocumentReference *)ref
+ source:(FIRFirestoreSource)source {
__block FIRDocumentSnapshot *result;
XCTestExpectation *expectation = [self expectationWithDescription:@"getData"];
- [ref getDocumentWithCompletion:^(FIRDocumentSnapshot *doc, NSError *_Nullable error) {
- XCTAssertNil(error);
- result = doc;
- [expectation fulfill];
- }];
+ [ref getDocumentWithSource:source
+ completion:^(FIRDocumentSnapshot *doc, NSError *_Nullable error) {
+ XCTAssertNil(error);
+ result = doc;
+ [expectation fulfill];
+ }];
[self awaitExpectations];
return result;
}
- (FIRQuerySnapshot *)readDocumentSetForRef:(FIRQuery *)query {
+ return [self readDocumentSetForRef:query source:FIRFirestoreSourceDefault];
+}
+
+- (FIRQuerySnapshot *)readDocumentSetForRef:(FIRQuery *)query source:(FIRFirestoreSource)source {
__block FIRQuerySnapshot *result;
XCTestExpectation *expectation = [self expectationWithDescription:@"getData"];
- [query getDocumentsWithCompletion:^(FIRQuerySnapshot *documentSet, NSError *error) {
- XCTAssertNil(error);
- result = documentSet;
- [expectation fulfill];
- }];
+ [query getDocumentsWithSource:source
+ completion:^(FIRQuerySnapshot *documentSet, NSError *error) {
+ XCTAssertNil(error);
+ result = documentSet;
+ [expectation fulfill];
+ }];
[self awaitExpectations];
return result;
@@ -329,6 +340,18 @@ extern "C" NSArray<NSString *> *FIRQuerySnapshotGetIDs(FIRQuerySnapshot *docs) {
return result;
}
+extern "C" NSArray<NSArray<id> *> *FIRQuerySnapshotGetDocChangesData(FIRQuerySnapshot *docs) {
+ NSMutableArray<NSMutableArray<id> *> *result = [NSMutableArray array];
+ for (FIRDocumentChange *docChange in docs.documentChanges) {
+ NSMutableArray<id> *docChangeData = [NSMutableArray array];
+ [docChangeData addObject:@(docChange.type)];
+ [docChangeData addObject:docChange.document.documentID];
+ [docChangeData addObject:docChange.document.data];
+ [result addObject:docChangeData];
+ }
+ return result;
+}
+
@end
NS_ASSUME_NONNULL_END