From 78d29be582cfefce53766cdd531a60263af1ce2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96rjan=20Fors?= Date: Fri, 1 Mar 2019 11:09:23 +0100 Subject: [PATCH 1/4] Add Timestamp --- src/timestamp.js | 19 +++++++++++++++++++ test/unit/timestamp.js | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/timestamp.js create mode 100644 test/unit/timestamp.js diff --git a/src/timestamp.js b/src/timestamp.js new file mode 100644 index 00000000..f07f8558 --- /dev/null +++ b/src/timestamp.js @@ -0,0 +1,19 @@ +'use strict'; + +function Timestamp(seconds, nanoseconds) { + this.seconds = seconds; + this.nanoseconds = nanoseconds; +} + +Timestamp.fromDate = function(date) { + var sec = Math.floor(date.getTime() / 1000); + var ns = (date.getTime() % 1000) * 1000 * 1000; + return new Timestamp(sec, ns); +}; + +Timestamp.prototype.toDate = function () { + var millis = this.seconds * 1000 + this.nanoseconds / (1000 * 1000); + return new Date(millis); +}; + +module.exports = Timestamp; diff --git a/test/unit/timestamp.js b/test/unit/timestamp.js new file mode 100644 index 00000000..5574064b --- /dev/null +++ b/test/unit/timestamp.js @@ -0,0 +1,23 @@ +'use strict'; + +var expect = require('chai').use(require('sinon-chai')).expect; +var sinon = require('sinon'); +var Timestamp = require('../../src/timestamp'); + +describe('Timestamp', function () { + describe('fromDate', function () { + it('should convert from date', function () { + var date = new Date('2009-02-13T23:31:30.123456789Z'); + var timestamp = Timestamp.fromDate(date); + expect(timestamp.seconds).to.equal(1234567890); + expect(timestamp.nanoseconds).to.equal(123000000); + }); + }); + describe('#toDate', function () { + it('should convert to date', function () { + var ts = new Timestamp(1234567890, 123456789); + var date = ts.toDate(); + expect(date.toISOString()).to.equal('2009-02-13T23:31:30.123Z'); + }); + }); +}); From c0aee179ce65d8d778f595c0746c28e4e3939a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96rjan=20Fors?= Date: Fri, 1 Mar 2019 11:09:49 +0100 Subject: [PATCH 2/4] Resolve create() with the write time --- src/firestore-document.js | 8 ++++++-- src/write-result.js | 7 +++++++ test/unit/firestore-document.js | 4 +++- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 src/write-result.js diff --git a/src/firestore-document.js b/src/firestore-document.js index ba51ef09..e3e2cae2 100644 --- a/src/firestore-document.js +++ b/src/firestore-document.js @@ -6,8 +6,10 @@ var Promise = require('rsvp').Promise; var autoId = require('firebase-auto-ids'); var DocumentSnapshot = require('./firestore-document-snapshot'); var Queue = require('./queue').Queue; +var Timestamp = require('./timestamp'); var utils = require('./utils'); var validate = require('./validators'); +var WriteResult = require('./write-result'); function MockFirestoreDocument(path, data, parent, name, CollectionReference) { this.ref = this; @@ -108,9 +110,11 @@ MockFirestoreDocument.prototype.create = function (data, callback) { var base = self._getData(); err = err || self._validateDoesNotExist(base); - if (err === null) { + if (err === null) { + var time = Timestamp.fromDate(new Date()); + var result = new WriteResult(time); self._dataChanged(data); - resolve(); + resolve(result); } else { if (callback) { callback(err); diff --git a/src/write-result.js b/src/write-result.js new file mode 100644 index 00000000..d7c98689 --- /dev/null +++ b/src/write-result.js @@ -0,0 +1,7 @@ +'use strict'; + +function WriteResult(writeTime) { + this.writeTime = writeTime; +} + +module.exports = WriteResult; diff --git a/test/unit/firestore-document.js b/test/unit/firestore-document.js index 59d91927..2823033d 100644 --- a/test/unit/firestore-document.js +++ b/test/unit/firestore-document.js @@ -96,7 +96,9 @@ describe('MockFirestoreDocument', function () { it('creates a new doc', function (done) { var createDoc = db.doc('createDoc'); - createDoc.create({prop: 'title'}); + createDoc.create({prop: 'title'}).then(function (result) { + expect(result).to.have.property('writeTime'); + }).catch(done); createDoc.get().then(function (snap) { expect(snap.exists).to.equal(true); From e77ea3e030744c69535b934b3b8c45025de711d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96rjan=20Fors?= Date: Sat, 2 Mar 2019 19:31:26 +0100 Subject: [PATCH 3/4] Move server clock handling out to utils --- src/firebase.js | 15 +++++---------- src/utils.js | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/firebase.js b/src/firebase.js index 36de4cbc..50dd97de 100644 --- a/src/firebase.js +++ b/src/firebase.js @@ -44,17 +44,12 @@ MockFirebase.ServerValue = { } }; -var getServerTime, defaultClock; -getServerTime = defaultClock = function () { - return new Date().getTime(); -}; - MockFirebase.setClock = function (fn) { - getServerTime = fn; + utils.setServerClock(fn); }; MockFirebase.restoreClock = function () { - getServerTime = defaultClock; + utils.restoreServerClock(); }; MockFirebase.autoId = function () { @@ -449,7 +444,7 @@ MockFirebase.prototype._dataChanged = function (unparsedData) { var data = utils.cleanData(unparsedData); if (utils.isServerTimestamp(data)) { - data = getServerTime(); + data = utils.getServerTime(); } if (pri !== this.priority) { @@ -475,7 +470,7 @@ MockFirebase.prototype._dataChanged = function (unparsedData) { keysToChange.forEach(function (key) { var childData = unparsedData[key]; if (utils.isServerTimestamp(childData)) { - childData = getServerTime(); + childData = utils.getServerTime(); } self._updateOrAdd(key, childData, events); }); @@ -493,7 +488,7 @@ MockFirebase.prototype._dataChanged = function (unparsedData) { MockFirebase.prototype._priChanged = function (newPriority) { if (utils.isServerTimestamp(newPriority)) { - newPriority = getServerTime(); + newPriority = utils.getServerTime(); } this.priority = newPriority; if (this.parent) { diff --git a/src/utils.js b/src/utils.js index df4d6008..0b5bcd72 100644 --- a/src/utils.js +++ b/src/utils.js @@ -75,6 +75,24 @@ exports.priorityComparator = function priorityComparator(a, b) { return 0; }; +var serverClock, defaultClock; + +serverClock = defaultClock = function () { + return new Date().getTime(); +}; + +exports.getServerTime = function getServerTime() { + return serverClock(); +}; + +exports.setServerClock = function setServerTime(fn) { + serverClock = fn; +}; + +exports.restoreServerClock = function restoreServerTime() { + serverClock = defaultClock; +}; + exports.isServerTimestamp = function isServerTimestamp(data) { return _.isObject(data) && data['.sv'] === 'timestamp'; }; From 4563e8f876f009ffd3193b9a6201960ae1f3ea9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96rjan=20Fors?= Date: Sat, 2 Mar 2019 19:46:25 +0100 Subject: [PATCH 4/4] Use serverClock in WriteResult --- src/firestore-document.js | 2 +- src/timestamp.js | 8 ++++++-- test/unit/firestore-document.js | 5 +++++ test/unit/timestamp.js | 7 +++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/firestore-document.js b/src/firestore-document.js index e3e2cae2..2656a687 100644 --- a/src/firestore-document.js +++ b/src/firestore-document.js @@ -111,7 +111,7 @@ MockFirestoreDocument.prototype.create = function (data, callback) { var base = self._getData(); err = err || self._validateDoesNotExist(base); if (err === null) { - var time = Timestamp.fromDate(new Date()); + var time = Timestamp.fromMillis(utils.getServerTime()); var result = new WriteResult(time); self._dataChanged(data); resolve(result); diff --git a/src/timestamp.js b/src/timestamp.js index f07f8558..312eb974 100644 --- a/src/timestamp.js +++ b/src/timestamp.js @@ -6,8 +6,12 @@ function Timestamp(seconds, nanoseconds) { } Timestamp.fromDate = function(date) { - var sec = Math.floor(date.getTime() / 1000); - var ns = (date.getTime() % 1000) * 1000 * 1000; + return Timestamp.fromMillis(date.getTime()); +}; + +Timestamp.fromMillis = function(ms) { + var sec = Math.floor(ms / 1000); + var ns = (ms % 1000) * 1000 * 1000; return new Timestamp(sec, ns); }; diff --git a/test/unit/firestore-document.js b/test/unit/firestore-document.js index 2823033d..e4668a92 100644 --- a/test/unit/firestore-document.js +++ b/test/unit/firestore-document.js @@ -10,6 +10,7 @@ chai.use(require('sinon-chai')); var expect = chai.expect; var _ = require('../../src/lodash'); var Firestore = require('../../').MockFirestore; +var Firebase = require('../../').MockFirebase; describe('MockFirestoreDocument', function () { @@ -94,10 +95,14 @@ describe('MockFirestoreDocument', function () { describe('#create', function () { it('creates a new doc', function (done) { + Firebase.setClock(function() { + return 1234567890123; + }); var createDoc = db.doc('createDoc'); createDoc.create({prop: 'title'}).then(function (result) { expect(result).to.have.property('writeTime'); + expect(result.writeTime.seconds).to.equal(1234567890); }).catch(done); createDoc.get().then(function (snap) { diff --git a/test/unit/timestamp.js b/test/unit/timestamp.js index 5574064b..3e0ea5b8 100644 --- a/test/unit/timestamp.js +++ b/test/unit/timestamp.js @@ -13,6 +13,13 @@ describe('Timestamp', function () { expect(timestamp.nanoseconds).to.equal(123000000); }); }); + describe('fromMillis', function () { + it('should convert from milliseconds', function () { + var timestamp = Timestamp.fromMillis(1234567890123); + expect(timestamp.seconds).to.equal(1234567890); + expect(timestamp.nanoseconds).to.equal(123000000); + }); + }); describe('#toDate', function () { it('should convert to date', function () { var ts = new Timestamp(1234567890, 123456789);