From ae958a0ad5eb1e3372b5e1d046d272362c16f2a6 Mon Sep 17 00:00:00 2001 From: CallMeTechie <34693633+CallMeTechie@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:05:28 +0200 Subject: [PATCH] fix(smarthome): tidy deferred TP3 rule minors + close coverage gaps - rule-limit 409 shows banner only (no double alert) - rule-name maxlength=20 client-side (3 themes) - limitWarn derives from deconzCapabilities.ruleLimit.warnAtGcRules (single source) - correct cancelConditionsFrom comment (daylight is eq-invertible, included) - tests: daylight trigger translation, unknown_button_action, deleteSchedule --- CHANGELOG.md | 12 ++++++++++++ public/js/smarthome-rules.js | 2 +- src/services/smarthome/rulesTranslate.js | 4 ++-- src/services/smarthome/smarthomeRules.js | 2 +- .../partials/modals/smarthome-rule-builder.njk | 2 +- .../partials/modals/smarthome-rule-builder.njk | 2 +- .../partials/modals/smarthome-rule-builder.njk | 2 +- tests/smarthome_deconz_rules_client.test.js | 5 +++++ tests/smarthome_rules_translate.test.js | 17 +++++++++++++++++ 9 files changed, 41 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dda1552..b1ceff5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [Unreleased] + +### Fixed +- Smart Home rules: rule-limit (409) now shows only the banner instead of banner + alert (double signal) +- Smart Home rules: rule-name field enforces the 20-char cap client-side (`maxlength`) across all three themes +- Smart Home rules: `limitWarn` now derives from `deconzCapabilities.ruleLimit.warnAtGcRules` (single source) instead of a duplicated magic threshold; corrected a stale comment on cancel-condition inversion + +### Tests +- Added coverage for the daylight trigger translation, the unknown-button-action rejection, and `deconzClient.deleteSchedule` + +--- + ## [1.113.1] — 2026-07-01 ### Fixes diff --git a/public/js/smarthome-rules.js b/public/js/smarthome-rules.js index 7e5ff793..21c01caf 100644 --- a/public/js/smarthome-rules.js +++ b/public/js/smarthome-rules.js @@ -299,7 +299,7 @@ else await api('/rules', { method: 'POST', body: JSON.stringify({ gateway_id: gatewayId, name, definition }) }); closeBuilder(); await loadRules(); } catch (e) { - if (e.status === 409) showLimit(e.message); // rule-limit / no-api-key + if (e.status === 409) { showLimit(e.message); return; } // rule-limit / no-api-key → banner only alert(e.message); // 400 = validation detail from the server } } diff --git a/src/services/smarthome/rulesTranslate.js b/src/services/smarthome/rulesTranslate.js index 0ce8ce7a..dba7dbe4 100644 --- a/src/services/smarthome/rulesTranslate.js +++ b/src/services/smarthome/rulesTranslate.js @@ -83,8 +83,8 @@ function relTime(mins) { } // Cancel-condition = trigger back to its inverse binary state. -// Only eq-conditions with 'true'/'false' values are binary-invertible. -// button (numeric code) and daylight (non-eq) are excluded. +// Only eq-conditions with 'true'/'false' values are binary-invertible (presence/open/water/daylight). +// button conditions (numeric buttonevent code) are excluded — not invertible. function cancelConditionsFrom(conditions) { return conditions .filter((c) => c.operator === 'eq' && (c.value === 'true' || c.value === 'false')) diff --git a/src/services/smarthome/smarthomeRules.js b/src/services/smarthome/smarthomeRules.js index ba690345..22bd084a 100644 --- a/src/services/smarthome/smarthomeRules.js +++ b/src/services/smarthome/smarthomeRules.js @@ -9,7 +9,7 @@ const caps = require('./deconzCapabilities'); const LIMIT_CODES = new Set(caps.ruleLimit.errorCodes); // deckt HTTP-Status UND 200-Body-Error-Codes ab (Spike Step 6) function isLimit(e) { return !!(e && LIMIT_CODES.has(e.code)); } function ruleLimitError() { const e = new Error('deconz rule limit reached'); e.code = 'DECONZ_RULE_LIMIT_REACHED'; return e; } -function limitWarn(gcRuleCount) { return gcRuleCount * 4 > 150; } // Worst-Case-Slot-Multiplikator (§8/§10) +function limitWarn(gcRuleCount) { return gcRuleCount >= caps.ruleLimit.warnAtGcRules; } // §8/§10: gc rules × Worst-Case-4-Slots > 150 ⇒ ≥ warnAtGcRules (=38) // Default-Factory: lokaler Gateway-Client wie index.js' privates clientForGateway (kein index-Import → kein Zirkularbezug). function defaultClientFactory(gatewayId) { diff --git a/templates/aurora/partials/modals/smarthome-rule-builder.njk b/templates/aurora/partials/modals/smarthome-rule-builder.njk index 014b6134..24831335 100644 --- a/templates/aurora/partials/modals/smarthome-rule-builder.njk +++ b/templates/aurora/partials/modals/smarthome-rule-builder.njk @@ -9,7 +9,7 @@