# frozen_string_literal: true require_relative "test_helper" class ConfigTest < Minitest::Test def config FeatherCaseWizard::Config.create(name: "Bench GPS", slug: "bench-gps") end def test_default_case_has_expected_parts_and_dimensions assert_equal %w[body lid], config.printable_parts assert_in_delta 60.8, config.dimensions["length"], 0.01 assert_in_delta 41.66, config.dimensions["width"], 0.01 assert_equal ["3mf"], config.outputs["formats"] end def test_oled_buttons_and_selected_coupons_are_printable subject = config subject.parameters["top_profile"] = "oled128x64" subject.parameters["button_a"] = false subject.parameters["button_b"] = true subject.outputs["coupons"] = %w[fit_coupon] assert_equal %w[body lid buttons fit_coupon], subject.printable_parts end def test_wall_local_cutouts_map_to_model_coordinates subject = config length = subject.dimensions["length"] width = subject.dimensions["width"] subject.data["cutouts"] = [ cutout("front", 12.0), cutout("rear", 13.0), cutout("left", 14.0), cutout("right", 15.0) ] result = subject.scad_cutouts assert_in_delta width - 12.0, result[0][2], 0.001 assert_in_delta 13.0, result[1][2], 0.001 assert_in_delta 14.0, result[2][2], 0.001 assert_in_delta length - 15.0, result[3][2], 0.001 end def test_cutout_cannot_intersect_floor subject = config subject.data["cutouts"] = [cutout("rear", 12.0).merge("z" => 2.0)] error = assert_raises(FeatherCaseWizard::ConfigError) { subject.validate! } assert_match(/floor/, error.message) end def test_yaml_round_trip_preserves_resolved_cutouts subject = config subject.data["cutouts"] = [cutout("left", 20.0)] Dir.mktmpdir do |directory| path = File.join(directory, "case.yml") File.write(path, subject.to_yaml) loaded = FeatherCaseWizard::Config.load(path) assert_equal subject.data["cutouts"], loaded.data["cutouts"] assert_equal subject.scad_cutouts, loaded.data.dig("resolved", "extra_cutouts") end end def test_unsafe_yaml_is_rejected Dir.mktmpdir do |directory| path = File.join(directory, "case.yml") File.write(path, "--- !ruby/object:Object {}\n") assert_raises(FeatherCaseWizard::ConfigError) do FeatherCaseWizard::Config.load(path) end end end private def cutout(face, horizontal) { "name" => "#{face}-cable", "face" => face, "shape" => "roundrect", "horizontal" => horizontal, "z" => 12.0, "width" => 6.0, "height" => 4.0, "radius" => 1.0 } end end