Files
NestQuest/frontend/tests/render-party-board.mjs
T
overseer 9e9b8c5938 Discover the party board's children from the household roster (Feature 20)
The board rendered nothing until a parent hand-wrote child_order with
each child's slug — the DAKOS bring-up gap. The household rollup now
publishes an ordered child_roster attribute (snapshot sort_order, each
entry carrying the slug the way HA derives entity ids, so the card can
build sensor.nestquest_<slug>_...), and the card discovers its plates
from it when the config carries no child_order; a supplied child_order
still wins. The rollups' existing per-child children counts attribute
is unchanged. Render tests drive the committed bundle under jsdom, so
the discovery contract is asserted on the artifact HACS ships.
2026-09-23 09:35:42 -04:00

57 lines
1.8 KiB
JavaScript

/**
* Render the built party-board card under jsdom and print its plates.
*
* Usage: node render-party-board.mjs < spec.json
*
* The spec JSON carries {bundle, tag, config, hass}; stdout receives one JSON
* object {plates, html} where plates is the ordered plate list the shadow DOM
* renders (name + present/away/unknown kind). The Python panel tests drive
* this harness so the assertions run against the exact bundle HACS ships.
*/
import { readFileSync } from "node:fs";
import { pathToFileURL } from "node:url";
import { JSDOM } from "jsdom";
const spec = JSON.parse(readFileSync(0, "utf8"));
const dom = new JSDOM("<!doctype html><html><body></body></html>", {
url: "http://homeassistant.local/nestquest/board",
pretendToBeVisual: true,
});
// Expose the jsdom globals the Lit bundle expects. Node's own intrinsics
// (Object, Array, ...) are kept — only what globalThis lacks is copied.
for (const key of Object.getOwnPropertyNames(dom.window)) {
if (!(key in globalThis)) {
try {
globalThis[key] = dom.window[key];
} catch {
// jsdom getters may throw on access; the card does not need them.
}
}
}
globalThis.window = dom.window;
await import(pathToFileURL(spec.bundle).href);
const element = document.createElement(spec.tag);
element.setConfig(spec.config);
element.hass = spec.hass;
document.body.appendChild(element);
await element.updateComplete;
const plates = [
...element.shadowRoot.querySelectorAll(".plates .plate"),
].map((plate) => ({
name: plate.querySelector(".name")?.textContent?.trim() ?? "",
kind: plate.classList.contains("unknown")
? "unknown"
: plate.classList.contains("away")
? "away"
: "present",
}));
const payload = JSON.stringify({ plates, html: element.shadowRoot.innerHTML });
await new Promise((resolve) => process.stdout.write(payload, () => resolve()));
process.exit(0);