Skip to content

Commit 3de3e17

Browse files
committed
test: add tests for handling map keys with "/" in Firestore operations
1 parent 4872123 commit 3de3e17

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

packages/google_cloud_firestore/lib/src/field_value.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,14 +440,17 @@ void _validateUserInput(
440440

441441
case Map<Object?, Object?>():
442442
for (final entry in value.entries) {
443+
final keyPath = switch (entry.key) {
444+
final FieldPath fp => fp,
445+
final String s => FieldPath([s]),
446+
_ => FieldPath([entry.key.toString()]),
447+
};
443448
_validateUserInput(
444449
arg,
445450
entry.value,
446451
description: description,
447452
options: options,
448-
path: path == null
449-
? FieldPath.from(entry.key)
450-
: path._appendPath(FieldPath.from(entry.key)),
453+
path: path == null ? keyPath : path._appendPath(keyPath),
451454
level: level + 1,
452455
inArray: inArray,
453456
);

packages/google_cloud_firestore/test/integration/firestore_test.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,38 @@ void main() {
3434

3535
expect(collections, containsAll([a, b]));
3636
});
37+
38+
group('map keys with "/" characters', () {
39+
test('set() round-trips a map with "/" in key', () async {
40+
final docRef = firestore.doc('activities/new-activity');
41+
42+
await docRef.set({
43+
'activityType': 'activityA',
44+
'agents': {'products/product-a': 5.0},
45+
});
46+
47+
final data = (await docRef.get()).data()!;
48+
expect(data['activityType'], 'activityA');
49+
expect(
50+
(data['agents']! as Map<String, Object?>)['products/product-a'],
51+
5.0,
52+
);
53+
});
54+
55+
test('update() round-trips a map value with "/" in key', () async {
56+
final docRef = firestore.doc('activities/update-activity');
57+
await docRef.set({'activityType': 'activityA'});
58+
59+
await docRef.update({
60+
'agents': {'products/product-b': 10.0},
61+
});
62+
63+
final data = (await docRef.get()).data()!;
64+
expect(
65+
(data['agents']! as Map<String, Object?>)['products/product-b'],
66+
10.0,
67+
);
68+
});
69+
});
3770
});
3871
}

packages/google_cloud_firestore/test/unit/firestore_test.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,39 @@ void main() {
185185
final batch = firestore.batch();
186186
expect(batch, isA<WriteBatch>());
187187
});
188+
189+
group('set() with map keys containing "/"', () {
190+
test('accepts a top-level map value with "/" in key', () {
191+
final firestore = Firestore(
192+
settings: const Settings(projectId: 'test'),
193+
);
194+
final batch = firestore.batch();
195+
final docRef = firestore.doc('activities/new-activity');
196+
197+
expect(
198+
() => batch.set(docRef, {
199+
'activityType': 'activityA',
200+
'agents': {'products/product-a': 5.0},
201+
}),
202+
returnsNormally,
203+
);
204+
});
205+
206+
test('accepts nested maps with "/" in keys', () {
207+
final firestore = Firestore(
208+
settings: const Settings(projectId: 'test'),
209+
);
210+
final batch = firestore.batch();
211+
final docRef = firestore.doc('col/doc');
212+
213+
expect(
214+
() => batch.set(docRef, {
215+
'refs': {'users/alice': true, 'users/bob': false},
216+
}),
217+
returnsNormally,
218+
);
219+
});
220+
});
188221
});
189222

190223
group('bulkWriter()', () {

0 commit comments

Comments
 (0)