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:
@@ -143,7 +143,7 @@ test("Observatory owns a bounded explicit-open lifecycle around the shared recor
|
||||
/advanced-index|resolveObservationSessionReplay|resolveCanonicalLabReplay|RerunViewport/,
|
||||
);
|
||||
assert.equal(sharedReplay.match(/<RerunViewport\b/g)?.length, 1);
|
||||
assert.match(sharedReplay, /recordedSessionRerunProfile/);
|
||||
assert.match(sharedReplay, /laboratoryResultRerunProfile/);
|
||||
assert.match(sharedReplay, /useState<0 \| 1>\(hasTgs \? 1 : 0\)/);
|
||||
assert.match(sharedReplay, /hasTgs \? 0\.000001 : 0/);
|
||||
for (const adapter of ["CanonicalVegetationRerunReplay", "PortableResultReplay"]) {
|
||||
|
||||
@@ -1676,7 +1676,7 @@ test("physical-command guidance projects backend policy without exposing reason
|
||||
);
|
||||
});
|
||||
|
||||
test("restart-recovery guidance describes automatic recovery without protocol ceremony", () => {
|
||||
test("restart-recovery guidance offers an explicit read-only recovery", () => {
|
||||
const deniedFresh = {
|
||||
connection_policy: {
|
||||
schema_version: "missioncore.xgrids-k1-connection-policy/v1",
|
||||
@@ -1712,7 +1712,7 @@ test("restart-recovery guidance describes automatic recovery without protocol ce
|
||||
);
|
||||
assert.deepEqual(durableGuidance, {
|
||||
reason: "В свежем Bluetooth-поиске не найден K1, связанный с незавершённой записью.",
|
||||
nextAction: "Дождитесь автоматического восстановления сохранённого подключения K1.",
|
||||
nextAction: "Нажмите «Переподключиться», чтобы проверить сохранённое подключение K1.",
|
||||
});
|
||||
assert.doesNotMatch(
|
||||
`${durableGuidance.reason} ${durableGuidance.nextAction}`,
|
||||
@@ -1725,7 +1725,7 @@ test("restart-recovery guidance describes automatic recovery without protocol ce
|
||||
deniedFresh,
|
||||
"observe-fresh-device-network",
|
||||
).nextAction,
|
||||
"Дождитесь автоматического восстановления связи с тем же K1.",
|
||||
"Нажмите «Переподключиться», чтобы проверить связь с тем же K1.",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -3461,7 +3461,7 @@ test("each terminal explicit provisioning click starts a fresh operation identit
|
||||
|
||||
assert.match(
|
||||
connectRecovery,
|
||||
/failedOperation\?\.status === "succeeded"[\s\S]*?!exactAppliedNetworkIntentCompleted\([\s\S]*?&& !hasExactConnectionReady/,
|
||||
/observeProvisioningRequest\([\s\S]*?observedState = observation\.state[\s\S]*?const exactNetworkIntentCompleted = exactAppliedNetworkIntentCompleted\(/,
|
||||
);
|
||||
assert.match(
|
||||
connectRecovery,
|
||||
@@ -4009,7 +4009,7 @@ test("failed network-profile writes close the UI session with a fresh explicit n
|
||||
|
||||
assert.equal(
|
||||
message,
|
||||
"Bluetooth-периферия завершила сетевую операцию ошибкой. Команда могла быть принята K1; итог текущей попытки не подтверждён. Автоматический повтор команды K1 не отправлялся. Сессия подключения в интерфейсе сброшена. Выполните новый поиск Bluetooth, выберите K1 и запустите подключение ещё раз.",
|
||||
"Bluetooth-периферия завершила сетевую операцию ошибкой. Команда могла быть принята K1; итог текущей попытки не подтверждён. Автоматический повтор команды K1 не отправлялся. Проверьте состояние K1 через «Переподключиться» или начните новое подключение через поиск Bluetooth.",
|
||||
);
|
||||
assert.doesNotMatch(message, /Bleak|GATT|ATT/i);
|
||||
|
||||
@@ -4024,8 +4024,8 @@ test("failed network-profile writes close the UI session with a fresh explicit n
|
||||
});
|
||||
assert.match(attMessage, /ATT 4 INVALID_PDU/);
|
||||
assert.match(attMessage, /Автоматический повтор команды K1 не отправлялся/);
|
||||
assert.match(attMessage, /Сессия подключения в интерфейсе сброшена/);
|
||||
assert.match(attMessage, /новый поиск Bluetooth, выберите K1/);
|
||||
assert.match(attMessage, /Проверьте состояние K1 через «Переподключиться»/);
|
||||
assert.match(attMessage, /новое подключение через поиск Bluetooth/);
|
||||
|
||||
const preWriteAttMessage = networkProvisionFailureMessage({
|
||||
action: "network.provision",
|
||||
@@ -4059,7 +4059,7 @@ test("post-dispatch ambiguity resets the UI session without an automatic retry",
|
||||
|
||||
assert.equal(
|
||||
message,
|
||||
"После BLE-команды K1 вернул сетевой статус, неотличимый от исходного; итог текущей попытки подключения не подтверждён. Автоматический повтор команды K1 не отправлялся. Сессия подключения в интерфейсе сброшена. Выполните новый поиск Bluetooth, выберите K1 и запустите подключение ещё раз.",
|
||||
"После BLE-команды K1 вернул сетевой статус, неотличимый от исходного; итог текущей попытки подключения не подтверждён. Автоматический повтор команды K1 не отправлялся. Проверьте состояние K1 через «Переподключиться» или начните новое подключение через поиск Bluetooth.",
|
||||
);
|
||||
assert.doesNotMatch(message, /ручн|read-only|защитный барьер/i);
|
||||
});
|
||||
@@ -4247,7 +4247,7 @@ test("host Wi-Fi failures close the attempt and require a fresh explicit connect
|
||||
|
||||
assert.equal(
|
||||
operationTimeout,
|
||||
"Локальная операция подготовки Wi‑Fi не завершилась вовремя; итог текущей попытки подключения не подтверждён. Автоматический повтор команды K1 не отправлялся. Сессия подключения в интерфейсе сброшена. Выполните новый поиск Bluetooth, выберите K1 и запустите подключение ещё раз.",
|
||||
"Локальная операция подготовки Wi‑Fi не завершилась вовремя; итог текущей попытки подключения не подтверждён. Автоматический повтор команды K1 не отправлялся. Проверьте состояние K1 через «Переподключиться» или начните новое подключение через поиск Bluetooth.",
|
||||
);
|
||||
assert.doesNotMatch(operationTimeout, /получите пароль|пароль отсутствует/i);
|
||||
assert.match(missingNetwork, /K1 принял команду Quick Connect/);
|
||||
|
||||
@@ -218,8 +218,8 @@ test("K1 connection surface enforces one scan, local selection, and one Apply",
|
||||
);
|
||||
assert.match(provisioning, /scanSecondsRemaining/);
|
||||
assert.match(provisioning, /setInterval\(updateCountdown, 250\)/);
|
||||
assert.match(provisioning, /Поиск Bluetooth · \{scanSecondsRemaining \?\? 6\} с/);
|
||||
assert.match(provisioning, /scanWithResult\(\{[^}]*durationSeconds:\s*6/);
|
||||
assert.match(provisioning, /Поиск Bluetooth · до \{scanSecondsRemaining \?\? BLE_DISCOVERY_TIMEOUT_SECONDS\} с/);
|
||||
assert.match(provisioning, /scanWithResult\(\{[^}]*durationSeconds:\s*BLE_DISCOVERY_TIMEOUT_SECONDS/);
|
||||
assert.doesNotMatch(provisioning, /K1 уже доступен|Сетевой адрес K1 доступен/);
|
||||
assert.doesNotMatch(
|
||||
provisioning,
|
||||
@@ -284,7 +284,7 @@ test("K1 click-owned actions are fenced without hidden frontend continuations",
|
||||
provisioning.indexOf("const verifyAppliedNetwork"),
|
||||
);
|
||||
assert.equal((search.match(/scanWithResult\(/g) ?? []).length, 1);
|
||||
assert.match(search, /durationSeconds:\s*6/);
|
||||
assert.match(search, /durationSeconds:\s*BLE_DISCOVERY_TIMEOUT_SECONDS/);
|
||||
assert.equal((apply.match(/await connect\(/g) ?? []).length, 1);
|
||||
assert.doesNotMatch(
|
||||
apply,
|
||||
@@ -680,7 +680,7 @@ test("automatic K1 live start opens the selected delivered camera despite an old
|
||||
assert.match(layout, /source\.capabilities\.overlay/);
|
||||
});
|
||||
|
||||
test("K1 connect errors reset the UI session without exposing reconciliation ceremony", () => {
|
||||
test("K1 connect errors preserve the result and expose explicit recovery", () => {
|
||||
const runtime = readFileSync(
|
||||
join(pluginFrontendRoot, "useXgridsK1Runtime.ts"),
|
||||
"utf8",
|
||||
@@ -691,15 +691,17 @@ test("K1 connect errors reset the UI session without exposing reconciliation cer
|
||||
assert.notEqual(connectEnd, -1);
|
||||
const connectFlow = runtime.slice(connectStart, connectEnd);
|
||||
|
||||
assert.match(connectFlow, /operationByIdempotencyKey\(/);
|
||||
assert.match(connectFlow, /failedOperation\?\.status === "succeeded"/);
|
||||
assert.match(connectFlow, /resetConnectSessionMessage\(/);
|
||||
assert.match(connectFlow, /observeProvisioningRequest\(/);
|
||||
assert.match(connectFlow, /operation\?\.status !== "succeeded"/);
|
||||
assert.match(connectFlow, /networkProvisionFailureMessage\(/);
|
||||
assert.doesNotMatch(
|
||||
connectFlow,
|
||||
/требует ручной проверки|измените параметры только после проверки устройства|Сохранён тот же ключ/,
|
||||
);
|
||||
assert.match(runtime, /Сессия подключения в интерфейсе сброшена/);
|
||||
assert.match(runtime, /новый поиск Bluetooth, выберите K1 и запустите подключение ещё раз/);
|
||||
const networkFlow = readFileSync(join(pluginFrontendRoot, "networkProvisioning.ts"), "utf8");
|
||||
assert.match(networkFlow, /Проверьте состояние K1 через «Переподключиться»/);
|
||||
assert.match(networkFlow, /новое подключение через поиск Bluetooth/);
|
||||
assert.equal((networkFlow.match(/await context\.send\(/g) ?? []).length, 1);
|
||||
const verifyStart = runtime.indexOf("const verifyConnection = useCallback(");
|
||||
const verifyEnd = runtime.indexOf("const probeConfiguredEndpoint = useCallback(", verifyStart);
|
||||
const verifyFlow = runtime.slice(verifyStart, verifyEnd);
|
||||
@@ -729,7 +731,7 @@ test("K1 provisioning keeps the operator draft separate from the backend lease",
|
||||
assert.match(selection, /requestExplicitProvisioning\(device\.device_id/);
|
||||
assert.equal((apply.match(/await connect\(/g) ?? []).length, 1);
|
||||
assert.doesNotMatch(apply, /scanWithResult\(|verifyConnection\(|candidateRefresh/);
|
||||
assert.match(provisioning, /scanWithResult\(\{ durationSeconds: 6 \}\)/);
|
||||
assert.match(provisioning, /scanWithResult\(\{ durationSeconds: BLE_DISCOVERY_TIMEOUT_SECONDS \}\)/);
|
||||
assert.match(
|
||||
provisioning,
|
||||
/onChange=\{\(event\) => setPassword\(event\.target\.value\)\}/,
|
||||
|
||||
@@ -65,7 +65,7 @@ test("default environment exposes every current product page", () => {
|
||||
"system",
|
||||
"polygon",
|
||||
]);
|
||||
assert.equal(defaults.pages.fleet.primaryWorkspaceId, "contour-health");
|
||||
assert.equal(defaults.pages.fleet.primaryWorkspaceId, "vehicles");
|
||||
assert.equal(defaults.pages.observation.primaryWorkspaceId, "spatial-scene");
|
||||
});
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ test("K1 one-intent source contract makes mode reset explicit and keeps device I
|
||||
"const chooseAnother",
|
||||
);
|
||||
|
||||
assert.match(search, /scanWithResult\(\{[^}]*durationSeconds:\s*6/);
|
||||
assert.match(search, /scanWithResult\(\{[^}]*durationSeconds:\s*BLE_DISCOVERY_TIMEOUT_SECONDS/);
|
||||
assert.equal((search.match(/scanWithResult\(/g) ?? []).length, 1);
|
||||
assert.doesNotMatch(search, /\b(?:connect|verifyConnection|submitConnect)\s*\(/);
|
||||
|
||||
@@ -295,7 +295,7 @@ test("K1 one-intent source contract makes mode reset explicit and keeps device I
|
||||
}
|
||||
assert.equal((source.match(/buttonLabel:\s*"Применить"/g) ?? []).length, 3);
|
||||
assert.match(source, /устарел|stale/i);
|
||||
assert.match(source, /неизвест|outcome-unknown|safe_to_retry/i);
|
||||
assert.match(source, /network_outcome_unknown|safe_to_retry/i);
|
||||
});
|
||||
|
||||
test("exact network-applied REST proof completes frontend Apply before control is ready", () => {
|
||||
@@ -377,7 +377,7 @@ test("exact network-applied REST proof completes frontend Apply before control i
|
||||
);
|
||||
assert.match(
|
||||
connectFlow,
|
||||
/failedOperation\?\.status === "succeeded"[\s\S]*?!exactAppliedNetworkIntentCompleted\([\s\S]*?&& !hasExactConnectionReady/,
|
||||
/observeProvisioningRequest\([\s\S]*?observedState = observation\.state[\s\S]*?const exactNetworkIntentCompleted = exactAppliedNetworkIntentCompleted\(/,
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
connectFlow,
|
||||
@@ -1359,7 +1359,7 @@ function actionByLabel(node, label) {
|
||||
return actionByLabel(node.props.children, label);
|
||||
}
|
||||
|
||||
function renderProvisioningWithAttempt(props, presentation) {
|
||||
function renderProvisioningWithAttempt(props, presentation, afterSearch = false) {
|
||||
function AttemptHarness() {
|
||||
const internals =
|
||||
React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
|
||||
@@ -1367,6 +1367,12 @@ function renderProvisioningWithAttempt(props, presentation) {
|
||||
assert.equal(typeof dispatcher?.useState, "function");
|
||||
const originalUseState = dispatcher.useState;
|
||||
dispatcher.useState = (initialState) => {
|
||||
if (afterSearch && initialState === emptySearchPresentation) {
|
||||
const state = props.controller.state;
|
||||
return [{ sequence: 1, snapshotRuntimeId: state.snapshot_runtime_id,
|
||||
connectionMode: props.desiredMode, desiredModeRevision: state.desired_connection_mode_revision,
|
||||
active: false, completedDiscoveryGeneration: state.ble_discovery_generation }, () => undefined];
|
||||
}
|
||||
if (initialState === emptyProvisioningAttemptPresentation) {
|
||||
return [presentation, () => undefined];
|
||||
}
|
||||
@@ -2487,10 +2493,11 @@ test("toolbar reset in one runtime rejects late Scan A and admits exactly one Sc
|
||||
}
|
||||
});
|
||||
|
||||
test("local connection navigation and selector copy use process nouns", () => {
|
||||
test("operator-local connection belongs to LAB and retains all test modes", () => {
|
||||
const localConnection = workspaces.find((workspace) => workspace.id === "local-device");
|
||||
assert.equal(localConnection?.label, "Подключение");
|
||||
assert.equal(localConnection?.title, "Подключение");
|
||||
assert.equal(localConnection?.root, "polygon");
|
||||
assert.equal(localConnection?.label, "Тестовые устройства");
|
||||
assert.equal(localConnection?.title, "Тестовые устройства");
|
||||
assert.equal(model().displayName, "XGRIDS LixelKity K1");
|
||||
assert.deepEqual(
|
||||
connectionModeOptions.map(({ label }) => label),
|
||||
@@ -7185,7 +7192,7 @@ test("a current-authority Bluetooth scan owns Step 01 and no network step", () =
|
||||
});
|
||||
|
||||
assert.match(markup, /<span>01<\/span>/);
|
||||
assert.match(markup, /Поиск Bluetooth · 6 с/);
|
||||
assert.match(markup, /Поиск Bluetooth · до 20 с/);
|
||||
assert.equal(
|
||||
(markup.match(/class="nodedc-activity-indicator"/g) ?? []).length,
|
||||
1,
|
||||
@@ -7478,7 +7485,7 @@ test("applied-network recovery spends the old intent and admits only explicit se
|
||||
search,
|
||||
/const recoveryScanAttempt = appliedRecoveryEscape[\s\S]*?canScanAppliedRecovery[\s\S]*?unresolvedAppliedAttempt/,
|
||||
);
|
||||
assert.match(search, /scanResult = await scanWithResult\(\{ durationSeconds: 6 \}\)/);
|
||||
assert.match(search, /scanResult = await scanWithResult\(\{ durationSeconds: BLE_DISCOVERY_TIMEOUT_SECONDS \}\)/);
|
||||
assert.match(
|
||||
search,
|
||||
/if \(scanResult\.succeeded && recoveryAttemptKey\) \{\s*setEscapedAppliedAttemptKey\(recoveryAttemptKey\)/,
|
||||
@@ -7708,3 +7715,56 @@ test("contour health never promotes selection or replay metrics to live authorit
|
||||
});
|
||||
assert.equal(replay.aiActive, false);
|
||||
});
|
||||
|
||||
|
||||
test("the recovery panel explains the reviewed K1 network-not-found reply", () => {
|
||||
const state = terminalConnectionRecoveryState();
|
||||
state.connection_attempt.public_error_code = "k1-wifi-network-not-found";
|
||||
const markup = renderToStaticMarkup(createElement(K1OperatorError, {
|
||||
attempt: state.connection_attempt, onRefresh() {}, onClear() {},
|
||||
}));
|
||||
assert.match(markup, /K1 не смог найти указанную сеть Wi‑Fi/);
|
||||
assert.match(markup, /точное название сети/);
|
||||
assert.doesNotMatch(markup, /ошибкой Bluetooth|INVALID_PDU/);
|
||||
});
|
||||
|
||||
test("a reviewed Wi-Fi rejection offers explicit network setup for the same K1", () => {
|
||||
const state = terminalConnectionRecoveryState();
|
||||
state.connection_attempt.public_error_code = "k1-wifi-network-not-found";
|
||||
const controller = {
|
||||
...provisioningController(state), error: "private transport error",
|
||||
errorCorrelation: {
|
||||
action: "connect", runtimeId: state.snapshot_runtime_id, leaseGeneration: 0,
|
||||
connectionAttemptId: state.connection_attempt.attempt_id,
|
||||
},
|
||||
getConnectionRecoveryObservationTarget: () => recommendedConnectionRecoveryObservationTarget(state),
|
||||
};
|
||||
const markup = renderProvisioningWithAttempt({ controller, desiredMode: "bridge" },
|
||||
provisioningAttemptPresentation({ snapshotRuntimeId: state.snapshot_runtime_id,
|
||||
attemptId: state.connection_attempt.attempt_id, localPhase: "failed" }), true);
|
||||
assert.equal(buttonMarkupWithText(markup, "Указать сеть Wi‑Fi заново").length, 1);
|
||||
assert.doesNotMatch(markup, /Подключить новый K1|private transport error/);
|
||||
});
|
||||
|
||||
test("a failed Connect after completed Bluetooth search exposes recovery instead of a locked form", () => {
|
||||
const state = terminalConnectionRecoveryState();
|
||||
state.ble_discovery_generation = 6;
|
||||
state.connection_attempt.public_error_code = "BleakGATTProtocolError";
|
||||
state.connection_attempt.stage = "gatt-write-failed";
|
||||
const controller = {
|
||||
...provisioningController(state),
|
||||
error: "private transport exception must stay hidden",
|
||||
errorCorrelation: {
|
||||
action: "connect", runtimeId: state.snapshot_runtime_id, leaseGeneration: 0,
|
||||
connectionAttemptId: state.connection_attempt.attempt_id,
|
||||
},
|
||||
getConnectionRecoveryObservationTarget: () => recommendedConnectionRecoveryObservationTarget(state),
|
||||
};
|
||||
const markup = renderProvisioningWithAttempt({ controller, desiredMode: "bridge" },
|
||||
provisioningAttemptPresentation({ snapshotRuntimeId: state.snapshot_runtime_id,
|
||||
attemptId: state.connection_attempt.attempt_id, localPhase: "failed" }), true);
|
||||
assert.equal(buttonMarkupWithText(markup, "Переподключиться").length, 1);
|
||||
assert.equal(buttonMarkupWithText(markup, "Подключить новый K1").length, 1);
|
||||
assert.match(markup, /K1 ответил ошибкой Bluetooth/);
|
||||
assert.doesNotMatch(markup, /Подключение не выполнено|дождитесь, пока система|private transport exception|Пароль передан/);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
@@ -27,7 +27,7 @@ async function read(relativePath) {
|
||||
test("Observatory is the third independent Polygon workspace", () => {
|
||||
assert.deepEqual(
|
||||
productModel.workspacesForRoot("polygon").map(({ id }) => id),
|
||||
["lab-archive", "simulations", "observatory"],
|
||||
["lab-archive", "simulations", "observatory", "local-device"],
|
||||
);
|
||||
assert.deepEqual(
|
||||
productModel.workspaceById("observatory"),
|
||||
@@ -138,7 +138,7 @@ test("Observatory mounts the one shared canonical replay only after explicit adm
|
||||
/RerunViewport|ObservationSessionSelect|resolveObservationSessionReplay|resolveCanonicalLabReplay|deleteObservationSession|setInterval|setTimeout|useObservationSessions|useAdvancedLaboratoryCatalog|advanced-index|prefetch|preload/,
|
||||
);
|
||||
assert.equal(sharedReplay.match(/<RerunViewport\b/g)?.length, 1);
|
||||
assert.match(sharedReplay, /recordedSessionRerunProfile/);
|
||||
assert.match(sharedReplay, /laboratoryResultRerunProfile/);
|
||||
assert.match(sharedReplay, /timelineStartSeconds/);
|
||||
assert.doesNotMatch(sharedReplay, /live-acquisition|lab-recorded-evidence/);
|
||||
assert.match(
|
||||
|
||||
@@ -324,7 +324,7 @@ test("Polygon exposes one dataset surface and keeps legacy links compatible", ()
|
||||
assert.equal(workspaceById("datasets").kind, "datasets");
|
||||
assert.deepEqual(
|
||||
workspacesForRoot("polygon").map(({ id }) => id),
|
||||
["lab-archive", "simulations", "observatory"],
|
||||
["lab-archive", "simulations", "observatory", "local-device"],
|
||||
);
|
||||
assert.equal(
|
||||
workspacesForRoot("system").some(({ id }) => id === "polygon-run"),
|
||||
|
||||
@@ -29,7 +29,7 @@ test("top navigation has no Center and Park owns contour health first", () => {
|
||||
assert.equal(productModel.workspaceById("contour-health")?.root, "fleet");
|
||||
assert.deepEqual(
|
||||
productModel.workspacesForRoot("polygon").map(({ id }) => id),
|
||||
["lab-archive", "simulations", "observatory"],
|
||||
["lab-archive", "simulations", "observatory", "local-device"],
|
||||
);
|
||||
assert.equal(productModel.workspaceById("lab-archive")?.kind, "lab-archive");
|
||||
assert.deepEqual(
|
||||
|
||||
@@ -7,6 +7,7 @@ let server;
|
||||
let LABORATORY_RECORDED_EVIDENCE_VIEWER_PROFILE;
|
||||
let liveAcquisitionRerunProfile;
|
||||
let recordedSessionRerunProfile;
|
||||
let laboratoryResultRerunProfile;
|
||||
|
||||
before(async () => {
|
||||
server = await createServer({
|
||||
@@ -18,6 +19,7 @@ before(async () => {
|
||||
LABORATORY_RECORDED_EVIDENCE_VIEWER_PROFILE,
|
||||
liveAcquisitionRerunProfile,
|
||||
recordedSessionRerunProfile,
|
||||
laboratoryResultRerunProfile,
|
||||
} = await server.ssrLoadModule("/src/core/observation/viewerProfile.ts"));
|
||||
});
|
||||
|
||||
@@ -86,3 +88,14 @@ test("the old LAB transport is fenced as explicit legacy comparison only", () =>
|
||||
});
|
||||
assert.equal(Object.isFrozen(LABORATORY_RECORDED_EVIDENCE_VIEWER_PROFILE), true);
|
||||
});
|
||||
|
||||
test("LAB has its own immutable result identity and discriminator", () => {
|
||||
const input = {resultId:"E38-result-1",sourceUrl:"/shared.rrd",kind:"recorded-session",clock:"stream_time"};
|
||||
const lab = laboratoryResultRerunProfile(input);
|
||||
assert.equal(lab.kind,"laboratory-result");
|
||||
assert.equal(lab.clock,"session_time");
|
||||
assert.equal(lab.resultId,"E38-result-1");
|
||||
assert.equal(recordedSessionRerunProfile({...input}).kind,"recorded-session");
|
||||
assert.equal(liveAcquisitionRerunProfile({...input}).kind,"live-acquisition");
|
||||
assert.throws(()=>laboratoryResultRerunProfile({...input,resultId:" "}));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user