chore(node): preserve pre-canonicalization experiment snapshot
Historical working copy retained for audit before consolidation into main. The canonicalized plugin architecture and later fixes already live in main; this snapshot is not a release or a request to restore obsolete source layout.
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { before, after, test } from "node:test";
|
||||
import { createServer } from "vite";
|
||||
|
||||
let server;
|
||||
let observeProvisioningRequest;
|
||||
let networkProvisionFailureMessage;
|
||||
let ApiError;
|
||||
before(async () => {
|
||||
server = await createServer({ appType: "custom", logLevel: "silent", server: { middlewareMode: true } });
|
||||
({ observeProvisioningRequest, networkProvisionFailureMessage } = await server.ssrLoadModule("@xgrids-k1/frontend/networkProvisioning.ts"));
|
||||
({ ApiError } = await server.ssrLoadModule("@xgrids-k1/frontend/api.ts"));
|
||||
});
|
||||
after(async () => { await server?.close(); });
|
||||
|
||||
test("reviewed station errors explain Wi-Fi recovery without claiming a Bluetooth failure", () => {
|
||||
for (const [code, pattern] of [
|
||||
["k1-wifi-network-not-found", /точное название сети/],
|
||||
["k1-wifi-credentials-required", /введите пароль нужной сети заново/],
|
||||
]) {
|
||||
const message = networkProvisionFailureMessage({ status: "failed", error: { code } });
|
||||
assert.match(message, pattern);
|
||||
assert.doesNotMatch(message, /INVALID_PDU|ошибкой Bluetooth|Переподключиться/);
|
||||
}
|
||||
assert.match(networkProvisionFailureMessage({ status: "failed", error: {
|
||||
code: "BleakGATTProtocolError", ble_att_error_code: 4, ble_att_error_name: "INVALID_PDU",
|
||||
} }), /INVALID_PDU/);
|
||||
assert.match(networkProvisionFailureMessage({ status: "failed", error: {
|
||||
code: "network-not-found",
|
||||
} }), /macOS/);
|
||||
});
|
||||
|
||||
const request = { device_id: "synthetic-k1", connection_mode: "bridge", idempotency_key: "explicit-one" };
|
||||
function snapshot(status, revision = 2) {
|
||||
return {
|
||||
snapshot_runtime_id: "runtime-one",
|
||||
snapshot_runtime_started_at_utc: "2026-09-06T00:00:00Z",
|
||||
snapshot_revision: revision,
|
||||
operations: status ? [{
|
||||
operation_id: "op-one", action: "network.provision", idempotency_key: request.idempotency_key,
|
||||
status, error: status === "failed" ? {
|
||||
code: "BleakGATTProtocolError", ble_att_error_code: 4, ble_att_error_name: "INVALID_PDU",
|
||||
device_write_attempted: true, device_write_confirmed: false,
|
||||
safe_to_retry: false, side_effect_status: "unknown",
|
||||
} : null,
|
||||
}] : [],
|
||||
};
|
||||
}
|
||||
function context(overrides = {}) {
|
||||
let current = snapshot(null, 1);
|
||||
const calls = [];
|
||||
return {
|
||||
calls,
|
||||
initialState: current,
|
||||
send: async (input) => { calls.push(["send", input]); throw new ApiError("transport", 502); },
|
||||
readState: async () => { calls.push(["read"]); return snapshot("failed"); },
|
||||
acceptState: (incoming) => { if (incoming.snapshot_revision >= current.snapshot_revision) current = incoming; },
|
||||
currentState: () => current,
|
||||
assertCurrent() {},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test("HTTP 502 retains the exact failed snapshot and ATT facts after one submission", async () => {
|
||||
const ctx = context();
|
||||
const result = await observeProvisioningRequest(request, ctx);
|
||||
assert.deepEqual(ctx.calls.map(([kind]) => kind), ["send", "read"]);
|
||||
assert.equal(ctx.calls[0][1], request);
|
||||
assert.equal(result.operation.operation_id, "op-one");
|
||||
assert.equal(result.operation.error.ble_att_error_name, "INVALID_PDU");
|
||||
assert.equal(result.state.operations[0], result.operation);
|
||||
assert.equal(result.transportError.status, 502);
|
||||
});
|
||||
|
||||
test("an existing failed or successful intent is never resubmitted", async () => {
|
||||
for (const status of ["failed", "succeeded"]) {
|
||||
const ctx = context({ initialState: snapshot(status) });
|
||||
const result = await observeProvisioningRequest(request, ctx);
|
||||
assert.equal(result.operation.status, status);
|
||||
assert.equal(ctx.calls.length, 0);
|
||||
}
|
||||
});
|
||||
|
||||
test("lost HTTP response can observe journal success without another command", async () => {
|
||||
const ctx = context({ readState: async () => snapshot("succeeded") });
|
||||
const result = await observeProvisioningRequest(request, ctx);
|
||||
assert.equal(result.operation.status, "succeeded");
|
||||
assert.equal(ctx.calls.filter(([kind]) => kind === "send").length, 1);
|
||||
});
|
||||
|
||||
test("an admitted pending intent is followed only by bounded local state reads", async () => {
|
||||
let now = 0;
|
||||
const ctx = context({
|
||||
initialState: snapshot("running"),
|
||||
settlementOptions: { now: () => now, wait: async (ms) => { now += ms; } },
|
||||
});
|
||||
const result = await observeProvisioningRequest(request, ctx);
|
||||
assert.equal(result.operation.status, "failed");
|
||||
assert.deepEqual(ctx.calls.map(([kind]) => kind), ["read"]);
|
||||
});
|
||||
|
||||
test("newer WebSocket failure outranks a stale running REST result", async () => {
|
||||
const newer = snapshot("failed", 7);
|
||||
const ctx = context({
|
||||
send: async () => snapshot("running", 5),
|
||||
currentState: () => newer,
|
||||
});
|
||||
const result = await observeProvisioningRequest(request, ctx);
|
||||
assert.equal(result.state, newer);
|
||||
assert.equal(result.operation.status, "failed");
|
||||
assert.equal(ctx.calls.length, 0);
|
||||
});
|
||||
|
||||
test("superseding an intent after dispatch stops continuation without replay", async () => {
|
||||
let active = true;
|
||||
const ctx = context({
|
||||
send: async () => { active = false; throw new ApiError("lost", 502); },
|
||||
assertCurrent: () => { if (!active) throw new Error("superseded"); },
|
||||
});
|
||||
await assert.rejects(observeProvisioningRequest(request, ctx), /superseded/);
|
||||
assert.equal(ctx.calls.length, 0);
|
||||
});
|
||||
|
||||
test("an unrelated journal row cannot confirm the current command", async () => {
|
||||
const unrelated = snapshot("succeeded");
|
||||
unrelated.operations[0].idempotency_key = "another-intent";
|
||||
const ctx = context({ readState: async () => unrelated });
|
||||
const result = await observeProvisioningRequest(request, ctx);
|
||||
assert.equal(result.operation, null);
|
||||
assert.equal(result.transportError.status, 502);
|
||||
assert.equal(ctx.calls.length, 1);
|
||||
});
|
||||
Reference in New Issue
Block a user