sc-frank-cucumber 1.2.1.00af28c

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +38 -0
  4. data/bin/frank +6 -0
  5. data/bin/frank-skeleton +33 -0
  6. data/frank-skeleton/features/my_first.feature +12 -0
  7. data/frank-skeleton/features/step_definitions/launch_steps.rb +20 -0
  8. data/frank-skeleton/features/support/env.rb +8 -0
  9. data/frank-skeleton/frank_static_resources.bundle/ViewAttributeMapping.plist +63 -0
  10. data/frank-skeleton/frank_static_resources.bundle/ViewAttributeMappingMac.plist +99 -0
  11. data/frank-skeleton/frank_static_resources.bundle/images/ajax-loader.gif +0 -0
  12. data/frank-skeleton/frank_static_resources.bundle/images/file.gif +0 -0
  13. data/frank-skeleton/frank_static_resources.bundle/images/folder-closed.gif +0 -0
  14. data/frank-skeleton/frank_static_resources.bundle/images/folder.gif +0 -0
  15. data/frank-skeleton/frank_static_resources.bundle/images/loader.gif +0 -0
  16. data/frank-skeleton/frank_static_resources.bundle/images/loader.png +0 -0
  17. data/frank-skeleton/frank_static_resources.bundle/images/minus.gif +0 -0
  18. data/frank-skeleton/frank_static_resources.bundle/images/plus.gif +0 -0
  19. data/frank-skeleton/frank_static_resources.bundle/images/treeview-black-line.gif +0 -0
  20. data/frank-skeleton/frank_static_resources.bundle/images/treeview-black.gif +0 -0
  21. data/frank-skeleton/frank_static_resources.bundle/images/treeview-default-line.gif +0 -0
  22. data/frank-skeleton/frank_static_resources.bundle/images/treeview-default.gif +0 -0
  23. data/frank-skeleton/frank_static_resources.bundle/images/treeview-famfamfam-line.gif +0 -0
  24. data/frank-skeleton/frank_static_resources.bundle/images/treeview-famfamfam.gif +0 -0
  25. data/frank-skeleton/frank_static_resources.bundle/images/treeview-gray-line.gif +0 -0
  26. data/frank-skeleton/frank_static_resources.bundle/images/treeview-gray.gif +0 -0
  27. data/frank-skeleton/frank_static_resources.bundle/images/treeview-red-line.gif +0 -0
  28. data/frank-skeleton/frank_static_resources.bundle/images/treeview-red.gif +0 -0
  29. data/frank-skeleton/frank_static_resources.bundle/index.html +86 -0
  30. data/frank-skeleton/frank_static_resources.bundle/index.html.haml +76 -0
  31. data/frank-skeleton/frank_static_resources.bundle/js/accessible_views_view.coffee +41 -0
  32. data/frank-skeleton/frank_static_resources.bundle/js/accessible_views_view.js +46 -0
  33. data/frank-skeleton/frank_static_resources.bundle/js/controller.coffee +134 -0
  34. data/frank-skeleton/frank_static_resources.bundle/js/controller.js +139 -0
  35. data/frank-skeleton/frank_static_resources.bundle/js/details_view.coffee +42 -0
  36. data/frank-skeleton/frank_static_resources.bundle/js/details_view.js +51 -0
  37. data/frank-skeleton/frank_static_resources.bundle/js/dropdown_control.coffee +64 -0
  38. data/frank-skeleton/frank_static_resources.bundle/js/dropdown_control.js +73 -0
  39. data/frank-skeleton/frank_static_resources.bundle/js/ersatz_model.coffee +46 -0
  40. data/frank-skeleton/frank_static_resources.bundle/js/ersatz_model.js +60 -0
  41. data/frank-skeleton/frank_static_resources.bundle/js/ersatz_view.coffee +167 -0
  42. data/frank-skeleton/frank_static_resources.bundle/js/ersatz_view.js +205 -0
  43. data/frank-skeleton/frank_static_resources.bundle/js/experiment_bar_model.coffee +10 -0
  44. data/frank-skeleton/frank_static_resources.bundle/js/experiment_bar_model.js +17 -0
  45. data/frank-skeleton/frank_static_resources.bundle/js/experiment_bar_view.coffee +44 -0
  46. data/frank-skeleton/frank_static_resources.bundle/js/experiment_bar_view.js +63 -0
  47. data/frank-skeleton/frank_static_resources.bundle/js/frank.coffee +96 -0
  48. data/frank-skeleton/frank_static_resources.bundle/js/frank.js +146 -0
  49. data/frank-skeleton/frank_static_resources.bundle/js/lib/backbone.js +1431 -0
  50. data/frank-skeleton/frank_static_resources.bundle/js/lib/coffee-script.js +8 -0
  51. data/frank-skeleton/frank_static_resources.bundle/js/lib/jquery-ui.min.js +405 -0
  52. data/frank-skeleton/frank_static_resources.bundle/js/lib/jquery.min.js +4 -0
  53. data/frank-skeleton/frank_static_resources.bundle/js/lib/jquery.treeview.js +251 -0
  54. data/frank-skeleton/frank_static_resources.bundle/js/lib/json2.js +481 -0
  55. data/frank-skeleton/frank_static_resources.bundle/js/lib/raphael.js +5815 -0
  56. data/frank-skeleton/frank_static_resources.bundle/js/lib/require.js +2053 -0
  57. data/frank-skeleton/frank_static_resources.bundle/js/lib/underscore.js +1059 -0
  58. data/frank-skeleton/frank_static_resources.bundle/js/main.coffee +27 -0
  59. data/frank-skeleton/frank_static_resources.bundle/js/main.js +29 -0
  60. data/frank-skeleton/frank_static_resources.bundle/js/tabs_controller.coffee +13 -0
  61. data/frank-skeleton/frank_static_resources.bundle/js/tabs_controller.js +22 -0
  62. data/frank-skeleton/frank_static_resources.bundle/js/toast_controller.coffee +15 -0
  63. data/frank-skeleton/frank_static_resources.bundle/js/toast_controller.js +28 -0
  64. data/frank-skeleton/frank_static_resources.bundle/js/transform_stack.coffee +59 -0
  65. data/frank-skeleton/frank_static_resources.bundle/js/transform_stack.js +78 -0
  66. data/frank-skeleton/frank_static_resources.bundle/js/tree_view.coffee +53 -0
  67. data/frank-skeleton/frank_static_resources.bundle/js/tree_view.js +64 -0
  68. data/frank-skeleton/frank_static_resources.bundle/js/view_hier_model.coffee +37 -0
  69. data/frank-skeleton/frank_static_resources.bundle/js/view_hier_model.js +48 -0
  70. data/frank-skeleton/frank_static_resources.bundle/js/view_model.coffee +39 -0
  71. data/frank-skeleton/frank_static_resources.bundle/js/view_model.js +62 -0
  72. data/frank-skeleton/frank_static_resources.bundle/pictos/index.html +329 -0
  73. data/frank-skeleton/frank_static_resources.bundle/pictos/pictos-web.eot +0 -0
  74. data/frank-skeleton/frank_static_resources.bundle/pictos/pictos-web.svg +114 -0
  75. data/frank-skeleton/frank_static_resources.bundle/pictos/pictos-web.ttf +0 -0
  76. data/frank-skeleton/frank_static_resources.bundle/pictos/pictos-web.woff +0 -0
  77. data/frank-skeleton/frank_static_resources.bundle/pictos/pictos.css +20 -0
  78. data/frank-skeleton/frank_static_resources.bundle/pictos/pictos_base64.css +18 -0
  79. data/frank-skeleton/frank_static_resources.bundle/stylesheets/css/symbiote.css +1 -0
  80. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_elements.scss +28 -0
  81. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_header.scss +61 -0
  82. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_inspect_tabs_list_tabs.scss +194 -0
  83. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_jquery.treeview.scss +68 -0
  84. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_jqui.scss +2 -0
  85. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_layout.scss +13 -0
  86. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_mixins.sass +137 -0
  87. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_reset.scss +32 -0
  88. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_selector_test_toolbar.scss +81 -0
  89. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_solarized.scss +16 -0
  90. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_typography.scss +11 -0
  91. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_unicode.scss +3 -0
  92. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/_z_index.scss +2 -0
  93. data/frank-skeleton/frank_static_resources.bundle/stylesheets/sass/symbiote.scss +26 -0
  94. data/frank-skeleton/frankify.xcconfig.tt +6 -0
  95. data/frank-skeleton/libCocoaAsyncSocket.a +0 -0
  96. data/frank-skeleton/libCocoaAsyncSocketMac.a +0 -0
  97. data/frank-skeleton/libCocoaHTTPServer.a +0 -0
  98. data/frank-skeleton/libCocoaHTTPServerMac.a +0 -0
  99. data/frank-skeleton/libCocoaLumberjack.a +0 -0
  100. data/frank-skeleton/libCocoaLumberjackMac.a +0 -0
  101. data/frank-skeleton/libFrank.a +0 -0
  102. data/frank-skeleton/libFrankMac.a +0 -0
  103. data/frank-skeleton/libShelley.a +0 -0
  104. data/frank-skeleton/libShelleyMac.a +0 -0
  105. data/frank-skeleton/plugins/.empty_directory +0 -0
  106. data/lib/frank-cucumber.rb +15 -0
  107. data/lib/frank-cucumber/app_bundle_locator.rb +58 -0
  108. data/lib/frank-cucumber/bonjour.rb +73 -0
  109. data/lib/frank-cucumber/cli.rb +299 -0
  110. data/lib/frank-cucumber/color_helper.rb +13 -0
  111. data/lib/frank-cucumber/console.rb +28 -0
  112. data/lib/frank-cucumber/core_frank_steps.rb +260 -0
  113. data/lib/frank-cucumber/frank.xcconfig.erb +17 -0
  114. data/lib/frank-cucumber/frank_helper.rb +459 -0
  115. data/lib/frank-cucumber/frank_localize.rb +43 -0
  116. data/lib/frank-cucumber/frank_mac_helper.rb +120 -0
  117. data/lib/frank-cucumber/frankifier.rb +150 -0
  118. data/lib/frank-cucumber/gateway.rb +135 -0
  119. data/lib/frank-cucumber/gesture_helper.rb +99 -0
  120. data/lib/frank-cucumber/host_scripting.rb +96 -0
  121. data/lib/frank-cucumber/keyboard_helper.rb +69 -0
  122. data/lib/frank-cucumber/launcher.rb +70 -0
  123. data/lib/frank-cucumber/localize.yml +104 -0
  124. data/lib/frank-cucumber/location_helper.rb +20 -0
  125. data/lib/frank-cucumber/mac_launcher.rb +35 -0
  126. data/lib/frank-cucumber/plugins/plugin.rb +57 -0
  127. data/lib/frank-cucumber/rect.rb +26 -0
  128. data/lib/frank-cucumber/scroll_helper.rb +24 -0
  129. data/lib/frank-cucumber/version.rb +5 -0
  130. data/lib/frank-cucumber/wait_helper.rb +57 -0
  131. data/sc-frank-cucumber.gemspec +37 -0
  132. data/test/keyboard_helper_test.rb +84 -0
  133. data/test/launcher_test.rb +57 -0
  134. data/test/rect_test.rb +25 -0
  135. data/test/test_helper.rb +16 -0
  136. metadata +395 -0
@@ -0,0 +1,43 @@
1
+ require 'i18n'
2
+
3
+ module Frank
4
+ module Cucumber
5
+ module Localize
6
+
7
+ def self.system_locale
8
+ case ENV['LANG']
9
+ when /^fr_/
10
+ :fr
11
+ when /^de_/
12
+ :de
13
+ when /^ru_/
14
+ :ru
15
+ when /^zh_/
16
+ :zh
17
+ when /^ja_/
18
+ :ja
19
+ when /^es_/
20
+ :es
21
+ when /^it_/
22
+ :it
23
+ else
24
+ :en
25
+ end
26
+ end
27
+
28
+ def self.load_translations
29
+ if I18n.backend.send(:translations).size == 0
30
+ I18n.locale = self.system_locale
31
+ I18n.load_path = [ File.join(File.dirname(__FILE__), 'localize.yml') ]
32
+ I18n.backend.load_translations
33
+ end
34
+ end
35
+
36
+ def self.t(key)
37
+ self.load_translations
38
+ I18n.t(key)
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,120 @@
1
+ require 'frank-cucumber/frank_helper'
2
+
3
+ module Frank module Cucumber
4
+
5
+ module FrankMacHelper
6
+
7
+ # Performs a click at the center of the selected object.
8
+ #
9
+ # This method creates CGEvents to move and click the mouse. Before calling this method,
10
+ # you should make sure that the element that you want to click is frontmost by calling
11
+ # bring_to_front.
12
+ #
13
+ # This method is designed to act on a single object, so do not pass a selector that will
14
+ # return multiple objects.
15
+ def click ( selector )
16
+ frame = accessibility_frame(selector)
17
+ frankly_map( selector, 'FEX_mouseDownX:y:', frame.center.x, frame.center.y )
18
+ frankly_map( selector, 'FEX_mouseUpX:y:', frame.center.x, frame.center.y )
19
+ end
20
+
21
+ # Performs a double-click at the center of the selected object.
22
+ #
23
+ # This method creates CGEvents to move and click the mouse. Before calling this method,
24
+ # you should make sure that the element that you want to click is frontmost by calling
25
+ # bring_to_front.
26
+ #
27
+ # This method is designed to act on a single object, so do not pass a selector that will
28
+ # return multiple objects.
29
+ def double_click ( selector )
30
+ click(selector)
31
+ click(selector)
32
+ end
33
+
34
+ #@api private
35
+ def perform_action_on_selector( action, selector )
36
+ touch_successes = frankly_map( selector, action )
37
+ raise "could not find anything matching [#{selector}] which supports that action" if touch_successes == nil or touch_successes.empty?
38
+ raise "some objects do not support that action" if touch_successes.include?(false)
39
+ end
40
+
41
+ # Simulates the effect of clicking on the selected objects without actually moving the
42
+ # mouse or clicking.
43
+ #
44
+ # If the object supports the NSAccessibilityPressAction, that action is performed.
45
+ # Otherwise, if the object is a table cell or row, that row is selected,
46
+ # Otherwise, if the object is an NSView, it is made the first responder, if possible
47
+ # Otherwise, if the object is a menu item, it opens its submenu if it has one, or
48
+ # performs it's action if not.
49
+ def simulate_click( selector )
50
+ perform_action_on_selector( 'FEX_simulateClick', selector )
51
+ end
52
+
53
+ # Brings the selected application or window to the front.
54
+ def bring_to_front( selector )
55
+ perform_action_on_selector( 'FEX_raise', selector )
56
+ end
57
+
58
+ # Cancels the current action, such as editing a text field.
59
+ def cancel( selector )
60
+ perform_action_on_selector( 'FEX_cancel', selector )
61
+ end
62
+
63
+ # Finishes the current action, such as editing a text field.
64
+ def confirm( selector )
65
+ perform_action_on_selector( 'FEX_confirm', selector )
66
+ end
67
+
68
+ # Decrements the value of NSSliders, NSSteppers, and similar controls
69
+ def decrement_value( selector )
70
+ perform_action_on_selector( 'FEX_decrement', selector )
71
+ end
72
+
73
+ # Deletes the user-inputted value
74
+ def delete_value( selector )
75
+ perform_action_on_selector( 'FEX_delete', selector )
76
+ end
77
+
78
+ # Increments the value of NSSliders, NSSteppers, and similar controls
79
+ def increment_value( selector )
80
+ perform_action_on_selector( 'FEX_increment', selector )
81
+ end
82
+
83
+ # Selects a menu item. This action is considered "outdated" by the Accessibility API, so
84
+ # don't use it without a good reason.
85
+ def pick( selector )
86
+ perform_action_on_selector( 'FEX_pick', selector )
87
+ end
88
+
89
+ # Shows the contextual menu associated with the selector. This is the menu that would
90
+ # appear if the user right-clicked the selector, or, in some cases, held down the left
91
+ # mouse button on the selector.
92
+ def show_menu( selector )
93
+ perform_action_on_selector( 'FEX_showMenu', selector )
94
+ end
95
+
96
+ # Expands the row the selector belongs to in an NSOutlineView. Do not expand more than
97
+ # one row at a time.
98
+ def expand_row( selector )
99
+ perform_action_on_selector( 'FEX_expand', selector )
100
+ end
101
+
102
+ # Collapses the row the selector belongs to in an NSOutlineView. Do not expand more than
103
+ # one row at a time.
104
+ def collapse_row( selector )
105
+ perform_action_on_selector( 'FEX_collapse', selector )
106
+ end
107
+
108
+ # @return [Boolean] whether the rows the selectors belong to in an NSOutlineView are all
109
+ # expanded
110
+ def row_is_expanded( selector )
111
+ successes = frankly_map( selector, "FEX_isExpanded" )
112
+ return false if successes == nil or successes.empty?
113
+ return !successes.include?(false)
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+
120
+ end
@@ -0,0 +1,150 @@
1
+ require 'pathname'
2
+ require 'xcodeproj'
3
+
4
+ class Frankifier
5
+ include Thor::Shell
6
+
7
+ def self.frankify! root_dir, options = {}
8
+ me = new(root_dir, options)
9
+ me.frankify!
10
+ me
11
+ end
12
+
13
+ def initialize( root_dir, options = {} )
14
+ @root = Pathname.new( root_dir )
15
+ @target_build_configuration = options[:build_config]
16
+ @target_selection = options[:target]
17
+ load_xcode_proj_option(options[:project])
18
+ end
19
+
20
+ def frankify!
21
+ decide_on_project if @project.nil?
22
+ decide_on_target
23
+ report_project_and_target
24
+
25
+ check_target_build_configuration_is_valid!
26
+
27
+ say ''
28
+ add_linker_flag
29
+
30
+ say ''
31
+ add_library_search_path
32
+
33
+ save_changes
34
+ end
35
+
36
+ private
37
+ def load_xcode_proj_option(xcodeproj)
38
+ if xcodeproj
39
+ unless File.exists?(xcodeproj)
40
+ raise "Project file '#{xcodeproj}' does not exist. Please specify the relative path."
41
+ end
42
+
43
+ @xcodeproj_path = Pathname.new(xcodeproj)
44
+ @project = Xcodeproj::Project.open(@xcodeproj_path)
45
+ end
46
+ end
47
+
48
+ def decide_on_project
49
+ projects = Pathname.glob( @root+'*.xcodeproj' )
50
+ xcodeproj = case projects.size
51
+ when 0
52
+ raise "There are no .xcodeproj files in this directory. Please move to your root project directory and try again."
53
+ when 1
54
+ projects.first
55
+ else
56
+ choice = ask_menu(
57
+ "I found more than one .xcodeproj. Which is the main app project that you wish to Frankify?",
58
+ projects.map(&:basename)
59
+ )
60
+ projects[choice]
61
+ end
62
+
63
+ @xcodeproj_path = xcodeproj
64
+ @project = Xcodeproj::Project.open(xcodeproj)
65
+ end
66
+
67
+ def decide_on_target
68
+ targets = @project.targets
69
+ @target = targets.find { |item| item.name.eql?(@target_selection) } if @target_selection
70
+ return @target if @target
71
+ @target = case targets.size
72
+ when 0
73
+ raise "Sorry, this project appears to contain no targets. Nothing I can do here."
74
+ when 1
75
+ targets.first
76
+ else
77
+ choice = ask_menu(
78
+ "I found more than one target in this project. Which is the main app target that you wish to Frankify?",
79
+ targets.map(&:name)
80
+ )
81
+ targets.to_a[choice]
82
+ end
83
+ end
84
+
85
+ def report_project_and_target
86
+ puts "Frankifying target [#{@target.name}] in project #{@xcodeproj_path.basename}"
87
+ end
88
+
89
+ def add_linker_flag
90
+ add_frank_entry_to_build_setting( 'OTHER_LDFLAGS', 'FRANK_LDFLAGS' )
91
+ end
92
+
93
+ def add_library_search_path
94
+ add_frank_entry_to_build_setting( 'LIBRARY_SEARCH_PATHS', 'FRANK_LIBRARY_SEARCH_PATHS' )
95
+ end
96
+
97
+ def add_frank_entry_to_build_setting( build_setting, entry_to_add )
98
+ setting_array = Array( build_settings_to_edit[build_setting] )
99
+
100
+ if setting_array.find{ |flag| flag.start_with? "$(FRANK_" }
101
+ say "It appears that your '#{@target_build_configuration}' configuration's #{build_setting} build setting already include some FRANK setup. Namely: #{setting_array.inspect}. I won't change anything here."
102
+ return
103
+ end
104
+
105
+ say "Adding $(inherited) and $(#{entry_to_add}) to your '#{@target_build_configuration}' configuration's #{build_setting} build setting ..."
106
+ setting_array.unshift "$(inherited)"
107
+ setting_array << "$(#{entry_to_add})"
108
+ setting_array.uniq! # mainly to avoid duplicate $(inherited) entries
109
+ say "... #{build_setting} is now: #{setting_array.inspect}"
110
+
111
+ build_settings_to_edit[build_setting] = setting_array
112
+ end
113
+
114
+ def check_target_build_configuration_is_valid!
115
+ unless @target.build_configuration_list.build_settings(@target_build_configuration)
116
+ 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:|
117
+ @target.build_configuration_list.build_configurations.each do |bc|
118
+ say " '#{bc.name}'"
119
+ end
120
+ say ''
121
+ say %Q|Please specify one of those build configurations using the --build_configuration flag|
122
+ exit
123
+ end
124
+
125
+ end
126
+
127
+ def build_settings_to_edit
128
+ @_build_settings_to_edit ||= @target.build_configuration_list.build_settings(@target_build_configuration)
129
+ end
130
+
131
+ def save_changes
132
+ @project.save
133
+ end
134
+
135
+ # TODO: send this as a pull request to thor
136
+ def ask_menu message, options
137
+ option_lines = options.each_with_index.map{ |o,i| "#{i+1}: #{o}" }
138
+ full_message = ([message,'']+option_lines+[">"]).join("\n")
139
+
140
+ allowed_range = (1..options.length)
141
+ valid_choice = nil
142
+ until valid_choice
143
+ choice = ask(full_message).to_i
144
+ valid_choice = choice if allowed_range.include?(choice)
145
+ say("You must choose an option between #{allowed_range.first} and #{allowed_range.last}") unless valid_choice
146
+ end
147
+ valid_choice-1
148
+ end
149
+
150
+ end
@@ -0,0 +1,135 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
4
+ module Frank module Cucumber
5
+
6
+ class Gateway
7
+ DEFAULT_BASE_URL = "http://localhost:37265/"
8
+
9
+ def initialize( base_url = nil )
10
+ @base_url = URI.parse( (base_url || DEFAULT_BASE_URL).to_s )
11
+ end
12
+
13
+ def ping
14
+ send_get('')
15
+ return true
16
+ rescue FrankNetworkError
17
+ return false
18
+ end
19
+
20
+ class << self
21
+ def build_operation_map( method_sig, method_args )
22
+ num_args_according_to_method_sig = method_sig.count(':')
23
+
24
+ if num_args_according_to_method_sig != method_args.count
25
+ raise <<-EOS
26
+
27
+ The method you've specified - #{method_sig} - wants #{num_args_according_to_method_sig} arguments, but you've supplied #{method_args.count} arguments.
28
+
29
+ EOS
30
+ end
31
+
32
+ if num_args_according_to_method_sig > 0 && !method_sig.end_with?(':')
33
+ raise <<-EOS
34
+
35
+ The method signature you've specified - #{method_sig} - is invalid. Objective C method signatures which take parameters must end with a :
36
+
37
+ EOS
38
+ end
39
+
40
+ {
41
+ :method_name => method_sig,
42
+ :arguments => method_args,
43
+ }
44
+ end
45
+
46
+ def evaluate_frankly_response( json, req_desc )
47
+ res = JSON.parse( json )
48
+ if res['outcome'] != 'SUCCESS'
49
+ raise "#{req_desc} failed because: #{res['reason']}\n#{res['details']}"
50
+ end
51
+
52
+ res['results']
53
+ end
54
+ end
55
+
56
+ #taken from Ian Dee's Encumber
57
+ def send_post( verb, command )
58
+ command = command.to_json unless command.is_a? String
59
+
60
+ url = frank_url_for( verb )
61
+ req = Net::HTTP::Post.new url.path
62
+ req.body = command
63
+
64
+ make_http_request( url, req )
65
+ end
66
+
67
+ def send_get( verb )
68
+ url = frank_url_for( verb )
69
+ req = Net::HTTP::Get.new url.path
70
+ make_http_request( url, req )
71
+ end
72
+
73
+ private
74
+
75
+ def frank_url_for( verb )
76
+ url = @base_url.clone
77
+ url.path = '/'+verb
78
+ url
79
+ end
80
+
81
+ def make_http_request( url, req )
82
+ http = Net::HTTP.new(url.host, url.port)
83
+
84
+ begin
85
+ res = http.start do |sess|
86
+ sess.request req
87
+ end
88
+
89
+ res.body
90
+ rescue Errno::ECONNREFUSED
91
+ raise FrankNetworkError
92
+ rescue EOFError
93
+ raise FrankNetworkError
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+
100
+ class FrankNetworkError < RuntimeError
101
+ OVERLY_VERBOSE_YET_HELPFUL_ERROR_MESSAGE = <<EOS
102
+
103
+
104
+ *********************************************
105
+ Oh dear. Your app fell over and can't get up.
106
+ *********************************************
107
+
108
+
109
+ We just encountered an error while trying to talk to the Frank server embedded
110
+ within the app under test. This usually means that the app has just crashed,
111
+ either while carrying out the current step or while finishing up the previous
112
+ step.
113
+
114
+ Here are some things you could do next:
115
+
116
+ - Take a look at the app's logs to see why it crashed. You can view the logs
117
+ in Console.app (a search for 'Frankified' will usually find your frankified
118
+ app's output).
119
+
120
+ - Launch your frankified app in the XCode debugger and then run this scenario
121
+ again. You'll get lots of helpful output from XCode. Don't forget to do
122
+ something to prevent cucumber from automatically re-launching your app when
123
+ you run the scenario by hand. If you don't prevent the relaunch then you
124
+ won't still be in the XCode debugger when the crash happens.
125
+
126
+
127
+
128
+ EOS
129
+
130
+ def initialize
131
+ super OVERLY_VERBOSE_YET_HELPFUL_ERROR_MESSAGE
132
+ end
133
+ end
134
+
135
+ end end