New apps Added
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
/** Smoke-test the WS write paths used by the new section cards.
|
||||
*
|
||||
* 1. Enable vacation via vacation/update → expect enabled=true
|
||||
* 2. Set start/end + buffer → expect persisted
|
||||
* 3. Disable vacation → expect enabled=false
|
||||
* 4. Set monthly + yearly budget via global/update → expect persisted
|
||||
* 5. Create + rename + delete a group → expect roundtrip
|
||||
*/
|
||||
import http from "http";
|
||||
import WebSocket from "ws";
|
||||
|
||||
const HA = "http://localhost:8125";
|
||||
const WSURL = "ws://localhost:8125/api/websocket";
|
||||
|
||||
function post(p, body, ct = "application/json") {
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = typeof body === "string" ? body : JSON.stringify(body);
|
||||
const opts = { hostname: "localhost", port: 8125, path: p, method: "POST",
|
||||
headers: { "Content-Type": ct, "Content-Length": Buffer.byteLength(data) } };
|
||||
const req = http.request(opts, (r) => { let d = ""; r.on("data", (c) => (d += c)); r.on("end", () => resolve(JSON.parse(d))); });
|
||||
req.on("error", reject); req.write(data); req.end();
|
||||
});
|
||||
}
|
||||
|
||||
async function getToken() {
|
||||
const flow = await post("/auth/login_flow", { client_id: HA + "/", handler: ["homeassistant", null], redirect_uri: HA + "/" });
|
||||
const auth = await post(`/auth/login_flow/${flow.flow_id}`, { client_id: HA + "/", username: "dev", password: "dev" });
|
||||
const tok = await post("/auth/token", `grant_type=authorization_code&code=${auth.result}&client_id=${HA}/`, "application/x-www-form-urlencoded");
|
||||
return tok.access_token;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const token = await getToken();
|
||||
const ws = new WebSocket(WSURL);
|
||||
let id = 1;
|
||||
const pending = new Map();
|
||||
|
||||
ws.on("message", (raw) => {
|
||||
const m = JSON.parse(raw);
|
||||
if (m.type === "auth_required") {
|
||||
ws.send(JSON.stringify({ type: "auth", access_token: token }));
|
||||
} else if (m.type === "auth_ok") {
|
||||
pending.get("auth")?.resolve();
|
||||
} else if (m.type === "result") {
|
||||
const p = pending.get(m.id);
|
||||
if (p) {
|
||||
if (m.success === false) p.reject(new Error(JSON.stringify(m.error)));
|
||||
else p.resolve(m.result);
|
||||
pending.delete(m.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await new Promise((resolve) => { ws.once("open", resolve); });
|
||||
await new Promise((resolve) => pending.set("auth", { resolve }));
|
||||
|
||||
function call(payload) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const i = id++;
|
||||
pending.set(i, { resolve, reject });
|
||||
ws.send(JSON.stringify({ id: i, ...payload }));
|
||||
});
|
||||
}
|
||||
|
||||
let ok = 0, total = 0;
|
||||
function check(label, cond, value) {
|
||||
total++;
|
||||
if (cond) ok++;
|
||||
console.log(` ${cond ? "✓" : "✗"} ${label}${value !== undefined ? " — " + value : ""}`);
|
||||
}
|
||||
|
||||
console.log("\n=== Vacation enable + dates ===");
|
||||
await call({ type: "maintenance_supporter/vacation/update", enabled: true, start: "2026-06-01", end: "2026-06-15", buffer_days: 3 });
|
||||
let s = await call({ type: "maintenance_supporter/vacation/state" });
|
||||
check("enabled=true", s.enabled === true);
|
||||
check("start=2026-06-01", s.start === "2026-06-01", s.start);
|
||||
check("end=2026-06-15", s.end === "2026-06-15", s.end);
|
||||
check("buffer_days=3", s.buffer_days === 3, s.buffer_days);
|
||||
|
||||
console.log("\n=== Vacation disable ===");
|
||||
await call({ type: "maintenance_supporter/vacation/update", enabled: false });
|
||||
s = await call({ type: "maintenance_supporter/vacation/state" });
|
||||
check("enabled=false after disable", s.enabled === false);
|
||||
check("dates preserved", s.start === "2026-06-01" && s.end === "2026-06-15");
|
||||
|
||||
console.log("\n=== Budget update via global/update ===");
|
||||
await call({ type: "maintenance_supporter/global/update", settings: { budget_monthly: 200, budget_yearly: 2000 } });
|
||||
let bs = await call({ type: "maintenance_supporter/budget_status" });
|
||||
check("monthly=200", bs.monthly_budget === 200, bs.monthly_budget);
|
||||
check("yearly=2000", bs.yearly_budget === 2000, bs.yearly_budget);
|
||||
|
||||
// Restore previous values
|
||||
await call({ type: "maintenance_supporter/global/update", settings: { budget_monthly: 150, budget_yearly: 1500 } });
|
||||
|
||||
console.log("\n=== Groups: create + rename + delete ===");
|
||||
const created = await call({ type: "maintenance_supporter/group/create", name: "TmpTestGroup" });
|
||||
check("group created with id", typeof created.group_id === "string");
|
||||
const gid = created.group_id;
|
||||
|
||||
let g = await call({ type: "maintenance_supporter/groups" });
|
||||
check("new group present", !!g.groups[gid] && g.groups[gid].name === "TmpTestGroup", g.groups[gid]?.name);
|
||||
|
||||
await call({ type: "maintenance_supporter/group/update", group_id: gid, name: "RenamedGroup" });
|
||||
g = await call({ type: "maintenance_supporter/groups" });
|
||||
check("renamed", g.groups[gid]?.name === "RenamedGroup", g.groups[gid]?.name);
|
||||
|
||||
await call({ type: "maintenance_supporter/group/delete", group_id: gid });
|
||||
g = await call({ type: "maintenance_supporter/groups" });
|
||||
check("deleted", !g.groups[gid]);
|
||||
|
||||
console.log(`\n=== SUMMARY ===\n ${ok}/${total} checks passed`);
|
||||
ws.close();
|
||||
process.exit(ok === total ? 0 : 1);
|
||||
}
|
||||
|
||||
main().catch((e) => { console.error(e); process.exit(1); });
|
||||
Reference in New Issue
Block a user