UNPKG

mockbase

Version:
255 lines 10.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockQuery = exports.QUERY_SNAPSHOT_COMPLETE_EVENT = exports.QUERY_SNAPSHOT_ERROR_EVENT = exports.QUERY_SNAPSHOT_NEXT_EVENT = void 0; const firebase = require("firebase"); const util_1 = require("../util"); const document_snapshot_1 = require("./document-snapshot"); const query_snapshot_1 = require("./query-snapshot"); exports.QUERY_SNAPSHOT_NEXT_EVENT = "snapshot:next"; exports.QUERY_SNAPSHOT_ERROR_EVENT = "snapshot:error"; exports.QUERY_SNAPSHOT_COMPLETE_EVENT = "snapshot:complete"; class MockQuery { constructor(firestore, path, converter) { this.firestore = firestore; this.path = path; this.converter = converter; this.filters = {}; this.noInitialSnapshot = false; } get emitter() { const emitter = this.firestore.collectionEvents.get(this.path) || new util_1.EventEmitter(); this.firestore.collectionEvents.set(this.path, emitter); return emitter; } emitChange() { return __awaiter(this, void 0, void 0, function* () { if (!this.emitter.hasListeners(exports.QUERY_SNAPSHOT_NEXT_EVENT)) { return; } // TODO: this emits even if there wasn't an actual change with the current filters const snapshot = yield this.get(); this.emitter.emit(exports.QUERY_SNAPSHOT_NEXT_EVENT, [snapshot]); }); } setNoInitialSnapshot() { this.noInitialSnapshot = true; return this; } clone() { const query = new MockQuery(this.firestore, this.path, this.converter); Object.assign(query, this); query.filters = Object.assign({}, this.filters); return query; } where(fieldPath, opStr, value) { const key = `where:${fieldPath}:${opStr}:${value}`; const query = this.clone(); query.filters[key] = (doc) => { const fieldValue = doc.get(fieldPath.toString()); switch (opStr) { case "==": return fieldValue == value; case ">": return fieldValue > value; case "<": return fieldValue < value; case ">=": return fieldValue >= value; case "<=": return fieldValue <= value; default: return true; } }; return query; } orderBy(fieldPath, direction = "asc") { if (fieldPath instanceof firebase.firestore.FieldPath) { throw new Error("Ordering a query by FieldPath is not supported"); } const query = this.clone(); query.ordering = { fieldPath, direction }; return query; } limit(limit) { const query = this.clone(); query.docsStartLimit = limit; query.docsEndLimit = undefined; return query; } limitToLast(limit) { const query = this.clone(); query.docsStartLimit = undefined; query.docsEndLimit = limit; return query; } startAt(value, ...rest) { const query = this.clone(); query.addStartFilter({ value, inclusive: true }); return query; } startAfter(value, ...rest) { const query = this.clone(); query.addStartFilter({ value, inclusive: false }); return query; } addStartFilter({ value, inclusive }) { const findStartingIndex = value instanceof document_snapshot_1.MockDocumentSnapshot ? (docs) => docs.findIndex((doc) => { return value.isEqual(doc); }) + (inclusive ? 0 : 1) : (docs, ordering) => docs.findIndex((doc) => { const fieldValue = doc.get(ordering.fieldPath); return inclusive ? fieldValue >= value : fieldValue > value; }); this.filters["start"] = (_doc, index, allDocs) => { const { ordering } = this; if (!ordering) { return true; } const startingIndex = findStartingIndex(allDocs, ordering); return startingIndex <= index; }; } endBefore(value, ...rest) { const query = this.clone(); query.addEndFilter({ value, inclusive: false }); return query; } endAt(value, ...rest) { const query = this.clone(); query.addEndFilter({ value, inclusive: true }); return query; } addEndFilter({ value, inclusive }) { const findEndingIndex = value instanceof document_snapshot_1.MockDocumentSnapshot ? (docs) => docs.findIndex((doc) => { return value.isEqual(doc); }) + (inclusive ? 1 : 0) : (docs, ordering) => docs.length - docs .slice() .reverse() .findIndex((doc) => { const fieldValue = doc.get(ordering.fieldPath); return inclusive ? fieldValue <= value : fieldValue < value; }); this.filters["end"] = (_doc, index, allDocs) => { const { ordering } = this; if (!ordering) { return true; } const endingIndex = findEndingIndex(allDocs, ordering); return endingIndex > index; }; } isEqual(other) { var _a, _b, _c, _d; if (other.firestore !== this.firestore || !(other instanceof MockQuery) || other.path !== this.path || other.converter !== this.converter) { return false; } const filtersMatch = Object.keys(other.filters).join(",") === Object.keys(this.filters).join(","); const limitsMatch = other.docsStartLimit === this.docsStartLimit && other.docsEndLimit === this.docsEndLimit; if (!filtersMatch || !limitsMatch) { return false; } if ((!other.ordering && this.ordering) || (other.ordering && !this.ordering)) { return false; } const orderingMatches = ((_a = other.ordering) === null || _a === void 0 ? void 0 : _a.direction) === ((_b = this.ordering) === null || _b === void 0 ? void 0 : _b.direction) && ((_c = other.ordering) === null || _c === void 0 ? void 0 : _c.fieldPath) === ((_d = this.ordering) === null || _d === void 0 ? void 0 : _d.fieldPath); if (!orderingMatches) { return false; } return true; } compareFunction(a, b) { if (!this.ordering) { return 0; } const direction = this.ordering.direction === "asc" ? 1 : -1; const aValue = a.get(this.ordering.fieldPath); const bValue = b.get(this.ordering.fieldPath); if (aValue == null || bValue == null) { return aValue === bValue ? 0 : (aValue == null ? -1 : 1) * direction; } const result = aValue === bValue ? 0 : aValue < bValue ? -1 : 1; return result * direction; } /** * Gets a list of doc keys that should be fetched by the #get() method. * Made protected so that the collection group implementation can override it. */ getCandidateDocKeys() { return this.firestore.collectionDocuments.get(this.path) || new Set(); } get(options) { if (!this.ordering && this.docsEndLimit) { return Promise.reject(new Error("#orderBy() not specified with #limitToLast()")); } const allDocs = Array.from(this.getCandidateDocKeys().values()); const allSnapshots = allDocs.map((doc) => new document_snapshot_1.MockQueryDocumentSnapshot(this.firestore.doc(doc).withConverter(this.converter), this.firestore.documentData.get(doc))); const actualSnapshots = allSnapshots .sort(this.compareFunction.bind(this)) .filter((snapshot, index) => Object.values(this.filters).every((filter) => filter(snapshot, index, allSnapshots))) .slice(this.docsEndLimit ? -this.docsEndLimit : 0, this.docsStartLimit); return Promise.resolve(new query_snapshot_1.MockQuerySnapshot(this, actualSnapshots)); } onSnapshot(options, onNext, onError, onCompletion) { let actualListeners; if (typeof options === "object") { if (typeof onNext === "object") { actualListeners = onNext; } else if (typeof onNext === "function") { actualListeners = { next: onNext, error: onError, }; } else { actualListeners = options; } } else { actualListeners = { next: options, error: onNext, }; } let prevSnapshot; const actualNext = (snapshot) => { const surrogate = new query_snapshot_1.MockQuerySnapshot(this, snapshot.docs, prevSnapshot); actualListeners.next(surrogate); prevSnapshot = surrogate; }; this.emitter.on(exports.QUERY_SNAPSHOT_NEXT_EVENT, actualNext); actualListeners.error && this.emitter.on(exports.QUERY_SNAPSHOT_ERROR_EVENT, actualListeners.error); if (!this.noInitialSnapshot) { this.get().then((snapshot) => actualNext(snapshot)); } return () => { this.emitter.off(exports.QUERY_SNAPSHOT_NEXT_EVENT, actualNext); actualListeners.error && this.emitter.off(exports.QUERY_SNAPSHOT_ERROR_EVENT, actualListeners.error); }; } withConverter(converter) { const query = this.clone(); query.converter = converter; return query; } } exports.MockQuery = MockQuery; //# sourceMappingURL=query.js.map