- 새 D03_PlanAnalysis_UI_Site — 지금 주소 · 찾기(createFindList · searchPlaces) · 실패 · 끊김 한 줄 + [다시 받기] · [임도망 올리기] - 위치 = 캐시 한 걸음(Snap site · 판 5 · 되돌리기 · 떠남 물음) → [저장] 몸 site · 지점 이름 point_names - 고름 → 지도 이동 → 둘레 받기(center) · 멂 · 다른 TM 띠 = 물음 한 번 뒤 reset · 아니오 = 위치 되돌림 - 임도망 올린 뒤 지도 맞춤 = 주소지 둘레 ∪ 잘린 임도 상자(없으면 주소지) - 조용히 받기 = 기준점 10 km 안 지점 · 선만 · 칸 글 걷음(실패 · 끊김 · 기준점 없음 · 못 불러옴만) - 등록(D01) 지도 머리 [위성] 오른쪽 찾기 = 같은 createPlaceFind · 사전 DE_Reg_Find* - 시험 553_4 위치 칸 · 등록 찾기 부품 · 560_4 savedJson 꼴 · 584_3 올리기 자리(위치 칸) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
287 lines
14 KiB
Python
287 lines
14 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_d03_points_parts():
|
|
"""591-2 — D02 걷음 · 지점 칸 = 목록 줄 · 아이콘 단추 · 우클릭 메뉴 부품."""
|
|
assert not (ROOT / "D02_PlanBase" / "D02_PlanBase_UI_Page.ts").exists()
|
|
ts = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_Points.ts")
|
|
assert "createListRow(" in ts and "createIconButton(" in ts and "createMapContextMenu(" in ts
|
|
for raw in ('createElement("button")', 'createElement("input")', 'el("input"'):
|
|
assert raw not 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")
|
|
draw_panel = _src("D03_PlanAnalysis/D03_PlanAnalysis_UI_DrawPanel.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(" not in ts
|
|
assert "createProgressCircle({ size: 40, corner: true })" in ts # 596-3 받기 = 지도 귀퉁이 서클
|
|
site = _src(
|
|
"D03_PlanAnalysis/D03_PlanAnalysis_UI_Site.ts"
|
|
) # 596-2 위치 칸 · 596-5 등록 찾기 = 같은 부품
|
|
assert "createFindList(" in site and "searchPlaces(" in site and "createPlanSite(" in ts
|
|
assert "createPlaceFind(" in _src("D01_PlanRegister/D01_PlanRegister_UI_Page.ts")
|
|
for raw in ('createElement("button")', 'createElement("input")'):
|
|
assert raw not in site, raw
|
|
# 562-3 — 날 단추 · 입력 · 고르기 없음 · 도구줄 · 제약 칸 · 연도 고름은 부품
|
|
for src in (ts, draw, draw_panel, 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
|
|
# 599-1 — 방식 칸 = 마디 고름 2 × 2 · 길이 · 기울기 두 열 · 노드 판(598-4)과 같은 함수
|
|
assert "createSegment({" in draw_panel and draw_panel.count("createInputField(") == 2
|
|
assert "columns: 2" in draw_panel and "export function createDrawKindFields(" in draw_panel
|
|
assert ".d03-plan__draw-fields" in css and "createDrawKindFields(" in draw
|
|
assert '"길이·기울기 고정"' in draw_panel and '"둘 다"' not in draw_panel
|
|
assert "d03-plan__hint" not in draw # 칸 설명 글 걷음(요구 463-6)
|
|
# 599-4 — 연도 구역 마커 = 그리기 칸 단추(끌어 놓기) · 지도 도구줄에서 뺌
|
|
assert "YEAR_MARK_DRAG" in draw_panel and '"year-mark"' not in tools
|
|
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" not in three
|
|
) # 601 선 고름 걷음
|
|
assert (
|
|
"createCheckbox" not in three and "setCorridors(" in three
|
|
) # 601 노선망 예상 코리도 한 번에
|
|
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
|