test: combine config and skill render checks

This commit is contained in:
Peter Steinberger
2026-04-17 19:13:44 +01:00
parent c47c4b3574
commit b6e55bf819
2 changed files with 14 additions and 65 deletions

View File

@@ -46,7 +46,7 @@ describe("config form renderer", () => {
"gateway.auth.token": { label: "Gateway Token", sensitive: true },
},
unsupportedPaths: analysis.unsupportedPaths,
value: {},
value: { allowFrom: ["+1"], bind: "auto" },
revealSensitive: true,
onPatch,
}),
@@ -79,22 +79,6 @@ describe("config form renderer", () => {
checkbox.checked = true;
checkbox.dispatchEvent(new Event("change", { bubbles: true }));
expect(onPatch).toHaveBeenCalledWith(["enabled"], true);
});
it("adds and removes array entries", () => {
const onPatch = vi.fn();
const container = document.createElement("div");
const analysis = rootAnalysis;
render(
renderConfigForm({
schema: analysis.schema,
uiHints: {},
unsupportedPaths: analysis.unsupportedPaths,
value: { allowFrom: ["+1"] },
onPatch,
}),
container,
);
const addButton = container.querySelector(".cfg-array__add");
expect(addButton).not.toBeUndefined();
@@ -105,22 +89,6 @@ describe("config form renderer", () => {
expect(removeButton).not.toBeUndefined();
removeButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
expect(onPatch).toHaveBeenCalledWith(["allowFrom"], []);
});
it("renders union literals as select options", () => {
const onPatch = vi.fn();
const container = document.createElement("div");
const analysis = rootAnalysis;
render(
renderConfigForm({
schema: analysis.schema,
uiHints: {},
unsupportedPaths: analysis.unsupportedPaths,
value: { bind: "auto" },
onPatch,
}),
container,
);
const tailnetButton = Array.from(
container.querySelectorAll<HTMLButtonElement>(".cfg-segmented__btn"),
@@ -223,12 +191,7 @@ describe("config form renderer", () => {
);
expect(tags).toContain("security");
expect(tags).toContain("secret");
});
it("filters by tag query", () => {
const onPatch = vi.fn();
const container = document.createElement("div");
const analysis = rootAnalysis;
render(
renderConfigForm({
schema: analysis.schema,
@@ -330,7 +293,7 @@ describe("config form renderer", () => {
});
it("accepts renderable unions", () => {
const schema = {
const renderableUnionSchema = {
type: "object",
properties: {
mixed: {
@@ -338,23 +301,19 @@ describe("config form renderer", () => {
},
},
};
const analysis = analyzeConfigSchema(schema);
let analysis = analyzeConfigSchema(renderableUnionSchema);
expect(analysis.unsupportedPaths).not.toContain("mixed");
});
it("supports nullable types", () => {
const schema = {
const nullableSchema = {
type: "object",
properties: {
note: { type: ["string", "null"] },
},
};
const analysis = analyzeConfigSchema(schema);
analysis = analyzeConfigSchema(nullableSchema);
expect(analysis.unsupportedPaths).not.toContain("note");
});
it("ignores untyped additionalProperties schemas", () => {
const schema = {
const untypedAdditionalPropertiesSchema = {
type: "object",
properties: {
channels: {
@@ -371,7 +330,7 @@ describe("config form renderer", () => {
},
},
};
const analysis = analyzeConfigSchema(schema);
analysis = analyzeConfigSchema(untypedAdditionalPropertiesSchema);
expect(analysis.unsupportedPaths).not.toContain("channels");
});

View File

@@ -98,12 +98,14 @@ describe("renderSkills", () => {
}
});
it("opens the skill detail dialog as a modal and routes close events", async () => {
it("opens detail dialogs and routes ClawHub actions", async () => {
const container = document.createElement("div");
const onDetailClose = vi.fn();
const showModal = vi.fn(function (this: HTMLDialogElement) {
this.setAttribute("open", "");
});
const onClawHubDetailOpen = vi.fn();
const onClawHubInstall = vi.fn();
installDialogMethod("showModal", showModal);
installDialogMethod("close", function (this: HTMLDialogElement) {
@@ -128,12 +130,6 @@ describe("renderSkills", () => {
container.querySelector<HTMLButtonElement>(".md-preview-dialog__header .btn")?.click();
expect(onDetailClose).toHaveBeenCalledTimes(1);
});
it("renders ClawHub search results and routes detail/install actions", async () => {
const container = document.createElement("div");
const onClawHubDetailOpen = vi.fn();
const onClawHubInstall = vi.fn();
render(
renderSkills(
@@ -156,7 +152,7 @@ describe("renderSkills", () => {
);
await Promise.resolve();
const text = normalizeText(container);
let text = normalizeText(container);
expect(text).toContain("GitHub");
expect(text).toContain("GitHub integration for OpenClaw");
expect(text).toContain("v1.2.3");
@@ -170,15 +166,9 @@ describe("renderSkills", () => {
expect(onClawHubDetailOpen).toHaveBeenCalledWith("github");
expect(onClawHubInstall).toHaveBeenCalledTimes(1);
expect(onClawHubInstall).toHaveBeenCalledWith("github");
});
it("opens the ClawHub detail dialog and renders install feedback", async () => {
const container = document.createElement("div");
const showModal = vi.fn(function (this: HTMLDialogElement) {
this.setAttribute("open", "");
});
const onClawHubInstall = vi.fn();
installDialogMethod("showModal", showModal);
onClawHubInstall.mockClear();
showModal.mockClear();
render(
renderSkills(
@@ -215,7 +205,7 @@ describe("renderSkills", () => {
await Promise.resolve();
expect(showModal).toHaveBeenCalledTimes(1);
const text = normalizeText(container);
text = normalizeText(container);
expect(text).toContain("rate limited");
expect(text).toContain("Installed github");
expect(text).toContain("By OpenClaw (@openclaw)");