185 files

This commit is contained in:
Home Assistant Version Control
2026-08-19 11:38:13 +00:00
parent 5f9330abd7
commit a718af6423
185 changed files with 16868 additions and 3088 deletions
@@ -101,6 +101,41 @@ describe("complete-dialog", () => {
expect("feedback" in msg).to.be.false;
expect("checklist_state" in msg).to.be.false;
expect("photo_doc_id" in msg).to.be.false;
expect("completed_at" in msg).to.be.false;
});
it("sends completed_at with seconds re-added when a backdate is picked (#133)", async () => {
const { el, sent } = await mount();
const dt = el.shadowRoot!.querySelector<HTMLInputElement>('input[type="datetime-local"]')!;
expect(dt, "backdate field rendered").to.exist;
dt.value = "2026-01-10T14:30";
dt.dispatchEvent(new Event("change"));
await el.updateComplete;
clickComplete(el);
await new Promise((r) => setTimeout(r, 10));
const msg = sent.find((m) => m.type === "maintenance_supporter/task/complete")!;
expect(msg).to.exist;
expect(msg.completed_at).to.equal("2026-01-10T14:30:00");
});
it("rejects a future completed_at client-side without a WS roundtrip (#133)", async () => {
const { el, sent } = await mount();
const future = new Date(Date.now() + 48 * 3600 * 1000);
const pad = (n: number) => String(n).padStart(2, "0");
const v = `${future.getFullYear()}-${pad(future.getMonth() + 1)}-${pad(future.getDate())}T12:00`;
const dt = el.shadowRoot!.querySelector<HTMLInputElement>('input[type="datetime-local"]')!;
dt.value = v;
dt.dispatchEvent(new Event("change"));
await el.updateComplete;
clickComplete(el);
await new Promise((r) => setTimeout(r, 10));
expect(sent.find((m) => m.type === "maintenance_supporter/task/complete")).to.equal(undefined);
await el.updateComplete;
expect(el.shadowRoot!.textContent).to.include("future");
});
it("attaches an uploaded photo as photo_doc_id", async () => {
@@ -63,6 +63,31 @@ describe("task-dialog trigger_config roundtrip closure (#103 class)", () => {
});
});
it("threshold: =/≠ limits and the all-combinator survive", async () => {
const tc = await saveRoundtrip({
type: "threshold",
entity_id: "sensor.a",
trigger_equals: 3,
trigger_not_equals: 1,
trigger_combinator: "all",
});
expect(tc).to.deep.include({
type: "threshold",
trigger_equals: 3,
trigger_not_equals: 1,
trigger_combinator: "all",
});
});
it("combinator defaults to any and is then omitted from the payload", async () => {
const tc = await saveRoundtrip({
type: "threshold",
entity_id: "sensor.a",
trigger_above: 80,
});
expect(tc.trigger_combinator, "any must not be persisted").to.equal(undefined);
});
it("threshold stored with ONLY plural entity_ids survives an edit (#106)", async () => {
// The Battery Fleet task's trigger has no singular entity_id; the save
// path gates on _triggerEntityId, so before the hydration fallback an
@@ -179,4 +204,34 @@ describe("task-dialog trigger_config roundtrip closure (#103 class)", () => {
entity_logic: "any",
});
});
it("compound: condition =/≠ limits and task-level combinator survive", async () => {
const tc = await saveRoundtrip({
type: "compound",
compound_logic: "AND",
trigger_combinator: "all",
conditions: [
{
type: "threshold",
entity_id: "sensor.a",
entity_ids: ["sensor.a"],
trigger_equals: 3,
trigger_not_equals: 1,
},
{
type: "threshold",
entity_id: "sensor.b",
entity_ids: ["sensor.b"],
trigger_above: 80,
},
],
});
expect(tc.trigger_combinator).to.equal("all");
const conds = tc.conditions as Array<Record<string, unknown>>;
expect(conds[0]).to.deep.include({
type: "threshold",
trigger_equals: 3,
trigger_not_equals: 1,
});
});
});