- 종단 보기 구독이 배수유역도 관 마커 · 유역 · 마름모까지 알림 없이 칠함 · 재계산 뒤 다시 얹음 - 지도 고름 · 목록 관 고름 · 목록 다시 누름도 고름 한 칸에 적고 칠하기는 구독 몫 - 목록 관 줄 폭 PIPE_MATCH_M · 조금 옮겨진 관도 고름 따라감 · 저장 뒤 목록 주입이 관 폼 안 닫음 - design_pick_escape — Esc = 고름 한 칸 비움 → 종단 · 3D · 지도 · 폼 · 횡단 카드 · 범위 · 형상 모두 풂 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STqEqztUthVFBmEP18wBSz
104 lines
4.0 KiB
Python
104 lines
4.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""233-2 3D(띠 · 핀 · 부재) · 횡단 카드(고름 · --span · 형상 · 포장층) · [상세] 선 조각 = 고름 한 칸에서 파생.
|
|
|
|
까닭: 3D 는 화면끼리 손으로 부르는 사슬로만 칠해져 길마다 빠짐(구조물 고름 뒤 옛 띠 남음 · 횡단 카드
|
|
고름은 부재를 안 켬) · 횡단 카드를 풀어도 `--span` · 포장층이 남음(a4) · 풀기 길마다 끄는 범위가 다름 ·
|
|
[상세] 선 조각은 다시 그릴 때(창 크기 · 카드 다시 세움) 고름을 지워 바로 꺼짐.
|
|
고침: 종단 보기 구독이 3D 띠 · 핀 · 부재까지 값으로 칠함(마커 알림 없이) · 횡단 보기 구독(`bindCrossPick`)은
|
|
다른 곳이 바꾼 값을 넘김 적용 길로 다시 세우고 · 풀기는 한 길(`releaseCrossHighlights` — 카드 · 폼 관 ·
|
|
범위 테두리 · 포장층 · 형상) · [상세] 다시 그림은 같은 자리 조각 고름 유지.
|
|
진짜 TS 를 `helper_233_2_view_pick.cjs` 가 Node(three 포함)로 돌린다.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
ROOT = os.path.abspath(os.path.join(HERE, "..", ".."))
|
|
|
|
pytestmark = pytest.mark.skipif(
|
|
not os.path.isdir(os.path.join(ROOT, "config", "node_modules")),
|
|
reason="프론트엔드 의존성 미설치",
|
|
)
|
|
|
|
|
|
def _read(*parts: str) -> str:
|
|
with open(os.path.join(ROOT, *parts), encoding="utf-8") as handle:
|
|
return handle.read()
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def out() -> dict:
|
|
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
|
|
["node", os.path.join(HERE, "helper_233_2_view_pick.cjs")],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=60,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def test_3D_횡단_카드_고름은_띠_핀_그_측점_부재(out) -> None:
|
|
card = out["card120"]
|
|
assert (card["red"], card["pin"], card["wall"], card["member"]) == (["s120"], True, True, False)
|
|
assert card["profile"]["station"] == "s120"
|
|
|
|
|
|
def test_3D_부재키_고름은_그_부재만_띠는_없음(out) -> None:
|
|
part = out["part160"]
|
|
assert (part["red"], part["pin"], part["member"], part["wall"]) == ([], False, True, False)
|
|
|
|
|
|
def test_3D_구조물_고름은_그_자리_구조물_측점_띠(out) -> None:
|
|
assert out["sign"]["red"] == ["irregular:sign"]
|
|
assert out["sign"]["profile"]["structure"] == "sign"
|
|
|
|
|
|
def test_3D_풂과_알림_없음(out) -> None:
|
|
released = out["released3d"]
|
|
assert (released["red"], released["pin"], released["member"], released["wall"]) == (
|
|
[],
|
|
False,
|
|
False,
|
|
False,
|
|
)
|
|
assert out["notified"] == 0 # 칠하기만 — 마커 알림이 사슬을 다시 돌리지 않음
|
|
|
|
|
|
def test_횡단_제_누름은_되받지_않고_다른_곳_값은_다시_세움(out) -> None:
|
|
assert out["ownPick"] == []
|
|
assert out["otherPick"] == ["reapply"]
|
|
assert out["hidden"] == [] # 숨은 보기는 안 받음
|
|
|
|
|
|
def test_횡단_풀기_한_길은_범위_테두리_형상까지(out) -> None:
|
|
for key in ("release", "otherRelease"):
|
|
assert out[key] == ["releaseForm", "focus:null", "mark:null", out[key][-1]]
|
|
assert out["release"][-1] == "refresh:120"
|
|
assert out["revetAfter"] == []
|
|
|
|
|
|
def test_상세_다시_그려도_같은_자리_조각_고름_유지(out) -> None:
|
|
assert out["detailPicked"] == 1
|
|
assert out["detailAfterRedraw"] == 1
|
|
assert out["detailAfterChange"] == 0
|
|
|
|
|
|
def test_배선() -> None:
|
|
cross = _read("A00_Common", "design", "design_view_cross.ts")
|
|
assert "bindCrossPick(projectId, host," in cross
|
|
assert "crossPick.release()" in cross
|
|
# 카드 다시 누름 = 풀기 한 길
|
|
assert "releaseCross(); // 카드 다시 누름" in cross
|
|
assert len(cross.splitlines()) <= 685
|
|
profile = _read("A00_Common", "design", "design_view_profile.ts")
|
|
assert "{ profile: profilePanel, viewer," in profile
|
|
assert len(profile.splitlines()) <= 700
|