mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
L1: memoized space model + open pairs (structural fingerprint key, epoch bumped synchronously at mutation time, not inside the debounce); hoisted per-room geometry out of the render loop; smoke asserts zero recomputation across state pushes. L4: openings get the 3 px drag threshold used by every other pipeline and only write when the geometry actually changed — taps open the dialog again. G2: interiorPoint() replaces the vertex mean, so island rooms inside concave (U/L) parents are accepted and their evenodd holes render; traced duplicates still are not containment. G3: segKey rounds before ordering — one shared wall, one key. B2: _check_write fails closed when the entry is unavailable. B3: layout/set honours expected_rev and returns the new rev. B4: config/set without expected_rev over a non-empty store logs a warning. B5: coordinates reject NaN/Infinity; spaces/rooms/markers/decor/layout capped. +2 unit tests (118), +2 backend tests (14), smoke_render_perf; docs same-commit
37 lines
1.8 KiB
JavaScript
37 lines
1.8 KiB
JavaScript
import { launch } from './serve.mjs';
|
|
const { page, browser } = await launch();
|
|
const res = await page.evaluate(async () => {
|
|
const out = {};
|
|
const c = window.__card;
|
|
// счётчики вызовов тяжёлой геометрии
|
|
let pairsCalls = 0, buildCalls = 0;
|
|
const origPairs = c._computeOpenPairs.bind(c);
|
|
c._computeOpenPairs = (...a) => { pairsCalls++; return origPairs(...a); };
|
|
const origBuild = c._buildModel.bind(c);
|
|
c._buildModel = (...a) => { buildCalls++; return origBuild(...a); };
|
|
// открыть границу, чтобы pairs было что считать
|
|
const sp = c._curSpaceCfg;
|
|
const r1 = sp.rooms[0], r2 = sp.rooms[1];
|
|
r1.open_to = [r2.id]; r2.open_to = [r1.id];
|
|
c._saveConfig(); c.requestUpdate(); await c.updateComplete;
|
|
pairsCalls = 0; buildCalls = 0;
|
|
// 10 «пушей состояния» от HA без изменения конфига
|
|
for (let i = 0; i < 10; i++) {
|
|
c.hass = { ...c.hass, states: { ...c.hass.states } };
|
|
await c.updateComplete;
|
|
}
|
|
out.pairsPerRender = pairsCalls; // должно быть 0: кэш живёт между рендерами
|
|
out.modelBuildsPer10Renders = buildCalls;
|
|
// правка конфига обязана инвалидировать кэш
|
|
const before = pairsCalls;
|
|
const r3 = sp.rooms[2] || sp.rooms[0];
|
|
r3.open_to = [r1.id]; r1.open_to = [r2.id, r3.id];
|
|
c._saveConfig(); c.requestUpdate(); await c.updateComplete;
|
|
out.invalidatesOnEdit = pairsCalls > before;
|
|
// геометрия по-прежнему правильная: пунктир на месте
|
|
out.dashesStillRendered = (c.shadowRoot || c.renderRoot).querySelectorAll('.openwall').length > 0;
|
|
return out;
|
|
});
|
|
console.log(JSON.stringify(res, null, 1));
|
|
await browser.close();
|