atn832 / fake_cloud_firestore Goto Github PK
View Code? Open in Web Editor NEWLicense: BSD 2-Clause "Simplified" License
License: BSD 2-Clause "Simplified" License
(I haven’t tested but I assume the function is not implemented yet. So far I don’t use transactions in my Flutter app)
https://firebase.google.com/docs/firestore/manage-data/transactions#transactions
final DocumentReference postRef = Firestore.instance.document('posts/123');
Firestore.instance.runTransaction((Transaction tx) async {
DocumentSnapshot postSnapshot = await tx.get(postRef);
if (postSnapshot.exists) {
await tx.update(postRef, <String, dynamic>{'likesCount': postSnapshot.data['likesCount'] + 1});
}
});
Excerpt from https://pub.dev/packages/cloud_firestore
One has to replace localhost
by 10.0.2.2
at https://github.com/atn832/cloud_firestore_mocks/blob/8088e32135b54511abcdb864a59583d2d6be29f3/test_driver/cloud_firestore_behaviors.dart#L26 before running.
Returning a document reference in transaction handler's return value causes PlatformException(error, Invalid argument: Instance of 'DocumentReference', null)
:
final result = await _firestore.runTransaction((Transaction tx) async {
...
// In cloud_firestore, the transaction handler should return void
// or a map somehow. The value of the Map cannot be Person.
// https://github.com/FirebaseExtended/flutterfire/issues/1642
return <String, dynamic>{
'personId': personId,
'noteDocumentReference': noteDocumentReference,
};
});
MockQuery presently supports an impressive list of actual Firestore queries. The one that is sorely missing is arrayContainsAny
, which is like doing multiple arrayContains
queries simultaneously.
I believe providing an implementation for this will not be too complicated or time consuming. Please consider adding support for it.
So that it doesn't show up in the documentation.
Test case:
final snapshot1 =
await firestore.collection('users').document(nonExistentId).get();
expect(snapshot1, isNotNull);
expect(snapshot1.documentID, nonExistentId);
// data field should be null before the document is saved
expect(snapshot1.data, isNull);
As of now, this test fails because snapshot1.data
is an empty Map. Real Firestore has null there.
Seems not support nested sub collection.
firestore = MockFirestoreInstance();
await firestore
.collection('userProfiles')
.document('a')
.collection('relationship')
.document('1')
.setData(relationship1);
await firestore
.collection('userProfiles')
.document('a')
.collection('relationship')
.document('2')
.setData(relationship2);
await firestore
.collection('userProfiles')
.document('a')
.collection('relationship')
.document('3')
.setData(relationship3);
await firestore
.collection('userProfiles')
.document('a')
.collection('relationship')
.document('4')
.setData(relationship4);
relsApi.allRelationships('a').listen(expectAsync1((rs) {
print(rs.map((r) => r.relId)); // -> (1, 1, 1, 1) should be(1,2,3,4)
expect(rs.length, equals(4));
}));
test('FieldValue.arrayUnion() adds unique items', () async {
final firestore = MockFirestoreInstance();
// Empty document before updateData
await firestore.collection('messages').document(uid).setData({
'reference array': [
firestore.collection('messages').document('document1')
]
});
await firestore.collection('messages').document(uid).updateData({
'reference array': FieldValue.arrayUnion(
[firestore.collection('messages').document('document1')]),
});
final users = await firestore.collection('messages').getDocuments();
final snapshot = users.documents.first;
expect(snapshot['reference array'], [
firestore.collection('messages').document('document1')
]);
});
This failed:
Expected: [MockDocumentReference:MockDocumentReference]
Actual: [MockDocumentReference:MockDocumentReference, null]
Which: was MockDocumentReference:<MockDocumentReference> instead of MockDocumentReference:<MockDocumentReference> at location [0]
there's a version issue between cloud_firestore and cloud_firestore_mocks.
want a new version of cloud_firestore_mocks
Because every version of cloud_firestore_mocks depends on cloud_firestore ^0.12.9+6 and <project name> depends on cloud_firestore ^0.13.0, cloud_firestore_mocks is forbidden.
MockQuery should defer query execution. In this example code, subcollection
is updated twice. In real Firebase, querying the same subcollection
should work.
test('Saving documents in subcollection', () async {
final instance = MockFirestoreInstance();
await instance
.collection('users')
.document(uid)
.collection('friends')
.add(<String, dynamic>{'name': 'Foo'});
final documentReference = instance
.collection('users')
.document(uid)
.collection('friends')
.document();
var subcollection =
instance.collection('users').document(uid).collection('friends');
var querySnapshot = await subcollection.getDocuments();
expect(querySnapshot.documents, hasLength(1));
// Only after setData, the document is available for getDocuments
await documentReference.setData({'name': 'Bar'});
// This line below should be unnecessary.
subcollection =
instance.collection('users').document(uid).collection('friends');
querySnapshot = await subcollection.getDocuments();
expect(querySnapshot.documents, hasLength(2));
This test fails at 0.4.2:
test('Document reference path', () async {
final instance = MockFirestoreInstance();
final documentReference = instance
.collection('users')
.document('aaa')
.collection('friends')
.document('bbb')
.collection('friends-friends')
.document('ccc');
final friendsFriends = documentReference.parent(); // null
final bbb = friendsFriends.parent();
final friends = bbb.parent();
final bbbSibling = friends.document('bbb-sibling');
expect(bbbSibling.path, 'users/aaa/friends/bbb-sibling');
});
I/flutter (19814): 00:01 +0: Where: array-contains (Cloud Firestore) [E]
I/flutter (19814): PlatformException(Error performing setData, PERMISSION_DENIED: Missing or insufficient permissions., null)
I/flutter (19814): package:flutter/src/services/message_codecs.dart 569:7 StandardMethodCodec.decodeEnvelope
I/flutter (19814): package:flutter/src/services/platform_channel.dart 321:33 MethodChannel.invokeMethod
I/flutter (19814): ===== asynchronous gap ===========================
I/flutter (19814): dart:async/zone.dart 1064:19 _CustomZone.registerBinaryCallback
I/flutter (19814): dart:async-patch/async_patch.dart 82:23 _asyncErrorWrapperHelper
I/flutter (19814): package:test_api/src/backend/invoker.dart Invoker.waitForOutstandingCallbacks.<fn>
I/flutter (19814): dart:async/zone.dart 1126:13 _rootRun
I/flutter (19814): dart:async/zone.dart 1023:19 _CustomZone.run
I/flutter (19814): dart:async/zone.dart 1518:10 _runZoned
I/flutter (19814): dart:async/zone.dart 1465:12 runZoned
I/flutter (19814): package:test_api/src/backend/invoker.dart 239:5 Invoker.waitForOutstandingCallbacks
I/flutter (19814): package:test_api/src/backend/declarer.dart 169:33 Declarer.test.<fn>.<fn>
Perhaps we should create a Firebase project of our own and set up the right permissions.
At https://github.com/atn832/cloud_firestore_mocks/blob/38c30d477399648551a589ffe2fc6fd239b21a77/lib/src/mock_document_reference.dart#L137, we should return a deep copy like it's done in https://github.com/atn832/cloud_firestore_mocks/blob/38c30d477399648551a589ffe2fc6fd239b21a77/lib/src/mock_document_reference.dart#L120
Is there any workaround for chaining calls?
main() {
group('A', () {
test('return right item', () async {
final firestore = MockFirestoreInstance();
await firestore.collection('A').document('1').setData(preparedData1);
await firestore.collection('A').document('2').setData(preparedData2);
// Fail. Mockito does not support deep stubbing
var res1 = await firestore.collection('A').document('1').get();
when(firestore.collection('rooms').document('1').snapshots())
.thenAnswer((_) => Stream.value(res1));
// Mokcito suggest way which is below. Also fail.
var docSnap = MockDocumentSnapshot('1', res1.data);
when(docSnap).thenAnswer((_) => Stream.value(res1));
final api = SomeApi(firestore);
api.getStreamA("1").listen(expectAsync1((res) {
expect(res.documentID, equals("1"));
}));
});
});
}
Deep Stubbing
dart-lang/mockito#21
Mockito Suggest
https://github.com/dart-lang/mockito#how-it-works
var mockUtils = MockUtils();
var mockStringUtils = MockStringUtils();
// Setting up mockUtils.stringUtils to return a mock StringUtils implementation
when(mockUtils.stringUtils).thenReturn(mockStringUtils);
// Some tests
// FAILS!
verify(mockUtils.stringUtils.uppercase()).called(1);
// Instead use this:
verify(mockStringUtils.uppercase()).called(1);
Follow up of #22.
DocumentSnapshotMatcher may optionally ignore the documentID field when the calling test does not need to assert on the ID.
Variables “expectedDumpAfterXXXX” can move to local variables and take ${addedDocument.documentID}
in the String.
The cloud_firestore example uses this extensively: main.dart.
Trying to mock when().then() but I get an error:
ERROR: Bad state: Mock method was not called within when(). Was a real method called?
test(
'should return user document',
() async {
when(mockService.collection(any).document(any)).thenAnswer(
(_) => tUserDoc,
);
// expect
// verify
},
documentReference.setData
with keys containing dots should create nested documents. Test case to confirm the expected behavior:
import 'package:cloud_firestore_mocks/cloud_firestore_mocks.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Nested documents created by setData with keys containing dots',
(WidgetTester tester) async {
final fakeFirestore = MockFirestoreInstance()..setupFieldValueFactory();
final documentRef1 = fakeFirestore
.collection('users')
.document();
final createdTime = DateTime.now();
await documentRef1.setData(<String, dynamic>{
'favorites.keyA.name': 'Banana',
'favorites.keyA.created': createdTime,
});
await documentRef1.setData(<String, dynamic>{
'favorites.keyB.name': 'Apple',
'favorites.keyB.created': createdTime,
});
final snapshot = await documentRef1.get();
expect(snapshot['favorites'], isNotNull); // This fails.
final favoritesMap = snapshot['favorites'] as Map<dynamic, dynamic>;
expect(favoritesMap.keys as Iterable<String>, hasLength(2));
final bananaMap = favoritesMap['keyA'] as Map<dynamic, dynamic>;
expect(bananaMap['name'] as String, 'Banana');
expect(bananaMap['created'] as DateTime, createdTime);
});
}
Screenshot from real Firebase (from a different example):
I might contribute a PR to this issue.
(I haven’t tested but I assume this is not implemented. I’m going to use batch in my Flutter app)
Similar to a transaction but a batch holds only write operations.
Example usage of batch
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/cloud_firestore/cloud_firestore/example/lib/main.dart#L110
The following test fails:
test('isEqualTo should work with DocumentReferences', () async {
final instance = MockFirestoreInstance();
await instance.collection('users').document('123').setData({
'name': 'Alex'
});
await instance.collection('courses').document('123').setData({
'title': 'Learn flutter & Dart the easy way'
});
await instance.collection('usercourses').add({
'user': instance.document('users/123'),
'course': instance.document('courses/123'),
'started_at': DateTime.now()
});
var query = instance.collection('usercourses')
.where('user', isEqualTo: instance.document('users/123'));
query.snapshots().listen(expectAsync1(
(event) {
expect(event.documents.length, greaterThan(0));
},
));
});
The object returned from the actual Firestore implementation of DocumentSnapshot.data
getter is a Map<String, dynamic>
that apparently does not respond to value changes.
For example, something like this presently works with cloud_firestore_mocks but not with the real cloud_firestore:
final snapshot = await store.collection('products').document(productId).get();
// snapshot.data is a Map like { 'id': null, 'name': 'iPhone SE', 'price': 399.0 }
snapshot.data['id'] = snapshot.documentID;
return snapshot.data; // 'id' in returned Map is still null (with real Firestore)
A way around with real Firestore is:
final snapshot = await store.collection('products').document(productId).get();
final data = snapshot.data;
data['id'] = snapshot.documentID;
return data; // 'id' in returned Map is now correctly set
This is weird as snapshot.data
and the new data
variables both essentially point to the same Map. But it works for some reason.
This is a small quirk that MockDocumentSnapshot.data
should also handle. Because of the current implementation, my unit tests that expect "id" to be set correctly passed with cloud_firestore_mocks but my logic with cloud_firestore failed.
Seems not support startAfter(List values).
int d1 = 1;
int d2 = 2;
int d3 = 3;
var collectionRef =
Firestore.instance.collection("users/");
await collectionRef.add({'created': d1});
await collectionRef.add({'created': d2});
await collectionRef.add({'created': d3});
var results =
await collectionRef.orderBy('created', descending: true).startAfter([d2]).getDocuments();
results.documents.forEach((d) => print(d.data['created']));
Extending Mock
makes it possible to call Mockito methods like when
even though that's not how the library should be used. See #26.
https://firebase.google.com/docs/firestore/data-model
For convenience, you can also create references by specifying the path to a document or collection as a string, with path components separated by a forward slash (/)
final firestore = Firestore.instance;
// 2020-03-01 19:54:20.127922-0500 Runner[59725:2435047] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'FIRESTORE INTERNAL ASSERTION FAILED: Invalid document reference. Document references must have an even number of segments, but foo has 1'
final abc = firestore.document('abc');
Interestingly, this is not a Dart exception. Due to the NSInternalInconsistencyException, the app fails.
Maybe assert would suffice.
and perhaps show that they pass on the master branch too.
Follow the rule in Firestore document: https://firebase.google.com/docs/firestore/manage-data/data-types .
Throw corresponding exceptions if invalid types are being saved.
This test fails at 0.4.2:
test('Saving documents through FirestoreInstance.document()',
() async {
final instance = MockFirestoreInstance();
// Creates 1st document in "users/abc/friends/<documentId>"
await instance.document('users/$uid/friends/xyz').setData({
'name': 'Foo',
'nested': {
'k1': 'v1',
}
});
final documentReference = instance
.collection('users')
.document(uid)
.collection('friends')
.document('xyz');
final snapshot = await documentReference.get();
expect(snapshot.data['name'], 'Foo');
final nested = snapshot.data['nested'] as Map<String, dynamic>;
expect(nested['k1'], 'v1');
});
Test case:
test('Snapshot should remain after updating data', () async {
final firestore = MockFirestoreInstance();
// These documents are not saved
final reference = firestore.collection('users').document('foo');
await reference.setData(
<String, dynamic>{'name': 'old'}
);
final snapshot1 = await reference.get();
await reference.setData(
<String, dynamic>{'name': 'new'}
);
expect(snapshot1.data['name'], 'old');
});
I guess I'll need to implement deep copy of Firestore documents.
I wish there is a way to run the test with real Firestore instance. With such setup, contributors of this repository feel confident that cloud_firestore_mocks follows the behavior of the real implementation.
Not sure if this is expected behavior, but this test fails:
test('my tests', () async {
final instance = MockFirestoreInstance();
await instance.collection('usercourses').add({
'started_at': Timestamp.fromDate(DateTime.now().subtract(Duration(days: 4))),
'completed_at': Timestamp.fromDate(DateTime.now())
});
await instance.collection('usercourses').add({
'started_at': Timestamp.fromDate(DateTime.now().subtract(Duration(days: 5))),
'completed_at': null
});
var query = instance.collection('usercourses')
.orderBy('completed_at');
query.snapshots().listen(expectAsync1(
(event) {
expect(event.documents.length, greaterThan(0));
},
));
});
ERROR: NoSuchMethodError: The getter 'seconds' was called on null.
Receiver: null
Tried calling: seconds
dart:core Object.noSuchMethod
package:cloud_firestore_platform_interface/src/timestamp.dart 89:26 Timestamp.compareTo
package:cloud_firestore_mocks/src/mock_query.dart 51:32 MockQuery.orderBy.<fn>.<fn>
dart:collection ListMixin.sort
package:cloud_firestore_mocks/src/mock_query.dart 48:18 MockQuery.orderBy.<fn>
package:cloud_firestore_mocks/src/mock_query.dart 35:23 MockQuery.getDocuments
I would expect that there would still be results sorted from fields with values to fields that are null
. I think it works like that with regular firebase queries as well.
https://firebase.google.com/docs/firestore/manage-data/add-data .
I want the set-style list operations.
Add the unit tests from #69 to https://github.com/atn832/cloud_firestore_mocks/blob/master/test_driver/cloud_firestore_behaviors.dart.
This ensures that cloud_firestore_mocks behaves the same as the real Firestore and Firestore emulator.
Looks like the actual Firebase implementation doesn't return a Map<String, dynamic>, so the tests crash when casting to Map<string, dynamic>.
https://gist.github.com/atn832/5dcae11307d4c59de143a3259dbb87cf
flutter: 00:02 +9: Firestore behavior comparison: Document creation by setData (Cloud Firestore) [E]
flutter: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>' in type cast
flutter: Users/anhtuan/git/cloud_firestore_mocks/test_driver/cloud_firestore_behaviors.dart 138:43 main..
await fs.collection("tests").add({"testSubObject": {"key": "abc"}});
var result = await fs.collection("tests").where("testSubObject.key", isEqualTo: "abc").getDocuments();
print(result.documents.length);
Right now this returns 0 documents, whilst in FireStore it returns 1 document.
This has lead to some of our code becoming impossible to test with cloud_firestore_mocks, though I am not sure how many people actually use this feature...
The fix is to add
android.useAndroidX=true
android.enableJetifier=true
to gradle.properties, as explained in https://flutter.dev/docs/development/androidx-migration#how-do-i-know-if-my-project-is-using-androidx.
Error log:
example % flutter drive --target=test_driver/cloud_firestore.dart
Using device Android SDK built for x86.
Starting application: test_driver/cloud_firestore.dart
Installing build/app/outputs/apk/app.apk... 2.8s
[!] Your app isn't using AndroidX.
To avoid potential build failures, you can quickly migrate your app by following the steps on https://goo.gl/CP92wY.
Note: ~/flutter/.pub-cache/hosted/pub.dartlang.org/cloud_firestore-0.13.1+1/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
/[somepath]/cloud_firestore_mocks/example/android/app/src/main/AndroidManifest.xml:22:18-91 Error:
Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:6:5-18:19 to override.
FAILURE: Build failed with an exception.
When I upgraded cloud_firestore: 0.13.4 in my project, one of the existing tests throws the following error:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following NoSuchMethodError was thrown running a test:
Class 'FieldValue' has no instance getter '_delegate'.
Receiver: Instance of 'FieldValue'
Tried calling: _delegate
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 FieldValuePlatform.getDelegate (package:cloud_firestore_platform_interface/src/platform_interface/field_value.dart:19:18)
#2 MockDocumentReference.updateData.<anonymous closure> (package:cloud_firestore_mocks/src/mock_document_reference.dart:57:50)
#3 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:379:8)
#4 MockDocumentReference.updateData (package:cloud_firestore_mocks/src/mock_document_reference.dart:49:10)
#5 _DummyTransaction.update (package:cloud_firestore_mocks/src/cloud_firestore_mocks_base.dart:158:30)
#6 TagsModel.save.<anonymous closure> (package:hitomemo/person_tags_model.dart:185:18)
<asynchronous suspension>
#7 MockFirestoreInstance.runTransaction (package:cloud_firestore_mocks/src/cloud_firestore_mocks_base.dart:63:51)
#8 TagsModel.save (package:hitomemo/person_tags_model.dart:173:39)
#9 main.<anonymous closure> (file:///Users/suztomo/Documents/hitomemo/test/tags_model_test.dart:56:30)
<asynchronous suspension>
...
As in the #39 's test case, updateData should throw PlatformException if there's no document.
flutter: 00:01 +7 -2: Firestore behavior comparison: Nested objects update (Cloud Firestore) [E]
flutter: PlatformException(Error 5, FIRFirestoreErrorDomain, No document to update:
projects/flutter-firestore/databases/(default)/documents/messages/UYK7FkXENdf7mshYHrjR)
This test fails:
await firebase.collection('places').add({
location: GeoPoint(10, 100)
});
final snapshot = await firebase.collection('places').getDocuments();
final document = snapshot.documents.first;
expect(document['location'], equals(GeoPoint(10, 100)); // this works
expect(firebase.dump(), contains('location: ...')); // this does not.
This is so that:
MockQueries
also fire events to the snapshotswhere
calls can be chained: collection.where(some condition).where(some other condition)
It would be great upon documentRefeference.setData
, the document reference has a random String ID within the collection.
My expectation in the following test:
import 'package:cloud_firestore_mocks/cloud_firestore_mocks.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('documentRefeference.setData should set documentId',
(WidgetTester tester) async {
final fakeFirestore = MockFirestoreInstance()..setupFieldValueFactory();
final documentRef1 = fakeFirestore
.collection('users')
.document();
await documentRef1.setData(<String, dynamic>{
'content': 'MockFirestoreInstance is great',
'createdBy': 'Tomo',
});
expect(documentRef1.documentID, isNotNull); // This fails.
final documentRef2 = fakeFirestore
.collection('users')
.document();
await documentRef2.setData(<String, dynamic>{
'content': 'Mock tests are good',
'createdBy': 'Joichiro',
});
expect(documentRef2.documentID, isNotNull);
expect(documentRef2.documentID, isNot(documentRef1.documentID));
});
}
Otherwise I get the following error when running integration tests in Android:
% flutter drive --target=test_driver/cloud_firestore_behaviors.dart
Using device Android SDK built for x86.
Starting application: test_driver/cloud_firestore_behaviors.dart
Installing build/app/outputs/apk/app.apk... 2.9s
[!] Your app isn't using AndroidX.
To avoid potential build failures, you can quickly migrate your app by following the steps on https://goo.gl/CP92wY.
Note: /Users/anhtuan/flutter/.pub-cache/hosted/pub.dartlang.org/cloud_firestore-0.13.5/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
/Users/anhtuan/git/cloud_firestore_mocks/android/app/src/main/AndroidManifest.xml:22:18-91 Error:
Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:6:5-18:19 to override.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:6:5-18:19 to override.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 10s
Running Gradle task 'assembleDebug'...
Running Gradle task 'assembleDebug'... Done 10.9s
AndroidX incompatibilities may have caused this build to fail. Please migrate your app to AndroidX. See https://goo.gl/CP92wY.
Gradle task assembleDebug failed with exit code 1
The fix seems to be to add:
android.enableJetifier=true
android.useAndroidX=true
to https://github.com/atn832/cloud_firestore_mocks/blob/master/android/gradle.properties.
With current implementation, the following test code fails:
final reference1 = firestore.collection('users').document();
final reference2 = firestore.collection('users').document();
await reference1.setData({
'someField': 'someValue',
});
QuerySnapshot querySnapshot = await firestore.collection('users').getDocuments();
// Only reference1 is saved
expect(querySnapshot.documents, hasLength(1));
expect(querySnapshot.documents.first['someField'], 'someValue');
It fails because as of now cloud_firestore_mocks does not distinguish saved and unsaved documents.
I suspect code below should be updated to accommodate this.
@override
DocumentReference document([String path]) {
if (path == null) {
path = _generateAutoId();
}
return MockDocumentReference(path, getSubpath(root, path), root,
getSubpath(snapshotStreamControllerRoot, path));
}
getSubpath(root, path)
creates a document to the root.
Firestore does not natively support SQL's LIKE-style queries. That means, we cannot do something like this:
var docs = await db.collection('products').where('name', like: keyword).getDocuments();
As per official Firebase docs, the solution is to add full-text search through a third-party service.
This is an overkill for simple use cases. Another solution floating around on stackoverflow is to leverage startAt
and endAt
query methods, something like this:
var docs = await db.collection("users").startAt(searchText).endAt(searchText+ "\uf8ff").getDocuments();
cloud_firestore_mocks's MockQuery class does not support these methods at the moment. It'd be cool to have them to be able to test such use cases. Please consider adding them.
In #9, I removed support for FieldValue.delete()
because of a change in cloud_firestore's API.
To restore the feature, I have to figure out how to decode a FieldValue
.
cloud_firestore_platform_interface seems to have done it in its tests:
But maybe they're running tests on a different layer, so I can't do it the same way.
When the fix is properly implemented, this test should pass:
test('FieldValue.delete() deletes key values', () async {
final firestore = MockFirestoreInstance();
firestore.setup();
await firestore.document('root').setData({
'flower': 'rose'
});
await firestore.document('root').setData({
'flower': FieldValue.delete()
});
// expect 'flower' not to be present
});
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.