feat: add patch panel runtime sync
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import { createWiringConfig } from "./model.mjs";
|
||||
import { createPatchPanelRuntime } from "./runtime.mjs";
|
||||
|
||||
test("runtime applies config and delivers DO->DI through endpoint map", async () => {
|
||||
const writes = [];
|
||||
const runtime = createPatchPanelRuntime({
|
||||
wiringConfig: createWiringConfig({
|
||||
wiringConfigId: "wir_runtime_unit",
|
||||
projectId: "prj_runtime_unit",
|
||||
gatewaySessionId: "gws_runtime_unit",
|
||||
connections: [
|
||||
{
|
||||
from: {
|
||||
resourceId: "res_alpha",
|
||||
port: "DO1"
|
||||
},
|
||||
to: {
|
||||
resourceId: "res_beta",
|
||||
port: "DI1"
|
||||
},
|
||||
mode: "exclusive"
|
||||
}
|
||||
],
|
||||
now: "2026-01-01T00:00:00.000Z"
|
||||
}),
|
||||
endpointMap: {
|
||||
res_beta: "http://127.0.0.1:7202"
|
||||
},
|
||||
now: () => "2026-01-01T00:00:01.000Z",
|
||||
requestJson: async (url, body) => {
|
||||
writes.push({ url, body });
|
||||
return {
|
||||
status: 200,
|
||||
json: {
|
||||
accepted: true
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(runtime.status().state, "active");
|
||||
const result = await runtime.tick({
|
||||
signals: [
|
||||
{
|
||||
fromResourceId: "res_alpha",
|
||||
fromPort: "DO1",
|
||||
value: true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
assert.equal(result.accepted, true);
|
||||
assert.equal(result.deliveryCount, 1);
|
||||
assert.equal(writes.length, 1);
|
||||
assert.equal(writes[0].url, "http://127.0.0.1:7202/internal/ports/write");
|
||||
assert.deepEqual(writes[0].body, {
|
||||
port: "DI1",
|
||||
value: true,
|
||||
source: "patch-panel",
|
||||
sourceResourceId: "res_alpha",
|
||||
sourcePort: "DO1",
|
||||
propagatedBy: "hwlab-patch-panel",
|
||||
observedAt: "2026-01-01T00:00:01.000Z"
|
||||
});
|
||||
assert.equal(runtime.evidenceSummary.configApplied, true);
|
||||
assert.equal(runtime.evidenceSummary.tickCount, 1);
|
||||
assert.equal(runtime.evidenceSummary.deliveryCount, 1);
|
||||
});
|
||||
|
||||
test("runtime reports missing target endpoint as readable diagnostics", async () => {
|
||||
const runtime = createPatchPanelRuntime({
|
||||
wiringConfig: createWiringConfig({
|
||||
wiringConfigId: "wir_runtime_missing_endpoint",
|
||||
projectId: "prj_runtime_unit",
|
||||
gatewaySessionId: "gws_runtime_unit",
|
||||
connections: [
|
||||
{
|
||||
from: {
|
||||
resourceId: "res_alpha",
|
||||
port: "AO1"
|
||||
},
|
||||
to: {
|
||||
resourceId: "res_beta",
|
||||
port: "AI1"
|
||||
},
|
||||
mode: "exclusive"
|
||||
}
|
||||
],
|
||||
now: "2026-01-01T00:00:00.000Z"
|
||||
}),
|
||||
endpointMap: {},
|
||||
now: () => "2026-01-01T00:00:01.000Z",
|
||||
requestJson: async () => {
|
||||
throw new Error("requestJson should not be called without endpoint");
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(runtime.status().state, "faulted");
|
||||
assert.ok(runtime.diagnostics().diagnostics.some((diagnostic) => diagnostic.code === "target_endpoint_missing"));
|
||||
|
||||
const result = await runtime.routeSignal({
|
||||
fromResourceId: "res_alpha",
|
||||
fromPort: "AO1",
|
||||
value: 1.5
|
||||
});
|
||||
assert.equal(result.accepted, false);
|
||||
assert.equal(result.deliveryCount, 1);
|
||||
assert.ok(result.diagnostics.some((diagnostic) => diagnostic.code === "target_endpoint_missing"));
|
||||
});
|
||||
Reference in New Issue
Block a user