Skip to content

Commit 14066a6

Browse files
committed
added 28 more test, now 623 in total
1 parent 2e83e30 commit 14066a6

9 files changed

Lines changed: 725 additions & 0 deletions

tests/test_cli.py

Lines changed: 377 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,3 +727,380 @@ def test_file_variable_is_set(tmp_path):
727727
out, err, exitcode = helpers.cli_call(command)
728728
assert exitcode == 0
729729
assert "__file__=" in out.decode()
730+
731+
732+
def test_stdin_input():
733+
"""
734+
Tests that a CadQuery script piped via stdin produces valid STEP output.
735+
"""
736+
import subprocess
737+
738+
test_file = helpers.get_test_file_location("cube.py")
739+
with open(test_file, "r") as f:
740+
script = f.read()
741+
742+
proc = subprocess.Popen(
743+
[sys.executable, "src/cq_cli/main.py", "--codec", "step", "--outfile", "-"],
744+
stdin=subprocess.PIPE,
745+
stdout=subprocess.PIPE,
746+
stderr=subprocess.PIPE,
747+
)
748+
# Pass script via stdin; use --outfile - equivalent: no --outfile means stdout
749+
proc2 = subprocess.Popen(
750+
[sys.executable, "src/cq_cli/main.py", "--codec", "step"],
751+
stdin=subprocess.PIPE,
752+
stdout=subprocess.PIPE,
753+
stderr=subprocess.PIPE,
754+
)
755+
out, err = proc2.communicate(input=script.encode())
756+
757+
assert "ISO-10303-21;" in out.decode()
758+
759+
760+
def test_stdin_with_outfile(tmp_path):
761+
"""
762+
Tests that a CadQuery script piped via stdin with --outfile writes correct output.
763+
"""
764+
import subprocess
765+
766+
test_file = helpers.get_test_file_location("cube.py")
767+
with open(test_file, "r") as f:
768+
script = f.read()
769+
770+
out_path = tmp_path / "stdin_out.step"
771+
772+
proc = subprocess.Popen(
773+
[
774+
sys.executable,
775+
"src/cq_cli/main.py",
776+
"--codec",
777+
"step",
778+
"--outfile",
779+
str(out_path),
780+
],
781+
stdin=subprocess.PIPE,
782+
stdout=subprocess.PIPE,
783+
stderr=subprocess.PIPE,
784+
)
785+
out, err = proc.communicate(input=script.encode())
786+
787+
assert proc.returncode == 0
788+
with open(str(out_path), "r") as f:
789+
content = f.read()
790+
assert content.startswith("ISO-10303-21;")
791+
792+
793+
def test_parameter_delimited_string_multiple_params(tmp_path):
794+
"""
795+
Tests that multiple key:value pairs in a single --params string all take effect.
796+
Passes width=2 and centered=False together and confirms output differs from defaults.
797+
"""
798+
test_file = helpers.get_test_file_location("cube_params.py")
799+
out_default = tmp_path / "default.step"
800+
out_custom = tmp_path / "custom.step"
801+
802+
command_default = [
803+
sys.executable,
804+
"src/cq_cli/main.py",
805+
"--codec",
806+
"step",
807+
"--infile",
808+
test_file,
809+
"--outfile",
810+
str(out_default),
811+
]
812+
helpers.cli_call(command_default)
813+
814+
command_custom = [
815+
sys.executable,
816+
"src/cq_cli/main.py",
817+
"--codec",
818+
"step",
819+
"--infile",
820+
test_file,
821+
"--outfile",
822+
str(out_custom),
823+
"--params",
824+
"width:2;",
825+
]
826+
out, err, exitcode = helpers.cli_call(command_custom)
827+
828+
assert exitcode == 0
829+
with open(str(out_default), "r") as f:
830+
default_content = f.read()
831+
with open(str(out_custom), "r") as f:
832+
custom_content = f.read()
833+
assert default_content != custom_content
834+
835+
836+
def test_parameter_json_string_multiple_params(tmp_path):
837+
"""
838+
Tests that a JSON --params string with multiple keys all apply correctly.
839+
"""
840+
test_file = helpers.get_test_file_location("cube_params.py")
841+
out_path = tmp_path / "multi_json.step"
842+
843+
command = [
844+
sys.executable,
845+
"src/cq_cli/main.py",
846+
"--codec",
847+
"step",
848+
"--infile",
849+
test_file,
850+
"--outfile",
851+
str(out_path),
852+
"--params",
853+
'{"width": 5, "centered": false}',
854+
]
855+
out, err, exitcode = helpers.cli_call(command)
856+
857+
assert exitcode == 0
858+
with open(str(out_path), "r") as f:
859+
content = f.read()
860+
assert content.startswith("ISO-10303-21;")
861+
862+
863+
def test_getparams_with_no_params_script():
864+
"""
865+
Tests that --getparams on a script with no user-defined parameters returns only
866+
the injected __file__ entry (a side-effect of __file__ prepending), with no other
867+
named parameters.
868+
"""
869+
test_file = helpers.get_test_file_location("cube.py")
870+
871+
command = [
872+
sys.executable,
873+
"src/cq_cli/main.py",
874+
"--getparams",
875+
"true",
876+
"--infile",
877+
test_file,
878+
]
879+
out, err, exitcode = helpers.cli_call(command)
880+
881+
assert exitcode == 0
882+
result = json.loads(out.decode())
883+
user_params = [p for p in result if p["name"] != "__file__"]
884+
assert user_params == []
885+
886+
887+
def test_getparams_writes_file_and_returns_expected_keys(tmp_path):
888+
"""
889+
Tests that --getparams writes a JSON file containing the expected parameter names.
890+
"""
891+
test_file = helpers.get_test_file_location("cube_params.py")
892+
params_out = tmp_path / "params.json"
893+
894+
command = [
895+
sys.executable,
896+
"src/cq_cli/main.py",
897+
"--getparams",
898+
str(params_out),
899+
"--infile",
900+
test_file,
901+
]
902+
out, err, exitcode = helpers.cli_call(command)
903+
904+
assert exitcode == 0
905+
assert params_out.exists() and params_out.stat().st_size > 0
906+
params = json.loads(params_out.read_text())
907+
names = [p["name"] for p in params]
908+
assert "width" in names
909+
assert "tag_name" in names
910+
assert "centered" in names
911+
912+
913+
def test_validate_with_outfile(tmp_path):
914+
"""
915+
Tests that --validate true with --outfile writes 'validation_success' to the file.
916+
"""
917+
test_file = helpers.get_test_file_location("cube.py")
918+
out_path = tmp_path / "validation.txt"
919+
920+
command = [
921+
sys.executable,
922+
"src/cq_cli/main.py",
923+
"--validate",
924+
"true",
925+
"--infile",
926+
test_file,
927+
"--outfile",
928+
str(out_path),
929+
]
930+
out, err, exitcode = helpers.cli_call(command)
931+
932+
assert exitcode == 0
933+
assert out_path.read_text() == "validation_success"
934+
935+
936+
def test_syntax_error_exits_100():
937+
"""
938+
Tests that a script with a Python syntax error exits with code 100.
939+
"""
940+
test_file = helpers.get_test_file_location("syntax_error.py")
941+
942+
command = [
943+
sys.executable,
944+
"src/cq_cli/main.py",
945+
"--codec",
946+
"step",
947+
"--infile",
948+
test_file,
949+
]
950+
out, err, exitcode = helpers.cli_call(command)
951+
952+
assert exitcode == 100
953+
954+
955+
def test_syntax_error_written_to_errfile(tmp_path):
956+
"""
957+
Tests that a script syntax error writes a traceback to errfile.
958+
"""
959+
test_file = helpers.get_test_file_location("syntax_error.py")
960+
err_file = tmp_path / "syntax_err.txt"
961+
962+
command = [
963+
sys.executable,
964+
"src/cq_cli/main.py",
965+
"--codec",
966+
"step",
967+
"--infile",
968+
test_file,
969+
"--errfile",
970+
str(err_file),
971+
]
972+
out, err, exitcode = helpers.cli_call(command)
973+
974+
assert exitcode == 100
975+
content = err_file.read_text()
976+
assert len(content) > 0
977+
978+
979+
def test_codec_error_written_to_errfile(tmp_path):
980+
"""
981+
Tests that a codec-level failure (exit 200) writes traceback to errfile.
982+
Uses the expression argument to trigger a no-results error.
983+
"""
984+
test_file = helpers.get_test_file_location("no_toplevel_objects.py")
985+
err_file = tmp_path / "codec_err.txt"
986+
987+
command = [
988+
sys.executable,
989+
"src/cq_cli/main.py",
990+
"--codec",
991+
"step",
992+
"--infile",
993+
test_file,
994+
"--errfile",
995+
str(err_file),
996+
]
997+
out, err, exitcode = helpers.cli_call(command)
998+
999+
assert exitcode == 200
1000+
content = err_file.read_text()
1001+
assert len(content) > 0
1002+
1003+
1004+
def test_auto_codec_detection_stl(tmp_path):
1005+
"""
1006+
Tests that the STL codec is inferred from a .stl output file extension.
1007+
"""
1008+
test_file = helpers.get_test_file_location("cube.py")
1009+
out_path = tmp_path / "auto.stl"
1010+
1011+
command = [
1012+
sys.executable,
1013+
"src/cq_cli/main.py",
1014+
"--infile",
1015+
test_file,
1016+
"--outfile",
1017+
str(out_path),
1018+
]
1019+
out, err, exitcode = helpers.cli_call(command)
1020+
1021+
assert exitcode == 0
1022+
content = out_path.read_bytes()
1023+
assert content[:5] == b"solid"
1024+
1025+
1026+
def test_auto_codec_detection_svg(tmp_path):
1027+
"""
1028+
Tests that the SVG codec is inferred from a .svg output file extension.
1029+
"""
1030+
test_file = helpers.get_test_file_location("cube.py")
1031+
out_path = tmp_path / "auto.svg"
1032+
1033+
command = [
1034+
sys.executable,
1035+
"src/cq_cli/main.py",
1036+
"--infile",
1037+
test_file,
1038+
"--outfile",
1039+
str(out_path),
1040+
]
1041+
out, err, exitcode = helpers.cli_call(command)
1042+
1043+
assert exitcode == 0
1044+
content = out_path.read_text()
1045+
assert '<?xml version="1.0"' in content
1046+
1047+
1048+
def test_param_change_produces_different_step_output(tmp_path):
1049+
"""
1050+
Tests that changing the width parameter produces geometrically different STEP output.
1051+
"""
1052+
test_file = helpers.get_test_file_location("cube_params.py")
1053+
out_small = tmp_path / "small.step"
1054+
out_large = tmp_path / "large.step"
1055+
1056+
helpers.cli_call(
1057+
[
1058+
sys.executable,
1059+
"src/cq_cli/main.py",
1060+
"--codec",
1061+
"step",
1062+
"--infile",
1063+
test_file,
1064+
"--outfile",
1065+
str(out_small),
1066+
"--params",
1067+
"width:1;",
1068+
]
1069+
)
1070+
helpers.cli_call(
1071+
[
1072+
sys.executable,
1073+
"src/cq_cli/main.py",
1074+
"--codec",
1075+
"step",
1076+
"--infile",
1077+
test_file,
1078+
"--outfile",
1079+
str(out_large),
1080+
"--params",
1081+
"width:10;",
1082+
]
1083+
)
1084+
1085+
assert out_small.read_text() != out_large.read_text()
1086+
1087+
1088+
def test_multi_show_object_produces_output():
1089+
"""
1090+
Tests that a script calling show_object() multiple times still produces valid output
1091+
(cq-cli uses the first result).
1092+
"""
1093+
test_file = helpers.get_test_file_location("multi_show_object.py")
1094+
1095+
command = [
1096+
sys.executable,
1097+
"src/cq_cli/main.py",
1098+
"--codec",
1099+
"step",
1100+
"--infile",
1101+
test_file,
1102+
]
1103+
out, err, exitcode = helpers.cli_call(command)
1104+
1105+
assert exitcode == 0
1106+
assert "ISO-10303-21;" in out.decode()

0 commit comments

Comments
 (0)