user form, backup: two gaps the mockup comparison found

Owner, 2026-10-18: "Что ещё из макетов мы также прошляпили?" - every mockup
held against the panel; two small gaps beyond the queues:

- user.html: with All ticked, a list's single domains are disabled
  (mockup user.html:34-36). A panel.js show-when rule with disable: the
  boxes data-single-out / data-single-in follow data-all-out / data-all-in,
  at load and on change; a disabled box is not submitted, which the server
  ignores with All anyway. node test testdata/alldomains_test.js (fails on
  the previous panel.js).
- backup.html: "domain's settings" is a link, to Outbound › Domains (mockup
  backup.html:35 links a domain's settings; a server page has no one domain).

Tests: go test ./internal/web/... pass, TestPanelJS with node 24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-18 23:30:44 +03:00
co-authored by Claude Opus 5.5
parent 6db3704711
commit 6edf8314bc
8 changed files with 106 additions and 10 deletions
+56
View File
@@ -0,0 +1,56 @@
// The user form (Server › Users): with "All outbound domains" ticked the
// single outbound domains are disabled, as the mockup user.html draws them, and
// enabled again when it is unticked; the inbound list follows its own All the
// same way, and neither touches the other. Run by TestPanelJS
// (paneljs_test.go): node alldomains_test.js <panel.js>. Exits non-zero with
// what went wrong.
"use strict";
const fs = require("fs");
const vm = require("vm");
const failures = [];
function check(cond, what) {
if (!cond) failures.push(what);
}
const listeners = {};
const box = (attr, checked) => ({ attr, checked, disabled: false, matches: (sel) => sel === "input[" + attr + "]", closest: () => form });
const allOut = box("data-all-out", true);
const allIn = box("data-all-in", false);
const singlesOut = [box("data-single-out", true), box("data-single-out", false)];
const singlesIn = [box("data-single-in", true)];
const form = {
querySelectorAll: (sel) =>
sel === "input[data-single-out]" ? singlesOut : sel === "input[data-single-in]" ? singlesIn : [],
};
const document = {
hidden: false,
addEventListener: (type, fn) => (listeners[type] = listeners[type] || []).push(fn),
body: { addEventListener() {} },
getElementById: () => null,
querySelectorAll: (sel) =>
sel === "input[data-all-out]" ? [allOut] : sel === "input[data-all-in]" ? [allIn] : [],
};
vm.runInNewContext(fs.readFileSync(process.argv[2], "utf8"), {
document, window: { addEventListener() {} }, htmx: { config: {}, ajax() {} }, setTimeout, clearTimeout, Date, Object, Math, console,
});
const fire = (type, ev) => (listeners[type] || []).forEach((fn) => fn(ev));
fire("DOMContentLoaded", {});
check(singlesOut.every((b) => b.disabled), "at load, with All outbound ticked, the single outbound domains are not disabled");
check(singlesIn.every((b) => !b.disabled), "at load, with All inbound unticked, a single inbound domain is disabled");
allOut.checked = false;
fire("change", { target: allOut });
check(singlesOut.every((b) => !b.disabled), "unticking All outbound leaves the single outbound domains disabled");
check(singlesOut[0].checked && !singlesOut[1].checked, "unticking All outbound changed which single domains are ticked");
allIn.checked = true;
fire("change", { target: allIn });
check(singlesIn.every((b) => b.disabled), "ticking All inbound does not disable the single inbound domains");
check(singlesOut.every((b) => !b.disabled), "ticking All inbound disabled the outbound list");
if (failures.length) {
console.error(failures.join("\n"));
process.exit(1);
}