Reference · 09

Testing.

An in-process database for tests: the same methods, errors and client, with time under your control.

Test databases

@flower-js/sdk/testing runs an application on Flower’s reference engine, in-process. It is Node only; keep it out of application bundles. The testing guide shows it in use.

APIContract
testDatabase<App>(app, options?): Promise<TestDatabase<App>>Starts a database. Pass the imported define(...) module to run it directly, or a path to bundle it and run it in an isolated node:vm context, as the server does; with a path, pass typeof app yourself for typed calls.
TestDatabaseOptionsOptional now (starting server time; 1,000,000 ms), credentials (sent by the client and by calls that pass none) and partitions (names of extra logical databases running the same app).
TestCallOptionsOptional credentials and requestId, as the last argument of a call.
TestDatabase<App>The root database. Mutable now; readonly client; getters revision and data (a copy of the raw state, for debugging; its format isn’t stable).
constructor(module, engine, options?, local?)Used by testDatabase; call that instead.
query(alias, args?, options?): VCalls an exposed query synchronously and returns its value. Arguments, access checks and failures behave as over HTTP: failures throw FlowerError with the same status, code and failure.
mutate(alias, args?, options?): VCalls an exposed mutation or transaction and commits it. A reused request ID replays the first result; with different arguments it throws REQUEST_ID_REUSED.
call(alias, args?, options?): VCalls any alias. Transactions run across the test partitions and return { results }, plus value when the plan has one; a participant failure throws TRANSACTION_ABORTED with its failure, and nothing commits.
maintain(limit = 10_000, partition = ""): numberRuns due maintenance like the leader, one task per commit, while tasks stay due. Returns the number of committed runs.
advance(ms): numberMoves now forward, then runs due maintenance in every partition and refreshes watches. Returns the number of committed runs.
partition(name): TestPartition<App>A named partition from options.partitions; unknown names throw PARTITION_NOT_FOUND. Partitions share the clock.
fetch(url, init): Promise<Response>A FlowerFetch serving /v1/query, /v1/mutate, /v1/call and /v1/watch from this database, for root and partition URLs. client uses it; pass it to other clients.
TestPartition<App>One named partition. Readonly client, scoped to the partition.
constructor(database, name)Used by db.partition(name); call that instead.
query(alias, args?, options?), mutate(…), call(…)The same calls as on TestDatabase, against this partition.
maintain(limit?): numberRuns this partition’s due maintenance.
  • Time moves only through now and advance. Maintenance runs only through maintain and advance.
  • If the app has access checks, a partition’s principals must carry its name as their tenant, as on a server.
  • Native crypto isn’t available: NaCl, JWT, managed keys and jwtBearer fail. Retry sessions and bounded retries aren’t simulated.
  • Index reads on indexes that aren’t declared fail with UNDECLARED_INDEX, where a server would silently scan.
  • Watches send full snapshots rather than patches.