Repository: mdowds/python-mock-firestore

Issue:
`!=` operator is not supported in queries
Firestore supports `!=` operators now: https://firebase.google.com/docs/firestore/query-data/queries#query_operators

I get the following error (which goes away if I use the `==` operator instead). 
```
doc_snapshots = [doc_snapshot for doc_snapshot in doc_snapshots
>                    if compare(doc_snapshot._get_by_field_path(field), value)]
E   TypeError: 'NoneType' object is not callable
```

I believe a simple condition just needs to be added here in `compare_func`: https://github.com/mdowds/python-mock-firestore/blob/master/mockfirestore/query.py#L122

Discussion:

Patch:
diff --git a/README.md b/README.md
index f4a7906..ea92013 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ mock_db.reset()
 mock_db = MockFirestore()
 
 # Collections
+mock_db.collections()
 mock_db.collection('users')
 mock_db.collection('users').get()
 mock_db.collection('users').list_documents()
diff --git a/mockfirestore/client.py b/mockfirestore/client.py
index 07fd398..75943bd 100644
--- a/mockfirestore/client.py
+++ b/mockfirestore/client.py
@@ -1,4 +1,4 @@
-from typing import Iterable
+from typing import Iterable, Sequence
 from mockfirestore.collection import CollectionReference
 from mockfirestore.document import DocumentReference, DocumentSnapshot
 from mockfirestore.transaction import Transaction
@@ -44,6 +44,9 @@ class MockFirestore:
                 self._data[name] = {}
             return CollectionReference(self._data, [name])
 
+    def collections(self) -> Sequence[CollectionReference]:
+        return [CollectionReference(self._data, [collection_name]) for collection_name in self._data]
+
     def reset(self):
         self._data = {}
 
diff --git a/mockfirestore/query.py b/mockfirestore/query.py
index 4761a92..7a4618d 100644
--- a/mockfirestore/query.py
+++ b/mockfirestore/query.py
@@ -121,6 +121,8 @@ class Query:
     def _compare_func(self, op: str) -> Callable[[T, T], bool]:
         if op == '==':
             return lambda x, y: x == y
+        elif op == '!=':
+            return lambda x, y: x != y
         elif op == '<':
             return lambda x, y: x < y
         elif op == '<=':


Test patch:
diff --git a/tests/test_collection_reference.py b/tests/test_collection_reference.py
index 59397be..ed34c8b 100644
--- a/tests/test_collection_reference.py
+++ b/tests/test_collection_reference.py
@@ -81,6 +81,16 @@ class TestCollectionReference(TestCase):
         docs = list(fs.collection('foo').where('valid', '==', True).stream())
         self.assertEqual({'valid': True}, docs[0].to_dict())
 
+    def test_collection_whereNotEquals(self):
+        fs = MockFirestore()
+        fs._data = {'foo': {
+            'first': {'count': 1},
+            'second': {'count': 5}
+        }}
+
+        docs = list(fs.collection('foo').where('count', '!=', 1).stream())
+        self.assertEqual({'count': 5}, docs[0].to_dict())
+
     def test_collection_whereLessThan(self):
         fs = MockFirestore()
         fs._data = {'foo': {
diff --git a/tests/test_mock_client.py b/tests/test_mock_client.py
index 227c5c7..7f99414 100644
--- a/tests/test_mock_client.py
+++ b/tests/test_mock_client.py
@@ -16,4 +16,18 @@ class TestMockFirestore(TestCase):
         expected_doc_snapshot = doc.get().to_dict()
         self.assertEqual(returned_doc_snapshot, expected_doc_snapshot)
 
+    def test_client_collections(self):
+        fs = MockFirestore()
+        fs._data = {
+            'foo': {
+                'first': {'id': 1},
+                'second': {'id': 2}
+            },
+            'bar': {}
+        }
+        collections = fs.collections()
+        expected_collections = fs._data
 
+        self.assertEqual(len(collections), len(expected_collections))
+        for collection in collections:
+            self.assertTrue(collection._path[0] in expected_collections)