Merge remote-tracking branch 'origin/dev' into sub_laptop_5

This commit is contained in:
2026-10-04 20:42:46 +09:00
4 changed files with 72 additions and 10 deletions
+4 -2
View File
@@ -57,5 +57,7 @@ def test_실패는_카드_안_글과_다시_불러오기():
assert "showToast" not in cards # 토스트 안 씀(저장 알림은 틀)
assert "c.shell.fail(" in cards and "reload" in cards
picker = (ROOT / "ui_template" / "ui_template_item_picker_detail.ts").read_text("utf-8")
assert "inputs.set(null, why(error), () => void paintInputs(row, seq));" in picker
assert "const stop = inputs.loading();" in picker
# 일위대가 카드 · 값 카드가 다시 불러오기 하나(retry)를 같이 씀(39-1c)
assert "const retry = (): void => void paintLabor(row, seq);" in picker
assert "inputs.set(null, why(error), retry);" in picker
assert "const stops = [labor.loading(), inputs.loading()];" in picker
+51
View File
@@ -99,3 +99,54 @@ def test_값_셈() -> None:
assert got["known"] == {"kept": {"높이": 2}, "lost": ["없앤것"]}
assert got["line"] == {"text": "높이 2m · 규격 40", "empty": 2} # 종류 · 지역 = 자동값 없음
assert got["lineEmpty"] == {"text": "", "empty": 3} # 높이는 자동값이 있어 빈 값 아님
ROWS_SCRIPT = r"""
const fs = require("fs");
const path = require("path");
const root = process.argv[1];
const ts = require(path.join(root, "config", "node_modules", "typescript"));
const stub = new Proxy({}, {
get: (_t, k) => (k === "currentLanguageIndex" ? 0 : () => undefined),
});
function load(f) {
const js = ts.transpileModule(fs.readFileSync(f, "utf8"), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
}).outputText;
const box = { exports: {} };
const req = (id) => {
if (id.startsWith(".") && !id.includes("M01_MasterData")) {
const p = path.resolve(path.dirname(f), id);
return fs.existsSync(p + ".ts") ? load(p + ".ts") : stub;
}
return stub;
};
new Function("exports", "module", "require", js)(box.exports, box, req);
return box.exports;
}
const m = load(path.join(root, "M02_MasterTemplete", "M02_MasterTemplete_Labor_Rows.ts"));
const cells = new Map([["돌쌓기|㎡", "B6"]]);
console.log(JSON.stringify([
m.qtyText({ 수량: 20, 수량출처: "칸", 알약: "돌쌓기|㎡" }, "㎡", cells),
m.qtyText({ 수량: 20, 수량출처: "칸", 알약: "돌쌓기|㎡" }, "㎡"),
m.qtyText({ 수량: 3, 수량출처: "손", 알약: "돌쌓기|㎡" }, "㎡", cells),
m.qtyText({ 수량: null, 수량출처: "없음", 알약: "돌쌓기|㎡" }, "㎡", cells),
]));
"""
def test_수량_글은_이은_칸_주소를_보임() -> None:
"""`Labor_View.setQty(수량, 칸)` 의 칸 주소로 「수량 B6 = 20 ㎡」 — 없으면 「면적산출 칸」."""
node = shutil.which("node")
if not node:
pytest.skip("node 없음")
out = subprocess.run(
[node, "-e", ROWS_SCRIPT, str(ROOT)], capture_output=True, text=True, encoding="utf-8"
)
assert out.returncode == 0, out.stderr
assert json.loads(out.stdout) == [
"수량 B6 = 20 ㎡",
"수량 면적산출 칸 = 20 ㎡",
"수량 손 입력 3 ㎡",
"",
]
+4 -1
View File
@@ -80,6 +80,9 @@ def test_실패_글과_다시_불러오기_M02_자리():
edit = _text(M02 / "M02_MasterTemplete_Labor_Edit.ts")
assert "loadingError(reason(error), () => void open(key))" in edit
assert "(current ? () => {} : showLoading(view))" in edit
assert "const stop = editor.loading();" in _text(M02 / "M02_MasterTemplete_Labor.ts")
# 좌측 일위대가 조합 나무(Labor.ts)는 39-2 에 지움 — 그 목록 자리는 실무문서 화면(같은 꼴)
practice = _text(M02 / "M02_MasterTemplete_Practice.ts")
assert "const stop = showLoading(view);" in practice
assert "loadingError(why(error), () => void drawList())" in practice
assert "cards.map((c) => c.shell.loading())" in _text(M02 / "M02_MasterTemplete_ItemCards.ts")
assert "loading: () => showLoading(host)," in _text(M02 / "M02_MasterTemplete_CardShell.ts")