- 줌 [+ − ⤢] = 아이콘 단추 22 · 상세 [칸에 넣기] = 단추 22 · [여럿] = 켜기 칩 22 · 사이 금 지움 - 구조물 조정창 십자 · 9키 · 단 수 [-][+] = 아이콘 단추(선) 22 · ✕ = 고스트 · 옵션 연동 · 경사 = 켜기 칩 24(유입 · 유출 칸 꼴은 그대로) - 카드 머리 단면유형 = 배지(정보) 20 · 구조물 = 배지(강조) 20 - 알림 칩 = 단추(고스트) 20(색만 경고 / 정보) · 측점 목록 날 단추 = 단추(고스트) 20 - 날 details 넷(변수 위치 안내 · 상세값 · 다른 프로젝트 불러오기 · 횡단 조정) = 접이 구역(ui-collapsible) · 가이드 장면 선택자 `details.` 뗌 - 측점 없는 구조물 줄 · 표준 미반영 알림 = 띠 알림(경고) — 날 색 #fff8e6 · #e0b872 · #7a5a12 · #8a6a22 · 폴백 #d98324 지움 - 빈 그림 자리 = 빈 상태 · 선 치수 글 옛 보라 이름 → --color-accent - 흉내 DOM 시험 · 서버 Node 묶음이 끄는 파일이라 부품 함수 대신 클래스 · data-size 계약 + 부품 CSS 직접 실음(묶음 셋 빌드 정상) - 시험 넷 기대 고침 — 108(닫기 클래스) · 179-1(줌 사이 금 규칙 없음) · 196-1(칩 클래스) · 207-1(칩 반경 = 부품) - 그대로 둔 것 — 수량 산출표(b06-detail__qtable · B07 산출서 병합 칸 · 세로선 = 부품 표에 없는 꼴) · 조정창 고르기 · 암 절토 칸(작은 단 없음) · 조정창 · ⋯ · 측점 목록 떠 있는 판 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
118 lines
4.6 KiB
Python
118 lines
4.6 KiB
Python
"""207-1 B06 알림 칩 다듬기 — 둥근 사각 · 내용 칸 겹쳐 띄움 · 고르면 접힘 · 고른 측점 강조.
|
|
|
|
동작은 `B06_Section_UI_Cross_Notice_Chips.ts` 를 Node 로 그대로 돌림(196-1 가짜 DOM 재사용).
|
|
모양 · 흐름 밖(겹침) · 줄 높이만 재는 scroll-margin 은 CSS · 부르는 쪽 원문 대조.
|
|
"""
|
|
|
|
import json
|
|
import subprocess
|
|
|
|
from test_196_1_b06_notice_chips import B06, PRELUDE
|
|
|
|
CSS = (B06 / "B06_Section_UI_Style_Cross.css").read_text(encoding="utf-8")
|
|
|
|
|
|
def _rule(selector: str) -> str:
|
|
body = CSS[CSS.index(selector + " {") :]
|
|
return body[: body.index("}")]
|
|
|
|
|
|
def _node(body: str):
|
|
script = (
|
|
PRELUDE
|
|
+ """
|
|
const sel = { id: null };
|
|
const picked = [];
|
|
const bar2 = mod.exports.createNoticeChips((id) => { picked.push(id); sel.id = id; }, () => sel.id);
|
|
const [chips2, panel2] = bar2.root.children;
|
|
const chip2 = (key) => chips2.children.find((c) => c.dataset.noticeKey === key);
|
|
const marks = () => panel2.children.map((b) => [b.dataset.stationId, b.classList.contains("is-selected")]);
|
|
"""
|
|
+ body
|
|
+ "\nconsole.log(JSON.stringify(out));"
|
|
)
|
|
got = subprocess.run(
|
|
["node", "-e", script], capture_output=True, text=True, encoding="utf-8", timeout=60
|
|
)
|
|
assert got.returncode == 0, got.stderr
|
|
return json.loads(got.stdout)
|
|
|
|
|
|
def test_칩은_둥근_사각_공용_단추_반경_알약_아님():
|
|
# 553-2 — 칩 = 부품 단추(고스트 · 둥근 사각) · 페이지는 색만
|
|
chip = _rule(".b06-section__notice-chip")
|
|
assert "border-radius" not in chip and "radius-pills" not in chip
|
|
chips = (B06 / "B06_Section_UI_Cross_Notice_Chips.ts").read_text(encoding="utf-8")
|
|
assert "`ui-btn ui-btn--ghost b06-section__notice-chip" in chips
|
|
|
|
|
|
def test_내용_칸은_흐름_밖_카드_위에_겹침():
|
|
panel = _rule(".b06-section__notice-list")
|
|
assert "position: absolute" in panel and "top: 100%" in panel
|
|
assert "z-index" in panel and "box-shadow: var(--shadow-lg)" in panel
|
|
assert "background: var(--color-surface-raised)" in panel
|
|
# 기준 = 고정 줄(sticky 는 absolute 의 기준 상자) · 그 사이에 기준을 바꾸는 position 없음
|
|
assert "position: sticky" in _rule(".b06-section__notice-bar")
|
|
assert "position" not in _rule(".b06-section__notice-blocks")
|
|
|
|
|
|
def test_열고_닫아도_카드_자리_그대로_scroll_margin은_칩_줄_높이만():
|
|
view = (B06 / "B06_Section_UI_Section_View.ts").read_text(encoding="utf-8")
|
|
# 줄 높이 = 고정 줄 offsetHeight — 흐름 밖 내용 칸은 높이에 안 듦
|
|
assert '"--b06-notice-h", `${fillSlopeNotice.root.offsetHeight}px`' in view
|
|
assert "scroll-margin-top: calc(var(--b06-notice-h, 0px) + var(--spacing-8))" in CSS
|
|
# 내용 칸만 흐름 밖 — 칩 줄은 흐름 안
|
|
assert "position" not in _rule(".b06-section__notice-chips")
|
|
|
|
|
|
def test_측점_고르면_그_카드로_가며_내용_칸_접힘():
|
|
got = _node(
|
|
"""
|
|
bar2.update(items(["a", "b"], ["p"], []));
|
|
chip2("fill").click();
|
|
out.before = panel2.hidden;
|
|
panel2.children[1].click();
|
|
out.picked = picked.slice();
|
|
out.after = panel2.hidden;
|
|
out.rows = panel2.children.length;
|
|
out.expanded = chips2.children.map((c) => c.getAttribute("aria-expanded"));
|
|
"""
|
|
)
|
|
assert got["before"] is False
|
|
assert got["picked"] == ["b"]
|
|
assert got["after"] is True and got["rows"] == 0
|
|
assert got["expanded"] == ["false", "false"]
|
|
|
|
|
|
def test_고른_측점이_있으면_열_때_그_단추_강조_없으면_강조_없음():
|
|
got = _node(
|
|
"""
|
|
bar2.update(items(["a", "b", "c"], ["b"], []));
|
|
chip2("fill").click();
|
|
out.none = marks();
|
|
chip2("fill").click();
|
|
sel.id = "b"; // 측점 횡단도를 고른 상태
|
|
chip2("fill").click();
|
|
out.fill = marks();
|
|
chip2("pave").click();
|
|
out.pave = marks();
|
|
sel.id = "zz"; // 목록에 없는 측점
|
|
chip2("fill").click();
|
|
out.absent = marks();
|
|
"""
|
|
)
|
|
assert got["none"] == [["a", False], ["b", False], ["c", False]]
|
|
assert got["fill"] == [["a", False], ["b", True], ["c", False]]
|
|
assert got["pave"] == [["b", True]]
|
|
assert got["absent"] == [["a", False], ["b", False], ["c", False]]
|
|
|
|
|
|
def test_고른_측점_넘김_부르는_쪽_이음과_강조_색():
|
|
notice = (B06 / "B06_Section_UI_Cross_FillSlope_Notice.ts").read_text(encoding="utf-8")
|
|
assert "createNoticeChips(onPick, selected)" in notice
|
|
view = (B06 / "B06_Section_UI_Section_View.ts").read_text(encoding="utf-8")
|
|
assert "() => selectedStationId," in view
|
|
mark = _rule(".b06-section__notice-list > button.is-selected")
|
|
assert "var(--color-danger)" in mark # 카드 고름 색과 같음
|
|
assert "border-color: var(--color-danger)" in _rule(".b06-cross-card--selected")
|