from __future__ import annotations import numpy as np from app import ( ADVANCED_NOZZLE_SPACING_HEADERS, SCALE_MODE_UNIFORM_FACTOR, SHAPE_SETTINGS_HEADERS, _auto_align_grid_spacing_rows, _apply_shape_settings, _contour_tracing_sources, delete_shape_from_settings, _format_nozzle_spacing_status, _grid_spacing_rows, _parts_from_records, _records_from_files, _shape_settings_rows, normalize_shape_dimensions_for_mode, _resolve_nozzle_grid_layout, ) from vector_toolpath import ( RASTER_PATTERN_CIRCLE_SPIRAL, RASTER_PATTERN_RECTANGULAR_SPIRAL, RASTER_PATTERN_SAME_DIRECTION, RASTER_PATTERN_Y_DIRECTION, ) def _part( idx: int, bounds: tuple[tuple[float, float, float], tuple[float, float, float]], nozzle: int | None = None, ) -> dict: return { "idx": idx, "nozzle": nozzle if nozzle is not None else idx, "color": "#000000", "parsed": {"bounds": bounds, "moves": [{"kind": "print"}], "point_count": 1}, } def test_spacing_status_lists_all_nozzle_pair_distances() -> None: parts = [ _part(1, ((0.0, 0.0, 0.0), (10.0, 10.0, 1.0))), _part(2, ((0.0, 0.0, 0.0), (4.0, 10.0, 1.0))), _part(3, ((0.0, 0.0, 0.0), (6.0, 10.0, 1.0))), ] offsets = {1: (0.0, 0.0), 2: (13.0, 2.0), 3: (20.0, 4.0)} spacings = [ {"from": 1, "to": 2, "dx": 13.0, "dy": 2.0}, {"from": 2, "to": 3, "dx": 7.0, "dy": 2.0}, ] status = _format_nozzle_spacing_status(parts, offsets, spacings) assert "Nozzle 1: X 0.00 mm, Y 0.00 mm." in status assert "Nozzle 1 -> 2: Delta X 13.00 mm, Delta Y 2.00 mm" in status assert "Nozzle 1 -> 3: Delta X 20.00 mm, Delta Y 4.00 mm" in status assert "Nozzle 2 -> 3: Delta X 7.00 mm, Delta Y 2.00 mm" in status def test_keep_proportions_uses_most_recently_edited_dimension() -> None: records = [ { "idx": 1, "name": "wide_part", "stl_path": "wide_part.stl", "original_x": 10.0, "original_y": 20.0, "original_z": 5.0, "target_x": 10.0, "target_y": 20.0, "target_z": 5.0, "pressure": 25.0, "valve": 4, "port": 1, "color": "#000000", "last_scaled_axis": "target_x", } ] settings = _shape_settings_rows(records) settings[0][3] = 50.0 updated_records, updated_settings = normalize_shape_dimensions_for_mode( records, settings, SCALE_MODE_UNIFORM_FACTOR, ) assert updated_records[0]["last_scaled_axis"] == "target_y" assert updated_settings[0][2:5] == [25.0, 50.0, 12.5] def test_shape_settings_round_trip_contour_tracing_column() -> None: records = [ { "idx": 1, "name": "circle", "stl_path": "circle.stl", "target_x": 10.0, "target_y": 11.0, "target_z": 12.0, "pressure": 25.0, "valve": 4, "nozzle": 1, "port": 1, "color": "#111111", "contour_tracing": False, } ] rows = _shape_settings_rows(records) assert SHAPE_SETTINGS_HEADERS[6:9] == ["Valve", "Nozzle", "Port"] assert SHAPE_SETTINGS_HEADERS[-3:] == ["Contour Tracing", "Lead In", "Delete"] contour_pos = SHAPE_SETTINGS_HEADERS.index("Contour Tracing") lead_in_pos = SHAPE_SETTINGS_HEADERS.index("Lead In") assert rows[0][6:9] == [4, 1, 1] assert rows[0][contour_pos] is False assert rows[0][lead_in_pos] is False # lead-in is opt-in per shape assert rows[0][-1] == "Delete" rows[0][7] = 3 rows[0][8] = 2 rows[0][contour_pos] = True rows[0][lead_in_pos] = True updated = _apply_shape_settings(records, rows) assert updated[0]["nozzle"] == 3 assert updated[0]["port"] == 2 assert updated[0]["contour_tracing"] is True assert updated[0]["lead_in"] is True def test_shape_settings_round_trip_infill_column() -> None: records = [ { "idx": 1, "name": "circle", "stl_path": "circle.stl", "target_x": 10.0, "target_y": 11.0, "target_z": 12.0, "pressure": 25.0, "valve": 4, "nozzle": 1, "port": 1, "color": "#111111", "contour_tracing": False, } ] rows = _shape_settings_rows(records) infill_pos = SHAPE_SETTINGS_HEADERS.index("Infill %") assert rows[0][infill_pos] == 100.0 rows[0][infill_pos] = 50 updated = _apply_shape_settings(records, rows) assert updated[0]["infill"] == 50.0 # Out-of-range values clamp to 0..100. rows[0][infill_pos] = 250 assert _apply_shape_settings(records, rows)[0]["infill"] == 100.0 rows[0][infill_pos] = -10 assert _apply_shape_settings(records, rows)[0]["infill"] == 0.0 def test_color_cell_renders_an_in_table_dropdown() -> None: from app import PARALLEL_COLOR_CHOICES records = [ { "idx": 1, "name": "circle", "stl_path": "circle.stl", "target_x": 10.0, "target_y": 11.0, "target_z": 12.0, "pressure": 25.0, "valve": 4, "nozzle": 1, "port": 1, "color": "#ff7f0e", "contour_tracing": False, } ] rows = _shape_settings_rows(records) color_pos = SHAPE_SETTINGS_HEADERS.index("Color") cell = rows[0][color_pos] # The cell is a select carrying the record idx (as a class token — data # attributes get sanitized out of markdown cells), wrapped in the # pp-color-cell span the head script's pointer-event isolation keys on, # with every palette color as an option and the current one selected. assert cell.startswith('') assert '