Skip to content
Browse files

Setup, build, and launch Mac apps from the command-line. Symbiote mak…

…es some iDevice-specific assumptions, so it does not yet load the view hierarchy from Mac apps.
  • Loading branch information...
1 parent 69780c6 commit ef64f84166aef0d6dbb25f344c305c7f68f535ac @MichaelBuckley MichaelBuckley committed
View
22 Frank.xcodeproj/project.pbxproj
@@ -16,12 +16,13 @@
30228E241642161200B1F9E7 /* DumpCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = D6D05CA211C883AA0081C5A5 /* DumpCommand.m */; };
30228E261642161200B1F9E7 /* EnginesCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = D6FA01B714283C4F00576AEE /* EnginesCommand.m */; };
30228E281642161200B1F9E7 /* ExitCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = A91F3AA515F6E456003F434F /* ExitCommand.m */; };
- 30228E2A16421C4400B1F9E7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30228E2916421C4400B1F9E7 /* Cocoa.framework */; };
302B80411646DE02000F9861 /* NSImage+Frank.h in Headers */ = {isa = PBXBuildFile; fileRef = 302B803F1646DE02000F9861 /* NSImage+Frank.h */; };
302B80421646DE02000F9861 /* NSImage+Frank.m in Sources */ = {isa = PBXBuildFile; fileRef = 302B80401646DE02000F9861 /* NSImage+Frank.m */; };
303A751316702D3D00B93673 /* NSObject+FrankAutomation.m in Sources */ = {isa = PBXBuildFile; fileRef = 303A751116702D3D00B93673 /* NSObject+FrankAutomation.m */; };
30412D30165333E300719CD2 /* NSView+FrankImageCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 30412D2E165333E300719CD2 /* NSView+FrankImageCapture.h */; };
30412D31165333E300719CD2 /* NSView+FrankImageCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 30412D2F165333E300719CD2 /* NSView+FrankImageCapture.m */; };
+ 304374F6167D2BC8006D5D71 /* AnyJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = C177A4CB1632319A0081DF77 /* AnyJSON.m */; };
+ 304A0C821699105600150BE8 /* NSApplication+FrankAutomation.m in Sources */ = {isa = PBXBuildFile; fileRef = 304A0C801699105600150BE8 /* NSApplication+FrankAutomation.m */; };
305CA784164205F800C4ACE5 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = AB7947C115C4418700052B74 /* GCDAsyncSocket.m */; };
305CA785164205F800C4ACE5 /* HTTPAuthenticationRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = AB79477E15C4412300052B74 /* HTTPAuthenticationRequest.m */; };
305CA786164205F800C4ACE5 /* HTTPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = AB79478015C4412300052B74 /* HTTPConnection.m */; };
@@ -61,6 +62,10 @@
30AC65A4165C39FF00DEB0AB /* FrankMac-Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 30AC65A3165C39FF00DEB0AB /* FrankMac-Prefix.pch */; };
30AC65A7165C3A4D00DEB0AB /* OSXKeyboardCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 30AC65A5165C3A4D00DEB0AB /* OSXKeyboardCommand.h */; };
30AC65A8165C3A4D00DEB0AB /* OSXKeyboardCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 30AC65A6165C3A4D00DEB0AB /* OSXKeyboardCommand.m */; };
+ 30C544B1167E4D9E0034F49C /* SuccessCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C544AF167E4D9E0034F49C /* SuccessCommand.h */; };
+ 30C544B2167E4D9E0034F49C /* SuccessCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C544AF167E4D9E0034F49C /* SuccessCommand.h */; };
+ 30C544B3167E4D9E0034F49C /* SuccessCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C544B0167E4D9E0034F49C /* SuccessCommand.m */; };
+ 30C544B4167E4D9E0034F49C /* SuccessCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C544B0167E4D9E0034F49C /* SuccessCommand.m */; };
4C1DD76C12BADFE100E10B8C /* OrientationCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1DD76812BADFE100E10B8C /* OrientationCommand.m */; };
4C1DD76D12BADFE100E10B8C /* OrientationCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1DD76912BADFE100E10B8C /* OrientationCommand.h */; };
4C1DD76E12BADFE100E10B8C /* AppCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1DD76A12BADFE100E10B8C /* AppCommand.m */; };
@@ -204,6 +209,7 @@
303A751116702D3D00B93673 /* NSObject+FrankAutomation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+FrankAutomation.m"; sourceTree = "<group>"; };
30412D2E165333E300719CD2 /* NSView+FrankImageCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+FrankImageCapture.h"; sourceTree = "<group>"; };
30412D2F165333E300719CD2 /* NSView+FrankImageCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+FrankImageCapture.m"; sourceTree = "<group>"; };
+ 304A0C801699105600150BE8 /* NSApplication+FrankAutomation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSApplication+FrankAutomation.m"; sourceTree = "<group>"; };
305CA7721642059400C4ACE5 /* libFrankMac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFrankMac.a; sourceTree = BUILT_PRODUCTS_DIR; };
305CA7731642059400C4ACE5 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; };
305CA7761642059400C4ACE5 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@@ -214,6 +220,8 @@
30AC65A3165C39FF00DEB0AB /* FrankMac-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FrankMac-Prefix.pch"; sourceTree = "<group>"; };
30AC65A5165C3A4D00DEB0AB /* OSXKeyboardCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSXKeyboardCommand.h; sourceTree = "<group>"; };
30AC65A6165C3A4D00DEB0AB /* OSXKeyboardCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OSXKeyboardCommand.m; sourceTree = "<group>"; };
+ 30C544AF167E4D9E0034F49C /* SuccessCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SuccessCommand.h; sourceTree = "<group>"; };
+ 30C544B0167E4D9E0034F49C /* SuccessCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SuccessCommand.m; sourceTree = "<group>"; };
4C1DD76812BADFE100E10B8C /* OrientationCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OrientationCommand.m; sourceTree = "<group>"; };
4C1DD76912BADFE100E10B8C /* OrientationCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OrientationCommand.h; sourceTree = "<group>"; };
4C1DD76A12BADFE100E10B8C /* AppCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppCommand.m; sourceTree = "<group>"; };
@@ -328,7 +336,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 30228E2A16421C4400B1F9E7 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -555,6 +562,8 @@
4C1DD76812BADFE100E10B8C /* OrientationCommand.m */,
30AC65A5165C3A4D00DEB0AB /* OSXKeyboardCommand.h */,
30AC65A6165C3A4D00DEB0AB /* OSXKeyboardCommand.m */,
+ 30C544AF167E4D9E0034F49C /* SuccessCommand.h */,
+ 30C544B0167E4D9E0034F49C /* SuccessCommand.m */,
);
name = Commands;
sourceTree = "<group>";
@@ -616,6 +625,7 @@
C18A5F1D160D547A00DC25F6 /* UIView+PublicAutomation.m */,
00E864BA161D6E6400E01209 /* UIScrollView+FrankScrolling.m */,
C177A4CE163234B60081DF77 /* JSON.h */,
+ 304A0C801699105600150BE8 /* NSApplication+FrankAutomation.m */,
302B803F1646DE02000F9861 /* NSImage+Frank.h */,
302B80401646DE02000F9861 /* NSImage+Frank.m */,
303A751116702D3D00B93673 /* NSObject+FrankAutomation.m */,
@@ -670,6 +680,7 @@
30412D30165333E300719CD2 /* NSView+FrankImageCapture.h in Headers */,
30AC65A4165C39FF00DEB0AB /* FrankMac-Prefix.pch in Headers */,
30AC65A7165C3A4D00DEB0AB /* OSXKeyboardCommand.h in Headers */,
+ 30C544B2167E4D9E0034F49C /* SuccessCommand.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -709,6 +720,7 @@
C18A5EF5160D4AD300DC25F6 /* UIView+ImageCapture.h in Headers */,
C177A4CC1632319A0081DF77 /* AnyJSON.h in Headers */,
9B3E52AF163FB98300EB24C2 /* LocationCommand.h in Headers */,
+ 30C544B1167E4D9E0034F49C /* SuccessCommand.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -850,6 +862,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 304374F6167D2BC8006D5D71 /* AnyJSON.m in Sources */,
302B80421646DE02000F9861 /* NSImage+Frank.m in Sources */,
303A751316702D3D00B93673 /* NSObject+FrankAutomation.m in Sources */,
30412D31165333E300719CD2 /* NSView+FrankImageCapture.m in Sources */,
@@ -870,6 +883,8 @@
3072649B165812FB00815A1A /* Operation.m in Sources */,
3072649D165812FB00815A1A /* SelectorEngineRegistry.m in Sources */,
3072649F165812FB00815A1A /* ViewJSONSerializer.m in Sources */,
+ 30C544B4167E4D9E0034F49C /* SuccessCommand.m in Sources */,
+ 304A0C821699105600150BE8 /* NSApplication+FrankAutomation.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -966,6 +981,7 @@
00E864BC161D6E6400E01209 /* UIScrollView+FrankScrolling.m in Sources */,
C177A4CD1632319A0081DF77 /* AnyJSON.m in Sources */,
9B3E52B0163FB98300EB24C2 /* LocationCommand.m in Sources */,
+ 30C544B3167E4D9E0034F49C /* SuccessCommand.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1097,6 +1113,7 @@
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
+ VALID_ARCHS = "x86_64 i386";
};
name = Debug;
};
@@ -1125,6 +1142,7 @@
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
+ VALID_ARCHS = "x86_64 i386";
};
name = Release;
};
View
20 Rakefile
@@ -1,21 +1,33 @@
-def discover_latest_sdk_version
+def discover_latest_ios_sdk_version
latest_iphone_sdk = `xcodebuild -showsdks | grep -o "iphoneos.*$"`.chomp
version_part = latest_iphone_sdk[/iphoneos(.*)/,1]
version_part
end
+def discover_latest_osx_sdk_version
+ latest_osx_sdk = `xcodebuild -showsdks | grep -o "iphoneos.*$"`.chomp
+ version_part = latest_osx_sdk[/macosx(.*)/,1]
+ version_part
+end
+
def build_dir
File.expand_path 'build'
end
desc "Build the arm library"
task :build_iphone_lib do
- sh "xcodebuild -workspace Frank.xcworkspace -scheme Frank -configuration Release -sdk iphoneos#{discover_latest_sdk_version} BUILD_DIR=\"#{build_dir}\" clean build"
+ sh "xcodebuild -workspace Frank.xcworkspace -scheme Frank -configuration Release -sdk iphoneos#{discover_latest_ios_sdk_version} BUILD_DIR=\"#{build_dir}\" clean build"
end
desc "Build the i386 library"
task :build_simulator_lib do
- sh "xcodebuild -workspace Frank.xcworkspace -scheme Frank -configuration Release -sdk iphonesimulator#{discover_latest_sdk_version} BUILD_DIR=\"#{build_dir}\" clean build"
+ sh "xcodebuild -workspace Frank.xcworkspace -scheme Frank -configuration Release -sdk iphonesimulator#{discover_latest_ios_sdk_version} BUILD_DIR=\"#{build_dir}\" clean build"
+end
+
+desc "Build the Mac library"
+task :build_mac_lib do
+ sh "xcodebuild -workspace Frank.xcworkspace -scheme FrankMac -configuration Release -sdk macosx#{discover_latest_osx_sdk_version} BUILD_DIR=\"#{build_dir}\" clean build"
+ sh "cp #{build_dir}/Release/*Mac.a dist"
end
task :combine_libraries do
@@ -25,7 +37,7 @@ task :combine_libraries do
end
desc "Build a univeral library for both iphone and iphone simulator"
-task :build_lib => [:build_iphone_lib, :build_simulator_lib, :combine_libraries]
+task :build_lib => [:build_iphone_lib, :build_simulator_lib, :combine_libraries, :build_mac_lib]
desc "clean build artifacts"
task :clean do
View
1 gem/frank-skeleton/frankify.xcconfig.tt
@@ -1,4 +1,5 @@
INSTALL_PATH = /./
FRANK_LDFLAGS = -all_load -ObjC -framework CFNetwork -framework Security -lShelley <%= @without_http_server ? "" : "-lCocoaHTTPServer" %> -lFrank
+FRANK_MAC_LDFLAGS = -all_load -ObjC -framework CFNetwork -framework Security -LFrank <%= @without_http_server ? "" : "-lCocoaHTTPServerMac" %> -lFrankMac
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = FRANKIFIED
View
BIN gem/frank-skeleton/libCocoaHTTPServerMac.a
Binary file not shown.
View
BIN gem/frank-skeleton/libFrankMac.a
Binary file not shown.
View
56 gem/lib/frank-cucumber/cli.rb
@@ -1,12 +1,13 @@
-begin
+begin
require 'pry'
-rescue LoadError
+rescue LoadError
end
require 'thor'
require 'frank-cucumber/launcher'
require 'frank-cucumber/console'
require 'frank-cucumber/frankifier'
+require 'frank-cucumber/mac_launcher'
module Frank
class CLI < Thor
@@ -36,7 +37,7 @@ def setup
desc "update", "updates the frank server components inside your Frank directory"
long_desc "This updates the parts of Frank that are embedded inside your app (e.g. libFrank.a and frank_static_resources.bundle)"
def update
- %w{libFrank.a libShelley.a}.each do |f|
+ %w{libFrank.a libCocoaHTTPServer.a libShelley.a libFrankMac.a libCocoaHTTPServerMac.a}.each do |f|
copy_file f, File.join( 'Frank', f ), :force => true
end
directory( 'frank_static_resources.bundle', 'Frank/frank_static_resources.bundle', :force => true )
@@ -48,6 +49,7 @@ def update
method_option option
end
method_option 'arch', :type => :string, :default => 'i386'
+ method_option 'mac', :type => :boolean, :default => false
method_option :noclean, :type => :boolean, :default => false, :aliases => '--nc', :desc => "Don't clean the build directory before building"
def build
clean = !options['noclean']
@@ -76,21 +78,35 @@ def build
end
extra_opts = XCODEBUILD_OPTIONS.map{ |o| "-#{o} \"#{options[o]}\"" if options[o] }.compact.join(' ')
- extra_opts += " -arch #{options['arch']}"
- run %Q|xcodebuild -xcconfig Frank/frankify.xcconfig #{build_steps} #{extra_opts} -configuration Debug -sdk iphonesimulator DEPLOYMENT_LOCATION=YES DSTROOT="#{build_output_dir}" FRANK_LIBRARY_SEARCH_PATHS="\\"#{frank_lib_directory}\\""|
+ if options['mac']
+ run %Q|xcodebuild -xcconfig Frank/frankify.xcconfig #{build_steps} #{extra_opts} -configuration Debug DEPLOYMENT_LOCATION=YES DSTROOT="#{build_output_dir}" FRANK_LIBRARY_SEARCH_PATHS="\\"#{frank_lib_directory}\\""|
+ else
+ extra_opts += " -arch #{options['arch']}"
+
+ run %Q|xcodebuild -xcconfig Frank/frankify.xcconfig #{build_steps} #{extra_opts} -configuration Debug -sdk iphonesimulator DEPLOYMENT_LOCATION=YES DSTROOT="#{build_output_dir}" FRANK_LIBRARY_SEARCH_PATHS="\\"#{frank_lib_directory}\\""|
+ end
app = Dir.glob("#{build_output_dir}/*.app").delete_if { |x| x =~ /\/#{app_bundle_name}$/ }
app = app.first
FileUtils.cp_r("#{app}/.", frankified_app_dir)
- fix_frankified_apps_bundle_identifier
+ if options['mac']
+ in_root do
+ FileUtils.cp_r(
+ File.join( 'Frank',static_bundle),
+ File.join( frankified_app_dir, "Contents", "Resources", static_bundle )
+ )
+ end
+ else
+ fix_frankified_apps_bundle_identifier
- in_root do
- FileUtils.cp_r(
- File.join( 'Frank',static_bundle),
- File.join( frankified_app_dir, static_bundle )
- )
+ in_root do
+ FileUtils.cp_r(
+ File.join( 'Frank',static_bundle),
+ File.join( frankified_app_dir, static_bundle )
+ )
+ end
end
end
@@ -102,7 +118,7 @@ def build_and_launch
desc "launch", "open the Frankified app in the simulator"
method_option :debug, :type => :boolean, :default => false
- method_option :idiom, :banner => 'iphone|ipad', :type => :string, :default => (ENV['FRANK_SIM_IDIOM'] || 'iphone')
+ method_option :idiom, :banner => 'iphone|ipad|mac', :type => :string, :default => (ENV['FRANK_SIM_IDIOM'] || 'iphone')
def launch
$DEBUG = options[:debug]
launcher = case options[:idiom].downcase
@@ -110,8 +126,10 @@ def launch
SimLauncher::DirectClient.for_iphone_app( frankified_app_dir )
when 'ipad'
SimLauncher::DirectClient.for_ipad_app( frankified_app_dir )
+ when 'mac'
+ Frank::MacLauncher.new( frankified_app_dir )
else
- say "idiom must be either iphone or ipad. You supplied '#{options[:idiom]}'", :red
+ say "idiom must be either iphone, ipad, or mac. You supplied '#{options[:idiom]}'", :red
exit 10
end
@@ -138,15 +156,15 @@ def inspect
desc 'console', "launch a ruby console connected to your Frankified app"
def console
# TODO: check whether app is running (using ps or similar), and launch it if it's not
-
+
begin
require 'pry'
rescue LoadError
say 'The Frank console requires the pry gem.'
say 'Simply run `sudo gem install pry` (the `sudo` bit might be optional), and then try again. Thanks!'
- exit 41
+ exit 41
end
-
+
Frank::Cucumber::FrankHelper.use_shelley_from_now_on
console = Frank::Console.new
if console.check_for_running_app
@@ -163,7 +181,7 @@ def product_name
def app_bundle_name
"#{product_name}.app"
end
-
+
def frank_lib_directory
File.expand_path "Frank"
end
@@ -178,9 +196,9 @@ def frankified_app_dir
def fix_frankified_apps_bundle_identifier
# as of iOS 6 the iOS Simulator locks up with a black screen if you try and launch an app which has the same
- # bundle identifier as a previously installed app but which is in fact a different app. This impacts us because our
+ # bundle identifier as a previously installed app but which is in fact a different app. This impacts us because our
# Frankified app is different but has the same bundle identifier as the standard non-Frankified app which most users
- # will want to have installed in the simulator as well.
+ # will want to have installed in the simulator as well.
#
# We work around this by modifying the Frankified app's bundle identifier inside its Info.plist.
inside frankified_app_dir do
View
25 gem/lib/frank-cucumber/frankifier.rb
@@ -41,7 +41,7 @@ def decide_on_project
projects.first
else
choice = ask_menu(
- "I found more than one .xcodeproj. Which is the main app project that you wish to Frankify?",
+ "I found more than one .xcodeproj. Which is the main app project that you wish to Frankify?",
projects.map(&:basename)
)
projects[choice]
@@ -60,7 +60,7 @@ def decide_on_target
targets.first
else
choice = ask_menu(
- "I found more than one target in this project. Which is the main app target that you wish to Frankify?",
+ "I found more than one target in this project. Which is the main app target that you wish to Frankify?",
targets.map(&:name)
)
targets.to_a[choice]
@@ -71,8 +71,19 @@ def report_project_and_target
puts "Frankifying target [#{@target.name}] in project #{@xcodeproj_path.basename}"
end
+ def target_is_mac
+ settings = @target.build_configurations.first.build_settings['SDKROOT'] \
+ || @project.build_configurations.first.build_settings['SDKROOT']
+
+ return settings.include? 'macosx'
+ end
+
def add_linker_flag
- add_frank_entry_to_build_setting( 'OTHER_LDFLAGS', 'FRANK_LDFLAGS' )
+ if target_is_mac
+ add_frank_entry_to_build_setting( 'OTHER_LDFLAGS', 'FRANK_MAC_LDFLAGS' )
+ else
+ add_frank_entry_to_build_setting( 'OTHER_LDFLAGS', 'FRANK_LDFLAGS' )
+ end
end
def add_library_search_path
@@ -97,16 +108,16 @@ def add_frank_entry_to_build_setting( build_setting, entry_to_add )
end
def check_target_build_configuration_is_valid!
- unless @target.build_configuration_list.build_settings(@target_build_configuration)
+ unless @target.build_configuration_list.build_settings(@target_build_configuration)
say %Q|I'm trying to Frankify the '#{@target_build_configuration}' build configuration, but I don't see it that build configuration in your XCode target. Here's a list of the build configurations I see:|
- @target.build_configuration_list.build_configurations.each do |bc|
+ @target.build_configuration_list.build_configurations.each do |bc|
say " '#{bc.name}'"
end
say ''
say %Q|Please specify one of those build configurations using the --build_configuration flag|
exit
end
-
+
end
def build_settings_to_edit
@@ -121,7 +132,7 @@ def save_changes
def ask_menu message, options
option_lines = options.each_with_index.map{ |o,i| "#{i+1}: #{o}" }
full_message = ([message,'']+option_lines+[">"]).join("\n")
-
+
allowed_range = (1..options.length)
valid_choice = nil
until valid_choice
View
35 gem/lib/frank-cucumber/mac_launcher.rb
@@ -0,0 +1,35 @@
+require "timeout"
+
+module Frank
+ class MacLauncher
+
+ def initialize(app_path)
+ @app_path = app_path
+ end
+
+ def launch
+ `open "#{@app_path}"`
+ end
+
+ def quit_if_running
+ pid = `ps -ax | grep "#{@app_path}" | grep -v grep`
+
+ if pid != ""
+ pid = pid.strip.split[0]
+ `kill #{pid}`
+ end
+
+ Timeout::timeout(60) {
+ while pid != ""
+ pid = `ps -ax | grep "#{@app_path}" | grep -v grep`
+ end
+ }
+
+ end
+
+ def relaunch
+ self.quit_if_running
+ self.launch
+ end
+ end
+end
View
59 src/DumpCommand.m
@@ -109,14 +109,15 @@ - (void)addAttributeMappings:(NSArray *)attributes forClass:(Class)clazz{
#pragma mark - Command handling
- (NSString *)handleCommandWithRequestBody:(NSString *)requestBody {
- // serialize starting from root window and return json representation of it
#if TARGET_OS_IPHONE
- UIWindow *window = [UIApplication sharedApplication].keyWindow;
+ // serialize starting from root window and return json representation of it
+ UIWindow *root = [UIApplication sharedApplication].keyWindow;
#else
- NSWindow *window = [[NSApplication sharedApplication] keyWindow];
+ // OS X apps can have multiple windows, so the application object is the root.
+ NSApplication *root = [NSApplication sharedApplication];
#endif
- NSDictionary *dom = [self serializeView: window];
+ NSDictionary *dom = [self serializeView: root];
return TO_JSON(dom);
}
@@ -148,6 +149,18 @@ - (NSDictionary *) serializeView: (FrankSerializeViewType *) view {
continue;
}
+#if !TARGET_OS_IPHONE
+ if ([attribute isEqualToString:@"FEX_accessibilityDescription"]) {
+ attribute = @"accessibilityDescription";
+ }
+ else if ([attribute isEqualToString:@"FEX_accessibilityLabel"]) {
+ attribute = @"accessibilityLabel";
+ }
+ else if ([attribute isEqualToString:@"FEX_accessibilityFrame"]) {
+ attribute = @"accessibilityFrame";
+ }
+#endif
+
[serializedView setObject:value forKey:attribute];
}
}
@@ -162,11 +175,45 @@ - (NSDictionary *) serializeView: (FrankSerializeViewType *) view {
[serializedSubviews addObject: serializedSubview];
}
#else
- if ([[view class] isKindOfClass: [NSWindow class]])
+ if ([view isKindOfClass: [NSApplication class]])
+ {
+ NSMutableArray *serializedSubviews = [NSMutableArray array];
+ for (NSWindow* window in [((NSApplication*) view) windows])
+ {
+ [serializedSubviews addObject: [self serializeView: window]];
+ }
+
+ [serializedSubviews addObject: [self serializeView: [((NSApplication*) view) mainMenu]]];
+
+ [serializedView setObject: serializedSubviews forKey: @"subviews"];
+ }
+ else if ([view isKindOfClass: [NSWindow class]])
{
NSArray *serializedSubview = [NSArray arrayWithObject: [self serializeView: [((NSWindow *) view) contentView]]];
[serializedView setObject: serializedSubview forKey: @"subviews"];
}
+ else if ([view isKindOfClass: [NSMenu class]])
+ {
+ NSMutableArray *serializedSubviews = [NSMutableArray array];
+ for (NSMenuItem* item in [((NSMenu*) view) itemArray])
+ {
+ [serializedSubviews addObject: [self serializeView: item]];
+ }
+
+ [serializedView setObject: serializedSubviews forKey: @"subviews"];
+ }
+ else if ([view isKindOfClass: [NSMenuItem class]])
+ {
+ NSMutableArray *serializedSubviews = [NSMutableArray array];
+ NSMenu* submenu = [((NSMenuItem*) view) submenu];
+
+ if (submenu != nil)
+ {
+ [serializedSubviews addObject: [self serializeView: submenu]];
+ }
+
+ [serializedView setObject: serializedSubviews forKey: @"subviews"];
+ }
else
{
NSArray* subviews = [((NSView *) view) subviews];
@@ -176,6 +223,8 @@ - (NSDictionary *) serializeView: (FrankSerializeViewType *) view {
{
[serializedSubviews addObject: [self serializeView: subview]];
}
+
+ [serializedView setObject: serializedSubviews forKey: @"subviews"];
}
#endif
View
8 src/FrankLoader.m
@@ -53,9 +53,15 @@ + (void)load{
[autoreleasePool drain];
+#if TARGET_OS_IPHONE
+ NSString *notificationName = @"UIApplicationDidBecomeActiveNotification";
+#else
+ NSString *notificationName = NSApplicationDidFinishLaunchingNotification;
+#endif
+
[[NSNotificationCenter defaultCenter] addObserver:[self class]
selector:@selector(applicationDidBecomeActive:)
- name:@"UIApplicationDidBecomeActiveNotification"
+ name:notificationName
object:nil];
}
View
4 src/FrankServer.m
@@ -18,6 +18,7 @@
#import "AppCommand.h"
#import "AccessibilityCheckCommand.h"
#import "EnginesCommand.h"
+#import "SuccessCommand.h"
#if TARGET_OS_IPHONE
#import "MapOperationCommand.h"
@@ -59,6 +60,9 @@ - (id) initWithStaticFrankBundleNamed:(NSString *)bundleName
[frankCommandRoute registerCommand:[[[LocationCommand alloc]init]autorelease] withName:@"location"];
[frankCommandRoute registerCommand:[[[IOSKeyboardCommand alloc] init]autorelease] withName:@"type_into_keyboard"];
#else
+ [frankCommandRoute registerCommand:[[[SuccessCommand alloc]init]autorelease] withName:@"map"];
+ [frankCommandRoute registerCommand:[[[SuccessCommand alloc]init]autorelease] withName:@"orientation"];
+ [frankCommandRoute registerCommand:[[[SuccessCommand alloc]init]autorelease] withName:@"location"];
[frankCommandRoute registerCommand:[[[OSXKeyboardCommand alloc] init]autorelease] withName:@"type_into_keyboard"];
#endif
View
33 src/NSApplication+FrankAutomation.m
@@ -0,0 +1,33 @@
+//
+// NSApplication+FrankAutomation.m
+// Frank
+//
+// Created by Buckley on 12/5/12.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+#import "LoadableCategory.h"
+MAKE_CATEGORIES_LOADABLE(NSApplication_FrankAutomation)
+
+@implementation NSApplication (FrankAutomation)
+
+- (CGRect) FEX_accessibilityFrame {
+ CGFloat maxWidth = 0;
+ CGFloat maxHeight = 0;
+
+ for (NSScreen* screen in [NSScreen screens])
+ {
+ NSRect frame = [screen frame];
+ CGFloat width = frame.origin.x + frame.size.width;
+ CGFloat height = frame.origin.y + frame.size.height;
+
+ maxWidth = MAX(width, maxWidth);
+ maxHeight = MAX(height, maxHeight);
+ }
+
+ return CGRectMake(0, 0, maxWidth, maxHeight);
+}
+
+@end
View
6 src/NSImage+Frank.m
@@ -13,7 +13,7 @@ @implementation NSImage (Frank)
+ (NSImage *) imageFromApplication:(BOOL)allWindows
{
- NSWindow* keyWindow = [[NSApplication sharedApplication] keyWindow];
+ NSWindow* mainWindow = [[NSApplication sharedApplication] mainWindow];
if (allWindows){
NSMutableArray *views = [NSMutableArray array];
@@ -22,10 +22,10 @@ + (NSImage *) imageFromApplication:(BOOL)allWindows
[views addObject:[window contentView]];
}
- return [NSView captureImageOfSize:keyWindow.frame.size fromViews:views];
+ return [NSView captureImageOfSize:mainWindow.frame.size fromViews:views];
}
else{
- return [[keyWindow contentView] captureImage];
+ return [[mainWindow contentView] captureImage];
}
}
View
47 src/NSObject+FrankAutomation.m
@@ -9,24 +9,31 @@
#import <Foundation/Foundation.h>
#import "LoadableCategory.h"
-MAKE_CATEGORIES_LOADABLE(NSVObject_FrankAutomation)
+MAKE_CATEGORIES_LOADABLE(NSObject_FrankAutomation)
@implementation NSObject (FrankAutomation)
- (NSString *) FEX_accessibilityLabel {
NSString* returnValue = nil;
- NSArray *candidateAttributes = @[ NSAccessibilityDescriptionAttribute,
- NSAccessibilityTitleAttribute,
- NSAccessibilityValueAttribute ];
-
- for (NSString *candidteAttribute in candidateAttributes)
+ if ([self respondsToSelector: @selector(accessibilityAttributeNames)] &&
+ [self respondsToSelector: @selector(accessibilityAttributeValue:)])
{
- id value = [self accessibilityAttributeValue: candidteAttribute];
+ NSArray *candidateAttributes = @[ NSAccessibilityDescriptionAttribute,
+ NSAccessibilityTitleAttribute,
+ NSAccessibilityValueAttribute ];
- if ([value isKindOfClass: [NSString class]]) {
- returnValue = value;
- break;
+ for (NSString *candidateAttribute in candidateAttributes)
+ {
+ if ([[self accessibilityAttributeNames] containsObject: candidateAttribute])
+ {
+ id value = [self accessibilityAttributeValue: candidateAttribute];
+
+ if ([value isKindOfClass: [NSString class]]) {
+ returnValue = value;
+ break;
+ }
+ }
}
}
@@ -35,10 +42,24 @@ - (NSString *) FEX_accessibilityLabel {
- (CGRect) FEX_accessibilityFrame {
NSPoint origin = NSZeroPoint;
- NSSize size = NSZeroSize;
+ NSSize size = NSZeroSize;
+
+ NSValue *originValue = nil;
+ NSValue *sizeValue = nil;
- NSValue *originValue = [self accessibilityAttributeValue: NSAccessibilityPositionAttribute];
- NSValue *sizeValue = [self accessibilityAttributeValue: NSAccessibilitySizeAttribute];
+ if ([self respondsToSelector: @selector(accessibilityAttributeNames)] &&
+ [self respondsToSelector: @selector(accessibilityAttributeValue:)])
+ {
+ if ([[self accessibilityAttributeNames] containsObject: NSAccessibilityPositionAttribute])
+ {
+ [self accessibilityAttributeValue: NSAccessibilityPositionAttribute];
+ }
+
+ if ([[self accessibilityAttributeNames] containsObject: NSAccessibilitySizeAttribute])
+ {
+ [self accessibilityAttributeValue: NSAccessibilitySizeAttribute];
+ }
+ }
if (originValue != nil) {
origin = [originValue pointValue];
View
8 src/OSXKeyboardCommand.m
@@ -14,9 +14,9 @@ @implementation OSXKeyboardCommand
- (void) synthesizeNSEventForString:(NSString *)aString
{
- NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
+ NSWindow *mainWindow = [[NSApplication sharedApplication] mainWindow];
- if (keyWindow != nil)
+ if (mainWindow != nil)
{
for (NSUInteger charIndex = 0; charIndex < [aString length]; ++charIndex)
{
@@ -26,7 +26,7 @@ - (void) synthesizeNSEventForString:(NSString *)aString
location:NSMakePoint(0, 0)
modifierFlags:0
timestamp:0
- windowNumber:[keyWindow windowNumber]
+ windowNumber:[mainWindow windowNumber]
context:nil
characters:eventChar
charactersIgnoringModifiers:nil
@@ -39,7 +39,7 @@ - (void) synthesizeNSEventForString:(NSString *)aString
location:NSMakePoint(0, 0)
modifierFlags:0
timestamp:0
- windowNumber:[keyWindow windowNumber]
+ windowNumber:[mainWindow windowNumber]
context:nil
characters:eventChar
charactersIgnoringModifiers:nil
View
14 src/SuccessCommand.h
@@ -0,0 +1,14 @@
+//
+// SuccessCommand.h
+// Frank
+//
+// Created by Buckley on 12/16/12.
+//
+//
+
+#import <Foundation/Foundation.h>
+#import "FrankCommandRoute.h"
+
+@interface SuccessCommand : NSObject<FrankCommand>
+
+@end
View
18 src/SuccessCommand.m
@@ -0,0 +1,18 @@
+//
+// SuccessCommand.m
+// Frank
+//
+// Created by Buckley on 12/16/12.
+//
+//
+
+#import "SuccessCommand.h"
+#import "FranklyProtocolHelper.h"
+
+@implementation SuccessCommand
+
+- (NSString *) handleCommandWithRequestBody:(NSString *) requestBody {
+ return [FranklyProtocolHelper generateSuccessResponseWithoutResults];
+}
+
+@end

0 comments on commit ef64f84

Please sign in to comment.
Something went wrong with that request. Please try again.