firestore-jest-mock
Advanced tools
Comparing version 0.11.1 to 0.12.0
@@ -66,3 +66,3 @@ const { mockGoogleCloudFirestore } = require('firestore-jest-mock'); | ||
expect(mockAdd).toHaveBeenCalled(); | ||
expect(docRef).toHaveProperty('id', 'abc123'); | ||
expect(docRef).toHaveProperty('id'); | ||
}); | ||
@@ -69,0 +69,0 @@ }); |
@@ -87,3 +87,3 @@ const { mockFirebase } = require('firestore-jest-mock'); | ||
expect(mockAdd).toHaveBeenCalled(); | ||
expect(docRef).toHaveProperty('id', 'abc123'); | ||
expect(docRef).toHaveProperty('id'); | ||
}); | ||
@@ -336,3 +336,3 @@ }); | ||
expect(mockGet).toHaveBeenCalled(); | ||
expect(record).toHaveProperty('id', 'abc123'); | ||
expect(record).toHaveProperty('id'); | ||
expect(record.data).toBeInstanceOf(Function); | ||
@@ -339,0 +339,0 @@ }); |
@@ -286,8 +286,9 @@ const { FakeFirestore } = require('firestore-jest-mock'); | ||
expect.assertions(1); | ||
// As per docs, should have 'random' ID, but we'll use our usual 'abc123' for now. | ||
// See https://firebase.google.com/docs/reference/js/firebase.firestore.CollectionReference#doc | ||
// "If no path is specified, an automatically-generated unique ID will be used for the returned DocumentReference." | ||
const newDoc = db.collection('foo').doc(); | ||
expect(newDoc.path).toBe('database/foo/abc123'); | ||
const col = db.collection('characters'); | ||
const newDoc = col.doc(); | ||
const otherIds = col.records().map(doc => doc.id); | ||
expect(otherIds).not.toContainEqual(newDoc.id); | ||
}); | ||
}); |
{ | ||
"typescript.tsdk": "node_modules/typescript/lib" | ||
} | ||
} |
@@ -0,1 +1,4 @@ | ||
import type { FirebaseUser, FakeAuth } from './auth'; | ||
import type { FakeFirestore } from './firestore'; | ||
export interface DatabaseDocument { | ||
@@ -15,3 +18,3 @@ id: string; | ||
database?: DatabaseCollections; | ||
currentUser?: unknown; // TODO: User, to be defined later | ||
currentUser?: FirebaseUser; | ||
} | ||
@@ -28,4 +31,4 @@ | ||
}; | ||
auth(): unknown; // TODO: Auth, to be defined later | ||
firestore(): unknown; // TODO: FakeFirestore, to be defined later | ||
auth(): FakeAuth; | ||
firestore(): FakeFirestore; | ||
} | ||
@@ -32,0 +35,0 @@ |
@@ -29,2 +29,4 @@ const mockCollectionGroup = jest.fn(); | ||
const _randomId = () => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(); | ||
class FakeFirestore { | ||
@@ -55,2 +57,3 @@ constructor(stubbedDatabase = {}, options = {}) { | ||
return { | ||
_ref: this, | ||
delete() { | ||
@@ -60,8 +63,10 @@ mockBatchDelete(...arguments); | ||
}, | ||
set() { | ||
set(doc, data, setOptions = {}) { | ||
mockBatchSet(...arguments); | ||
this._ref._updateData(doc.path, data, setOptions.merge); | ||
return this; | ||
}, | ||
update() { | ||
update(doc, data) { | ||
mockBatchUpdate(...arguments); | ||
this._ref._updateData(doc.path, data, true); | ||
return this; | ||
@@ -122,2 +127,48 @@ }, | ||
} | ||
_updateData(path, object, merge) { | ||
// Do not update unless explicity set to mutable. | ||
if (!this.options.mutable) { | ||
return; | ||
} | ||
// note: this logic could be deduplicated | ||
const pathArray = path | ||
.replace(/^\/+/, '') | ||
.split('/') | ||
.slice(1); | ||
// Must be document-level, so even-numbered elements | ||
if (pathArray.length % 2) { | ||
throw new Error('The path array must be document-level'); | ||
} | ||
// The parent entry is the id of the document | ||
const docId = pathArray.pop(); | ||
// Find the parent of docId. Run through the path, creating missing entries | ||
const parent = pathArray.reduce((last, entry, index) => { | ||
const isCollection = index % 2 === 0; | ||
if (isCollection) { | ||
return last[entry] || (last[entry] = []); | ||
} else { | ||
const existingDoc = last.find(doc => doc.id === entry); | ||
if (existingDoc) { | ||
// return _collections, creating it if it doesn't already exist | ||
return existingDoc._collections || (existingDoc._collections = {}); | ||
} | ||
const _collections = {}; | ||
last.push({ id: entry, _collections }); | ||
return _collections; | ||
} | ||
}, this.database); | ||
// parent should now be an array of documents | ||
// Replace existing data, if it's there, or add to the end of the array | ||
const oldIndex = parent.findIndex(doc => doc.id === docId); | ||
parent[oldIndex >= 0 ? oldIndex : parent.length] = { | ||
...(merge ? parent[oldIndex] : undefined), | ||
...object, | ||
id: docId, | ||
}; | ||
} | ||
} | ||
@@ -165,2 +216,3 @@ | ||
} else { | ||
// eslint-disable-next-line no-unused-vars | ||
[options, callback, errorCallback] = arguments; | ||
@@ -186,40 +238,4 @@ } | ||
query.mocks.mockGet(...arguments); | ||
// Ignore leading slash | ||
const pathArray = this.path.replace(/^\/+/, '').split('/'); | ||
pathArray.shift(); // drop 'database'; it's always first | ||
let requestedRecords = this.firestore.database[pathArray.shift()]; | ||
let document = null; | ||
if (requestedRecords) { | ||
const documentId = pathArray.shift(); | ||
document = requestedRecords.find(record => record.id === documentId); | ||
} else { | ||
return Promise.resolve({ exists: false, data: () => undefined, id: this.id }); | ||
} | ||
for (let index = 0; index < pathArray.length; index += 2) { | ||
const collectionId = pathArray[index]; | ||
const documentId = pathArray[index + 1]; | ||
if (!document || !document._collections) { | ||
return Promise.resolve({ exists: false, data: () => undefined, id: this.id }); | ||
} | ||
requestedRecords = document._collections[collectionId] || []; | ||
if (requestedRecords.length === 0) { | ||
return Promise.resolve({ exists: false, data: () => undefined, id: this.id }); | ||
} | ||
document = requestedRecords.find(record => record.id === documentId); | ||
if (!document) { | ||
return Promise.resolve({ exists: false, data: () => undefined, id: this.id }); | ||
} | ||
// +2 skips to next document | ||
} | ||
if (!!document || false) { | ||
document._ref = this; | ||
return Promise.resolve(buildDocFromHash(document)); | ||
} | ||
return Promise.resolve({ exists: false, data: () => undefined, id: this.id, ref: this }); | ||
const data = this._get(); | ||
return Promise.resolve(data); | ||
} | ||
@@ -229,7 +245,11 @@ | ||
mockUpdate(...arguments); | ||
if (this._get().exists) { | ||
this.firestore._updateData(this.path, object, true); | ||
} | ||
return Promise.resolve(buildDocFromHash({ ...object, _ref: this })); | ||
} | ||
set(object) { | ||
set(object, setOptions = {}) { | ||
mockSet(...arguments); | ||
this.firestore._updateData(this.path, object, setOptions.merge); | ||
return Promise.resolve(buildDocFromHash({ ...object, _ref: this })); | ||
@@ -266,2 +286,43 @@ } | ||
_get() { | ||
// Ignore leading slash | ||
const pathArray = this.path.replace(/^\/+/, '').split('/'); | ||
pathArray.shift(); // drop 'database'; it's always first | ||
let requestedRecords = this.firestore.database[pathArray.shift()]; | ||
let document = null; | ||
if (requestedRecords) { | ||
const documentId = pathArray.shift(); | ||
document = requestedRecords.find(record => record.id === documentId); | ||
} else { | ||
return { exists: false, data: () => undefined, id: this.id }; | ||
} | ||
for (let index = 0; index < pathArray.length; index += 2) { | ||
const collectionId = pathArray[index]; | ||
const documentId = pathArray[index + 1]; | ||
if (!document || !document._collections) { | ||
return { exists: false, data: () => undefined, id: this.id }; | ||
} | ||
requestedRecords = document._collections[collectionId] || []; | ||
if (requestedRecords.length === 0) { | ||
return { exists: false, data: () => undefined, id: this.id }; | ||
} | ||
document = requestedRecords.find(record => record.id === documentId); | ||
if (!document) { | ||
return { exists: false, data: () => undefined, id: this.id }; | ||
} | ||
// +2 skips to next document | ||
} | ||
if (!!document || false) { | ||
document._ref = this; | ||
return buildDocFromHash(document); | ||
} | ||
return { exists: false, data: () => undefined, id: this.id, ref: this }; | ||
} | ||
withConverter() { | ||
@@ -292,8 +353,10 @@ query.mocks.mockWithConverter(...arguments); | ||
add() { | ||
add(object) { | ||
mockAdd(...arguments); | ||
return Promise.resolve(new FakeFirestore.DocumentReference('abc123', this)); | ||
const newDoc = new FakeFirestore.DocumentReference(_randomId(), this); | ||
this.firestore._updateData(newDoc.path, object); | ||
return Promise.resolve(newDoc); | ||
} | ||
doc(id = 'abc123') { | ||
doc(id = _randomId()) { | ||
mockDoc(id); | ||
@@ -300,0 +363,0 @@ return new FakeFirestore.DocumentReference(id, this, this.firestore); |
@@ -18,2 +18,3 @@ const defaultOptions = require('./helpers/defaultMockOptions'); | ||
Transaction: FakeFirestore.Transaction, | ||
/** @type {Firestore.constructor} */ | ||
Firestore, | ||
@@ -20,0 +21,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
import type { FakeFirestore } from '../firestore'; | ||
import type { FakeFirestore, FakeFirestoreDatabase } from '../firestore'; | ||
@@ -7,3 +7,3 @@ export type DocumentData = { [field: string]: unknown }; | ||
id?: string; | ||
_collections: unknown; // TODO: FakeFirestore subcollections, to be defined later | ||
_collections: FakeFirestoreDatabase; | ||
_ref: typeof FakeFirestore.DocumentReference; | ||
@@ -10,0 +10,0 @@ } |
export const includeIdsInData: boolean; | ||
export const mutable: boolean; |
{ | ||
"name": "firestore-jest-mock", | ||
"version": "0.11.1", | ||
"version": "0.12.0", | ||
"description": "Jest helper for mocking Google Cloud Firestore", | ||
@@ -5,0 +5,0 @@ "author": "", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
158901
51
2720