spec/unit/compressors/dmg_spec.rb (264 lines of code) (raw):

require "spec_helper" module Omnibus describe Compressor::DMG do let(:project) do Project.new.tap do |project| project.name("project") project.friendly_name("Project One") project.homepage("https://example.com") project.install_dir("/opt/project") project.build_version("1.2.3") project.build_iteration("2") project.maintainer("Chef Software") end end subject { described_class.new(project) } let(:project_root) { File.join(tmp_path, "project/root") } let(:package_dir) { File.join(tmp_path, "package/dir") } let(:staging_dir) { File.join(tmp_path, "staging/dir") } before do allow(project).to receive(:packagers_for_system) .and_return([Packager::PKG.new(project)]) Config.project_root(project_root) Config.package_dir(package_dir) allow(subject).to receive(:staging_dir) .and_return(staging_dir) create_directory(staging_dir) allow(subject).to receive(:shellout!) end describe "#window_bounds" do it "is a DSL method" do expect(subject).to have_exposed_method(:window_bounds) end it "has a default value" do expect(subject.window_bounds).to eq("100, 100, 750, 600") end end describe "#pkg_position" do it "is a DSL method" do expect(subject).to have_exposed_method(:pkg_position) end it "has a default value" do expect(subject.pkg_position).to eq("535, 50") end end describe "#id" do it "is :dmg" do expect(subject.id).to eq(:dmg) end end describe "#resources_dir" do it "is nested inside the staging_dir" do expect(subject.resources_dir).to eq("#{staging_dir}/Resources") end end describe "#clean_disks" do it "logs a message" do allow(subject).to receive(:shellout!) .and_return(double(Mixlib::ShellOut, stdout: "")) output = capture_logging { subject.clean_disks } expect(output).to include("Cleaning previously mounted disks") end end describe "#create_writable_dmg" do it "logs a message" do output = capture_logging { subject.create_writable_dmg } expect(output).to include("Creating writable dmg") end it "runs the hdiutil command" do expect(subject).to receive(:shellout!) .with <<-EOH.gsub(/^ {12}/, "") hdiutil create \\ -volname "Project One" \\ -fs HFS+ \\ -fsargs "-c c=64,a=16,e=16" \\ -size 512000k \\ "#{staging_dir}/project-writable.dmg" \\ -puppetstrings EOH subject.create_writable_dmg end end describe "#attach_dmg" do before do allow(subject).to receive(:shellout!) .and_return(shellout) end let(:shellout) { double(Mixlib::ShellOut, stdout: "hello\n") } it "logs a message" do output = capture_logging { subject.attach_dmg } expect(output).to include("Attaching dmg as disk") end it "runs the hdiutil command" do expect(subject).to receive(:shellout!) .with <<-EOH.gsub(/^ {12}/, "") hdiutil attach \\ -puppetstrings \\ -readwrite \\ -noverify \\ -noautoopen \\ "#{staging_dir}/project-writable.dmg" | egrep '^/dev/' | sed 1q | awk '{print $1}' EOH subject.attach_dmg end it "returns the stripped stdout" do expect(subject.attach_dmg).to eq("hello") end end describe "#copy_assets_to_dmg" do it "logs a message" do output = capture_logging { subject.copy_assets_to_dmg } expect(output).to include("Copying assets into dmg") end end describe "#set_volume_icon" do it "logs a message" do output = capture_logging { subject.set_volume_icon } expect(output).to include("Setting volume icon") end it "runs the sips commands" do icon = subject.resource_path("icon.png") expect(subject).to receive(:shellout!) .with <<-EOH.gsub(/^ {12}/, "") # Generate the icns mkdir tmp.iconset sips -z 16 16 #{icon} --out tmp.iconset/icon_16x16.png sips -z 32 32 #{icon} --out tmp.iconset/icon_16x16@2x.png sips -z 32 32 #{icon} --out tmp.iconset/icon_32x32.png sips -z 64 64 #{icon} --out tmp.iconset/icon_32x32@2x.png sips -z 128 128 #{icon} --out tmp.iconset/icon_128x128.png sips -z 256 256 #{icon} --out tmp.iconset/icon_128x128@2x.png sips -z 256 256 #{icon} --out tmp.iconset/icon_256x256.png sips -z 512 512 #{icon} --out tmp.iconset/icon_256x256@2x.png sips -z 512 512 #{icon} --out tmp.iconset/icon_512x512.png sips -z 1024 1024 #{icon} --out tmp.iconset/icon_512x512@2x.png iconutil -c icns tmp.iconset # Copy it over cp tmp.icns "/Volumes/Project One/.VolumeIcon.icns" # Source the icon SetFile -a C "/Volumes/Project One" EOH subject.set_volume_icon end end describe "#prettify_dmg" do it "logs a message" do output = capture_logging { subject.prettify_dmg } expect(output).to include("Making the dmg all pretty and stuff") end it "renders the apple script template" do subject.prettify_dmg expect("#{staging_dir}/create_dmg.osascript").to be_a_file end it "has the correct content" do subject.prettify_dmg contents = File.read("#{staging_dir}/create_dmg.osascript") expect(contents).to include('set found_disk to do shell script "ls /Volumes/ | grep \'Project One*\'"') expect(contents).to include(" set the bounds of Finder window 1 to {100, 100, 750, 600}") expect(contents).to include(' set position of item "project-1.2.3-2.x86_64.pkg" of container window to {535, 50}') end it "runs the apple script" do expect(subject).to receive(:shellout!) .with <<-EOH.gsub(/^ {12}/, "") osascript "#{staging_dir}/create_dmg.osascript" EOH subject.prettify_dmg end end describe "#compress_dmg" do it "logs a message" do output = capture_logging { subject.compress_dmg } expect(output).to include("Compressing dmg") end it "runs the magical command series" do device = "/dev/sda1" subject.instance_variable_set(:@device, device) expect(subject).to receive(:shellout!) .with <<-EOH.gsub(/^ {12}/, "") chmod -Rf go-w "/Volumes/Project One" sync hdiutil unmount "#{device}" # Give some time to the system so unmount dmg ATTEMPTS=1 until [ $ATTEMPTS -eq 6 ] || hdiutil detach "/dev/sda1"; do sleep 10 echo Attempt number $(( ATTEMPTS++ )) done hdiutil convert \\ "#{staging_dir}/project-writable.dmg" \\ -format UDZO \\ -imagekey \\ zlib-level=9 \\ -o "#{package_dir}/project-1.2.3-2.x86_64.dmg" \\ -puppetstrings EOH subject.compress_dmg end end describe "#verify_dmg" do it "logs a message" do output = capture_logging { subject.verify_dmg } expect(output).to include("Verifying dmg") end it "runs the command" do expect(subject).to receive(:shellout!) .with <<-EOH.gsub(/^ {12}/, "") hdiutil verify \\ "#{package_dir}/project-1.2.3-2.x86_64.dmg" \\ -puppetstrings EOH subject.verify_dmg end end describe "#remove_writable_dmg" do it "logs a message" do output = capture_logging { subject.remove_writable_dmg } expect(output).to include("Removing writable dmg") end it "runs the command" do expect(subject).to receive(:shellout!) .with <<-EOH.gsub(/^ {12}/, "") rm -rf "#{staging_dir}/project-writable.dmg" EOH subject.remove_writable_dmg end end describe "#set_dmg_icon" do it "logs a message" do output = capture_logging { subject.set_dmg_icon } expect(output).to include("Setting dmg icon") end it "runs the sips commands" do icon = subject.resource_path("icon.png") expect(subject).to receive(:shellout!) .with <<-EOH.gsub(/^ {12}/, "") # Convert the png to an icon sips -i "#{icon}" # Extract the icon into its own resource DeRez -only icns "#{icon}" > tmp.rsrc # Append the icon reosurce to the DMG Rez -append tmp.rsrc -o "#{package_dir}/project-1.2.3-2.x86_64.dmg" # Source the icon SetFile -a C "#{package_dir}/project-1.2.3-2.x86_64.dmg" EOH subject.set_dmg_icon end end describe "#package_name" do it "reflects the packager's unmodified package_name" do expect(subject.package_name).to eq("project-1.2.3-2.x86_64.dmg") end it "reflects the packager's modified package_name" do package_basename = "projectsub-1.2.3-3.x86_64" allow(project.packagers_for_system[0]).to receive(:package_name) .and_return("#{package_basename}.pkg") expect(subject.package_name).to eq("#{package_basename}.dmg") end end describe "#writable_dmg" do it "is in the staging_dir" do expect(subject.writable_dmg).to include(staging_dir) end it "is project-writable" do expect(subject.writable_dmg).to include("project-writable.dmg") end end describe "#volume_name" do it "is the project friendly_name" do expect(subject.volume_name).to eq("Project One") end end end end