from pathlib import Path import importlib.util import json import subprocess import sys import pytest import yaml HERE = Path(__file__).resolve().parent spec = importlib.util.spec_from_file_location("steel_beam_calc", HERE / "calc.py") assert spec is not None and spec.loader is not None module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) def result(): with (HERE / "input.yaml").open(encoding="utf-8") as handle: return module.compute(yaml.safe_load(handle)) def test_typst_load_demands_match_checked_inputs(): subprocess.run([sys.executable, str(HERE / "calc.py")], check=True, cwd=HERE.parents[1]) query = subprocess.run( [ "typst", "eval", "query()", "--root", ".", "--in", "calcs/steel-beam/steel-beam.typ", "--format", "json", ], check=True, capture_output=True, text=True, cwd=HERE.parents[1], ) published = json.loads(query.stdout) assert len(published) == 1 derived = published[0]["value"] values = result()["values"] assert derived["Mu_kipft"] == pytest.approx(values["moment_kipft"], abs=0.001) assert derived["Vu_kip"] == pytest.approx(values["shear_kip"], abs=0.001) def test_ground_truth_section_properties(): values = result()["values"] assert values["section_d"] == pytest.approx(5.875) assert values["section_A"] == pytest.approx(2.52) assert values["section_Sx"] == pytest.approx(5.1) assert values["section_Zx"] == pytest.approx(5.73) assert values["section_rts"] == pytest.approx(1.05) def test_ground_truth_demands_and_flexure(): output = result() values = output["values"] assert values["point_load_lbf"] == pytest.approx(7500) assert values["moment_kipft"] == pytest.approx(9.375) assert values["shear_kip"] == pytest.approx(3.75) assert values["Lp_in"] == pytest.approx(37.7, abs=0.1) assert values["Lr_ft"] == pytest.approx(9.48, abs=0.01) assert values["Fcr_ksi"] == pytest.approx(99.57, abs=0.25) assert values["Mp_kipft"] == pytest.approx(23.875) assert values["MnLTB_kipft"] == pytest.approx(21.235, abs=0.01) assert values["phiMn_kipft"] == pytest.approx(19.1, abs=0.1) assert output["checks"]["flexure"]["ok"] is True def test_ground_truth_shear_and_deflection(): output = result() values = output["values"] assert values["Aw_in2"] == pytest.approx(1.102, abs=0.001) assert values["Cv1"] == pytest.approx(1) assert values["phiVn_kip"] == pytest.approx(33.047, abs=0.1) assert values["delta_limit_in"] == pytest.approx(0.25) assert values["delta_in"] == pytest.approx(0.078, abs=0.001) assert all(output["checks"][name]["ok"] for name in ("shear", "deflection")) def test_invalid_section_is_rejected(): with pytest.raises(ValueError, match="not found"): module.compute({**yaml.safe_load((HERE / "input.yaml").read_text()), "section": "W0X0"}) def test_cli_can_write_json_to_stdout(): completed = subprocess.run( [sys.executable, str(HERE / "calc.py"), "--input", str(HERE / "input.yaml"), "--stdout"], check=True, capture_output=True, text=True, ) output = json.loads(completed.stdout) assert output["section"] == "W6X8.5" assert output["values"]["moment_kipft"] == pytest.approx(9.375) assert completed.stderr == ""