Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/support mocking server timestamp #287

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 11 additions & 4 deletions 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;
Expand Down Expand Up @@ -35,11 +36,17 @@ class FakeFirebaseFirestore implements FirebaseFirestore {
final BehaviorSubject<Map<String, dynamic>?> authObject =
BehaviorSubject<Map<String, dynamic>?>();
final FakeFirebaseSecurityRules securityRules;
final Clock _clock;

FakeFirebaseFirestore(
{Stream<Map<String, dynamic>?>? authObject, String? securityRules})
: securityRules =
FakeFirebaseSecurityRules(securityRules ?? allowAllDescription) {
Clock get clock => _clock;

FakeFirebaseFirestore({
Stream<Map<String, dynamic>?>? 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);
Expand Down
4 changes: 4 additions & 0 deletions lib/src/mock_document_reference.dart
Expand Up @@ -163,6 +163,10 @@ class MockDocumentReference<T extends Object?>
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);
Expand Down
17 changes: 14 additions & 3 deletions 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';
Expand All @@ -6,17 +7,27 @@ abstract class FakeFieldValue {
const FakeFieldValue();

static const delete = FieldValueDelete();
static const serverTimestamp = FieldValueServerTimestamp();
static final serverTimestamp = FieldValueServerTimestamp();

void updateDocument(Map<String, dynamic> 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<String, dynamic> document, String key) {
document[key] = Timestamp.now();
document[key] = now;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the Clock always set up, you can rewrite this as

document[key] = clock.now()

https://pub.dev/documentation/clock/latest/clock/Clock/now.html

}
}

Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Expand Up @@ -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:
Expand Down
16 changes: 16 additions & 0 deletions 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';
Expand Down Expand Up @@ -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
Expand Down