mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
feat v1.14.0: per-space display settings, hand-drawn spaces, manual-testing checklist
- space dialog 'Display' section: room borders/names toggles, color+opacity, fill by zigbee signal or lights (tri-state: on/off/no-lights) - draggable room name labels persisted as layout rl_<roomId> - 'no image, outline by hand' space source with canvas orientation; image optional now; switching an existing space to draw detaches its plan - demo/ synthetic-home harness lives in the repo (serve.mjs + smokes + icons gen) - docs/TESTING.md checklist (same-commit update policy); self-run found and fixed: plan_url not detached on image->draw, _stateClass crash on states without entity_id; perf measured (162 devices ~14ms build) - backend: SPACE_DISPLAY_SCHEMA validation (+test)
This commit is contained in:
+13
-1
@@ -1,6 +1,6 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { buildDevices, lightGroups, primaryEntity, lqiFor, tempFor } from '../test-build/devices.js';
|
||||
import { buildDevices, lightGroups, primaryEntity, lqiFor, tempFor, areaLights } from '../test-build/devices.js';
|
||||
import { compileIconRules } from '../test-build/rules.js';
|
||||
|
||||
/** Minimal fake hass around the pieces buildDevices reads. */
|
||||
@@ -158,3 +158,15 @@ test('lqiFor: dedicated sensor wins over attribute duplication; tempFor rounds',
|
||||
assert.equal(lqiFor(h, ['sensor.x_linkquality', 'sensor.temp']), 119); // avg(120,118)
|
||||
assert.equal(tempFor(h, ['sensor.temp']), 22.5);
|
||||
});
|
||||
|
||||
test('areaLights: on / off / none tri-state', () => {
|
||||
const hass = mkHass({ states: { 'light.a': { state: 'on' }, 'light.b': { state: 'off' } } });
|
||||
const devs = [
|
||||
{ area: 'living', entities: ['light.a', 'sensor.x'] },
|
||||
{ area: 'kitchen', entities: ['light.b'] },
|
||||
{ area: 'bath', entities: ['sensor.hum'] },
|
||||
];
|
||||
assert.equal(areaLights(hass, devs, 'living'), 'on');
|
||||
assert.equal(areaLights(hass, devs, 'kitchen'), 'off');
|
||||
assert.equal(areaLights(hass, devs, 'bath'), 'none');
|
||||
});
|
||||
|
||||
+28
-1
@@ -2,7 +2,7 @@ import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
lqiColor, snapToGrid, segKey, samePoint, pointInPolygon, markerIdForBinding, averageLqi,
|
||||
fitView, declump, safeUrl, resolveTapAction, floorsOf, subst,
|
||||
fitView, declump, safeUrl, resolveTapAction, floorsOf, subst, spaceDisplayOf, roomFillColor,
|
||||
} from '../test-build/logic.js';
|
||||
import {
|
||||
iconFor, compileIconRules, isValidPattern, iconFromDeviceClasses,
|
||||
@@ -212,3 +212,30 @@ test('subst: replaces every occurrence of a placeholder, ignores unknown', () =>
|
||||
assert.equal(subst('no vars'), 'no vars');
|
||||
assert.equal(subst('keep {unknown}', { n: 1 }), 'keep {unknown}');
|
||||
});
|
||||
|
||||
test('spaceDisplayOf: defaults differ for spaces with and without a plan', () => {
|
||||
const withPlan = spaceDisplayOf({ plan_url: '/x.svg' });
|
||||
assert.equal(withPlan.showBorders, false);
|
||||
assert.equal(withPlan.showNames, false);
|
||||
assert.equal(withPlan.fill, 'none');
|
||||
const noPlan = spaceDisplayOf({ plan_url: null });
|
||||
assert.equal(noPlan.showBorders, true);
|
||||
assert.equal(noPlan.showNames, true);
|
||||
const s = spaceDisplayOf({ plan_url: null, settings: { show_borders: false, room_color: '#ff0000', room_opacity: 2, fill_mode: 'lqi' } });
|
||||
assert.equal(s.showBorders, false);
|
||||
assert.equal(s.color, '#ff0000');
|
||||
assert.equal(s.opacity, 1);
|
||||
assert.equal(s.fill, 'lqi');
|
||||
const g = spaceDisplayOf({ settings: { room_color: 'javascript:alert(1)', fill_mode: 'weird' } });
|
||||
assert.equal(g.color, '#3ea6ff');
|
||||
assert.equal(g.fill, 'none');
|
||||
});
|
||||
|
||||
test('roomFillColor: lqi gradient, light tri-state, none', () => {
|
||||
assert.equal(roomFillColor('none', 200, 'on'), null);
|
||||
assert.equal(roomFillColor('lqi', null, 'on'), null);
|
||||
assert.equal(roomFillColor('lqi', 180, 'none'), 'hsl(120, 85%, 55%)');
|
||||
assert.equal(roomFillColor('light', null, 'on'), '#ffd45c');
|
||||
assert.equal(roomFillColor('light', null, 'off'), '#9aa0a6');
|
||||
assert.equal(roomFillColor('light', null, 'none'), null);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user