Separat status och mottagningsräknare för varje kanal.
Senaste råmeddelande, fel och ignoreringsorsaker. Pausa visning, rensa och kopiera logg. Uppdateras utan att störa inställningsfält eller tidtagning.
This commit is contained in:
@@ -118,6 +118,20 @@ try {
|
||||
await evaluate('document.getElementById("syncStatusRetry").click()');
|
||||
await waitFor(async () => (await savedState()).classes.some(item => item.name === "Offline Draft"), "retry persisted draft");
|
||||
await waitFor(async () => (await status()) === "saved", "confirmed saved status");
|
||||
await navigate("settings", "settingsForm");
|
||||
await evaluate(`(async () => {
|
||||
const panel = document.getElementById("decoderDiagnostics");
|
||||
if (!panel) throw new Error("Missing decoder diagnostics");
|
||||
panel.open = true;
|
||||
const field = document.querySelector('#settingsForm [name="wsUrl"]');
|
||||
field.value = "ws://draft.example:9000";
|
||||
const { decoderDiagnostics } = await import("/src/decoder_diagnostics.js");
|
||||
decoderDiagnostics.frame("main", "diagnostic sample");
|
||||
await new Promise(resolve => setTimeout(resolve, 1200));
|
||||
if (!panel.textContent.includes("diagnostic sample")) throw new Error("Diagnostics did not update");
|
||||
if (field.value !== "ws://draft.example:9000") throw new Error("Diagnostics reset settings draft");
|
||||
})()`);
|
||||
console.log("PASS decoder diagnostics update without resetting settings draft");
|
||||
await runOverlaySmoke({ evaluate });
|
||||
assert.deepEqual(errors, []);
|
||||
console.log("PASS offline save failure, local draft retention, retry and confirmed saved status");
|
||||
|
||||
36
tests/decoder_diagnostics.test.js
Normal file
36
tests/decoder_diagnostics.test.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createDecoderDiagnostics } from "../src/decoder_diagnostics.js";
|
||||
|
||||
test("diagnostics bounds logs, isolates channels and returns independent snapshots", () => {
|
||||
const model = createDecoderDiagnostics(() => 1234);
|
||||
model.socket("main", "connected", "ws://host:9000");
|
||||
for (let i = 0; i < 80; i++) {
|
||||
model.frame("main", "x".repeat(2000));
|
||||
model.message("main", {msg:"PASSING", transponder:123}, "lap_counted", "handled");
|
||||
}
|
||||
model.parseError("main");
|
||||
const entries = model.snapshot();
|
||||
assert.equal(entries[0].log.length, 50);
|
||||
assert.equal(entries[0].lastFrame.length, 512);
|
||||
assert.equal(entries[0].handled, 80);
|
||||
assert.equal(entries[0].parseErrors, 1);
|
||||
assert.equal(entries[1].frames, 0);
|
||||
entries[0].log[0].reason = "mutated";
|
||||
assert.notEqual(model.snapshot()[0].log[0].reason, "mutated");
|
||||
model.clear("main");
|
||||
assert.equal(model.snapshot()[0].frames, 0);
|
||||
assert.equal(model.snapshot()[0].status, "connected");
|
||||
assert.equal(model.snapshot()[0].connectedAt, 1234);
|
||||
});
|
||||
|
||||
test("diagnostics separates ignored, invalid and handled messages", () => {
|
||||
const model = createDecoderDiagnostics();
|
||||
model.message("split", {msg:"STATUS"}, "not_passing");
|
||||
model.message("split", {msg:"PASSING"}, "no_running_session");
|
||||
model.message("main", {msg:"PASSING"}, "below_min", "invalid");
|
||||
assert.equal(model.snapshot()[1].ignored, 2);
|
||||
assert.equal(model.snapshot()[1].passings, 1);
|
||||
assert.equal(model.snapshot()[0].invalid, 1);
|
||||
assert.equal(model.snapshot()[0].handled, 0);
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import { decoderDiagnostics } from "../src/decoder_diagnostics.js";
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
@@ -179,9 +180,17 @@ test("connect decoder opens one websocket per enabled role", () => {
|
||||
pit_entry: "ws://server:9002",
|
||||
pit_exit: "ws://server:9003",
|
||||
});
|
||||
decoderDiagnostics.clear("main");
|
||||
clients.main.onopen();
|
||||
clients.main.onmessage({ data: "not json" });
|
||||
clients.main.onmessage({ data: JSON.stringify({ msg: "STATUS" }) });
|
||||
assert.equal(decoderDiagnostics.snapshot()[0].frames, 2);
|
||||
assert.equal(decoderDiagnostics.snapshot()[0].parseErrors, 1);
|
||||
clients.main.onerror();
|
||||
clients.main.onclose();
|
||||
assert.equal(decoderDiagnostics.snapshot()[0].status, "disconnected");
|
||||
clients.main.onopen();
|
||||
assert.equal(decoderDiagnostics.snapshot()[0].status, "connected");
|
||||
assert.equal(renderCount, 0);
|
||||
} finally {
|
||||
globalThis.WebSocket = OriginalWebSocket;
|
||||
|
||||
@@ -17,3 +17,4 @@ import "./session_replay.test.js";
|
||||
import "./public_training_refresh.test.js";
|
||||
import "./list_sorting.test.js";
|
||||
import "./sync_status.test.js";
|
||||
import "./decoder_diagnostics.test.js";
|
||||
|
||||
Reference in New Issue
Block a user