Skip to content

Testing against a scripted host

./testing is a WireTransport a test hands to QgisSdk.fromBridgeSchema (or to its own BridgeClient), so the page’s real client, the SDK’s contract validation and the React bindings all run unchanged against a host the test scripts. Nothing global is mutated: two harnesses are two hosts, and a test can prove nothing crosses between their clients.

import { QgisSdk } from "@archont561/qgis-sdk";
import { SILENCE, createBridgeHarness, fault } from "@archont561/qgis-sdk/testing";
import schema from "./bridge.schema";
const harness = createBridgeHarness(schema); // expectations typed by the schema
const qgis = QgisSdk.fromBridgeSchema(schema, { transport: harness });
harness.expectInvoke("sites.summary", (payload) => ({ total: 1, largest: payload.layer_id, mode: "fast" }));
harness.expectInvoke("sites.summary", () => fault("forbidden", "not yours"));
harness.expectInvoke("sites.summary", () => SILENCE); // the client's own timeout speaks
harness.expectSubscribe("sites.watch", (_payload, stream) => {
stream.emit("data", { change: "added" });
stream.skip(2); // the next frame is a gap, ended the way the kernel promises
stream.end({ kind: "complete" });
});
await qgis.sites.summary({ layer_id: "sites" });
harness.calls; // every envelope the client sent, in order; the handshake first
harness.assertSatisfied(); // unmet expectations, unexpected calls, open subscriptions, handler throws
  • Handshake. A harness built on a schema answers the SDK’s handshake by itself, from the schema and HOST_OPERATIONS; createBridgeHarness(schema, { granted: ["layers.list"] }) narrows what qgis.host.granted reports, for tests of a page under a restricted host. The handshake is recorded in harness.calls with kind: "handshake"; filter it out when asserting the operations a page made.

  • Untyped form. createBridgeHarness<OperationId>() without a schema is what the 0.3.0 generated client and bare BridgeClient tests use; expectInvoke<Req, Res> then takes the types by hand.

  • Expectations are consumed FIFO per operation. A call no expectation covers is answered with the unexpected_call failure code and remembered; a handler that throws answers harness_error and is reported by assertSatisfied(). Both are QgisSdkBridgeHarnessErrors, as is an envelope that is not protocol 1.

  • Deliveries are asynchronous and ordered: an acknowledgement reaches the client before the first frame a script emitted, and await harness.settled() waits for everything queued.

  • expectSubscribe(op, script, { ack }) delays the acknowledgement until the ack() promise settles, for tests of what a component does while a subscription is still opening.

  • Evidence boundary. A green harness test says the page handles the frames a host could send; it says nothing about a QWebEngineView or a running host. That evidence lives in the Python suite and the qualification harnesses of doc-14. Keep the two apart in reports and never cite a mocked run as native behaviour.