"""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_칩은_둥근_사각_공용_단추_반경_알약_아님(): chip = _rule(".b06-section__notice-chip") assert "border-radius: var(--radius-buttons)" in chip assert "radius-pills" not in chip and "radius-sm" not in chip 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")