test_process_overrides.py 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. """Unit tests for the slice modal's process-setting overrides."""
  2. import json
  3. from backend.app.services.process_overrides import (
  4. apply_process_overrides,
  5. normalise_process_overrides,
  6. )
  7. def _process(**values: str) -> str:
  8. return json.dumps({"inherits": "0.20mm Standard @BBL X1C", **values})
  9. class TestNormaliseProcessOverrides:
  10. def test_bools_become_the_one_zero_strings_a_preset_stores(self):
  11. assert normalise_process_overrides({"enable_support": True}) == {"enable_support": "1"}
  12. assert normalise_process_overrides({"enable_support": False}) == {"enable_support": "0"}
  13. def test_numbers_become_strings(self):
  14. assert normalise_process_overrides({"wall_loops": 4, "layer_height": 0.16}) == {
  15. "wall_loops": "4",
  16. "layer_height": "0.16",
  17. }
  18. def test_strings_pass_through_including_the_percent_sign(self):
  19. # The frontend serialises percents with the sign; stripping it here
  20. # would silently change the value the slicer sees.
  21. assert normalise_process_overrides({"sparse_infill_density": "35%"}) == {"sparse_infill_density": "35%"}
  22. def test_vector_options_keep_their_list_shape(self):
  23. assert normalise_process_overrides({"default_acceleration": [500, 300]}) == {
  24. "default_acceleration": ["500", "300"]
  25. }
  26. def test_keys_that_are_not_config_identifiers_are_dropped(self):
  27. result = normalise_process_overrides({"wall_loops": 2, "Wall Loops": 3, "__proto__": 1, "a-b": 1, "": 1})
  28. assert result == {"wall_loops": "2"}
  29. def test_values_a_preset_cannot_hold_are_dropped_not_serialised(self):
  30. result = normalise_process_overrides({"wall_loops": 2, "nested": {"a": 1}, "none": None})
  31. assert result == {"wall_loops": "2"}
  32. def test_a_list_containing_a_non_scalar_drops_the_whole_key(self):
  33. # Half-applying a per-extruder vector would send a shorter list than the
  34. # printer has extruders, which is worse than not setting it at all.
  35. assert normalise_process_overrides({"default_acceleration": [500, {"a": 1}]}) == {}
  36. class TestApplyProcessOverrides:
  37. def test_writes_the_users_values_into_the_process_json(self):
  38. result = apply_process_overrides(_process(), {"wall_loops": 4, "enable_support": True})
  39. assert json.loads(result)["wall_loops"] == "4"
  40. assert json.loads(result)["enable_support"] == "1"
  41. def test_keeps_the_inherits_stub_so_the_preset_still_resolves(self):
  42. # A "standard" preset pick is a {inherits: ...} stub; dropping that key
  43. # would leave the slicer with a handful of orphaned values.
  44. result = apply_process_overrides(_process(), {"wall_loops": 4})
  45. assert json.loads(result)["inherits"] == "0.20mm Standard @BBL X1C"
  46. def test_user_value_wins_over_one_already_in_the_preset(self):
  47. result = apply_process_overrides(_process(wall_loops="2"), {"wall_loops": 6})
  48. assert json.loads(result)["wall_loops"] == "6"
  49. def test_empty_overrides_leave_the_json_untouched(self):
  50. original = _process(wall_loops="2")
  51. assert apply_process_overrides(original, {}) == original
  52. def test_overrides_that_all_get_dropped_leave_the_json_untouched(self):
  53. original = _process(wall_loops="2")
  54. assert apply_process_overrides(original, {"Bad Key": 1}) == original
  55. def test_unparseable_process_json_degrades_to_a_plain_slice(self):
  56. # Better a slice with the picked preset than a failed one.
  57. assert apply_process_overrides("not json", {"wall_loops": 4}) == "not json"
  58. def test_non_object_process_json_degrades_to_a_plain_slice(self):
  59. assert apply_process_overrides("[1, 2]", {"wall_loops": 4}) == "[1, 2]"