Documentation
Complete reference for FakeAdapter, deterministic model tests, and in-memory query subscriptions.
@dharayush7/fireclass-core/testing exports the in-memory FakeAdapter. It
implements the core adapter contract without Firebase credentials, a network,
or an emulator.
import { Collection, defineBaseModel } from "@dharayush7/fireclass-core";
import {
FakeAdapter,
type FakeAdapterOptions,
} from "@dharayush7/fireclass-core/testing";| Export | Kind | Purpose |
|---|---|---|
FakeAdapter | Class | In-memory FirestoreAdapter implementation. |
FakeAdapterOptions | Interface | Seed data and deterministic id configuration. |
The testing subpath is separate from the core root export.
interface FakeAdapterOptions {
seed?: Record<
string,
Record<string, Record<string, unknown>>
>;
idFactory?: () => string;
}Seed shape is collection -> document id -> document data.
const adapter = new FakeAdapter({
seed: {
users: {
ada: { name: "Ada", active: true },
grace: { name: "Grace", active: false },
},
},
idFactory: () => "generated_id",
});Without idFactory, generated ids are id_1, id_2, and so on for that
adapter instance. Seed and returned data are cloned with structuredClone so
tests cannot mutate the internal store by reference.
class FakeAdapter implements FirestoreAdapter {
constructor(options?: FakeAdapterOptions);
}Bind it to models with defineBaseModel:
const adapter = new FakeAdapter();
const BaseModel = defineBaseModel(adapter);
@Collection("todos")
class Todo extends BaseModel<Todo> {
title!: string;
done!: boolean;
}Create a fresh adapter and model binding per test when isolation matters.
| Method | Behavior |
|---|---|
add | Clones and stores data under the next generated id. |
set | Replaces data or shallow-merges it when merge: true. |
get | Returns a cloned object or null. |
query | Evaluates normalized filters, ordering, and limit in memory. |
delete | Removes one id and emits to collection listeners. |
batchDelete | Removes all ids and emits once. |
count | Returns the number of in-memory query results. |
subscribe | Registers a collection query callback and returns unsubscribe. |
convert | Uses core's recursive Firestore type conversion. |
All write methods notify listeners for the affected collection.
import { beforeEach, expect, it } from "vitest";
import { Collection, defineBaseModel } from "@dharayush7/fireclass-core";
import { FakeAdapter } from "@dharayush7/fireclass-core/testing";
let Todo: ReturnType<typeof createTodoModel>;
function createTodoModel() {
const adapter = new FakeAdapter({
idFactory: () => "todo_1",
});
const BaseModel = defineBaseModel(adapter);
@Collection("todos")
class TodoModel extends BaseModel<TodoModel> {
title!: string;
done!: boolean;
}
return TodoModel;
}
beforeEach(() => {
Todo = createTodoModel();
});
it("creates and reads a todo", async () => {
const todo = new Todo({ title: "Ship docs", done: false });
expect(await todo.save()).toBe("todo_1");
const stored = await Todo.findById("todo_1");
expect(stored).toMatchObject({
id: "todo_1",
title: "Ship docs",
done: false,
});
});The evaluator supports every normalized Fireclass operator:
const active = await User.findMany({
where: {
active: { equals: true },
age: { gte: 18, lt: 65 },
tags: { arrayContains: "staff" },
},
orderBy: { age: "desc" },
limit: 10,
});Equality and membership use JavaScript strict equality. Ordering compares numbers, booleans, strings, and Dates; other values fall back to string comparison.
Cursor values are not evaluated
FakeAdapter currently ignores QuerySpec.startAfter. Test cursor pagination
with an Admin or Client adapter connected to the Firebase emulator.
function subscribe(
collection: string,
spec: QuerySpec,
callback: (docs: DocSnapshot[]) => void,
): () => void;The callback receives the current query result immediately, then receives a new
result after add, set, delete, or batchDelete changes that collection.
const snapshots: string[][] = [];
const stop = adapter.subscribe(
"todos",
buildQuerySpec({ orderBy: { title: "asc" } }),
(docs) => snapshots.push(docs.map((doc) => doc.id)),
);
await adapter.add("todos", { title: "A", done: false });
stop();FakeAdapter implements collection subscribe, but not the React runtime's
additional subscribeDoc method. Use makeHooks with a custom
RealtimeAdapter when unit testing React hooks.
Use unit tests for model behavior and an emulator test suite for Firebase integration behavior.