import { describe, expect, it } from "vitest"; import { extractSaveError, saveLabelFor } from "./settings"; // The settings page's save feedback keys off the data-settings-save // attribute stamped on each form in templates/admin_settings.templ. If a // form loses the attribute (or a new save surface is added without one), // its saves silently regress to "no indicator" — the bug this module // exists to fix. These pins make that drift a test failure. function el(attrs: Record): Element { const node = document.createElement("form"); for (const [k, v] of Object.entries(attrs)) node.setAttribute(k, v); return node; } describe("saveLabelFor", () => { it("maps every stamped form to its success label", () => { expect(saveLabelFor(el({ "data-settings-save": "settings" }))).toBe("Settings saved"); expect(saveLabelFor(el({ "data-settings-save": "scan" }))).toBe("Scan settings saved"); expect(saveLabelFor(el({ "data-settings-save": "tunable" }))).toBe("Setting saved"); }); it("returns null for non-settings elements (listener filter)", () => { expect(saveLabelFor(document.createElement("div"))).toBeNull(); expect(saveLabelFor(null)).toBeNull(); expect(saveLabelFor(undefined)).toBeNull(); expect(saveLabelFor(el({ "data-settings-save": "unknown-kind" }))).toBeNull(); }); }); describe("extractSaveError", () => { function xhrWith(responseText: string, status: number): XMLHttpRequest { const xhr = new XMLHttpRequest(); Object.defineProperty(xhr, "responseText", { value: responseText }); Object.defineProperty(xhr, "status", { value: status }); return xhr; } it("surfaces the JSON error field the config endpoints return", () => { expect(extractSaveError(xhrWith(`{"error":"invalid timezone"}`, 400))).toBe("invalid timezone"); }); it("falls back to the message field when present", () => { expect(extractSaveError(xhrWith(`{"message":"boom"}`, 500))).toBe("boom"); }); it("never puts markup in a toast (tunable endpoint returns an HTML span on 400)", () => { const msg = extractSaveError( xhrWith(`value rejected`, 400), ); expect(msg).toBe("Save failed (HTTP 400)"); expect(msg).not.toContain("<"); }); it("degrades to a status line for empty bodies and network failures", () => { expect(extractSaveError(xhrWith("", 0))).toBe("Save failed (HTTP 0)"); expect(extractSaveError(undefined)).toBe("Save failed (HTTP 0)"); }); });