# frozen_string_literal: true require_relative "test_helper" class PackageBuilderTest < Minitest::Test def test_builds_self_contained_package_and_preserves_history Dir.mktmpdir do |directory| root = Pathname(directory) tools = create_fake_tools(root) model = root.join("model.scad") renderer = root.join("renderer.py") File.write(model, "cube([1,1,1]);\n") File.write(renderer, "# test renderer\n") config = FeatherCaseWizard::Config.create(name: "OLED Demo", slug: "oled-demo") config.parameters["top_profile"] = "oled128x64" config.outputs["formats"] = %w[3mf stl] config.outputs["coupons"] = %w[fit_coupon] destination = build(config, root.join("cases"), tools, model, renderer) assert destination.join("case.yml").file? assert destination.join("parameters.json").file? assert destination.join("build.rb").executable? %w[body lid buttons fit_coupon].each do |part| assert destination.join("exports/stl/#{part}.stl").file? assert destination.join("exports/3mf/#{part}.3mf").file? assert destination.join("previews/#{part}_iso.png").file? end %w[iso front back left right top].each do |view| assert destination.join("previews/assembly_#{view}.png").file? end refute_match(/\n\n\z/, destination.join("README.md").read) config.parameters["button_reset"] = true build(config, root.join("cases"), tools, model, renderer) assert_equal 1, Dir.glob(destination.join("history/case-*.yml")).length end end def test_failed_build_leaves_existing_package_untouched Dir.mktmpdir do |directory| root = Pathname(directory) destination = root.join("cases/demo") FileUtils.mkdir_p(destination) File.write(destination.join("sentinel"), "keep") model = root.join("model.scad") renderer = root.join("renderer.py") File.write(model, "cube(1);\n") File.write(renderer, "# renderer\n") failing = Class.new do attr_reader :openscad, :blender def initialize @openscad = @blender = "/fake" end def check! = self def run!(*) raise FeatherCaseWizard::ToolError, "planned failure" end end.new config = FeatherCaseWizard::Config.create(name: "Demo", slug: "demo") assert_raises(FeatherCaseWizard::ToolError) do FeatherCaseWizard::PackageBuilder.new( config, root: root.join("cases"), toolchain: failing, model_source: model, renderer_source: renderer ).build! end assert_equal "keep", destination.join("sentinel").read end end def test_builds_aligned_multicolor_lid_package_when_artwork_is_enabled Dir.mktmpdir do |directory| root = Pathname(directory) tools = create_fake_tools(root) model = root.join("model.scad") renderer = root.join("renderer.py") File.write(model, "cube([1,1,1]);\n") File.write(renderer, "# test renderer\n") config = FeatherCaseWizard::Config.create(name: "IMU", slug: "imu") config.parameters["lid_label"] = "IMU" config.parameters["lid_logo_enabled"] = true destination = build(config, root.join("cases"), tools, model, renderer) %w[lid lid_base lid_accent].each do |part| assert destination.join("exports/3mf/#{part}.3mf").file? end assert destination.join("exports/3mf/lid_multicolor.3mf").file? assert destination.join("source/assets/NME-fixed.svg").file? assert destination.join("tools/package_multimaterial_3mf.py").file? assert destination.join("previews/lid_multicolor_top.png").file? end end private def build(config, root, tools, model, renderer) FeatherCaseWizard::PackageBuilder.new( config, root: root, toolchain: tools, model_source: model, renderer_source: renderer ).build! end def create_fake_tools(root) bin = root.join("bin") FileUtils.mkdir_p(bin) openscad = bin.join("openscad") blender = bin.join("blender") File.write(openscad, <<~RUBY) #!/usr/bin/env ruby output = ARGV[ARGV.index("-o") + 1] require "fileutils" FileUtils.mkdir_p(File.dirname(output)) File.binwrite(output, "mesh") RUBY File.write(blender, <<~RUBY) #!/usr/bin/env ruby require "fileutils" args = ARGV[(ARGV.index("--") + 1)..] multicolor = ARGV[ARGV.index("--python") + 1].include?("render_multicolor") if multicolor _base, _accent, output, basename = args views = %w[iso top] else _mesh, output, basename, selected = args views = selected ? selected.split(",") : %w[iso front back left right top] end FileUtils.mkdir_p(output) views.each { |view| File.binwrite(File.join(output, "\#{basename}_\#{view}.png"), "png") } RUBY python = bin.join("python3") File.write(python, <<~RUBY) #!/usr/bin/env ruby File.binwrite(ARGV[3], "multipart") RUBY FileUtils.chmod(0o755, [openscad, blender, python]) FeatherCaseWizard::Toolchain.new( env: {"PATH" => bin.to_s, "OPENSCAD" => openscad.to_s, "BLENDER" => blender.to_s, "PYTHON" => python.to_s} ) end end