mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
fix: keep a stored zero draft thickness and guard both thickness writers (#313)
По находкам CODE-REVIEW-313-r1: High — резолвер больше не превращает сохранённый 0 сегмента драфта в 15: ноль — легитимное значение (docs/WALL-THICKNESS.md §6), к дефолту 15 падает только ОТСУТСТВУЮЩАЯ запись. Смок дополнен: hit нулевого сегмента несёт 0, диалог показывает пустое поле, Apply без правки отказывает и не портит данные. Medium — гвард #278 усилен: паттерн допускает перенос строки после скобки, и счётчик требует РОВНО ДВЕ точки коммита wall_thickness — мутация любой из них (включая новую независимую) красит юнит; краснота второго патча мутанта проверена изолированным исполнением. Issue: #313 User-Visible: no
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -20,7 +20,8 @@ const out = await page.evaluate(async () => {
|
||||
// exact duplicate over the room's top edge — the #308 layout
|
||||
{ id: 'overlay', a: [0.1, 0.1], b: [0.5, 0.1], cm: 30 },
|
||||
],
|
||||
room_drafts: [{ id: 'saved-draft', points: [[0.6, 0.5], [0.9, 0.5]], segments: [{ cm: 12 }] }],
|
||||
room_drafts: [{ id: 'saved-draft', points: [[0.6, 0.5], [0.9, 0.5], [0.9, 0.7]],
|
||||
segments: [{ cm: 12 }, { cm: 0 }] }],
|
||||
}], markers: [], settings: {} };
|
||||
card._layout = {}; card._space = 'wt'; card._modelCache = null; card._frame = null;
|
||||
card._cfgEpoch++; card._setMode('plan'); card._tool = 'wallthick'; await update();
|
||||
@@ -52,6 +53,15 @@ const out = await page.evaluate(async () => {
|
||||
card._wallDialog = { ...card._wallDialog, value: '18' };
|
||||
card._wallThickApply(false); await update();
|
||||
result.draftWritten = sp().room_drafts[0].segments[0].cm === 18;
|
||||
// CODE-REVIEW-313-r1 High: a STORED zero must surface as zero (empty field),
|
||||
// and Apply without editing must refuse — never silently turn 0 into 15.
|
||||
const zeroSegHit = card._wallThickHit([0.9 * NORM_W, 0.6 * NORM_W]);
|
||||
result.zeroSegmentSurvives = zeroSegHit?.source?.kind === 'draft' && zeroSegHit.cm === 0;
|
||||
card._wallThickClick([0.9 * NORM_W, 0.6 * NORM_W]); await update();
|
||||
result.zeroSegmentFieldEmpty = card._wallDialog?.value === '';
|
||||
card._wallThickApply(false); await update();
|
||||
result.zeroSegmentNotCorrupted = sp().room_drafts[0].segments[1].cm === 0;
|
||||
card._wallDialog = null; await update();
|
||||
// 4) #308 overlap: the independent wall owns the hit
|
||||
const overlapHit = card._wallThickHit([0.3 * NORM_W, 0.1 * NORM_W]);
|
||||
result.overlapPrefersIndependent = overlapHit?.source?.kind === 'partition'
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
||||
"version": 1,
|
||||
"fixture": "synthetic-only",
|
||||
"chromium": "151.0.7922.34",
|
||||
"sourceFingerprint": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceFingerprint": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"captureScriptSha256": "ce2e9542fed9dade3085be87d16f69adb2ac8262893ad78ad966b1b9673f2983",
|
||||
"command": "npm run build && node demo/docs/capture.mjs",
|
||||
"scenarios": {
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "36223106c073f07d8cc3ecf8eaab37192ebb2687daba65c5c21047d0b7890de0"
|
||||
},
|
||||
"view-touch": {
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "41e3ba67f8db0e98f26f484293af83ef937c369ca5ca6a59a3350d8954c906f4"
|
||||
},
|
||||
"space-create": {
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "c33a7279165a4cec6fa6fadb6fd08cd967e082a17fe101ef442d27d36ae59b6b"
|
||||
},
|
||||
"room-contour-close": {
|
||||
@@ -47,7 +47,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "b4777162eae89e0d95801721330bcd74ba761624b82b3362069d7e2d38317e08"
|
||||
},
|
||||
"plan-context-tray": {
|
||||
@@ -58,7 +58,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "c0e28edf82f45ccc6df568d3023b681e9e4394262ad34c1605fe9eacdb57a390"
|
||||
},
|
||||
"device-editor": {
|
||||
@@ -69,7 +69,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "d0ffd31ce80bfde21ab75da356a5fc1af38246f2b301030880320620c228d89d"
|
||||
},
|
||||
"device-display-preview": {
|
||||
@@ -80,7 +80,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "2cdabae1f89c3286e4fac0ce30f757ee1690b707ab8a5488748b7cd420626160"
|
||||
},
|
||||
"background-editor": {
|
||||
@@ -91,7 +91,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "30147bb00a90eea7136b4cee30995f6e6a9217b5132f3e8d3ad7471413b1af8a"
|
||||
},
|
||||
"room-card": {
|
||||
@@ -102,7 +102,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "029a3e69ec647a8a370d99e6bb7f9225833c526739076022f6b52ba54bff30ea"
|
||||
},
|
||||
"device-info": {
|
||||
@@ -113,7 +113,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "5fd7e29594eae558c770dc79fd15551d251cfcf7c8e5e335526f8bed3e517e07",
|
||||
"sourceSha256": "0a6db3a8e3e3cb63b28f1152f37a4a2dc0f9dba155d4e933ac90410eb578e56c",
|
||||
"imageSha256": "dd492f53150b7149085daada5cce9eeae9bde9e7ea1d86679a54b3041f72f517"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11971,9 +11971,14 @@ class HouseplanCard extends LitElement {
|
||||
for (let i = 0; i + 1 < draft.points.length; i++) {
|
||||
const a = [draft.points[i][0], draft.points[i][1]];
|
||||
const b = [draft.points[i + 1][0], draft.points[i + 1][1]];
|
||||
// Zero is a legitimate stored value («Empty / 0 leaves the new wall
|
||||
// thin», docs/WALL-THICKNESS.md §6) — only a MISSING record falls
|
||||
// back to the drawing default. `|| 15` would silently turn a stored
|
||||
// 0 into 15 on Apply (CODE-REVIEW-313-r1 High).
|
||||
const rawCm = Number(draft.segments[i]?.cm);
|
||||
offer({
|
||||
a, b, roomId: '', segs: [[a[0], a[1], b[0], b[1]]],
|
||||
open: false, cm: Number(draft.segments[i]?.cm) || 15,
|
||||
open: false, cm: Number.isFinite(rawCm) ? rawCm : 15,
|
||||
source: { kind: 'draft', id: draft.id, segment: i },
|
||||
}, distToSegment(raw, [a[0], a[1], b[0], b[1]]), true);
|
||||
}
|
||||
|
||||
@@ -104,8 +104,17 @@ test('#278 production source routes physical writers through one barrier and dec
|
||||
'physical_move', 'resize_room', 'close_boundary', 'open_boundary', 'wall_thickness',
|
||||
'move_opening', 'delete_opening', 'merge_rooms', 'contour_to_partitions',
|
||||
]) {
|
||||
assert.match(source, new RegExp(`_commitPhysicalGeometry\\(this\\._t\\('history\\.${historyKey}'`), historyKey);
|
||||
// The pattern tolerates a line break after the opening parenthesis: a
|
||||
// wrapped call must not slip past the barrier check (CODE-REVIEW-313-r1).
|
||||
assert.match(source,
|
||||
new RegExp(`_commitPhysicalGeometry\\(\\s*this\\._t\\('history\\.${historyKey}'`), historyKey);
|
||||
}
|
||||
// #313 introduced a second thickness commit point (independent masonry).
|
||||
// BOTH must go through the barrier: replacing either with _recordGeometry
|
||||
// reduces the count and reddens this line.
|
||||
assert.equal(
|
||||
(source.match(/_commitPhysicalGeometry\(\s*this\._t\('history\.wall_thickness'/g) || []).length,
|
||||
2, 'both thickness writers route through the common barrier');
|
||||
assert.match(source, /_commitPhysicalGeometry\([\s\S]{0,160}history\.edit_opening/);
|
||||
assert.match(source, /_commitPhysicalGeometry\([\s\S]{0,160}history\.split_room/);
|
||||
assert.match(source, /_recordGeometry\(this\._t\('history\.decor_edit'/);
|
||||
|
||||
Reference in New Issue
Block a user