Skip to content

Commit dca84cd

Browse files
committed
Merge branch 'firestore-pipelines-dart-api-v2' into firestore-pipelines-android
2 parents 54366bf + 41f97df commit dca84cd

9 files changed

Lines changed: 211 additions & 54 deletions

packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_add_fields_e2e.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ void runPipelineAddFieldsTests() {
1313
late FirebaseFirestore firestore;
1414

1515
setUpAll(() {
16-
firestore = FirebaseFirestore.instanceFor(app: Firebase.app(), databaseId: 'firestore-pipeline-test');
16+
firestore = FirebaseFirestore.instanceFor(
17+
app: Firebase.app(), databaseId: 'firestore-pipeline-test');
1718
});
1819

19-
test('addFields with expression returns expected transformed data', () async {
20+
test('addFields with expression returns expected transformed data',
21+
() async {
2022
final snapshot = await firestore
2123
.pipeline()
2224
.collection('pipeline-e2e')
@@ -29,9 +31,9 @@ void runPipelineAddFieldsTests() {
2931
.execute();
3032
expectResultCount(snapshot, 3);
3133
expectResultsData(snapshot, [
32-
{'title': 'alpha', 'score': -7, 'abs_score': 7},
33-
{'title': 'beta', 'score': 42, 'abs_score': 42},
34-
{'title': 'gamma', 'score': 0, 'abs_score': 0},
34+
{'title': 'alpha', 'score': -7, 'abs_score': 7},
35+
{'title': 'beta', 'score': 42, 'abs_score': 42},
36+
{'title': 'gamma', 'score': 0, 'abs_score': 0},
3537
]);
3638
});
3739
});

packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_aggregate_e2e.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ void runPipelineAggregateTests() {
3535
]);
3636
});
3737

38-
test('aggregateWithOptions with groups returns one row per group', () async {
38+
test('aggregateWithOptions with groups returns one row per group',
39+
() async {
3940
final snapshot = await firestore
4041
.pipeline()
4142
.collection('pipeline-e2e')
@@ -52,7 +53,8 @@ void runPipelineAggregateTests() {
5253
.execute();
5354
expectResultCount(snapshot, 2);
5455
final results = snapshot.result.map((r) => r.data()!).toList();
55-
results.sort((a, b) => (a['category'] as String).compareTo(b['category'] as String));
56+
results.sort((a, b) =>
57+
(a['category'] as String).compareTo(b['category'] as String));
5658
expect(results[0]['category'], 'x');
5759
expect(results[0]['total_score'], 30);
5860
expect(results[0]['count'], 2);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2026, the Chromium project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:cloud_firestore/cloud_firestore.dart';
6+
import 'package:firebase_core/firebase_core.dart';
7+
import 'package:flutter/foundation.dart'
8+
show defaultTargetPlatform, TargetPlatform;
9+
import 'package:flutter_test/flutter_test.dart';
10+
11+
import 'pipeline_test_helpers.dart';
12+
13+
void runPipelineExecuteOptionsTests() {
14+
group('Pipeline execute with options', () {
15+
late FirebaseFirestore firestore;
16+
17+
setUpAll(() {
18+
firestore = FirebaseFirestore.instanceFor(
19+
app: Firebase.app(),
20+
databaseId: 'firestore-pipeline-test',
21+
);
22+
});
23+
24+
test(
25+
'execute with ExecuteOptions returns expected results',
26+
() async {
27+
final snapshot = await firestore
28+
.pipeline()
29+
.collection('pipeline-e2e')
30+
.where(Expression.field('test').equalValue('add-fields'))
31+
.sort(Expression.field('title').ascending())
32+
.limit(2)
33+
.execute(
34+
options: const ExecuteOptions(
35+
indexMode: IndexMode.recommended,
36+
),
37+
);
38+
expectResultCount(snapshot, 2);
39+
expect(snapshot.result[0].data()!['title'], 'alpha');
40+
expect(snapshot.result[1].data()!['title'], 'beta');
41+
},
42+
skip: true,
43+
);
44+
});
45+
}

packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart

Lines changed: 83 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
import 'package:cloud_firestore/cloud_firestore.dart';
66
import 'package:firebase_core/firebase_core.dart';
7-
import 'package:flutter/foundation.dart' show defaultTargetPlatform, TargetPlatform;
7+
import 'package:flutter/foundation.dart'
8+
show defaultTargetPlatform, TargetPlatform;
89
import 'package:flutter_test/flutter_test.dart';
910

1011
import 'pipeline_test_helpers.dart';
@@ -46,9 +47,7 @@ void runPipelineExpressionsTests() {
4647
.where(Expression.field('test').equalValue('expressions'))
4748
.sort(Expression.field('score').ascending())
4849
.addFields(
49-
Expression.field('a')
50-
.add(Expression.field('b'))
51-
.as('sum_ab'),
50+
Expression.field('a').add(Expression.field('b')).as('sum_ab'),
5251
)
5352
.limit(5)
5453
.execute();
@@ -99,7 +98,8 @@ void runPipelineExpressionsTests() {
9998
.limit(5)
10099
.execute();
101100
expectResultCount(snapshot, 5);
102-
final withTags = snapshot.result.where((r) => r.data()!['tags_len'] == 2).toList();
101+
final withTags =
102+
snapshot.result.where((r) => r.data()!['tags_len'] == 2).toList();
103103
expect(withTags.length, 1);
104104
expect(withTags.first.data()!['score'], 50);
105105
});
@@ -185,7 +185,8 @@ void runPipelineExpressionsTests() {
185185
]);
186186
});
187187

188-
test('where with greaterThanValue and lessThanValue filter correctly', () async {
188+
test('where with greaterThanValue and lessThanValue filter correctly',
189+
() async {
189190
final snapshot = await firestore
190191
.pipeline()
191192
.collection('pipeline-e2e')
@@ -206,13 +207,15 @@ void runPipelineExpressionsTests() {
206207
]);
207208
});
208209

209-
test('where with greaterThanOrEqual and lessThanOrEqual filter correctly', () async {
210+
test('where with greaterThanOrEqual and lessThanOrEqual filter correctly',
211+
() async {
210212
final snapshot = await firestore
211213
.pipeline()
212214
.collection('pipeline-e2e')
213215
.where(Expression.field('test').equalValue('expressions'))
214216
.where(
215-
Expression.field('score').greaterThanOrEqual(Expression.constant(50)),
217+
Expression.field('score')
218+
.greaterThanOrEqual(Expression.constant(50)),
216219
)
217220
.where(
218221
Expression.field('score').lessThanOrEqual(Expression.constant(70)),
@@ -227,7 +230,9 @@ void runPipelineExpressionsTests() {
227230
]);
228231
});
229232

230-
test('addFields with subtract, multiply, divide, modulo return expected values', () async {
233+
test(
234+
'addFields with subtract, multiply, divide, modulo return expected values',
235+
() async {
231236
final snapshot = await firestore
232237
.pipeline()
233238
.collection('pipeline-e2e')
@@ -236,16 +241,44 @@ void runPipelineExpressionsTests() {
236241
.addFields(
237242
Expression.field('a').subtract(Expression.field('b')).as('diff'),
238243
Expression.field('a').multiply(Expression.field('b')).as('product'),
239-
Expression.field('score').divide(Expression.constant(10)).as('score_div_10'),
240-
Expression.field('score').modulo(Expression.constant(30)).as('score_mod_30'),
244+
Expression.field('score')
245+
.divide(Expression.constant(10))
246+
.as('score_div_10'),
247+
Expression.field('score')
248+
.modulo(Expression.constant(30))
249+
.as('score_mod_30'),
241250
)
242251
.limit(3)
243252
.execute();
244253
expectResultCount(snapshot, 3);
245254
expectResultsData(snapshot, [
246-
{'score': 40, 'a': 5, 'b': 5, 'diff': 0, 'product': 25, 'score_div_10': 4, 'score_mod_30': 10},
247-
{'score': 50, 'a': 1, 'b': 2, 'diff': -1, 'product': 2, 'score_div_10': 5, 'score_mod_30': 20},
248-
{'score': 60, 'a': 1, 'b': 2, 'diff': -1, 'product': 2, 'score_div_10': 6, 'score_mod_30': 0},
255+
{
256+
'score': 40,
257+
'a': 5,
258+
'b': 5,
259+
'diff': 0,
260+
'product': 25,
261+
'score_div_10': 4,
262+
'score_mod_30': 10
263+
},
264+
{
265+
'score': 50,
266+
'a': 1,
267+
'b': 2,
268+
'diff': -1,
269+
'product': 2,
270+
'score_div_10': 5,
271+
'score_mod_30': 20
272+
},
273+
{
274+
'score': 60,
275+
'a': 1,
276+
'b': 2,
277+
'diff': -1,
278+
'product': 2,
279+
'score_div_10': 6,
280+
'score_mod_30': 0
281+
},
249282
]);
250283
});
251284

@@ -297,7 +330,8 @@ void runPipelineExpressionsTests() {
297330
.where(Expression.field('test').equalValue('expressions'))
298331
.where(
299332
Expression.not(
300-
Expression.field('score').greaterThanOrEqual(Expression.constant(60)),
333+
Expression.field('score')
334+
.greaterThanOrEqual(Expression.constant(60)),
301335
),
302336
)
303337
.sort(Expression.field('score').ascending())
@@ -309,14 +343,17 @@ void runPipelineExpressionsTests() {
309343
]);
310344
});
311345

312-
test('addFields with ifAbsentValue uses default when field missing', () async {
346+
test('addFields with ifAbsentValue uses default when field missing',
347+
() async {
313348
final snapshot = await firestore
314349
.pipeline()
315350
.collection('pipeline-e2e')
316351
.where(Expression.field('test').equalValue('expressions'))
317352
.sort(Expression.field('score').ascending())
318353
.addFields(
319-
Expression.field('tags').ifAbsentValue('default_value').as('tags_or_empty'),
354+
Expression.field('tags')
355+
.ifAbsentValue('default_value')
356+
.as('tags_or_empty'),
320357
)
321358
.limit(2)
322359
.execute();
@@ -325,7 +362,9 @@ void runPipelineExpressionsTests() {
325362
expect(snapshot.result[1].data()!['tags_or_empty'], ['p', 'q']);
326363
});
327364

328-
test('addFields with ifAbsent(Expression) uses else expression when field missing', () async {
365+
test(
366+
'addFields with ifAbsent(Expression) uses else expression when field missing',
367+
() async {
329368
final snapshot = await firestore
330369
.pipeline()
331370
.collection('pipeline-e2e')
@@ -343,7 +382,8 @@ void runPipelineExpressionsTests() {
343382
expect(snapshot.result[1].data()!['tags_or_default'], ['p', 'q']);
344383
});
345384

346-
test('where arrayContainsValue filters docs with array containing value', () async {
385+
test('where arrayContainsValue filters docs with array containing value',
386+
() async {
347387
final snapshot = await firestore
348388
.pipeline()
349389
.collection('pipeline-e2e')
@@ -354,26 +394,41 @@ void runPipelineExpressionsTests() {
354394
.execute();
355395
expectResultCount(snapshot, 1);
356396
expectResultsData(snapshot, [
357-
{'score': 50, 'a': 1, 'b': 2, 'tags': ['p', 'q']},
397+
{
398+
'score': 50,
399+
'a': 1,
400+
'b': 2,
401+
'tags': ['p', 'q']
402+
},
358403
]);
359404
});
360405

361-
test('where arrayContainsElement(Expression) filters docs with array containing element', () async {
406+
test(
407+
'where arrayContainsElement(Expression) filters docs with array containing element',
408+
() async {
362409
final snapshot = await firestore
363410
.pipeline()
364411
.collection('pipeline-e2e')
365412
.where(Expression.field('test').equalValue('expressions'))
366413
.where(
367-
Expression.field('tags').arrayContainsElement(Expression.constant('q')),
414+
Expression.field('tags')
415+
.arrayContainsElement(Expression.constant('q')),
368416
)
369417
.execute();
370418
expectResultCount(snapshot, 1);
371419
expectResultsData(snapshot, [
372-
{'score': 50, 'a': 1, 'b': 2, 'tags': ['p', 'q']},
420+
{
421+
'score': 50,
422+
'a': 1,
423+
'b': 2,
424+
'tags': ['p', 'q']
425+
},
373426
]);
374427
});
375428

376-
test('addFields with string expressions (concat, length, toLower, toUpper, trim)', () async {
429+
test(
430+
'addFields with string expressions (concat, length, toLower, toUpper, trim)',
431+
() async {
377432
final snapshot = await firestore
378433
.pipeline()
379434
.collection('pipeline-e2e')
@@ -408,7 +463,9 @@ void runPipelineExpressionsTests() {
408463
.where(Expression.field('test').equalValue('expressions'))
409464
.where(Expression.field('score').equalValue(70))
410465
.addFields(
411-
Expression.field('s').substring(Expression.constant(0), Expression.constant(1)).as('s_first'),
466+
Expression.field('s')
467+
.substring(Expression.constant(0), Expression.constant(1))
468+
.as('s_first'),
412469
)
413470
.limit(1)
414471
.execute();
@@ -485,7 +542,7 @@ void runPipelineExpressionsTests() {
485542
}
486543
},
487544
skip: defaultTargetPlatform != TargetPlatform.iOS &&
488-
defaultTargetPlatform != TargetPlatform.macOS,
545+
defaultTargetPlatform != TargetPlatform.macOS,
489546
);
490547
});
491548
}

packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_filter_sort_e2e.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ void runPipelineFilterSortTests() {
1313
late FirebaseFirestore firestore;
1414

1515
setUpAll(() {
16-
firestore = FirebaseFirestore.instanceFor(app: Firebase.app(), databaseId: 'firestore-pipeline-test');
16+
firestore = FirebaseFirestore.instanceFor(
17+
app: Firebase.app(), databaseId: 'firestore-pipeline-test');
1718
});
1819

1920
test('where + limit returns expected count and data', () async {
@@ -77,7 +78,8 @@ void runPipelineFilterSortTests() {
7778
.limit(10)
7879
.execute();
7980
expectResultCount(snapshot, 3);
80-
final categories = snapshot.result.map((r) => r.data()!['category']).toList();
81+
final categories =
82+
snapshot.result.map((r) => r.data()!['category']).toList();
8183
expect(categories..sort(), ['a', 'b', 'c']);
8284
});
8385
});

packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_find_nearest_e2e.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ void runPipelineFindNearestTests() {
1717
);
1818
});
1919

20-
test('findNearest returns results ordered by distance when vector index exists', () async {
20+
test(
21+
'findNearest returns results ordered by distance when vector index exists',
22+
() async {
2123
final pipeline = firestore
2224
.pipeline()
2325
.collection('pipeline-e2e')

0 commit comments

Comments
 (0)