"""102 — M02 일위대가 상세 줄 배치 · 줄 통째 끌기 · 구분 열 품셈 글. 끌기(102-2) = Node 헬퍼(`helper_m02_labor_rowdrag.cjs`)가 `M02_MasterTemplete_Labor_RowDrag.ts` 를 가짜 DOM 에서 돌림 · 6px 문턱 · 끈 뒤 누름 삼킴 · 열린 줄 하위 줄에서 시작 · 단추 · 입력칸 · 수량 칸 막음 · 끄는 동안 다시 그림 미룸. 배치(102-1) · 품셈 글(102-3) = 소스 꼴. """ import json import os import subprocess from pathlib import Path import pytest HERE = os.path.dirname(os.path.abspath(__file__)) M02 = Path(HERE).parents[1] / "M02_MasterTemplete" @pytest.fixture(scope="module") def r(): proc = subprocess.run( ["node", os.path.join(HERE, "helper_m02_labor_rowdrag.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_문턱_6px(r): assert r["threshold"] == [False, True, True, False, True] def test_작게_움직이면_누름(r): assert r["small"] == {"moves": 0, "clickPasses": True, "capture": None} def test_끌어_놓으면_순서만_누름_삼킴(r): assert r["during"]["drawn"] == 0 # 끄는 동안 다시 그리지 않음 assert r["during"]["capture"] == 1 and r["during"]["select"] == "none" assert r["during"]["classes"][0] == "is-dragging" assert r["during"]["classes"][5] == "is-dragunder" assert r["drop"]["moves"] == [[0, 2]] assert r["drop"]["drawn"] == 1 # 끝난 뒤 마지막 것 한 번 assert r["drop"]["clickPasses"] is False # 열림 · 닫힘 그대로 assert set(r["drop"]["classes"]) == {""} assert r["afterFrame"]["listeners"] == 0 assert r["idleDraw"] == 1 def test_열린_줄_하위_줄째(r): assert r["fromSub"]["moves"] == [[1, 0]] assert r["fromSub"]["classes"][:5] == ["is-dragover"] + ["is-dragging"] * 4 assert r["downMark"][4] == "is-dragunder" and r["downMark"][-1] == "[[0,1]]" @pytest.mark.parametrize("name", ["button", "input", "qty"]) def test_단추_입력칸에선_시작_안_함(r, name): assert r[f"block_{name}"] == {"moves": 0, "capture": None, "clickPasses": True} def test_손잡이_제자리(r): assert r["gripSelf"] == {"moves": 0, "clickPasses": False} def test_배치_손잡이_차례칸_앞_단추칸(): rows = (M02 / "M02_MasterTemplete_Labor_Rows.ts").read_text(encoding="utf-8") assert "children: move ? [grip(), String(i + 1)] : [String(i + 1)]," in rows assert 'draggable: "true"' not in rows and "dragFrom" not in rows assert "if (move) attachRowDrag(out, move);" in rows css = (M02 / "M02_MasterTemplete_Labor.css").read_text(encoding="utf-8") order = css[css.index(".m02-labrow__order {") :] assert "flex-direction: column;" in order[: order.index("}")] assert ".m02-labrow__tools > .ui-btn-group {\n align-items: stretch;" in css detail = (M02 / "M02_MasterTemplete_Labor_Detail.ts").read_text(encoding="utf-8") assert "afterRowDrag(logicHost, () =>" in detail def test_구분열_품셈_글(): rows = (M02 / "M02_MasterTemplete_Labor_Rows.ts").read_text(encoding="utf-8") assert "const BOOK = /^(건설|산림)품셈/;" in rows assert 'const book = row.참조 ? undefined : BOOK.exec(logic?.출처 ?? "")?.[0];' in rows assert 'className: "m02-labrow__book"' in rows