The remote mock and the client test runtime are test tooling in the DataMind Oda source. The mock answers the web client's calls to the host side with responses that a test scripts; the runtime boots the real web client against it, in process and with no server in the loop. To choose between the test tiers, see Testing tiers.
{ ok: true, value }; a failure carries { ok: false, error } with a code, a message and details.undefined, and a queued one-shot answer is consumed before the default.push sends an item to every open stream of an endpoint; end and fail close that endpoint's open streams; each call reports how many streams changed.opened resolves once an endpoint has been opened a given number of times; drained resolves once the consumer of every matching stream has caught up and is waiting for more. A stream nobody reads never drains.pending, answered or failed; streams as open, ended, failed or cancelled; a request that found no rule records as a miss with its mode, unary or stream.mount is off by default; turn it on to mount into a fresh element. awaitConnected is on by default; turn it off to return as soon as the client is up. connectTimeoutMs is the budget for reaching connected, 5 seconds by default. Repeated start calls share one promise, so asking twice boots one client.The mock is loaded with answers for the calls the client makes while it starts, so a fresh client boots with no sessions, no workspaces and default settings. A spec layers its own answers on top.
| While starting, the client asks for | The mock answers |
|---|---|
| Its chat list | An empty list. |
| The default workspace setup | Success. |
| Its settings description | Writable, with no document. |
| The model catalogue | A default model entry. |
| Its preset list | Empty. |
| The account state | Signed out. |
| The follow stream | Declared as a stream, so a forgotten script reads as a stream miss. |
remote-mock: no rule for <endpoint>; registered: <sorted endpoints> The call found no default or script. The message lists what is registered, and the call records as a miss.remote-mock: <n> unmatched request(s): Teardown found calls that never had a rule; each is listed with its mode, unary or stream, then the registered endpoints. Add the missing rule or expect the call.remote-mock: payload of <endpoint> must be { args: unknown[] | object } The carrier got a payload in neither accepted shape. Pass an arguments array or a single object.remote-mock: call aborted The call was aborted before it settled; a call aborted while pending rejects with the abort reason.remote-mock: <endpoint> stream disposed A stream that was already disposed refused further use. Dispose a stream only after the reads and pushes in the test finish.remote-mock: <endpoint> stream has one consumer A second concurrent read started on one stream. Read each stream from one place.remote-mock: uplink was ended A send arrived after the uplink ended. Send before ending it; a repeated end is a no-op.remote-mock: <endpoint> uplink item is not a lossless JSON value An item sent over the uplink cannot round-trip as JSON. Send lossless values instead.client test runtime: file upload is not stubbed The bench's upload stub is still in place and rejects every call. Replace the upload function in a suite that exercises uploads.client-test-runtime: connection state is <state> after <ms>ms; unmatched: [<calls>]; streams: [<streams>] The whole-client start ran out of its budget before connected. The message carries the state, the budget, the unanswered calls and the open streams.client-test-runtime: start() called after its test fixture closed The start ran after its test closed. Start within the test; teardown already disposes the client.The endpoint has no default or script, so the call recorded as a miss (remote-mock: no rule for <endpoint>; registered: <sorted endpoints>). Register the endpoint, or expect the call; endpoints the startup never touches stay absent, so this is also how a call into unmocked territory fails.
Register a rule for the endpoint: a value returned exactly as given, or a handler that computes the answer from the call's arguments. A success answer is { ok: true, value }, a failure { ok: false, error }; re-registering the endpoint replaces its default.
Declare the endpoint as a stream before the code under test keeps a reference to its method, then register a script for its openings. The script receives the open arguments and a handle, pushes items, and the stream stays open until the test ends or fails it.
A stream has one consumer, so a second concurrent read is refused (remote-mock: <endpoint> stream has one consumer). Read each stream from one place; a consumer that stops early ends the stream without throwing and records it as cancelled.
The uplink was already ended (remote-mock: uplink was ended). Ending it again is a no-op, but a later send is refused; send before you end it.
Every item sent over the uplink must round-trip as JSON; a value that cannot, such as a bigint, is refused. Send lossless JSON values instead.
Clearing keeps every answer and queued reply, so later calls still get them; resetting instead drops overrides and restores the initial implementation, which reads the latest registered answer.
The readiness wait ran out. The failure names the connection's state, the budget it waited, the calls that found no answer and the streams still open; add a rule for a call the startup makes, or raise connectTimeoutMs.
A start call made after its test closed does not run (client-test-runtime: start() called after its test fixture closed). Start within the test; teardown already disposes the client.
The startup answers in the table above: an empty chat list, a successful default workspace setup, a writable settings description, a default model entry, an empty preset list, a signed-out account, and the follow stream declared. The built-in events frame is what lets the client reach connected.