Coder Social home page Coder Social logo

fake_cloud_firestore's Issues

Support Firestore.runTransaction

(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

runTransaction: check the return value of the map

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,
        };
      });

Missing support for query.arrayContainsAny

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.

documentSnapshot.data should be null before the document is saved

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.

Screen Shot 2020-02-25 at 7 41 05 PM

Support sub collection

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)); 
      }));

Add Equality on MockDocumentReference

    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]

conflict with cloud_firestore plugin

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

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));

DocumentReference.parent() unexpectedly returning null

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');
  });

Real Firebase project prevents .where(arrayContains:) requests

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.

Stubbing deep chaining calls

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"));
      }));
    });
  });
}
  1. Deep Stubbing
    dart-lang/mockito#21

  2. 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);

[ERROR: Bad state] Mocking response with when()

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
      },

setData with keys containing dots should create nested documents

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):

Screen Shot 2020-02-23 at 11 48 49 PM

I might contribute a PR to this issue.

isEqualTo doesn't work when comparing (Mock)DocumentReferences

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));
        },
      ));
  });

Map returned from `MockDocumentSnapshot.data` should be immutable

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.

Support StartAfter(List<dynamic> values)

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']));

Stop extending Mock

Extending Mock makes it possible to call Mockito methods like when even though that's not how the library should be used. See #26.

Firestore.document(...) should fail if the number of segments is not even

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.

https://stackoverflow.com/questions/53918354/inconsistent-flutter-behavior-with-native-ios-exceptions

Maybe assert would suffice.

DocumentReference through FirestoreInstance.document() does not save document

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');
  });

Updating a document should not affect previous snapshots

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.

orderBy throws when field is null

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.

cloud_firestore_behaviors fail when casting to Map<String, dynamic>

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..

Nested object support in MockQuery

  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...

Integration tests in the example project fail to compile on Android

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.

Error: Class 'FieldValue' has no instance getter '_delegate' with cloud_firestore: 0.13.4

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>
...

UpdateData should throw PlatformException if no existing document

As in the #39 's test case, updateData should throw PlatformException if there's no document.

https://github.com/atn832/cloud_firestore_mocks/pull/39/files#diff-bc4857fb99d367ed497ed395a5dfa274R98

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)

MockFirestoreInstance.dump() crashes on GeoPoint

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.

collection.document() to assign a random ID to the document reference

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));
  });
}

Migrate android/ to AndroidX

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.

collection('...').document() should not save a document

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.

Missing support for query.startAt and query.endAt

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.

Restore support for `FieldValue.delete()`

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
    });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.