diff --git a/lib/src/fake_cloud_firestore_instance.dart b/lib/src/fake_cloud_firestore_instance.dart index 4c09961..5cc9bbf 100644 --- a/lib/src/fake_cloud_firestore_instance.dart +++ b/lib/src/fake_cloud_firestore_instance.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:clock/clock.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart' as firestore_interface; @@ -35,11 +36,17 @@ class FakeFirebaseFirestore implements FirebaseFirestore { final BehaviorSubject?> authObject = BehaviorSubject?>(); final FakeFirebaseSecurityRules securityRules; + final Clock _clock; - FakeFirebaseFirestore( - {Stream?>? authObject, String? securityRules}) - : securityRules = - FakeFirebaseSecurityRules(securityRules ?? allowAllDescription) { + Clock get clock => _clock; + + FakeFirebaseFirestore({ + Stream?>? authObject, + String? securityRules, + Clock? clock, + }) : securityRules = + FakeFirebaseSecurityRules(securityRules ?? allowAllDescription), + _clock = clock ?? Clock() { // Wrap the Stream in a BehaviorSubject to access its latest value on // demand. authObject?.listen(this.authObject.add); diff --git a/lib/src/mock_document_reference.dart b/lib/src/mock_document_reference.dart index 10e1dd3..9bc9b12 100644 --- a/lib/src/mock_document_reference.dart +++ b/lib/src/mock_document_reference.dart @@ -163,6 +163,10 @@ class MockDocumentReference final valueDelegate = FieldValuePlatform.getDelegate(value); final fieldValuePlatform = valueDelegate as MockFieldValuePlatform; final fieldValue = fieldValuePlatform.value; + // setup the fake Clock for FieldValueServerTimestamp + if (fieldValue is FieldValueServerTimestamp) { + fieldValue.clock = _firestore.clock; + } fieldValue.updateDocument(document, key); } else { document[key] = transformValue(value, timestampFromDateTime); diff --git a/lib/src/mock_field_value_platform.dart b/lib/src/mock_field_value_platform.dart index 79f02aa..ac94282 100644 --- a/lib/src/mock_field_value_platform.dart +++ b/lib/src/mock_field_value_platform.dart @@ -1,3 +1,4 @@ +import 'package:clock/clock.dart'; import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; import 'package:fake_cloud_firestore/src/util.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; @@ -6,17 +7,27 @@ abstract class FakeFieldValue { const FakeFieldValue(); static const delete = FieldValueDelete(); - static const serverTimestamp = FieldValueServerTimestamp(); + static final serverTimestamp = FieldValueServerTimestamp(); void updateDocument(Map document, String key); } class FieldValueServerTimestamp extends FakeFieldValue { - const FieldValueServerTimestamp(); + Clock? _clock; + + set clock(Clock clock) { + _clock = clock; + } + + Timestamp get now { + return Timestamp.fromDate(_clock?.now() ?? DateTime.now()); + } + + FieldValueServerTimestamp(); @override void updateDocument(Map document, String key) { - document[key] = Timestamp.now(); + document[key] = now; } } diff --git a/pubspec.yaml b/pubspec.yaml index 7d3db14..a924397 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,6 +20,7 @@ dependencies: fake_firebase_security_rules: ^0.5.2 rx: ^0.3.0 equatable: ^2.0.5 + clock: ^1.1.1 dev_dependencies: flutter_test: diff --git a/test/fake_cloud_firestore_test.dart b/test/fake_cloud_firestore_test.dart index c2de7e1..d660fa3 100644 --- a/test/fake_cloud_firestore_test.dart +++ b/test/fake_cloud_firestore_test.dart @@ -1,3 +1,4 @@ +import 'package:clock/clock.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:flutter/services.dart'; @@ -683,6 +684,21 @@ void main() { expect(timeDiff, lessThan(1000)); }); + test('FieldValue.serverTimestamp() sets the time with fixed time', + () async { + final fixedTimestamp = Timestamp.fromMicrosecondsSinceEpoch(100); + final fakeClock = Clock.fixed(fixedTimestamp.toDate()); + final firestore = FakeFirebaseFirestore(clock: fakeClock); + await firestore.collection('users').doc(uid).set({ + 'created': FieldValue.serverTimestamp(), + }); + final users = await firestore.collection('users').get(); + final bob = users.docs.first; + expect(bob.get('created'), isNotNull); + final bobCreated = bob.get('created') as Timestamp; + expect(bobCreated, fixedTimestamp); + }); + test('FieldValue.increment() increments number', () async { final firestore = FakeFirebaseFirestore(); // Empty document before update