mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 16:38:31 +00:00
Vacuum first-use path: materialize the marker, count rectangle rooms, fix the toasts
Audit HP-1540-01 (High): an auto-discovered vacuum has no config marker until the device dialog is saved once, yet the live-position section was already interactive. setVac, _vacSaveMatrix and auto-calibration all did cfg.markers.find(...) and silently bailed out — while the auto-calibration toast still claimed success. Every vacuum edit now materializes a minimal marker (same id/binding the dialog Save would produce), _vacSaveMatrix reports whether the write landed, and success toasts are gated on it. HP-1540-04: the auto-calibration room matcher accepted only polygon rooms and told users their room names did not match. It goes through the shared roomPoly() now, so legacy x/y/w/h rectangles count like everywhere else. HP-1540-06: the no-rooms/no-match/rough-fit toasts pointed at the removed point calibration; they now point at the fit panel that shipped instead, and docs/VACUUM.md Setup UX describes the actual UI. Also extracted vacMapIdFromAttrs as the explicit frontend half of the map-id contract (backend half lands with HP-1540-02). Regressions: demo/smoke_vacuum_firstuse.mjs starts from cfg.markers=[] (the fixture gap the audit called out) with rectangle plan rooms and a zero map_index, and fails 11 checks on the v1.54.0 bundle; i18n unit test asserts no point/точк wording in either language.
This commit is contained in:
+18
-1
@@ -1,6 +1,6 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { solveAffine, applyAffine, affineResidual, readVacTelemetry, autoCalibrate, thinPath, pushTrailPoint, isVacMoving, isVacSourceState } from '../test-build/vacuum.js';
|
||||
import { solveAffine, applyAffine, affineResidual, readVacTelemetry, autoCalibrate, thinPath, pushTrailPoint, isVacMoving, isVacSourceState, vacMapIdFromAttrs } from '../test-build/vacuum.js';
|
||||
|
||||
test('solveAffine recovers rotation+scale+mirror+offset exactly', () => {
|
||||
// target = mirror-X, rotate 90°, scale 0.02, offset (300, 400)
|
||||
@@ -135,3 +135,20 @@ test('fitMatrix/fitFromMatrix round-trip, mirror and quarters', async () => {
|
||||
const c2 = applyAffine(fitMatrix(r2), 500, 500);
|
||||
assert.ok(Math.abs(c2[0] - c[0]) < 1e-6 && Math.abs(c2[1] - c[1]) < 1e-6);
|
||||
});
|
||||
|
||||
// HP-1540-02: the map-id contract, mirrored by trails.py resolve_map_id —
|
||||
// the first value that is not null/undefined wins; zero and '' are valid ids.
|
||||
test('vacMapIdFromAttrs: first NOT-nullish value wins, zero survives', () => {
|
||||
assert.equal(vacMapIdFromAttrs({ map_index: 0 }), '0');
|
||||
assert.equal(vacMapIdFromAttrs({ map_index: '0' }), '0');
|
||||
assert.equal(vacMapIdFromAttrs({ map_name: '', selected_map: 'Floor' }), '');
|
||||
assert.equal(vacMapIdFromAttrs({ map_name: 'A', map_index: 0 }), 'A');
|
||||
assert.equal(vacMapIdFromAttrs({ current_map: 2 }), '2');
|
||||
assert.equal(vacMapIdFromAttrs({ selected_map: 'Vac' }), 'Vac');
|
||||
assert.equal(vacMapIdFromAttrs({}), 'default');
|
||||
});
|
||||
|
||||
test('readVacTelemetry keeps numeric zero map_index as map id (HP-1540-02)', () => {
|
||||
const t = readVacTelemetry({ vacuum_position: { x: 1, y: 2 }, map_index: 0 });
|
||||
assert.equal(t.mapId, '0');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user