Files
houseplan-card/test/furniture-stroke-contract.test.mjs
2026-09-02 21:56:04 +00:00

52 lines
2.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
const card = readFileSync(new URL('../src/houseplan-card.ts', import.meta.url), 'utf8');
const editor = readFileSync(new URL('../src/houseplan-editor-runtime.ts', import.meta.url), 'utf8');
test('#361 saved furniture and placement preview share the physical screen resolver', () => {
const preview = editor.slice(
editor.indexOf('public _renderFurniturePlacementPreview('),
editor.indexOf('public _furnLive('),
);
const layer = card.slice(
card.indexOf('private _renderDecorLayer('),
card.indexOf('// ================= shared editor secondary surface'),
);
assert.match(preview, /furnitureStrokePx\([\s\S]*decorCmToUnits\([\s\S]*furnitureScreenScale/);
assert.match(preview, /stroke-width=\$\{strokeWidth\}/);
assert.doesNotMatch(
preview,
/stroke-width=\$\{decorCmToUnits/,
'preview must not bypass the camera-aware furniture resolver',
);
// #376(г): the compensation models the flat camera; the labs iso projection
// must fall back to 1 so furniture strokes track ordinary decor there.
assert.match(layer,
/const furnitureScreenScale = this\._renderProjection === 'iso' \? 1 : furniturePlanScreenScale\(/);
assert.match(layer, /const visibleStrokePx = furnitureStrokePx\(strokeWidth, furnitureScreenScale\)/);
assert.match(layer, /stroke-width="\$\{visibleStrokePx\}"/);
assert.match(layer, /_renderFurniturePlacementPreview\(furnitureScreenScale\)/);
assert.equal(
(layer.match(/furniturePlanScreenScale\(/g) || []).length,
1,
'the viewport scale is resolved once for the whole decor layer',
);
});
test('#361 keeps local anisotropic protection and screen-oriented erase hit separate', () => {
const layer = card.slice(
card.indexOf('private _renderDecorLayer('),
card.indexOf('// ================= shared editor secondary surface'),
);
assert.ok(
(layer.match(/vector-effect="non-scaling-stroke"/g) || []).length >= 2,
'saved and erase paths must keep rejecting the local artwork scale',
);
assert.match(layer, /class="dshape derasehit"[\s\S]*vector-effect="non-scaling-stroke"/);
assert.match(layer, /data-hp="decor"[\s\S]*data-kind="\$\{sh\.kind\}"[\s\S]*data-symbol="\$\{sh\.symbol\}"/);
});