mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
55 lines
3.0 KiB
JavaScript
55 lines
3.0 KiB
JavaScript
// review CR-1: exercise EVERY actuation path and prove locks/alarms are safe
|
||
import { launch, checkAll, finish } from './serve.mjs';
|
||
const { page, browser } = await launch();
|
||
const res = await page.evaluate(async () => {
|
||
const out = {};
|
||
const c = window.__card;
|
||
const calls = [];
|
||
c.hass = { ...c.hass, callService: (d, s, data) => { calls.push(`${d}.${s}:${data.entity_id}`); return Promise.resolve(); },
|
||
states: { ...c.hass.states,
|
||
'lock.front_door': { state: 'locked', attributes: { friendly_name: 'Front door' } },
|
||
'alarm_control_panel.home': { state: 'armed_away', attributes: {} } } };
|
||
await c.updateComplete;
|
||
c._setMode('view'); await c.updateComplete;
|
||
const lockCalls = () => calls.filter((x) => x.includes('lock.') || x.includes('alarm_control_panel.'));
|
||
// 1) тап по значку устройства с замком
|
||
const lockDev = c._devices.find((d) => d.entities?.some((e) => e.startsWith('lock.'))) || c._devices[0];
|
||
const fake = { ...lockDev, primary: 'lock.front_door', tapAction: 'toggle',
|
||
marker: { ...(lockDev.marker || {}), tap_action: 'toggle' } };
|
||
c._clickDevice(new MouseEvent('click'), fake);
|
||
out.iconTapSafe = lockCalls().length === 0;
|
||
// 2) controls[] с замком внутри
|
||
const withControls = { ...fake, tapAction: 'toggle',
|
||
marker: { controls: ['lock.front_door', 'alarm_control_panel.home'], tap_action: 'toggle' } };
|
||
c._clickDevice(new MouseEvent('click'), withControls);
|
||
out.controlsSafe = lockCalls().length === 0;
|
||
// 3) карточка устройства: замок отдаётся в more-info, а не тумблером
|
||
const kinds = c._cardEntities({ ...fake, entities: ['lock.front_door', 'alarm_control_panel.home'] });
|
||
out.cardNoToggleForLocks = kinds.every((k) => k.kind !== 'toggle');
|
||
c._cardToggle('lock.front_door');
|
||
c._cardToggle('alarm_control_panel.home');
|
||
out.cardToggleRefuses = lockCalls().length === 0;
|
||
// 4) кнопка в карточке двери — единственная разрешённая поверхность, и спрашивает подтверждение
|
||
c._openingEntityAvailable = () => true;
|
||
c._openingInfo = {
|
||
id: 'front', type: 'door', rx: 0.5, ry: 0.5, len_cm: 90, lock: 'lock.front_door',
|
||
};
|
||
let pending = c._lockAction('lock.front_door', 'unlock');
|
||
await c.updateComplete;
|
||
out.unlockAsksConfirm = c._dangerConfirm?.request?.key === 'unlock' && lockCalls().length === 0;
|
||
c._cancelDangerConfirm();
|
||
await pending;
|
||
pending = c._lockAction('lock.front_door', 'unlock');
|
||
await c.updateComplete;
|
||
(c.shadowRoot || c.renderRoot)
|
||
.querySelector('hp-confirm .danger-confirm-footer .btn.warn, hp-confirm .danger-confirm-footer .btn.on')?.click();
|
||
await pending;
|
||
out.unlockAfterConfirm = calls.at(-1) === 'lock.unlock:lock.front_door';
|
||
// запирание не спрашивает
|
||
await c._lockAction('lock.front_door', 'lock');
|
||
out.lockNoConfirm = c._dangerConfirm === null && calls.at(-1) === 'lock.lock:lock.front_door';
|
||
return out;
|
||
});
|
||
checkAll(res);
|
||
await finish(browser, res);
|