Files
Aislo/resources/tester/test_cross_pan_bounds.mjs
T
eomsangdonandClaude Opus 5 0ef32b5279 chore(tester): 시험을 resources/tester/ 로 옮김 — 창끼리 건너가게
⚠ **뿌리** — `tmp/` 는 창 사이에 안 건너감(실측 확인: 상대 창이 놓은 `tmp/_sync_probe.txt`
가 시간을 두고 두 번 봐도 안 보임). 그래서 **정본(등록부 스키마)만 건너가고 그것을 읽는
시험은 안 건너가** 오늘 두 번, 같은 시험이 **연 창은 통과·받은 창은 실패**가 됐음.

- `tmp/tests/*` 를 `resources/tester/` 로 **복사**(127 파일). 내용은 **한 줄도 안 고침**
- `tmp/tests` 는 **남겨 둠** — 되돌릴 자리(사용자 지시)
- 실행: `./venv/Scripts/python.exe -m pytest resources/tester/ -q`
  옮기기 전과 **같은 수**: 617 통과 / 22 건너뜀 / 실패 0

⇒ 이제 시험·예외·까닭이 **정본과 함께** 움직임. 오늘 세운 「예외는 정본 스키마에」와 짝임.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 17:12:30 +09:00

58 lines
2.7 KiB
JavaScript

// 확대 상태의 팬 한계가 캐시 보유 범위까지 늘어나는지 — Cross_View_Zoom.clampPan 로직 복제.
// 실행: node tmp/tests/test_cross_pan_bounds.mjs
import assert from "node:assert/strict";
const plot = { x: 58, y: 10, width: 552, height: 188 };
// 표시 반폭 12m(=플롯 폭)보다 넓은 캐시 20m — 좌우로 각각 플롯 폭의 2/3만큼 더 있다.
const content = { x: plot.x - 368, y: plot.y - 100, width: plot.width + 736, height: plot.height + 200 };
function clampAxis(value, scale, start, size, from, to) {
const lo = start + size - scale * to;
const hi = start - scale * from;
return Math.min(Math.max(value, Math.min(lo, hi)), Math.max(lo, hi));
}
function clampPan(tx, ty, scale, useContent = true) {
const bounds =
useContent && scale > 1 + 1e-6
? {
x: Math.min(content.x, plot.x),
y: Math.min(content.y, plot.y),
right: Math.max(content.x + content.width, plot.x + plot.width),
bottom: Math.max(content.y + content.height, plot.y + plot.height),
}
: { x: plot.x, y: plot.y, right: plot.x + plot.width, bottom: plot.y + plot.height };
return {
tx: clampAxis(tx, scale, plot.x, plot.width, bounds.x, bounds.right),
ty: clampAxis(ty, scale, plot.y, plot.height, bounds.y, bounds.bottom),
};
}
// 화면 창이 보는 원배율 좌표 구간.
const windowSpan = (tx, scale) => [(plot.x - tx) / scale, (plot.x + plot.width - tx) / scale];
// 원배율: 이동 없음(기존 규칙 유지).
assert.deepEqual(clampPan(200, 200, 1), { tx: 0, ty: 0 });
// 2배 확대: 캐시 왼쪽 끝까지 끌 수 있고, 창이 캐시 범위를 벗어나지 않는다.
const scale = 2;
const far = clampPan(100000, 100000, scale);
const [leftFrom] = windowSpan(far.tx, scale);
assert.ok(Math.abs(leftFrom - content.x) < 1e-6, `왼쪽 한계가 캐시 끝이 아님: ${leftFrom}`);
const farNeg = clampPan(-100000, -100000, scale);
const [, rightTo] = windowSpan(farNeg.tx, scale);
assert.ok(
Math.abs(rightTo - (content.x + content.width)) < 1e-6,
`오른쪽 한계가 캐시 끝이 아님: ${rightTo}`,
);
// 캐시 범위 밖으로는 못 나간다.
for (const raw of [-5000, -800, -100, 0, 100, 800, 5000]) {
const { tx } = clampPan(raw, 0, scale);
const [from, to] = windowSpan(tx, scale);
assert.ok(from >= content.x - 1e-6, `왼쪽 이탈 ${from}`);
assert.ok(to <= content.x + content.width + 1e-6, `오른쪽 이탈 ${to}`);
}
// content가 없으면(옛 규칙) 확대해도 플롯 영역 안으로만 움직인다.
const noContent = clampPan(100000, 0, scale, false);
const [fitFrom] = windowSpan(noContent.tx, scale);
assert.ok(Math.abs(fitFrom - plot.x) < 1e-6, `기본 한계 어긋남 ${fitFrom}`);
console.log("ok");