"""일위대가 넣을 값(39-3) — 입력 목록 길 `GET /api/m02/logic-lib/inputs` · 값 셈(TS 모델). 못박는 것 - 입력 목록 = 키 차례 · 겹친 키 한 번 · 입력마다 자동값 · 없는 키는 「빠진로직」. - 옛 선택 입력 길(`M02_MasterTemplete_Inputs.inputs`)과 몸 한 벌(`M02_Labor_Inputs`). - 값 셈 = 칸 글 → 저장 값(빈 글 = 자동값 · 범위 = 수 · 고르기 = 원래 모양) · 범위 밖 · 모르는 이름 버림(사라진 값 알림) · 줄 아래 작은 글 · 빈 값 수(자동값도 없는 입력만). 화면 TS 는 그 자리에서 트랜스파일해 node 로 돌림 · 정본은 읽기만. """ from __future__ import annotations import json import shutil import subprocess from pathlib import Path import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from common_util.common_util_auth import verify_session from M02_MasterTemplete import M02_Labor_Inputs as labor_inputs from M02_MasterTemplete import M02_MasterTemplete_Router_Combos as combos_router ROOT = Path(__file__).resolve().parents[2] A, B = "GF000222", "GF000221" # 찰쌓기 인력 · 장비 @pytest.fixture() def client() -> TestClient: app = FastAPI() app.include_router(combos_router.router) app.dependency_overrides[verify_session] = lambda: {"user_id": 42, "role": "USER"} return TestClient(app) def test_입력_목록은_키_차례_겹침_한_번_자동값_빠진_로직(client: TestClient) -> None: res = client.get("/api/m02/logic-lib/inputs", params={"keys": f"{B},{A},{B},GF999999,"}) assert res.status_code == 200, res.text got = res.json() assert [x["로직"] for x in got["로직"]] == [B, A] assert got["빠진로직"] == ["GF999999"] one = got["로직"][1] assert one["이름"] and one["결과단위"] assert one["입력"] and all("자동값" in i and "이름" in i for i in one["입력"]) # 옛 선택 입력 목록과 같은 몸 assert got["로직"] == labor_inputs.logic_inputs([B, A])["로직"] def test_빈_키는_빈_목록(client: TestClient) -> None: got = client.get("/api/m02/logic-lib/inputs").json() assert got == {"로직": [], "빠진로직": []} SCRIPT = r""" const fs = require("fs"); const path = require("path"); const ts = require(path.join(process.argv[1], "config", "node_modules", "typescript")); const file = path.join(process.argv[1], "M02_MasterTemplete", "M02_Labor_Values_Model.ts"); const js = ts.transpileModule(fs.readFileSync(file, "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; new Function("exports", "module", "require", js)(box.exports, box, require); const m = box.exports; const height = { 이름: "높이", 단위: "m", 범위: [0.5, 5], 자동값: 1.2 }; const kind = { 이름: "종류", 고르기: ["막돌", "견치돌"] }; const size = { 이름: "규격", 고르기: [25, 40] }; const area = { 이름: "지역" }; const inputs = [height, kind, size, area]; console.log(JSON.stringify({ stored: [ m.storedOf(height, ""), m.storedOf(height, "2.5"), m.storedOf(kind, "막돌"), m.storedOf(size, "40"), m.storedOf(area, "서울"), ], outside: [ m.isOutside(height, "9"), m.isOutside(height, "0.5"), m.isOutside(height, ""), m.isOutside(height, "abc"), m.isOutside(area, "9"), ], known: m.keepKnown(inputs, { 높이: 2, 종류: "", 없앤것: 3 }), line: m.valueLine(inputs, { 높이: 2, 규격: 40 }), lineEmpty: m.valueLine(inputs, {}), })); """ def test_값_셈() -> None: node = shutil.which("node") if not node: pytest.skip("node 없음") out = subprocess.run( [node, "-e", SCRIPT, str(ROOT)], capture_output=True, text=True, encoding="utf-8" ) assert out.returncode == 0, out.stderr got = json.loads(out.stdout) assert got["stored"] == [None, 2.5, "막돌", 40, "서울"] assert got["outside"] == [True, False, False, True, False] assert got["known"] == {"kept": {"높이": 2}, "lost": ["없앤것"]} assert got["line"] == {"text": "높이 2m · 규격 40", "empty": 2} # 종류 · 지역 = 자동값 없음 assert got["lineEmpty"] == {"text": "", "empty": 3} # 높이는 자동값이 있어 빈 값 아님