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