- 모달 = 공용 wide(96vw × 94vh) · 자기 폭 규칙 지움 - 도면 · 일위대가 · 면적산출 카드 = 한 줄 세 칸(3:2:2) · 카드 높이 큰 창에 맞춤 · 칸 사이 넓힘 - 조합끼리 가름줄 - 시험 test_156_1 덧붙임 · test_61_2 옛 폭 판정을 wide 로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STqEqztUthVFBmEP18wBSz
113 lines
5.5 KiB
Python
113 lines
5.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""B08 조합 [연결 끊기](PLAN 156-1 · 156-3) — 임시 저장소(154-2 시험 바탕 그대로).
|
|
|
|
- 링크 길에 null = 그 시설 칸만 비움 · 다른 시설 · 칸 · 관 지점 노선 지문 그대로 · 구조물 판 +1
|
|
- 끊기는 사본 맞춤을 안 부름 — 사본 폴더 그대로(고아 정리 안 함)
|
|
- 집계 응답 `facilities` = 모든 시설 칸(연결된 칸 포함) · 끊은 시설은 `unlinked` 로
|
|
- 화면 = 연결된 칸만 [연결 끊기] · 확인 창 · 초안이면 막음 · 단추 = 모달 [닫기] 양식
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from pathlib import Path
|
|
|
|
from B08_Quantity import B08_Quantity_Router_Summary as summary
|
|
from M02_MasterTemplete import M02_Item_Snapshot as snap
|
|
from M02_MasterTemplete import M02_Project_Items_Router as items_router
|
|
from M02_MasterTemplete.StructOptions import M02_SO_Definition as definition
|
|
from resources.tester.test_154_2_b08_direct_link import ( # noqa: F401 — 시험 저장소
|
|
MS,
|
|
PIPE,
|
|
ROOT,
|
|
_points,
|
|
_structures,
|
|
root,
|
|
)
|
|
|
|
|
|
def _folders(root: Path) -> set[str]:
|
|
return {p.name for p in snap.structures_dir(root).iterdir() if p.is_dir()}
|
|
|
|
|
|
def _unlink(monkeypatch, root: Path, copy: str, facility: str | None) -> dict:
|
|
async def fake_root(session, project_id):
|
|
return root
|
|
|
|
def no_sync(*args):
|
|
raise AssertionError("끊기는 사본 맞춤을 부르지 않음")
|
|
|
|
monkeypatch.setattr(items_router, "_root", fake_root)
|
|
monkeypatch.setattr(items_router, "safe_sync", no_sync)
|
|
body = items_router.LinkBody(summary_item=None, facility=facility)
|
|
return asyncio.run(items_router.link_item("proj", copy, body, session={}))
|
|
|
|
|
|
def test_구조물_끊기_그_칸만_사본_그대로(root, monkeypatch):
|
|
folders, points = _folders(root), _points(root)
|
|
assert snap.folder_name("st1") in folders
|
|
reply = _unlink(monkeypatch, root, "st1", None)
|
|
assert reply == {"폴더": snap.folder_name("st1"), "snapshot_failed": []}
|
|
got = _structures(root)
|
|
assert got["revision"] == 5
|
|
st0, st1 = got["structures"]
|
|
assert st1.get("summary_item") is None and st1["chainage_m"] == 400
|
|
assert st0.get("summary_item") is None and st0["chainage_m"] == 300
|
|
assert _points(root) == points # 관 지점 · 노선 지문 그대로
|
|
assert _folders(root) == folders # 사본 폴더 그대로
|
|
assert "st1" not in snap.linked_snapshots(root)
|
|
|
|
|
|
def test_관_그룹_끊기_다른_시설_그대로(root, monkeypatch):
|
|
folders, before = _folders(root), _points(root)
|
|
_unlink(monkeypatch, root, "pipe@100.0__grv6lny", "pipe")
|
|
after = _points(root)
|
|
assert after["route_signature"] == "sig-1"
|
|
assert "group_items" not in after["points"][0]
|
|
assert after["points"][1:] == before["points"][1:] # 같은 측점 박스 · 다른 관 그대로
|
|
assert _structures(root)["structures"][1]["summary_item"] == MS
|
|
assert _folders(root) == folders
|
|
|
|
|
|
def test_집계_모든_시설_칸_끊으면_미연결(root, monkeypatch):
|
|
names = definition.read()["종류"]["pipe"]["이름"]
|
|
designs = [{"chainage_m": 100.0, "design": {"pipe_length_m": 12}}]
|
|
first = summary.pipe_summary(root, designs, names, 6.0)
|
|
assert not any(u["id"] == "st1" for u in first["unlinked"])
|
|
st1 = next(f for f in first["facilities"] if f["id"] == "st1")
|
|
assert st1["slots"][0] == {"copy": "st1", "group": None, "item": MS, "linked": True}
|
|
pipe = next(
|
|
f for f in first["facilities"] if f["id"] == "pipe@100.0" and f["type_id"] == "pipe"
|
|
)
|
|
assert any(s["copy"] == "pipe@100.0__grv6lny" and s["linked"] for s in pipe["slots"])
|
|
assert {u["id"] for u in first["unlinked"]} <= {f["id"] for f in first["facilities"]}
|
|
_unlink(monkeypatch, root, "st1", None)
|
|
after = summary.pipe_summary(root, designs, names, 6.0)
|
|
st1 = next(u for u in after["unlinked"] if u["id"] == "st1")
|
|
assert st1["slots"][0]["linked"] is False and st1["chainage_m"] == 400
|
|
assert PIPE == _points(root)["points"][0]["group_items"]["grv6lny"] # 다른 칸 그대로
|
|
|
|
|
|
def test_화면_연결된_칸만_끊기_닫기_양식():
|
|
ui = (ROOT / "B08_Quantity/B08_Quantity_UI_Link.ts").read_text(encoding="utf-8")
|
|
assert 'if (slot.linked) buttons.append(act(L("B08_Quantity_Link_Unlink"), unlink))' in ui
|
|
assert ".link(slot.copy, facility.facility, null)" in ui
|
|
assert 'showConfirmDialog(L("B08_Quantity_Link_UnlinkAsk")' in ui
|
|
assert ui.count("hasPendingDesign(projectId)") == 2 # 선택 · 끊기 둘 다 막음
|
|
assert 'size: "sm"' not in ui # 모달 [닫기] = ghost · 기본 크기
|
|
modal = (ROOT / "ui_template/ui_template_modal.ts").read_text(encoding="utf-8")
|
|
assert 'label: opts.closeLabel,\n variant: "ghost",\n onClick' in modal
|
|
page = (ROOT / "B08_Quantity/B08_Quantity_UI_Summary.ts").read_text(encoding="utf-8")
|
|
assert "facilities: unlinkedAt(saved?.facilities ?? [], station)" in page
|
|
sheets = (ROOT / "B08_Quantity/B08_Quantity_UI_Drawing.ts").read_text(encoding="utf-8")
|
|
assert "linkSection(request.projectId, request.facilities" in sheets
|
|
|
|
|
|
def test_156_4_구조물도_모달_큰_창_세_칸():
|
|
sheets = (ROOT / "B08_Quantity/B08_Quantity_UI_Drawing.ts").read_text(encoding="utf-8")
|
|
assert "wide: true" in sheets
|
|
css = (ROOT / "B08_Quantity/B08_Quantity_UI_Drawing.css").read_text(encoding="utf-8")
|
|
assert "min(1320px" not in css # 자기 폭 없음 — 공용 wide 그대로
|
|
assert "minmax(0, 3fr) minmax(0, 2fr) minmax(0, 2fr)" in css # 도면 · 일위대가 · 면적산출
|
|
assert ".b08-sheets__combo + .b08-sheets__combo" in css
|