Files
Aislo/resources/tester/test_m02_df_inputpanel_material.py
T

247 lines
9.1 KiB
Python

"""단가산출 흐름도 입력 판 — 재료 요소 방식 셋 · 쪽 넘기기 · 다른 로직 입력(`M02_DF_InputPanel_Build.ts`).
화면 TS 를 그 자리에서 트랜스파일해 node 로 돌림 — 순수 함수만 부름. 견본 상자 · 로직은 이 시험 안에 둠.
"""
import json
import shutil
import subprocess
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
SOURCE = ROOT / "M02_MasterTemplete" / "DataFlow" / "M02_DF_InputPanel_Build.ts"
RUNNER = r"""
const fs = require("fs");
const path = require("path");
const [root, file] = process.argv.slice(1);
const ts = require(path.join(root, "config", "node_modules", "typescript"));
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, () => ({}));
const m = box.exports;
const jobs = JSON.parse(fs.readFileSync(0, "utf8"));
process.stdout.write(JSON.stringify(jobs.map((j) => m[j.name](...j.args))));
"""
def call(name: str, *args):
if shutil.which("node") is None:
pytest.skip("node 가 없음")
done = subprocess.run(
["node", "-e", RUNNER, str(ROOT), str(SOURCE)],
input=json.dumps([{"name": name, "args": list(args)}], ensure_ascii=False),
capture_output=True,
text=True,
encoding="utf-8",
check=True,
)
return json.loads(done.stdout)[0]
PLAIN = {"color": "#fff", "unit": "-", "x": 0, "y": 0}
def logic() -> dict:
return {
"key": None,
"name": "견본",
"resultUnit": "원/㎡",
"userElements": [],
"boxes": [
{
"id": "b1",
"kind": "input",
"name": "입력",
**PLAIN,
"input": {"mode": "variable", "elements": [], "variables": []},
},
{
"id": "b2",
"kind": "input",
"name": "관경",
**PLAIN,
"input": {
"mode": "variable",
"elements": [],
"variables": [{"name": "관경", "type": "text", "unit": "", "example": "300"}],
},
},
],
"links": [],
}
HUME = {"name": "각형흄관", "spec": "D=300mm"}
def test_규칙이_품목을_잡음_규격_이름_포함_같음():
in_spec = {"field": "규격", "op": "포함"}
assert call("matches", HUME, in_spec, "300") is True
assert call("matches", HUME, in_spec, "400") is False
assert call("matches", HUME, {"field": "이름", "op": "포함"}, "흄관") is True
assert call("matches", HUME, {"field": "이름", "op": "같음"}, "흄관") is False
assert (
call("matches", HUME, {"field": "이름", "op": "같음"}, "각형 흄관") is True
) # 띄어쓰기는 가리지 않음
assert call("matches", HUME, in_spec, "") is False # 알약 값이 비면 안 잡음
def test_잡힌_수에_따른_알림():
assert call("catchNote", 0)["kind"] == "none"
one = call("catchNote", 1, "각형흄관 D=300mm")
assert one["kind"] == "one" and "각형흄관" in one["text"]
many = call("catchNote", 3)
assert many["kind"] == "many" and "3 개" in many["text"]
def test_쪽_넘기기_범위():
assert call("pageRange", 25, 1, 12) == {"from": 1, "to": 12, "pages": 3}
assert call("pageRange", 25, 3, 12) == {"from": 25, "to": 25, "pages": 3}
assert call("pageRange", 25, 9, 12) == {
"from": 25,
"to": 25,
"pages": 3,
} # 쪽이 넘치면 마지막 쪽
assert call("pageRange", 0, 1, 12) == {"from": 0, "to": 0, "pages": 1}
def test_변수_알약_목록():
pills = call("variablePills", logic())
assert pills == [{"port": {"box": "b2", "name": "관경"}, "unit": "", "example": "300"}]
def test_선택_자리와_조건_찾기_요소():
item = {"ref": "MT009686", "spec": "D=300mm", "unit": "M"}
slot = call(
"materialElement",
"choice",
"흄관",
{"구분": "관·이음관", "상세구분": "", "찾는말": "흄관"},
{"item": item},
)
assert slot["mode"] == "choice" and slot["name"] == "흄관" and slot["slot"] == "흄관"
assert slot["default"] == "MT009686" and slot["scope"] == {
"구분": "관·이음관",
"찾는말": "흄관",
}
rule = {"field": "규격", "op": "포함", "from": {"box": "b2", "name": "관경"}}
found = call("materialElement", "rule", "흄관", {"찾는말": "흄관"}, {"rule": rule})
assert found["mode"] == "rule" and found["ref"] == "" and found["rule"] == rule
assert "default" not in found
def test_재료_요소_검사():
ok = call("materialElement", "choice", "흄관", {"찾는말": "흄관"})
assert call("checkMaterial", ok, []) is None
assert call("checkMaterial", {**ok, "name": ""}, []) == "자리 이름을 적어 주세요"
assert call("checkMaterial", ok, [ok]) == "같은 이름의 알약이 이미 있음"
assert "범위" in call("checkMaterial", call("materialElement", "choice", "흄관", {}), [])
rule_no_pill = call(
"materialElement",
"rule",
"흄관",
{"찾는말": "흄관"},
{"rule": {"field": "규격", "op": "포함", "from": {"box": "", "name": ""}}},
)
assert "변수 알약" in call("checkMaterial", rule_no_pill, [])
def test_조건_찾기_요소는_품목_키가_없어도_따로_넣고_이름으로_뺌():
rule = {"field": "규격", "op": "포함", "from": {"box": "b2", "name": "관경"}}
a = call("materialElement", "rule", "흄관", {"찾는말": "흄관"}, {"rule": rule})
b = call("materialElement", "rule", "받침", {"찾는말": "받침"}, {"rule": rule})
lg = call("addElement", logic(), "b1", a)
lg = call("addElement", lg, "b1", b)
assert [e["name"] for e in lg["boxes"][0]["input"]["elements"]] == ["흄관", "받침"]
assert call("addElement", lg, "b1", a) == lg # 같은 이름은 한 번만
gone = call("removeElementNamed", lg, "b1", "흄관")
assert [e["name"] for e in gone["boxes"][0]["input"]["elements"]] == ["받침"]
def other_logic() -> dict:
return {
"key": "DF-0009",
"name": "시간당 작업량",
"resultUnit": "㎥/시간",
"userElements": [],
"links": [],
"boxes": [
{
"id": "i1",
"kind": "input",
"name": "조건",
**PLAIN,
"input": {
"mode": "variable",
"elements": [],
"variables": [{"name": "q", "type": "number", "unit": "㎥", "example": 6}],
},
},
{
"id": "i2",
"kind": "input",
"name": "재료",
**PLAIN,
"input": {
"mode": "group",
"group": "재료",
"elements": [
{
"ref": "",
"name": "흄관",
"spec": "",
"unit": "M",
"mode": "rule",
"slot": "흄관",
}
],
"variables": [],
},
},
{
"id": "o1",
"kind": "output",
"name": "작업량",
**PLAIN,
"unit": "㎥/시간",
"output": {"cost": "값", "unit": "㎥/시간"},
},
],
}
def test_다른_로직_입력_알약():
ref = call("logicRefOf", "DF-0009", other_logic())
assert ref["key"] == "DF-0009" and ref["name"] == "시간당 작업량"
assert ref["outputs"] == [{"name": "작업량", "unit": "㎥/시간"}]
assert ref["designs"] == [{"name": "q", "unit": "㎥"}, {"name": "흄관", "unit": "M"}]
def test_다른_로직_상자는_출력_단위를_따르고_빼면_변수로_돌아감():
ref = call("logicRefOf", "DF-0009", other_logic())
lg = call("setLogicInput", logic(), "b1", ref)
box = lg["boxes"][0]
assert box["input"]["mode"] == "logic" and box["input"]["logic"]["key"] == "DF-0009"
assert box["unit"] == "㎥/시간"
assert call("pillNames", box) == ["작업량"]
lg["links"] = [
{"id": "l1", "from": {"box": "b1", "name": "작업량"}, "to": {"box": "b2", "name": "x"}}
]
back = call("setLogicInput", lg, "b1", None)
assert back["boxes"][0]["input"]["mode"] == "variable" and back["links"] == []
assert call("reconcileUnit", lg, "b1") == lg # 다른 로직 상자 단위는 안 건드림
def test_갈래를_다른_로직으로_바꾸면_고른_것을_비움():
el = {"ref": "LB1", "name": "석공", "spec": "", "unit": "원/일"}
lg = call("addElement", call("setKind", logic(), "b1", "인력"), "b1", el)
out = call("setKind", lg, "b1", "다른 로직")
assert (
out["boxes"][0]["input"]["mode"] == "logic" and out["boxes"][0]["input"]["elements"] == []
)