Files
houseplan-card/demo/smoke_tap_ctx.mjs
T
2026-08-30 07:48:16 +00:00

109 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 sr = () => c.shadowRoot || c.renderRoot;
// 1) Единый селектор содержит ровно пять актуальных действий;
// legacy cover и пустая авто-опция в UI не возвращаются.
c._setMode('devices'); await c.updateComplete;
// v1.39.0: у ЛАМП дефолт 'toggle', поэтому для проверки дефолта 'info'
// берём заведомо не-световое устройство
const dev = c._devices.find((d) => !d.virtual && d.primary && !d.primary.startsWith('light.'));
c._openMarkerDialog(dev); await c.updateComplete;
const sel = sr().querySelector('#marker-tap-action');
const values = sel ? [...sel.options].map((o) => o.value) : [];
out.fiveCurrentOptions = JSON.stringify(values) === JSON.stringify([
'info', 'more-info', 'toggle', 'run', 'none',
]);
out.noLegacyOptions = !values.includes('') && !values.includes('cover');
out.defaultInfo = sel && sel.value === 'info';
c._markerDialog = null; await c.updateComplete;
// 2) правый клик в Просмотре открывает more-info
c._setMode('view'); await c.updateComplete;
let moreInfo = null;
c._openMoreInfo = (eid) => { moreInfo = eid; };
const ev = new MouseEvent('contextmenu', { bubbles: true, cancelable: true });
c._ctxDevice(ev, dev);
out.ctxMoreInfo = moreInfo === dev.primary;
out.ctxPrevented = ev.defaultPrevented;
// 3) в редакторах правый клик не перехватывается
c._setMode('devices'); await c.updateComplete;
moreInfo = null;
const ev2 = new MouseEvent('contextmenu', { bubbles: true, cancelable: true });
c._ctxDevice(ev2, dev);
out.editorNative = moreInfo === null && !ev2.defaultPrevented;
// 4) виртуальное без primary → инфо-карточка
c._setMode('view'); await c.updateComplete;
const virt = c._devices.find((d) => d.virtual && !d.primary) || null;
if (virt) {
c._ctxDevice(new MouseEvent('contextmenu', { cancelable: true }), virt);
out.virtInfo = c._infoCard === virt;
c._infoCard = null;
} else out.virtInfo = 'no-virt';
// 5) card-wide tap_action игнорируется: без явного действия клик = инфо
c._config = { ...c._config, tap_action: 'toggle' };
const calls = [];
c.hass = { ...c.hass, callService: (d2, s2, data) => { calls.push([d2, s2, data]); return Promise.resolve(); } };
await c.updateComplete;
// card-wide tap_action игнорируется: НЕ-световое устройство остаётся на инфо
const plain = c._devices.find((d) => !d.virtual && d.primary
&& !d.primary.startsWith('light.') && !d.tapAction && !d.marker?.controls?.length);
if (plain) {
c._infoCard = null;
c._clickDevice(new MouseEvent('click'), plain);
out.cardTapIgnored = calls.length === 0 && !!c._infoCard;
c._infoCard = null;
} else out.cardTapIgnored = 'no-plain-device';
// 6) Явный none поглощает click/keyboard, но не запускает ни один эффект.
if (dev) {
const originalDevices = c._devices;
const noOp = { ...dev, tapAction: 'none', marker: { ...dev.marker, tap_action: 'none' } };
c._devices = originalDevices.map((item) => item.id === dev.id ? noOp : item);
let bindingChecks = 0;
let feedback = 0;
let toasts = 0;
let wsCalls = 0;
let serviceCalls = 0;
const originalBindingActive = c._deviceBindingActive;
const originalFeedback = c._startDevicePressFeedback;
const originalToast = c._showToast;
const originalHass = c.hass;
const originalCallWS = c.hass.callWS;
const originalCallService = c.hass.callService;
c._deviceBindingActive = () => { bindingChecks += 1; return true; };
c._startDevicePressFeedback = () => { feedback += 1; };
c._showToast = () => { toasts += 1; };
c.hass = {
...c.hass,
callWS: (...args) => { wsCalls += 1; return originalCallWS(...args); },
callService: (...args) => { serviceCalls += 1; return originalCallService(...args); },
};
c._infoCard = null;
c._tapConfirm = null;
let stopped = false;
c._clickDevice({ stopPropagation() { stopped = true; } }, noOp);
const enter = new KeyboardEvent('keydown', { key: 'Enter', cancelable: true });
c._keyDevice(enter, noOp);
const space = new KeyboardEvent('keydown', { key: ' ', cancelable: true });
c._keyDevice(space, noOp);
out.noneConsumesActivation = stopped && enter.defaultPrevented && space.defaultPrevented;
out.noneHasNoEffects = bindingChecks === 0 && feedback === 0 && toasts === 0
&& wsCalls === 0 && serviceCalls === 0 && c._infoCard === null && c._tapConfirm === null;
c._devices = originalDevices;
c._deviceBindingActive = originalBindingActive;
c._startDevicePressFeedback = originalFeedback;
c._showToast = originalToast;
c.hass = originalHass;
} else {
out.noneConsumesActivation = false;
out.noneHasNoEffects = false;
}
return out;
});
// значения зафиксированы прогоном на v1.43.1 и сверены с кодом (audit T1)
checkAll(res, {
"virtInfo": "no-virt",
});
await finish(browser, res);