- 도구줄 「연도 마커」(공용 지도 도구줄 year-mark · 깃발 아이콘)를 선 위로 끌어 놓음 = 그 자리 구간을 둘로 — 구역만 나눔 · 해 그대로 - 끄는 동안 마름모 미리보기 · 선 끝 · 다른 마커 1 m 안 · 선 밖 = 경고 색 · 못 놓음 - 놓인 마커 끌기 = 경계 옮김 · 선 밖으로 끌어냄 · 오른쪽 누름 · Delete = 지움(앞 구간과 합침) · 같은 해 양쪽 = 속 빈 마름모 - 좌측 [연도 구분] · 「긋는 해」 걷음 · 새 선 = 사업연도 시작 해 · 새 갈래 = 붙은 자리 구간 해 - 속성 판 [갈래 시점 지정] = 다른 선에 닿은 끝을 시점(No.0)으로 갈래 · 꼬리에 닿은 머리 = 한 선 · 본선 = [방향 바꾸기] - 시험: 585-2 시험에 나눔 · 합침 · 갈래 해 · 갈래 시점 덧 · 530-3 갈래 해 · 553-4 속성 판 · 568-1 도구줄 목록 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
269 lines
12 KiB
Python
269 lines
12 KiB
Python
"""553-4 예정노선(D01~D04) · 안정성평가(E01~E07) 부품 옮김 지킴 시험 — 서버 · 화면 없이 소스만 본다.
|
|
옮긴 페이지는 날 `<input>` · `<progress>` · 날 색 · 안 쓰는 변종 CSS 가 다시 생기면 안 됨."""
|
|
|
|
import re
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def _src(path: str) -> str:
|
|
return (ROOT / path).read_text(encoding="utf-8")
|
|
|
|
|
|
def _no_hex(path: str) -> None:
|
|
css = re.sub(r"/\*.*?\*/", "", _src(path), flags=re.S)
|
|
assert not re.search(r"#[0-9a-fA-F]{3,8}\b", css), f"{path}: 날 색"
|
|
|
|
|
|
def test_d02_parts():
|
|
ts = _src("D02_PlanBase/D02_PlanBase_UI_Page.ts")
|
|
css = _src("D02_PlanBase/D02_PlanBase_UI_Style.css")
|
|
assert 'el("input"' not in ts
|
|
assert 'createInputField({ type: "number"' in ts
|
|
assert 'classList.add("d02-info")' in ts # 촬영 장면이 `p.d02-info` 로 잡음
|
|
for dead in (".d02-info", "is-invalid", "font-size: var(--text-caption);\n}\n\n.d02-info"):
|
|
assert dead not in css
|
|
assert "data-axis" in ts or "dataset.axis" in ts
|
|
|
|
|
|
def test_d03_parts():
|
|
ts = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_Page.ts")
|
|
three = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_3D.ts")
|
|
css = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_Style.css")
|
|
draw = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_Draw.ts")
|
|
tools = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_Map.ts")
|
|
layers = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_Layers.ts")
|
|
assert 'createElement("progress")' not in ts and "createProgressBar()" in ts
|
|
# 562-3 — 날 단추 · 입력 · 고르기 없음 · 도구줄 · 제약 칸 · 연도 고름은 부품
|
|
for src in (ts, draw, tools, layers):
|
|
for raw in ('createElement("button")', 'createElement("input")', 'createElement("select")'):
|
|
assert raw not in src, raw
|
|
# 568-3 — 도구줄 = 공용 지도 도구줄 · 아홉([?] · 되돌리기 · 다시하기 · 3D · 돌리기 둘 · 측점 · 기울기 · 재기)
|
|
assert "createMapTools({" in tools and "hint:" in tools and "leftPan" not in tools
|
|
assert "createToolbar(" not in tools and "createIconButton(" not in tools
|
|
for act in ("undo", "redo", "view3d", "measure", "stations", "slopes"):
|
|
assert f'mapToolButton("{act}"' in tools or f'markButton("{act}"' in tools, act
|
|
assert '"rotate-ccw", "rotate-cw"' in tools
|
|
for b05_only in ("footprint", "station-snap", "contour-minor"):
|
|
assert f'"{b05_only}"' not in tools, b05_only
|
|
paint = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_DrawPaint.ts") # 580 — 그림 나눔
|
|
assert "map.stations" in paint and "map.slopes" in paint
|
|
# 569-2 · 581-1 · 581-2 — 바탕 겹 단추(공용 지도 도구줄 한 줄 · 묶음 셋) · 처음 켬 셋 · 취향 기억
|
|
defs = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_LayerDefs.ts")
|
|
assert "createMapTools({" in layers and "createIconButton({" in layers
|
|
assert "createToolbar(" not in layers
|
|
assert '"aislo:pref:d03.layers"' in layers and "writeByKey(PREF_KEY" in layers
|
|
keys = re.findall(r'key: "(\w+)",\s+icon: "\w+",\s+title:\s+"[^"]+",\s+on: (true|false)', defs)
|
|
assert keys == [
|
|
("satellite", "true"),
|
|
("hillshade", "false"),
|
|
("contour", "true"),
|
|
("slope", "false"),
|
|
("stream", "true"),
|
|
("water", "false"),
|
|
("road", "false"),
|
|
("forestRoad", "false"),
|
|
("forestRoadFile", "false"),
|
|
("cadastral", "false"),
|
|
("zones", "false"),
|
|
("soils", "false"),
|
|
("landslide", "false"),
|
|
("landslideZones", "false"),
|
|
("faults", "false"),
|
|
("lineaments", "false"),
|
|
("zeroOrder", "false"),
|
|
("bands", "false"),
|
|
("building", "false"),
|
|
("place", "false"),
|
|
], keys
|
|
assert ".d03-plan__layers" in css and ".d03-plan__legend" in css
|
|
assert "createSegment({" in draw and draw.count("createInputField(") == 2
|
|
props = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_Props.ts") # 585-2 조각 연도 = 속성 판
|
|
assert "createSelectField(" in props and "createFloatPanel(" in props
|
|
assert 'createElement("button")' not in props and 'createElement("select")' not in props
|
|
assert 'createElement("select")' not in three and "createSelectField" in three
|
|
assert "createCheckbox" not in three and "buildCorridor" not in three # 예상 코리도 걷음
|
|
for dead in (".d03-plan__bar", ".d03-plan__mode", "is-picked"):
|
|
assert dead not in css, dead
|
|
assert "b05-route__3d-modal" not in three and "b05-route__3d-body" not in three # 빌림 끊음
|
|
assert 'dialogClass: "d03-plan__3d-modal"' in three and ".d03-plan__3d-body" in css
|
|
scenes = _src("A05_EduDetail/guide/D03/_scenes.json")
|
|
assert "b05-route__3d-modal" not in scenes # 촬영 장면이 `.d03-plan__3d-modal` 로 잡음
|
|
|
|
|
|
def test_d04_parts():
|
|
ts = _src("D04_PlanConfirm/D04_PlanConfirm_UI_Page.ts")
|
|
css = _src("D04_PlanConfirm/D04_PlanConfirm_UI_Style.css")
|
|
assert 'el("input"' not in ts
|
|
assert ts.count("createInputField(") == 2 and "createCheckbox(" in ts
|
|
assert 'createBanner({ tone: "warning"' in ts
|
|
assert "input:checked" in ts # [확정] 이 고른 연도를 읽는 길
|
|
assert "border:" not in css.split(".d04-confirm__input")[1].split("}")[0]
|
|
assert ".d04-confirm__dirty" not in css
|
|
assert 'el("table"' not in ts and "tableShell(columns)" in ts
|
|
assert "d04-confirm__table" not in css # 표 모양은 표 부품 · 이름은 촬영 장면용 걸이
|
|
|
|
|
|
def test_e01_missing_is_banner_part():
|
|
ts = _src("E01_StabRegister/E01_StabRegister_UI_Missing.ts")
|
|
assert "createBanner" in ts and '"details"' not in ts
|
|
assert 'dataset.role = "missing-stations"' in ts # 시험 · 촬영이 잡음
|
|
assert not (ROOT / "E01_StabRegister/E01_StabRegister_UI_Missing.css").exists()
|
|
|
|
|
|
def test_e02_parts():
|
|
tables = _src("E02_StabGround/E02_StabGround_UI_Tables.ts")
|
|
page = _src("E02_StabGround/E02_StabGround_UI_Page.ts")
|
|
css = _src("E02_StabGround/E02_StabGround_UI_Style.css")
|
|
assert 'el("input"' not in tables and 'el("select"' not in tables
|
|
assert "createInputField(" in tables and "createSelectField(" in tables
|
|
assert "createCard({ title" in tables
|
|
assert "is-invalid" not in page + css and "is-error" in page
|
|
for dead in (".e02-card__head", ".e02-card__title", ".e02-hint", ".e02-empty"):
|
|
assert dead not in css, dead
|
|
_no_hex("E02_StabGround/E02_StabGround_UI_Style.css")
|
|
assert "createTable(" in tables and "createTHead" not in tables
|
|
assert 'className: "ui-field e02-field"' in tables # 칸 이름 줄은 입력 부품의 ui-field
|
|
assert ".e02-field" not in css and "border-collapse" not in css
|
|
|
|
|
|
def test_e03_parts():
|
|
names = [
|
|
"List", "Page", "Plan", "Prob", "ProbChart", "Reinforce", "Result", "Section", "Support", "View3D",
|
|
] # fmt: skip
|
|
ts = {n: _src(f"E03_StabSection/E03_StabSection_UI_{n}.ts") for n in names}
|
|
css = _src("E03_StabSection/E03_StabSection_UI_Style.css")
|
|
for n, src in ts.items():
|
|
assert 'el("table"' not in src, n # 표 = 표 부품(`E03_StabSection_UI_Table.ts`)
|
|
assert 'el("input"' not in src and 'el("select"' not in src, n
|
|
assert "e03-legend__item" not in src and "e03-legend__swatch" not in src, n
|
|
assert "createTable(" in _src("E03_StabSection/E03_StabSection_UI_Table.ts")
|
|
assert "dataset.role = role" in _src("E03_StabSection/E03_StabSection_UI_Table.ts")
|
|
assert "createLegend(" in _src("E03_StabSection/E03_StabSection_UI_Parts.ts")
|
|
assert "openModal(" in ts["View3D"] and 'className: "e03-view3d"' not in ts["View3D"]
|
|
for key in ("station-list", "slice-table", "methods", "whatif-table", "support-table"):
|
|
assert f'"{key}"' in "".join(ts.values()), key # 촬영 장면 · 시험이 잡는 data-role
|
|
for dead in (
|
|
".e03-legend__item", ".e03-legend__swatch", ".e03-table", ".e03-verdict", ".e03-kpi",
|
|
".e03-view3d {", ".e03-swatch-none", ".e03-list table", ".e03-list th {",
|
|
): # fmt: skip
|
|
assert dead not in css, dead
|
|
|
|
|
|
def test_e04_parts():
|
|
page = _src("E04_Stab3D/E04_Stab3D_UI_Page.ts")
|
|
view = _src("E04_Stab3D/E04_Stab3D_UI_View3D.ts")
|
|
css = _src("E04_Stab3D/E04_Stab3D_UI_Style.css")
|
|
assert 'el("progress"' not in page and "createProgressBar()" in page
|
|
for part in (
|
|
"createSegment(",
|
|
"createListRow(",
|
|
"createKv(",
|
|
"createFloatPanel(",
|
|
"createBanner(",
|
|
):
|
|
assert part in page, part
|
|
assert 'el("input"' not in view and "createCheckbox(" in view
|
|
assert (
|
|
'classList.add("e04-toggle")' in page
|
|
) # 촬영 장면이 `.e04-toggle button[data-value]` 로 잡음
|
|
assert 'row.classList.add("e04-section")' in page
|
|
for dead in (
|
|
".e04-toggle .ui-btn",
|
|
".e04-legend__row",
|
|
".e04-legend__swatch",
|
|
".e04-result__list",
|
|
".e04-section:hover",
|
|
):
|
|
assert dead not in css, dead
|
|
|
|
|
|
def test_e05_parts():
|
|
ts = _src("E05_StabReport/E05_StabReport_UI_Page.ts")
|
|
css = _src("E05_StabReport/E05_StabReport_UI_Style.css")
|
|
for part in ("createBanner(", "openModal(", "createEmpty(", "createText("):
|
|
assert part in ts, part
|
|
assert 'el("p"' not in ts and "previewBox" not in ts
|
|
assert 'classList.add("e05-stale")' in ts # 촬영 장면이 `.e05-stale .ui-btn` 으로 잡음
|
|
assert ".e05-stale[hidden]" in css # 띠 알림은 flex 라 hidden 을 덮음
|
|
for dead in (".e05-preview {", ".e05-preview__head", ".e05-status.is-error"):
|
|
assert dead not in css, dead
|
|
|
|
|
|
def test_e06_parts():
|
|
names = ["Joints", "Page", "Result", "Stereonet"]
|
|
ts = {n: _src(f"E06_StabRock/E06_StabRock_UI_{n}.ts") for n in names}
|
|
parts = _src("E06_StabRock/E06_StabRock_UI_Parts.ts")
|
|
css = _src("E06_StabRock/E06_StabRock_UI_Style.css")
|
|
for n, src in ts.items():
|
|
assert 'el("table"' not in src and 'el("input"' not in src, n
|
|
assert 'el("select"' not in src and 'el("p"' not in src, n
|
|
for part in ("createTable(", "createBadge(", "createSegment(", "createText(", "createEmpty("):
|
|
assert part in parts, part
|
|
assert "createLegend(" in ts["Stereonet"] and "createBanner(" in ts["Page"]
|
|
assert "createInputField(" in ts["Joints"] and "createSelectField(" in ts["Joints"]
|
|
assert "compact: true" in ts["Joints"] and ".e06-setting" not in css # 설정 줄 부품 좁은 꼴
|
|
assert (
|
|
'classList.add("e06-toggle")' in parts
|
|
) # 촬영 장면이 `.e06-toggle button[data-value]` 로 잡음
|
|
assert '"station-list"' in ts["Result"] # 촬영 장면 · 시험이 잡는 data-role
|
|
for dead in (
|
|
".e06-verdict",
|
|
".e06-list th",
|
|
".e06-cases",
|
|
".e06-table th",
|
|
".e06-legend__row",
|
|
".e06-toggle .ui-btn",
|
|
"is-invalid",
|
|
):
|
|
assert dead not in css, dead
|
|
assert "is-invalid" not in ts["Joints"] + ts["Page"]
|
|
|
|
|
|
def test_e07_parts():
|
|
page = _src("E07_StabArea/E07_StabArea_UI_Page.ts")
|
|
css = _src("E07_StabArea/E07_StabArea_UI_Style.css")
|
|
assert 'el("table"' not in page and 'el("progress"' not in page and 'el("p"' not in page
|
|
for part in (
|
|
"createSegment(",
|
|
"createFloatPanel(",
|
|
"createLegend(",
|
|
"createKv(",
|
|
"createTable(",
|
|
):
|
|
assert part in page, part
|
|
for part in ("createProgressBar()", "createBanner(", "createEmpty("):
|
|
assert part in page, part
|
|
assert (
|
|
'toggle.classList.add("e07-toggle")' in page
|
|
) # 촬영 장면이 `.e07-toggle button[data-value]` 로 잡음
|
|
assert "data-chainage" in css or "dataset.chainage" in page # 줄 누름 = 지도 이동
|
|
for dead in (
|
|
".e07-toggle .ui-btn",
|
|
".e07-legend__row",
|
|
".e07-summary",
|
|
".e07-table th",
|
|
".e07-progress {",
|
|
):
|
|
assert dead not in css, dead
|
|
|
|
|
|
def test_map_tips_use_tooltip_part():
|
|
for path, hook in (
|
|
("E03_StabSection/E03_StabSection_UI_Section.ts", "e03-tip"),
|
|
("E04_Stab3D/E04_Stab3D_UI_Map.ts", "e04-map__tip"),
|
|
("E07_StabArea/E07_StabArea_UI_Map.ts", "e07-map__tip"),
|
|
):
|
|
ts = _src(path)
|
|
assert 'tooltipBox("")' in ts and f'classList.add("{hook}")' in ts, path
|
|
for path, dead in (
|
|
(
|
|
"E03_StabSection/E03_StabSection_UI_Style.css",
|
|
"background: var(--color-surface);\n border:",
|
|
),
|
|
("E04_Stab3D/E04_Stab3D_UI_Style.css", "white-space: pre;"),
|
|
("E07_StabArea/E07_StabArea_UI_Style.css", "white-space: pre;"),
|
|
):
|
|
assert dead not in _src(path).replace("\r\n", "\n"), path
|