|
|
@@ -18,28 +18,6 @@ import FirebaseFirestore
|
|
|
import Foundation
|
|
|
|
|
|
class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
- /**
|
|
|
- * Checks that running the query while online (against the backend/emulator) results in the same
|
|
|
- * documents as running the query while offline. If expectedDocs is provided, it also checks
|
|
|
- * that both online and offline query result is equal to the expected documents.
|
|
|
- *
|
|
|
- * @param query The query to check.
|
|
|
- * @param expectedDocs Ordered list of document keys that are expected to match the query.
|
|
|
- */
|
|
|
- private func checkOnlineAndOfflineQuery(_ query: Query, matchesResult expectedDocs: [String]?) {
|
|
|
- let docsFromServer = readDocumentSet(forRef: query,
|
|
|
- source: FirestoreSource.server)
|
|
|
-
|
|
|
- let docsFromCache = readDocumentSet(forRef: query,
|
|
|
- source: FirestoreSource.cache)
|
|
|
-
|
|
|
- XCTAssertEqual(FIRQuerySnapshotGetIDs(docsFromServer),
|
|
|
- FIRQuerySnapshotGetIDs(docsFromCache))
|
|
|
- if expectedDocs != nil {
|
|
|
- XCTAssertEqual(FIRQuerySnapshotGetIDs(docsFromCache), expectedDocs)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
func testOrQueries() throws {
|
|
|
let collRef = collectionRef(
|
|
|
withDocuments: ["doc1": ["a": 1, "b": 0],
|
|
|
@@ -54,8 +32,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", isEqualTo: 1),
|
|
|
Filter.whereField("b", isEqualTo: 1)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter1),
|
|
|
- matchesResult: ["doc1", "doc2", "doc4", "doc5"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter1),
|
|
|
+ matchesResult: ["doc1", "doc2", "doc4", "doc5"])
|
|
|
|
|
|
// (a==1 && b==0) || (a==3 && b==2)
|
|
|
let filter2 = Filter.orFilter(
|
|
|
@@ -68,8 +46,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
Filter.whereField("b", isEqualTo: 2)]
|
|
|
)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter2),
|
|
|
- matchesResult: ["doc1", "doc3"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter2),
|
|
|
+ matchesResult: ["doc1", "doc3"])
|
|
|
|
|
|
// a==1 && (b==0 || b==3).
|
|
|
let filter3 = Filter.andFilter(
|
|
|
@@ -79,8 +57,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
Filter.whereField("b", isEqualTo: 3)]
|
|
|
)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter3),
|
|
|
- matchesResult: ["doc1", "doc4"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter3),
|
|
|
+ matchesResult: ["doc1", "doc4"])
|
|
|
|
|
|
// (a==2 || b==2) && (a==3 || b==3)
|
|
|
let filter4 = Filter.andFilter(
|
|
|
@@ -93,16 +71,16 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
Filter.whereField("b", isEqualTo: 3)]
|
|
|
)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter4),
|
|
|
- matchesResult: ["doc3"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter4),
|
|
|
+ matchesResult: ["doc3"])
|
|
|
|
|
|
// Test with limits without orderBy (the __name__ ordering is the tie breaker).
|
|
|
let filter5 = Filter.orFilter(
|
|
|
[Filter.whereField("a", isEqualTo: 2),
|
|
|
Filter.whereField("b", isEqualTo: 1)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter5).limit(to: 1),
|
|
|
- matchesResult: ["doc2"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter5).limit(to: 1),
|
|
|
+ matchesResult: ["doc2"])
|
|
|
}
|
|
|
|
|
|
func testOrQueriesWithCompositeIndexes() throws {
|
|
|
@@ -124,16 +102,16 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", isGreaterThan: 2),
|
|
|
Filter.whereField("b", isEqualTo: 1)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter1),
|
|
|
- matchesResult: ["doc5", "doc2", "doc3"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter1),
|
|
|
+ matchesResult: ["doc5", "doc2", "doc3"])
|
|
|
|
|
|
// Test with limits (implicit order by ASC): (a==1) || (b > 0) LIMIT 2
|
|
|
let filter2 = Filter.orFilter(
|
|
|
[Filter.whereField("a", isEqualTo: 1),
|
|
|
Filter.whereField("b", isGreaterThan: 0)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter2).limit(to: 2),
|
|
|
- matchesResult: ["doc1", "doc2"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter2).limit(to: 2),
|
|
|
+ matchesResult: ["doc1", "doc2"])
|
|
|
|
|
|
// Test with limits (explicit order by): (a==1) || (b > 0) LIMIT_TO_LAST 2
|
|
|
// Note: The public query API does not allow implicit ordering when limitToLast is used.
|
|
|
@@ -141,7 +119,7 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", isEqualTo: 1),
|
|
|
Filter.whereField("b", isGreaterThan: 0)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter3)
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter3)
|
|
|
.limit(toLast: 2)
|
|
|
.order(by: "b"),
|
|
|
matchesResult: ["doc3", "doc4"])
|
|
|
@@ -151,7 +129,7 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", isEqualTo: 2),
|
|
|
Filter.whereField("b", isEqualTo: 1)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter4).limit(to: 1)
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter4).limit(to: 1)
|
|
|
.order(by: "a"),
|
|
|
matchesResult: ["doc5"])
|
|
|
|
|
|
@@ -160,7 +138,7 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", isEqualTo: 2),
|
|
|
Filter.whereField("b", isEqualTo: 1)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter5).limit(toLast: 1)
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter5).limit(toLast: 1)
|
|
|
.order(by: "a"),
|
|
|
matchesResult: ["doc2"])
|
|
|
}
|
|
|
@@ -180,8 +158,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", isEqualTo: 2),
|
|
|
Filter.whereField("b", in: [2, 3])]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter),
|
|
|
- matchesResult: ["doc3", "doc4", "doc6"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter),
|
|
|
+ matchesResult: ["doc3", "doc4", "doc6"])
|
|
|
}
|
|
|
|
|
|
func testOrQueriesWithArrayMembership() throws {
|
|
|
@@ -199,16 +177,16 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", isEqualTo: 2),
|
|
|
Filter.whereField("b", arrayContains: 7)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter1),
|
|
|
- matchesResult: ["doc3", "doc4", "doc6"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter1),
|
|
|
+ matchesResult: ["doc3", "doc4", "doc6"])
|
|
|
|
|
|
// a==2 || b array-contains-any [0, 3]
|
|
|
let filter2 = Filter.orFilter(
|
|
|
[Filter.whereField("a", isEqualTo: 2),
|
|
|
Filter.whereField("b", arrayContainsAny: [0, 3])]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter2),
|
|
|
- matchesResult: ["doc1", "doc4", "doc6"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter2),
|
|
|
+ matchesResult: ["doc1", "doc4", "doc6"])
|
|
|
}
|
|
|
|
|
|
func testMultipleInOps() throws {
|
|
|
@@ -226,8 +204,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", in: [2, 3]),
|
|
|
Filter.whereField("b", in: [0, 2])]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter1).order(by: "a"),
|
|
|
- matchesResult: ["doc1", "doc6", "doc3"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter1).order(by: "a"),
|
|
|
+ matchesResult: ["doc1", "doc6", "doc3"])
|
|
|
|
|
|
// Two IN operations on same fields with disjunction.
|
|
|
// a IN [0,3] || a IN [0,2] should union them (similar to: a IN [0,2,3]).
|
|
|
@@ -235,8 +213,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", in: [0, 3]),
|
|
|
Filter.whereField("a", in: [0, 2])]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter2),
|
|
|
- matchesResult: ["doc3", "doc6"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter2),
|
|
|
+ matchesResult: ["doc3", "doc6"])
|
|
|
}
|
|
|
|
|
|
func testUsingInWithArrayContainsAny() throws {
|
|
|
@@ -253,8 +231,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", in: [2, 3]),
|
|
|
Filter.whereField("b", arrayContainsAny: [0, 7])]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter1),
|
|
|
- matchesResult: ["doc1", "doc3", "doc4", "doc6"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter1),
|
|
|
+ matchesResult: ["doc1", "doc3", "doc4", "doc6"])
|
|
|
|
|
|
let filter2 = Filter.orFilter(
|
|
|
[Filter.andFilter(
|
|
|
@@ -263,8 +241,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
),
|
|
|
Filter.whereField("b", arrayContainsAny: [0, 7])]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter2),
|
|
|
- matchesResult: ["doc1", "doc3", "doc4"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter2),
|
|
|
+ matchesResult: ["doc1", "doc3", "doc4"])
|
|
|
}
|
|
|
|
|
|
func testUseInWithArrayContains() throws {
|
|
|
@@ -281,15 +259,15 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
[Filter.whereField("a", in: [2, 3]),
|
|
|
Filter.whereField("b", arrayContainsAny: [3])]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter1),
|
|
|
- matchesResult: ["doc3", "doc4", "doc6"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter1),
|
|
|
+ matchesResult: ["doc3", "doc4", "doc6"])
|
|
|
|
|
|
let filter2 = Filter.andFilter(
|
|
|
[Filter.whereField("a", in: [2, 3]),
|
|
|
Filter.whereField("b", arrayContains: 7)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter2),
|
|
|
- matchesResult: ["doc3"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter2),
|
|
|
+ matchesResult: ["doc3"])
|
|
|
|
|
|
let filter3 = Filter.orFilter(
|
|
|
[Filter.whereField("a", in: [2, 3]),
|
|
|
@@ -298,8 +276,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
Filter.whereField("a", isEqualTo: 1)]
|
|
|
)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter3),
|
|
|
- matchesResult: ["doc3", "doc4", "doc6"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter3),
|
|
|
+ matchesResult: ["doc3", "doc4", "doc6"])
|
|
|
|
|
|
let filter4 = Filter.andFilter(
|
|
|
[Filter.whereField("a", in: [2, 3]),
|
|
|
@@ -308,8 +286,8 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
Filter.whereField("a", isEqualTo: 1)]
|
|
|
)]
|
|
|
)
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(filter4),
|
|
|
- matchesResult: ["doc3"])
|
|
|
+ checkOnlineAndOfflineCollection(collRef, query: collRef.whereFilter(filter4),
|
|
|
+ matchesResult: ["doc3"])
|
|
|
}
|
|
|
|
|
|
func testOrderByEquality() throws {
|
|
|
@@ -326,11 +304,15 @@ class QueryIntegrationTests: FSTIntegrationTestCase {
|
|
|
"doc6": ["a": 2, "c": 20]]
|
|
|
)
|
|
|
|
|
|
- checkOnlineAndOfflineQuery(collRef.whereFilter(Filter.whereField("a", isEqualTo: 1)),
|
|
|
- matchesResult: ["doc1", "doc4", "doc5"])
|
|
|
+ checkOnlineAndOfflineCollection(
|
|
|
+ collRef,
|
|
|
+ query: collRef.whereFilter(Filter.whereField("a", isEqualTo: 1)),
|
|
|
+ matchesResult: ["doc1", "doc4", "doc5"]
|
|
|
+ )
|
|
|
|
|
|
- checkOnlineAndOfflineQuery(
|
|
|
- collRef.whereFilter(Filter.whereField("a", in: [2, 3])).order(by: "a"),
|
|
|
+ checkOnlineAndOfflineCollection(
|
|
|
+ collRef,
|
|
|
+ query: collRef.whereFilter(Filter.whereField("a", in: [2, 3])).order(by: "a"),
|
|
|
matchesResult: ["doc6", "doc3"]
|
|
|
)
|
|
|
}
|