Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/frontend/packages/swarm-ui/test/flow-choices.test.mjs
iris b6da2bc9d0 swarm-wire, swarm-ui: the flow schema lists the values a field takes, and the editor picks them instead of asking for typed names
The schema's event fields gain values, a values_from marker (agents, repos)
and a closed flag; a node field gains the marker and the flag. kind is now
listed as issue and PR, what the router sends. The flow editor shows a
dropdown where the list is complete, suggestions where it is only examples,
and a plain box where there is none.
2026-10-25 12:14:46 +01:00

148 lines
4.5 KiB
JavaScript

// What the flow editor offers for a value: dropdown, suggestions or plain
// text, from the server's schema. Run by `npm test`.
import assert from "node:assert/strict";
import { test } from "node:test";
import {
eventSpec,
kindSpec,
markersIn,
offerFor,
} from "../src/pages/notifications/FlowChoices.ts";
const d = (name, description = "") => ({ name, description });
const schema = {
source_events: [d("issues")],
fields: [
{
...d("kind"),
values: [d("issue"), d("PR", "A pull request")],
closed: true,
},
{ ...d("action"), values: [d("opened"), d("closed")], closed: false },
{ ...d("repo"), values: [], values_from: "repos", closed: false },
{ ...d("title"), values: [] },
],
node_kinds: [
{
kind: "todo",
description: "",
fields: [
{
...d("to"),
required: true,
values: [],
values_from: "agents",
closed: true,
},
{
...d("op"),
required: true,
values: [d("upsert"), d("clear")],
closed: true,
},
],
},
{
kind: "request_reviewer",
description: "",
fields: [
{
...d("reviewer"),
required: true,
values: [],
values_from: "agents",
closed: false,
},
{
...d("later"),
required: false,
values: [],
values_from: "somewhere-new",
},
],
},
],
limits: { max_nodes: 1, max_depth: 1, max_flows: 1 },
};
test("a field with a complete list is a dropdown, its labels carrying the description", () => {
const offer = offerFor(eventSpec(schema, "kind"), {}, "PR");
assert.equal(offer.closed, true);
assert.deepEqual(
offer.options.map((o) => o.value),
["issue", "PR"],
);
assert.equal(offer.options[1].label, "PR — A pull request");
});
test("a list that is only examples stays a text box with suggestions", () => {
const offer = offerFor(eventSpec(schema, "action"), {}, "");
assert.equal(offer.closed, false);
assert.deepEqual(
offer.options.map((o) => o.value),
["opened", "closed"],
);
});
test("a field with no known values is plain text", () => {
assert.equal(offerFor(eventSpec(schema, "title"), {}, ""), null);
assert.equal(offerFor(undefined, {}, ""), null, "no schema entry at all");
});
test("a list fetched from the swarm fills the options, and a closed one becomes a dropdown", () => {
const spec = kindSpec(schema, "todo", "to");
const offer = offerFor(spec, { agents: ["atlas", "iris"] }, "iris");
assert.equal(offer.closed, true);
assert.deepEqual(
offer.options.map((o) => o.value),
["atlas", "iris"],
);
});
test("until its list arrives, or when it cannot be fetched, there is nothing to offer", () => {
const spec = kindSpec(schema, "todo", "to");
assert.equal(offerFor(spec, {}, ""), null);
// Open lists with names fetched are suggestions: any login still goes.
const reviewer = kindSpec(schema, "request_reviewer", "reviewer");
const offer = offerFor(reviewer, { agents: ["argus"] }, "review-classifier");
assert.equal(offer.closed, false);
assert.deepEqual(
offer.options.map((o) => o.value),
["argus"],
);
});
test("a dropdown whose source has not arrived falls back to suggestions", () => {
const spec = {
values: [d("a")],
values_from: "agents",
closed: true,
};
assert.equal(offerFor(spec, {}, "").closed, false);
assert.equal(offerFor(spec, { agents: ["b"] }, "").closed, true);
});
test("a value the list lacks stays selectable, marked as not listed", () => {
const spec = kindSpec(schema, "todo", "to");
const offer = offerFor(spec, { agents: ["atlas"] }, "gone");
assert.equal(offer.options[0].value, "gone");
assert.equal(offer.options[0].label, "gone (not listed)");
assert.equal(offer.options.length, 2);
// Nothing set yet adds nothing.
assert.equal(offerFor(spec, { agents: ["atlas"] }, "").options.length, 1);
});
test("a name in both the fixed values and the fetched list is offered once", () => {
const spec = { values: [d("x")], values_from: "agents" };
const offer = offerFor(spec, { agents: ["x", "y"] }, "");
assert.deepEqual(
offer.options.map((o) => o.value),
["x", "y"],
);
});
test("the markers to fetch are the ones the schema names and the editor knows, once each", () => {
assert.deepEqual(markersIn(schema), ["agents", "repos"]);
assert.deepEqual(markersIn({ ...schema, fields: [], node_kinds: [] }), []);
});