Skip to content

Commit 3a5ce84

Browse files
committed
More tests, some error is waiting for fix
1 parent 38b89eb commit 3a5ce84

File tree

2 files changed

+177
-10
lines changed

2 files changed

+177
-10
lines changed

Firestore/Swift/Source/Helper/PipelineHelper.swift

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,19 @@
1313
// limitations under the License.
1414

1515
enum Helper {
16-
static func sendableToExpr(_ value: Sendable) -> Expr {
17-
if value is Expr {
18-
return value as! Expr
19-
} else if value is [String: Sendable] {
20-
return map(value as! [String: Sendable])
21-
} else if value is [Sendable] {
22-
return array(value as! [Sendable])
16+
static func sendableToExpr(_ value: Sendable?) -> Expr {
17+
if value == nil {
18+
return Constant.nil
19+
}
20+
21+
if value! is Expr {
22+
return value! as! Expr
23+
} else if value! is [String: Sendable?] {
24+
return map(value! as! [String: Sendable?])
25+
} else if value! is [Sendable?] {
26+
return array(value! as! [Sendable?])
2327
} else {
24-
return Constant(value)
28+
return Constant(value!)
2529
}
2630
}
2731

@@ -33,7 +37,7 @@ enum Helper {
3337
return exprMap
3438
}
3539

36-
static func map(_ elements: [String: Sendable]) -> FunctionExpr {
40+
static func map(_ elements: [String: Sendable?]) -> FunctionExpr {
3741
var result: [Expr] = []
3842
for (key, value) in elements {
3943
result.append(Constant(key))
@@ -42,7 +46,7 @@ enum Helper {
4246
return FunctionExpr("map", result)
4347
}
4448

45-
static func array(_ elements: [Sendable]) -> FunctionExpr {
49+
static func array(_ elements: [Sendable?]) -> FunctionExpr {
4650
let transformedElements = elements.map { element in
4751
sendableToExpr(element)
4852
}

Firestore/Swift/Tests/Integration/PipelineTests.swift

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,4 +1186,167 @@ class PipelineIntegrationTests: FSTIntegrationTestCase {
11861186
)
11871187
expectSnapshots(snapshot: snapshot, expected: expectedResults)
11881188
}
1189+
1190+
func testSortOffsetAndLimitStages() async throws {
1191+
let collRef = collectionRef(withDocuments: bookDocs)
1192+
let db = collRef.firestore
1193+
1194+
let pipeline = db.pipeline()
1195+
.collection(collRef.path)
1196+
.sort(Field("author").ascending())
1197+
.offset(5)
1198+
.limit(3)
1199+
.select("title", "author")
1200+
1201+
let snapshot = try await pipeline.execute()
1202+
1203+
let expectedResults: [[String: Sendable]] = [
1204+
["title": "1984", "author": "George Orwell"],
1205+
["title": "To Kill a Mockingbird", "author": "Harper Lee"],
1206+
["title": "The Lord of the Rings", "author": "J.R.R. Tolkien"],
1207+
]
1208+
expectSnapshots(snapshot: snapshot, expected: expectedResults)
1209+
}
1210+
1211+
// MARK: - Generic Stage Tests
1212+
1213+
func testRawStageSelectFields() async throws {
1214+
let collRef = collectionRef(withDocuments: bookDocs)
1215+
let db = collRef.firestore
1216+
1217+
// Expected book: book2 (Pride and Prejudice, Jane Austen, 1813)
1218+
// It's the earliest published book.
1219+
let expectedSelectedData: [String: Sendable] = [
1220+
"title": "Pride and Prejudice",
1221+
// "metadata": ["author": "Douglas Adams"]
1222+
]
1223+
1224+
// The parameters for rawStage("select", ...) are an array containing a single dictionary.
1225+
// The keys of this dictionary are the output field names, and the values are Field objects.
1226+
let selectParameters: [[String: Sendable]] =
1227+
[
1228+
// Field("title").as("title")
1229+
["title": Field("author")],
1230+
]
1231+
1232+
let pipeline = db.pipeline()
1233+
.collection(collRef.path)
1234+
.sort(Field("published").ascending())
1235+
.limit(1)
1236+
.rawStage(name: "select", params: selectParameters) // Using rawStage for selection
1237+
1238+
let snapshot = try await pipeline.execute()
1239+
1240+
XCTAssertEqual(snapshot.results.count, 1, "Should retrieve one document")
1241+
expectSnapshots(snapshot: snapshot, expected: [expectedSelectedData])
1242+
}
1243+
1244+
// TODO:
1245+
1246+
// MARK: - Replace Stage Test
1247+
1248+
func testReplaceStagePromoteAwardsAndAddFlag() async throws {
1249+
let collRef = collectionRef(withDocuments: bookDocs)
1250+
let db = collRef.firestore
1251+
1252+
let pipeline = db.pipeline()
1253+
.collection(collRef.path)
1254+
.where(Field("title").eq("The Hitchhiker's Guide to the Galaxy"))
1255+
.replace(with: "awards")
1256+
1257+
let snapshot = try await pipeline.execute()
1258+
1259+
expectResults(snapshot, expectedCount: 1)
1260+
1261+
let expectedBook1Transformed: [String: Sendable?] = [
1262+
"hugo": true,
1263+
"nebula": false,
1264+
"others": ["unknown": ["year": 1980]],
1265+
]
1266+
1267+
// Need to use nullable Sendable for comparison because 'others' is nested
1268+
// and the areEqual function handles Sendable?
1269+
expectSnapshots(snapshot: snapshot, expected: [expectedBook1Transformed as [String: Sendable]])
1270+
}
1271+
1272+
// MARK: - Sample Stage Tests
1273+
1274+
func testSampleStageLimit3() async throws {
1275+
let collRef = collectionRef(withDocuments: bookDocs)
1276+
let db = collRef.firestore
1277+
1278+
let pipeline = db.pipeline()
1279+
.collection(collRef.path)
1280+
.sort(DocumentId().ascending()) // Sort for predictable results
1281+
.limit(3) // Simulate sampling 3 documents
1282+
1283+
let snapshot = try await pipeline.execute()
1284+
1285+
expectResults(snapshot, expectedCount: 3)
1286+
1287+
// Based on documentID ascending sort of bookDocs keys:
1288+
// book1, book10, book2, book3, ...
1289+
let expectedIDs = ["book1", "book10", "book2"]
1290+
expectResults(snapshot, expectedIDs: expectedIDs)
1291+
}
1292+
1293+
func testSampleStageLimitDocuments3() async throws {
1294+
let collRef = collectionRef(withDocuments: bookDocs)
1295+
let db = collRef.firestore
1296+
1297+
let pipeline = db.pipeline()
1298+
.collection(collRef.path)
1299+
.sort(DocumentId().ascending()) // Sort for predictable results
1300+
.limit(3) // Simulate sampling {documents: 3}
1301+
1302+
let snapshot = try await pipeline.execute()
1303+
1304+
expectResults(snapshot, expectedCount: 3)
1305+
1306+
// Based on documentID ascending sort of bookDocs keys:
1307+
// book1, book10, book2, book3, ...
1308+
let expectedIDs = ["book1", "book10", "book2"]
1309+
expectResults(snapshot, expectedIDs: expectedIDs)
1310+
}
1311+
1312+
func testSampleStageLimitPercentage60() async throws {
1313+
let collRef = collectionRef(withDocuments: bookDocs)
1314+
let db = collRef.firestore
1315+
1316+
let totalDocs = bookDocs.count
1317+
let percentage = 0.6
1318+
let limitCount = Int(Double(totalDocs) * percentage) // 10 * 0.6 = 6
1319+
1320+
let pipeline = db.pipeline()
1321+
.collection(collRef.path)
1322+
.sort(DocumentId().ascending()) // Sort for predictable results
1323+
.limit(Int32(limitCount)) // Simulate sampling {percentage: 0.6}
1324+
1325+
let snapshot = try await pipeline.execute()
1326+
1327+
expectResults(snapshot, expectedCount: limitCount) // Should be 6
1328+
1329+
// Based on documentID ascending sort of bookDocs keys:
1330+
// book1, book10, book2, book3, book4, book5, book6, book7, book8, book9
1331+
let expectedIDs = ["book1", "book10", "book2", "book3", "book4", "book5"]
1332+
expectResults(snapshot, expectedIDs: expectedIDs)
1333+
}
1334+
1335+
// MARK: - Union Stage Test
1336+
1337+
func testUnionStageCombineAuthors() async throws {
1338+
let collRef = collectionRef(withDocuments: bookDocs)
1339+
let db = collRef.firestore
1340+
1341+
let pipeline = db.pipeline()
1342+
.collection(collRef.path)
1343+
.union(db.pipeline()
1344+
.collection(collRef.path))
1345+
1346+
let snapshot = try await pipeline.execute()
1347+
1348+
let bookSequence = (1 ... 10).map { "book\($0)" }
1349+
let repeatedIDs = bookSequence + bookSequence
1350+
expectResults(snapshot, expectedIDs: repeatedIDs)
1351+
}
11891352
}

0 commit comments

Comments
 (0)