"""Phase 1: material + finish fields, color resolver, color helpers.""" import json from woodshop import colors from woodshop.scene import Scene, part_color def test_set_material_and_finish(): s = Scene() s.place("2x4", 24) s.set_material("p1", "oak") s.set_finish("p1", "sanded") p = s.get_part("p1") assert p.material == "oak" and p.finish == "sanded" def test_paint_normalizes_color_name(): s = Scene() s.place("2x4", 24) s.paint("p1", "navy") p = s.get_part("p1") assert p.finish == "paint" and p.finish_color == colors.NAMED["navy"] def test_finish_roundtrips_through_json(): s = Scene() s.place("2x4", 24) s.paint("p1", "#112233") s2 = Scene.from_dict(json.loads(json.dumps(s.to_dict()))) p = s2.get_part("p1") assert p.finish == "paint" and p.finish_color == "#112233" def test_legacy_finishes_list_migrates(): raw = {"parts": [{"id": "p1", "stock": "2x4", "length_in": 24.0, "section_in": [1.5, 3.5], "finishes": ["sanded"]}]} s = Scene.from_dict(raw) assert s.get_part("p1").finish == "sanded" def test_part_color_priority(): s = Scene() s.place("2x4", 24) p = s.get_part("p1") # raw spruce default raw = part_color(p) s.set_finish("p1", "sanded") assert part_color(p) != raw # sanded is lighter s.paint("p1", "#ff0000") assert part_color(p) == "#ff0000" # paint wins def test_part_color_fallback_when_no_material(): s = Scene() s.place("2x4", 24) p = s.get_part("p1") p.material = "__unknown__" assert part_color(p, fallback="#abcdef") == "#abcdef" def test_color_helpers(): assert colors.normalize_color("navy") == colors.NAMED["navy"] assert colors.normalize_color("#abc") == "#abc" assert colors.normalize_color("aabbcc") == "#aabbcc" assert colors.normalize_color("not-a-color") == "#808080" assert colors.lighten("#000000", 0.5) == "#808080" assert colors.darken("#ffffff", 0.5) == "#808080"