swarm-ui: a broadcast page that sends one message to several agents
Pick agents from a grid of their icons (running or all), type the text, send. The page posts the names and the text to the controller and shows what happened to each agent, with a retry that selects just the ones that failed. The selection rules and the controller's answer are read by plain functions with tests.
This commit is contained in:
parent
a429b30448
commit
89b20a5a50
7 changed files with 695 additions and 0 deletions
96
frontend/packages/swarm-ui/test/broadcast-types.test.mjs
Normal file
96
frontend/packages/swarm-ui/test/broadcast-types.test.mjs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// The broadcast page's selection and answer rules. Run by `npm test`, which
|
||||
// Node runs with its built-in test runner and type stripping, so the `.ts`
|
||||
// module is imported as it is.
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "node:test";
|
||||
import {
|
||||
failedAgents,
|
||||
MAX_BROADCAST,
|
||||
isRunning,
|
||||
parseResults,
|
||||
selectedVisible,
|
||||
sendLabel,
|
||||
tickAll,
|
||||
toggled,
|
||||
visibleAgents,
|
||||
} from "../src/pages/broadcast/broadcast-types.ts";
|
||||
|
||||
const up = { running: true };
|
||||
const down = { running: false };
|
||||
const agents = [
|
||||
{ name: "zed", snapshot: up },
|
||||
{ name: "bob", snapshot: down },
|
||||
{ name: "ann", snapshot: null },
|
||||
{ name: "cy", snapshot: up },
|
||||
];
|
||||
|
||||
test("only an agent that reported running counts as running", () => {
|
||||
assert.equal(isRunning({ snapshot: up }), true);
|
||||
assert.equal(isRunning({ snapshot: down }), false);
|
||||
assert.equal(isRunning({ snapshot: null }), false);
|
||||
});
|
||||
|
||||
test("the filter shows every agent or just the running ones, by name", () => {
|
||||
assert.deepEqual(
|
||||
visibleAgents(agents, "all").map((a) => a.name),
|
||||
["ann", "bob", "cy", "zed"],
|
||||
);
|
||||
assert.deepEqual(
|
||||
visibleAgents(agents, "running").map((a) => a.name),
|
||||
["cy", "zed"],
|
||||
);
|
||||
});
|
||||
|
||||
test("a ticked agent the filter hides is not sent to, and comes back with the filter", () => {
|
||||
const ticked = ["bob", "cy"];
|
||||
const running = visibleAgents(agents, "running");
|
||||
assert.deepEqual(selectedVisible(ticked, running), ["cy"]);
|
||||
assert.deepEqual(selectedVisible(ticked, visibleAgents(agents, "all")), [
|
||||
"bob",
|
||||
"cy",
|
||||
]);
|
||||
});
|
||||
|
||||
test("toggling flips one name and keeps the rest", () => {
|
||||
assert.deepEqual(toggled(["a", "b"], "c"), ["a", "b", "c"]);
|
||||
assert.deepEqual(toggled(["a", "b"], "a"), ["b"]);
|
||||
});
|
||||
|
||||
test("tick all adds the shown agents once", () => {
|
||||
const shown = visibleAgents(agents, "running");
|
||||
assert.deepEqual(tickAll(["cy", "bob"], shown), ["cy", "bob", "zed"]);
|
||||
});
|
||||
|
||||
test("the send button says how many it goes to", () => {
|
||||
assert.equal(sendLabel(0), "send");
|
||||
assert.equal(sendLabel(1), "send to 1 agent");
|
||||
assert.equal(sendLabel(3), "send to 3 agents");
|
||||
});
|
||||
|
||||
test("the controller's answer is read per agent", () => {
|
||||
const results = parseResults({
|
||||
results: [
|
||||
{ agent: "a", sent: true },
|
||||
{ agent: "b", sent: false, reason: "no subscriber" },
|
||||
{ agent: "c", sent: false, reason: "" },
|
||||
],
|
||||
});
|
||||
assert.deepEqual(results, [
|
||||
{ agent: "a", sent: true, reason: null },
|
||||
{ agent: "b", sent: false, reason: "no subscriber" },
|
||||
{ agent: "c", sent: false, reason: null },
|
||||
]);
|
||||
assert.deepEqual(failedAgents(results ?? []), ["b", "c"]);
|
||||
});
|
||||
|
||||
test("an answer that is not the agreed shape is null, not an empty list", () => {
|
||||
assert.equal(parseResults(null), null);
|
||||
assert.equal(parseResults({}), null);
|
||||
assert.equal(parseResults({ results: "x" }), null);
|
||||
assert.equal(parseResults({ results: [{ agent: "a" }] }), null);
|
||||
assert.equal(parseResults({ results: [null] }), null);
|
||||
});
|
||||
|
||||
test("one broadcast may name at most 64 agents", () => {
|
||||
assert.equal(MAX_BROADCAST, 64);
|
||||
});
|
||||
Loading…
Reference in a new issue