firestore-jest-mock
Advanced tools
Comparing version 0.14.0 to 0.15.0
@@ -19,2 +19,9 @@ const { FakeFirestore } = require('firestore-jest-mock'); | ||
address: { street: '742 Evergreen Terrace' }, | ||
// May 12, 1956. Conveniently, a negative number | ||
birthdate: { | ||
seconds: -430444800, | ||
nanoseconds: 0, | ||
}, | ||
// Test a pre-constructed Timestamp | ||
timestamp: new FakeFirestore.Timestamp(123, 456), | ||
}, | ||
@@ -344,2 +351,12 @@ { id: 'krusty', name: 'Krusty', occupation: 'clown' }, | ||
}); | ||
test('it properly converts timestamps', () => | ||
db() | ||
.doc('characters/homer') | ||
.get() | ||
.then(record => { | ||
expect(record.id).toEqual('homer'); | ||
const data = record.data(); | ||
expect(typeof data.birthdate.toDate).toEqual('function'); | ||
})); | ||
}); |
@@ -7,2 +7,4 @@ const { FakeFirestore } = require('firestore-jest-mock'); | ||
} = require('firestore-jest-mock/mocks/firestore'); | ||
const admin = require('firebase-admin'); | ||
const ref = admin.firestore.Timestamp; | ||
@@ -53,3 +55,3 @@ describe('Timestamp mock', () => { | ||
expect(timestamp.toMillis()).toBe(now.getMilliseconds()); | ||
expect(timestamp.toMillis()).toBe(0); // second call should be the original | ||
expect(timestamp.toMillis()).toBe(40000); // second call should be the original (40s) | ||
expect(mockTimestampToMillis).toHaveBeenCalledTimes(2); | ||
@@ -87,2 +89,10 @@ }); | ||
}); | ||
test('it handles negative seconds', () => { | ||
// Since this is a mock (and I'm bad with time maths) we don't expect nanosecond accuracy | ||
const timestamp = FakeFirestore.Timestamp.fromMillis(-54001); | ||
const rts = ref.fromMillis(-54001); | ||
expect(timestamp.seconds).toBe(rts.seconds); | ||
expect(timestamp.nanoseconds).toBe(rts.nanoseconds); | ||
}); | ||
}); |
@@ -35,3 +35,3 @@ const mockCollectionGroup = jest.fn(); | ||
constructor(stubbedDatabase = {}, options = {}) { | ||
this.database = stubbedDatabase; | ||
this.database = timestamp.convertTimestamps(stubbedDatabase); | ||
this.query = new query.Query('', this); | ||
@@ -38,0 +38,0 @@ this.options = options; |
@@ -22,13 +22,7 @@ const mockTimestampToDate = jest.fn(); | ||
toDate() { | ||
const d = new Date(0); | ||
d.setTime(this.seconds * 1000); | ||
d.setMilliseconds(this.nanoseconds / 1000000); | ||
return mockTimestampToDate(...arguments) || d; | ||
return mockTimestampToDate(...arguments) || new Date(this._toMillis()); | ||
} | ||
toMillis() { | ||
const d = new Date(0); | ||
d.setSeconds(this.seconds); | ||
d.setMilliseconds(this.nanoseconds / 1000000); | ||
return mockTimestampToMillis(...arguments) || d.getMilliseconds(); | ||
return mockTimestampToMillis(...arguments) || this._toMillis(); | ||
} | ||
@@ -41,14 +35,20 @@ | ||
static fromDate(date) { | ||
return ( | ||
mockTimestampFromDate(...arguments) || | ||
new Timestamp(date.getTime() * 0.001, date.getMilliseconds() * 1000000) | ||
); | ||
return mockTimestampFromDate(...arguments) || Timestamp._fromMillis(date.getTime()); | ||
} | ||
static fromMillis(millis) { | ||
const d = new Date(0); | ||
d.setMilliseconds(millis); | ||
return mockTimestampFromMillis(...arguments) || Timestamp.fromDate(d); | ||
return mockTimestampFromMillis(...arguments) || Timestamp._fromMillis(millis); | ||
} | ||
static _fromMillis(millis) { | ||
const seconds = Math.floor(millis / 1000); | ||
const nanoseconds = 1000000 * (millis - seconds * 1000); | ||
return new Timestamp(seconds, nanoseconds); | ||
} | ||
// Dates only return whole-number millis | ||
_toMillis() { | ||
return this.seconds * 1000 + Math.round(this.nanoseconds / 1000000); | ||
} | ||
static now() { | ||
@@ -60,4 +60,42 @@ const now = new Date(); | ||
// | ||
// Search data for possible timestamps and convert to class. | ||
function convertTimestamps(data, path = []) { | ||
if (!data) { | ||
return data; | ||
} | ||
// we need to avoid self-referencing DB's (can happen on db.get) | ||
// Check we have not looped. If we have, backout | ||
if (path.includes(data)) { | ||
return; | ||
} | ||
// Check if this object is or contains a timestamp | ||
if (typeof data === 'object') { | ||
const keys = Object.keys(data); | ||
// if it is a timestamp, convert to the appropriate class | ||
if ( | ||
keys.length === 2 && | ||
keys.find(k => k === 'seconds') && | ||
keys.find(k => k === 'nanoseconds') | ||
) { | ||
return new Timestamp(data.seconds, data.nanoseconds); | ||
} else { | ||
// Search recursively for any timestamps in this data | ||
// Keep track of the path taken, so we can avoid self-referencing loops | ||
// Note: running full-setup.test.js will fail without this check | ||
// add console.log(`${path} => ${k}`); to see how this class is added as a property | ||
path.push(data); | ||
keys.forEach(k => { | ||
data[k] = convertTimestamps(data[k], path); | ||
}); | ||
path.pop(); | ||
} | ||
} | ||
return data; | ||
} | ||
module.exports = { | ||
Timestamp, | ||
convertTimestamps, | ||
mocks: { | ||
@@ -64,0 +102,0 @@ mockTimestampToDate, |
{ | ||
"name": "firestore-jest-mock", | ||
"version": "0.14.0", | ||
"version": "0.15.0", | ||
"description": "Jest helper for mocking Google Cloud Firestore", | ||
@@ -5,0 +5,0 @@ "author": "", |
194614
3656