iCuke 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/.gitmodules +1 -1
  2. data/Gemfile +12 -0
  3. data/Gemfile.lock +41 -0
  4. data/README.markdown +126 -0
  5. data/Rakefile +34 -12
  6. data/VERSION +1 -1
  7. data/bin/icuke +12 -10
  8. data/ext/Rakefile +6 -0
  9. data/ext/iCuke/{sdk3.1/DefaultsResponse.h → DefaultsResponse.h} +0 -0
  10. data/ext/iCuke/{sdk3.1/DefaultsResponse.m → DefaultsResponse.m} +0 -0
  11. data/ext/iCuke/{sdk3.1/EventResponse.h → EventResponse.h} +0 -0
  12. data/ext/iCuke/{sdk3.1/EventResponse.m → EventResponse.m} +0 -0
  13. data/ext/iCuke/{sdk3.1/ModuleResponse.h → ModuleResponse.h} +0 -0
  14. data/ext/iCuke/{sdk3.1/ModuleResponse.m → ModuleResponse.m} +0 -0
  15. data/ext/iCuke/{sdk3.1/QuitResponse.h → QuitResponse.h} +0 -0
  16. data/ext/iCuke/{sdk3.1/QuitResponse.m → QuitResponse.m} +0 -0
  17. data/ext/iCuke/Rakefile +14 -13
  18. data/ext/iCuke/{sdk3.1/Recorder.h → Recorder.h} +0 -0
  19. data/ext/iCuke/{sdk3.1/Recorder.m → Recorder.m} +0 -0
  20. data/ext/iCuke/{sdk3.1/RecorderResponse.h → RecorderResponse.h} +0 -0
  21. data/ext/iCuke/{sdk3.1/RecorderResponse.m → RecorderResponse.m} +0 -0
  22. data/ext/iCuke/{sdk3.1/SynthesizeSingleton.h → SynthesizeSingleton.h} +0 -0
  23. data/ext/iCuke/{sdk3.1/ViewResponse.h → ViewResponse.h} +0 -0
  24. data/ext/iCuke/{sdk3.1/ViewResponse.m → ViewResponse.m} +0 -0
  25. data/ext/iCuke/{sdk3.1/Viewer.h → Viewer.h} +0 -0
  26. data/ext/iCuke/{sdk4.0/Viewer.m → Viewer.m} +0 -0
  27. data/ext/iCuke/{sdk3.1/iCukeHTTPResponseHandler.h → iCukeHTTPResponseHandler.h} +0 -0
  28. data/ext/iCuke/{sdk3.1/iCukeHTTPResponseHandler.m → iCukeHTTPResponseHandler.m} +0 -0
  29. data/ext/iCuke/{sdk3.1/iCukeHTTPServer.h → iCukeHTTPServer.h} +0 -0
  30. data/ext/iCuke/{sdk4.0/iCukeHTTPServer.m → iCukeHTTPServer.m} +4 -2
  31. data/ext/iCuke/{sdk3.1/iCukeServer.h → iCukeServer.h} +0 -0
  32. data/ext/iCuke/{sdk3.1/iCukeServer.m → iCukeServer.m} +0 -0
  33. data/ext/iCuke/{sdk3.1/json → json}/JSON.h +0 -0
  34. data/ext/iCuke/{sdk3.1/json → json}/NSObject+SBJSON.h +0 -0
  35. data/ext/iCuke/{sdk3.1/json → json}/NSObject+SBJSON.m +0 -0
  36. data/ext/iCuke/{sdk3.1/json → json}/NSString+SBJSON.h +0 -0
  37. data/ext/iCuke/{sdk3.1/json → json}/NSString+SBJSON.m +0 -0
  38. data/ext/iCuke/{sdk3.1/json → json}/SBJSON.h +0 -0
  39. data/ext/iCuke/{sdk3.1/json → json}/SBJSON.m +0 -0
  40. data/ext/iCuke/{sdk3.1/json → json}/SBJsonBase.h +0 -0
  41. data/ext/iCuke/{sdk3.1/json → json}/SBJsonBase.m +0 -0
  42. data/ext/iCuke/{sdk3.1/json → json}/SBJsonParser.h +0 -0
  43. data/ext/iCuke/{sdk3.1/json → json}/SBJsonParser.m +0 -0
  44. data/ext/iCuke/{sdk3.1/json → json}/SBJsonWriter.h +0 -0
  45. data/ext/iCuke/{sdk3.1/json → json}/SBJsonWriter.m +0 -0
  46. data/features/starting_project.feature +18 -0
  47. data/features/step_definitions/shell.rb +41 -0
  48. data/features/support/env.rb +2 -0
  49. data/features/support/environment.rb +40 -0
  50. data/features/supported_sdks.feature +12 -0
  51. data/iCuke.gemspec +149 -161
  52. data/lib/icuke/configuration.rb +19 -0
  53. data/lib/icuke/core_ext.rb +27 -0
  54. data/lib/icuke/cucumber.rb +29 -265
  55. data/lib/icuke/cucumber_compat.rb +4 -0
  56. data/lib/icuke/icuke_world.rb +149 -0
  57. data/lib/icuke/sdk.rb +5 -13
  58. data/lib/icuke/simulator_driver.rb +201 -0
  59. data/lib/icuke/waxsim.rb +47 -9
  60. data/spec/cucumber_spec.rb +130 -0
  61. data/spec/fixtures/controls_page.xml +252 -0
  62. data/spec/process_spec.rb +76 -0
  63. data/spec/screen_spec.rb +173 -0
  64. data/spec/simulate_spec.rb +75 -0
  65. data/spec/simulator_spec.rb +28 -0
  66. data/spec/spec.opts +2 -0
  67. data/spec/spec_helper.rb +67 -0
  68. metadata +222 -121
  69. data/.gitignore +0 -15
  70. data/README.rdoc +0 -68
  71. data/ext/WaxSim/Simulator.h +0 -31
  72. data/ext/WaxSim/Simulator.m +0 -131
  73. data/ext/WaxSim/WaxSim.m +0 -110
  74. data/ext/WaxSim/WaxSim.xcodeproj/project.pbxproj +0 -238
  75. data/ext/WaxSim/WaxSim_Prefix.pch +0 -7
  76. data/ext/WaxSim/build/Release/waxsim +0 -0
  77. data/ext/WaxSim/build/Release/waxsim.dSYM/Contents/Info.plist +0 -20
  78. data/ext/WaxSim/build/Release/waxsim.dSYM/Contents/Resources/DWARF/waxsim +0 -0
  79. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/Simulator.o +0 -0
  80. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/WaxSim.o +0 -0
  81. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/waxsim.LinkFileList +0 -2
  82. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/WaxSim.dep +0 -6
  83. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/WaxSim~.dep +0 -6
  84. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/build-state.dat +0 -227
  85. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/build-state~.dat +0 -227
  86. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-all-target-headers.hmap +0 -0
  87. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-generated-files.hmap +0 -0
  88. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-own-target-headers.hmap +0 -0
  89. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-project-headers.hmap +0 -0
  90. data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim.hmap +0 -0
  91. data/ext/WaxSim/iPhoneSimulatorRemoteClient/iPhoneSimulatorRemoteClient.h +0 -126
  92. data/ext/iCuke/sdk3.1/Rakefile +0 -20
  93. data/ext/iCuke/sdk3.1/Viewer.m +0 -203
  94. data/ext/iCuke/sdk3.1/iCukeHTTPServer.m +0 -365
  95. data/ext/iCuke/sdk4.0/DefaultsResponse.h +0 -5
  96. data/ext/iCuke/sdk4.0/DefaultsResponse.m +0 -66
  97. data/ext/iCuke/sdk4.0/EventResponse.h +0 -5
  98. data/ext/iCuke/sdk4.0/EventResponse.m +0 -130
  99. data/ext/iCuke/sdk4.0/ModuleResponse.h +0 -5
  100. data/ext/iCuke/sdk4.0/ModuleResponse.m +0 -76
  101. data/ext/iCuke/sdk4.0/QuitResponse.h +0 -5
  102. data/ext/iCuke/sdk4.0/QuitResponse.m +0 -23
  103. data/ext/iCuke/sdk4.0/Rakefile +0 -20
  104. data/ext/iCuke/sdk4.0/Recorder.h +0 -17
  105. data/ext/iCuke/sdk4.0/Recorder.m +0 -90
  106. data/ext/iCuke/sdk4.0/RecorderResponse.h +0 -6
  107. data/ext/iCuke/sdk4.0/RecorderResponse.m +0 -68
  108. data/ext/iCuke/sdk4.0/SynthesizeSingleton.h +0 -68
  109. data/ext/iCuke/sdk4.0/ViewResponse.h +0 -5
  110. data/ext/iCuke/sdk4.0/ViewResponse.m +0 -84
  111. data/ext/iCuke/sdk4.0/Viewer.h +0 -8
  112. data/ext/iCuke/sdk4.0/iCukeHTTPResponseHandler.h +0 -50
  113. data/ext/iCuke/sdk4.0/iCukeHTTPResponseHandler.m +0 -381
  114. data/ext/iCuke/sdk4.0/iCukeHTTPServer.h +0 -53
  115. data/ext/iCuke/sdk4.0/iCukeServer.h +0 -14
  116. data/ext/iCuke/sdk4.0/iCukeServer.m +0 -65
  117. data/ext/iCuke/sdk4.0/json/JSON.h +0 -50
  118. data/ext/iCuke/sdk4.0/json/NSObject+SBJSON.h +0 -68
  119. data/ext/iCuke/sdk4.0/json/NSObject+SBJSON.m +0 -53
  120. data/ext/iCuke/sdk4.0/json/NSString+SBJSON.h +0 -58
  121. data/ext/iCuke/sdk4.0/json/NSString+SBJSON.m +0 -55
  122. data/ext/iCuke/sdk4.0/json/SBJSON.h +0 -75
  123. data/ext/iCuke/sdk4.0/json/SBJSON.m +0 -212
  124. data/ext/iCuke/sdk4.0/json/SBJsonBase.h +0 -86
  125. data/ext/iCuke/sdk4.0/json/SBJsonBase.m +0 -78
  126. data/ext/iCuke/sdk4.0/json/SBJsonParser.h +0 -87
  127. data/ext/iCuke/sdk4.0/json/SBJsonParser.m +0 -475
  128. data/ext/iCuke/sdk4.0/json/SBJsonWriter.h +0 -129
  129. data/ext/iCuke/sdk4.0/json/SBJsonWriter.m +0 -228
@@ -0,0 +1,19 @@
1
+ module ICuke
2
+ class Configuration
3
+ def initialize(defaults = {})
4
+ @data = defaults
5
+ end
6
+
7
+ def set(key, value)
8
+ @data[key] = value
9
+ end
10
+
11
+ def get(key)
12
+ @data[key]
13
+ end
14
+
15
+ def [](key)
16
+ get(key)
17
+ end
18
+ end
19
+ end
@@ -24,3 +24,30 @@ end
24
24
  if Net::HTTP::Revision.to_i == 25851
25
25
  Net::HTTP.send :include, RequestWithSocketCheck
26
26
  end
27
+
28
+
29
+ class Hash
30
+
31
+ # Merges self with another hash, recursively.
32
+ #
33
+ # This code was lovingly stolen from some random gem:
34
+ # http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
35
+ #
36
+ # Thanks to whoever made it.
37
+
38
+ def deep_merge(hash)
39
+ target = dup
40
+
41
+ hash.keys.each do |key|
42
+ if hash[key].is_a? Hash and self[key].is_a? Hash
43
+ target[key] = target[key].deep_merge(hash[key])
44
+ next
45
+ end
46
+
47
+ target[key] = hash[key]
48
+ end
49
+
50
+ target
51
+ end
52
+
53
+ end
@@ -1,269 +1,33 @@
1
- require 'nokogiri'
2
-
3
- require 'icuke/sdk'
4
- require 'icuke/simulator'
5
- require 'icuke/simulate'
6
- require 'icuke/screen'
7
-
8
- class ICukeWorld
9
- include ICuke::Simulate::Gestures
10
-
11
- attr_reader :response, :simulator
12
-
13
- def initialize
14
- @simulator = ICuke::Simulator.new
15
- end
16
-
17
- def launch(application, options = {})
18
- process = ICuke::Simulator::Process.new(application, options)
19
- @simulator.launch(process)
20
- end
21
-
22
- def quit
23
- @simulator.quit
24
- end
25
-
26
- def suspend
27
- @simulator.suspend
28
- end
29
-
30
- def resume
31
- @simulator.resume
32
- end
33
-
34
- def screen
35
- @screen ||= Screen.new(response)
36
- end
37
-
38
- def response
39
- @response ||= @simulator.view
40
- end
41
-
42
- def record
43
- @simulator.record
44
- end
45
-
46
- def tap(label, options = {}, &block)
47
- options = {
48
- :pause => true
49
- }.merge(options)
50
-
51
- element = screen.first_tappable_element(label)
52
- x, y = screen.element_center(element)
53
-
54
- @simulator.fire_event(Tap.new(x, y, options))
55
-
56
- sleep(options[:pause] ? 2 : 0.2)
57
-
58
- refresh
59
-
60
- yield element if block_given?
61
- end
62
-
63
- def swipe(direction, options = {})
64
- x, y, x2, y2 = screen.swipe_coordinates(direction)
65
- @simulator.fire_event(Swipe.new(x, y, x2, y2, 0.015, options))
66
- sleep(1)
67
- refresh
68
- end
69
-
70
- def drag(source_x, source_y, dest_x, dest_y, options = {})
71
- @simulator.fire_event(Drag.new(source_x, source_y, dest_x, dest_y, 0.15, options))
72
- sleep(1)
73
- refresh
74
- end
75
-
76
- def drag_with_source(source, destination)
77
- sources = source.split(',').collect {|val| val.strip.to_i}
78
- destinations = destination.split(',').collect {|val| val.strip.to_i}
79
- drag(sources[0], sources[1], destinations[0], destinations[1])
80
- end
81
-
82
- def drag_slider_to(label, direction, distance)
83
- element = screen.first_slider_element(label)
84
- x, y = screen.find_slider_button(element)
85
-
86
- dest_x, dest_y = x, y
87
- modifier = direction_modifier(direction)
88
-
89
- if [:up, :down].include?(direction)
90
- dest_y += modifier * distance
91
- else
92
- dest_x += modifier * distance
93
- end
94
-
95
- drag(x, y, dest_x, dest_y)
96
- end
97
-
98
- def drag_slider_to_percentage(label, percentage)
99
- element = screen.first_slider_element(label)
100
- x, y = screen.find_slider_button(element)
101
- dest_x, dest_y = screen.find_slider_percentage_location(element, percentage)
102
- drag(x, y, dest_x, dest_y)
103
- end
104
-
105
- def type(textfield, text, options = {})
106
- tap(textfield, :hold_for => 0.75) do |field|
107
- if field['value']
108
- tap('Select All')
109
- tap('Delete')
110
- end
111
- end
112
-
113
- # Without this sleep fields which have auto-capitilisation/correction can
114
- # miss the first keystroke for some reason.
115
- sleep(0.5)
116
-
117
- text.split('').each do |c|
118
- begin
119
- tap(c == ' ' ? 'space' : c, :pause => false)
120
- rescue Exception => e
121
- try_keyboards =
122
- case c
123
- when /[a-zA-Z]/
124
- ['more, letters', 'shift']
125
- when /[0-9]/
126
- ['more, numbers']
127
- else
128
- ['more, numbers', 'more, symbols']
129
- end
130
- until try_keyboards.empty?
131
- begin
132
- tap(try_keyboards.shift, :pause => false)
133
- retry
134
- rescue
135
- end
136
- end
137
- raise e
1
+ require 'icuke/icuke_world'
2
+
3
+ module ICukeWorld
4
+
5
+ # Blatantly ripped from Capybara: (http://github.com/jnicklas/capybara)
6
+ #
7
+ # This block rewrites each of the driver methods in ICukeWorld to make
8
+ # them available as "bare" methods on the World object.
9
+ #
10
+ # icuke_driver.screen becomes #screen, for example. icuke_driver.tap
11
+ # becomes #tap.
12
+ #
13
+ # Obviously this is just syntactic sugar, but isn't that what makes life
14
+ # worth living?
15
+ #
16
+ # The trap with this is that some of the methods produced by this
17
+ # rewriting may conflict with other methods that are already in the World
18
+ # object. For example, there is a #drag method added by Capybara that
19
+ # conflicts with the #drag method in ICukeWorld.
20
+ #
21
+ # If you're stuck with this conflict, require 'icuke/cucumber_compat'
22
+ # instead of 'icuke/cucumber' to get the methods still scoped to an
23
+ # icuke_driver object.
24
+ #
25
+ ICuke::SimulatorDriver::DSL_METHODS.each do |method|
26
+ class_eval %Q{
27
+ def #{method}(*args, &block)
28
+ icuke_driver.#{method}(*args, &block)
138
29
  end
139
- end
140
-
141
- # From UIReturnKeyType
142
- # Should probably sort these in rough order of likelyhood?
143
- return_keys = ['return', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency call']
144
- return_keys.each do |key|
145
- begin
146
- tap(key)
147
- return
148
- rescue
149
- end
150
- end
151
- end
152
-
153
- def scroll_to(text, options = {})
154
- x, y, x2, y2 = screen.swipe_coordinates(swipe_direction(options[:direction]))
155
- previous_response = response.dup
156
- until screen.visible?(text) do
157
- @simulator.fire_event(Swipe.new(x, y, x2, y2, 0.15, options))
158
- refresh
159
- raise %Q{Content "#{text}" not found in: #{screen}} if response == previous_response
160
- end
161
- end
162
-
163
- def scroll(direction)
164
- swipe(swipe_direction(direction))
30
+ }, __FILE__, __LINE__
165
31
  end
166
-
167
- def set_application_defaults(defaults)
168
- @simulator.set_defaults(defaults)
169
- end
170
-
171
- private
172
-
173
- def refresh
174
- @response = nil
175
- @screen = nil
176
- end
177
-
178
- def swipe_direction(direction)
179
- swipe_directions = { :up => :down, :down => :up, :left => :right, :right => :left }
180
- swipe_directions[direction]
181
- end
182
-
183
- def direction_modifier(direction)
184
- [:up, :left].include?(direction) ? -1 : 1
185
- end
186
-
187
- end
188
-
189
- World do
190
- ICukeWorld.new
191
- end
192
-
193
- After do
194
- quit
195
- end
196
-
197
- Given /^(?:"([^\"]*)" from )?"([^\"]*)" is loaded in the (?:(iphone|ipad) )?simulator(?: with SDK ([0-9.]+))?$/ do |target, project, platform, sdk_version|
198
- if sdk_version
199
- ICuke::SDK.use(sdk_version)
200
- elsif platform
201
- ICuke::SDK.use_latest(platform.downcase.to_sym)
202
- else
203
- ICuke::SDK.use_latest
204
- end
205
-
206
- launch File.expand_path(project),
207
- :target => target,
208
- :platform => platform,
209
- :env => {
210
- 'DYLD_INSERT_LIBRARIES' => ICuke::SDK.dylib_fullpath
211
- }
212
- end
213
-
214
- Given /^the module "([^\"]*)" is loaded in the simulator$/ do |path|
215
- path.sub!(/#{File.basename(path)}$/, ICuke::SDK.dylib(File.basename(path)))
216
- simulator.load_module(File.expand_path(path))
217
- end
218
-
219
- Then /^I should see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, scope|
220
- raise %Q{Content "#{text}" not found in: #{screen.xml}} unless screen.visible?(text, scope)
221
- end
222
-
223
- Then /^I should not see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, scope|
224
- raise %Q{Content "#{text}" was found but was not expected in: #{screen.xml}} if screen.visible?(text, scope)
225
- end
226
-
227
- When /^I tap "([^\"]*)"$/ do |label|
228
- tap(label)
229
- end
230
-
231
- When /^I type "([^\"]*)" in "([^\"]*)"$/ do |text, textfield|
232
- type(textfield, text)
233
- end
234
-
235
- When /^I drag from (.*) to (.*)$/ do |source, destination|
236
- drag_with_source(source, destination)
237
- end
238
-
239
- When /^I select the "(.*)" slider and drag (.*) pixels (down|up|left|right)$/ do |label, distance, direction|
240
- drag_slider_to(label, direction.to_sym, distance.to_i)
241
- end
242
-
243
- When /^I move the "([^\"]*)" slider to (.*) percent$/ do |label, percent|
244
- drag_slider_to_percentage(label, percent.to_i)
245
- end
246
-
247
- When /^I scroll (down|up|left|right)(?: to "([^\"]*)")?$/ do |direction, text|
248
- if text
249
- scroll_to(text, :direction => direction.to_sym)
250
- else
251
- scroll(direction.to_sym)
252
- end
253
- end
254
-
255
- When /^I suspend the application/ do
256
- suspend
257
- end
258
-
259
- When /^I resume the application/ do
260
- resume
261
- end
262
-
263
- Then /^I put the phone into recording mode$/ do
264
- record
265
- end
266
32
 
267
- Then /^show me the screen$/ do
268
- puts screen.xml.to_s
269
33
  end
@@ -0,0 +1,4 @@
1
+ # This file is just a stub to allow us to provide different methods
2
+ # by requiring icuke/cucumber_compat or icuke/cucumber. See the README
3
+ # and icuke/cucumber.rb for the rationale for that.
4
+ require 'icuke/icuke_world'
@@ -0,0 +1,149 @@
1
+ require 'nokogiri'
2
+
3
+ require 'icuke/sdk'
4
+ require 'icuke/simulator_driver'
5
+
6
+ module ICukeWorld
7
+ def icuke_driver
8
+ @icuke_driver ||= ICuke::SimulatorDriver.default_driver(icuke_configuration)
9
+ end
10
+
11
+ def icuke_configuration
12
+ @icuke_configuration ||= ICuke::Configuration.new({
13
+ :build_configuration => 'Debug'
14
+ })
15
+ end
16
+ end
17
+
18
+ After do
19
+ icuke_driver.quit
20
+ end
21
+
22
+ ##
23
+ # :section: Loading the iOS Application
24
+ #
25
+ # Launching the application is the most difficult part. Many parts can be
26
+ # omitted, but the full form looks like this:
27
+ #
28
+ # Given "iCuke" from "app/iCuke/iCuke.xcodeproj" with build configuration "Debug" is loaded in the retina iphone simulator with SDK 4.1
29
+ #
30
+ # In this case:
31
+ # * "iCuke" is the name of the app to load.
32
+ # * "app/iCuke/iCuke.xcodeproj" is the path to the Xcode project.
33
+ # * "Debug" specifies the build configuration. "Debug" is used if not
34
+ # specified.
35
+ # * "retina" or "non-retina" can optionally be specified. If specified, the
36
+ # simulator is configured for retina or non-retina version of the device
37
+ # before launching the application. If not specified, the simulator
38
+ # chooses, which means that it will run with the last selected resolution.
39
+ # * "iphone" or "ipad" selects the device type. "iphone" is the default.
40
+ # * The optional clause "with SDK 4.0" selects the version of the simulator
41
+ # used. The iPhone simulator for that version of the SDK must be installed.
42
+ #
43
+ Given /^(?:"([^\"]*)" from )?"([^\"]*)"(?: with build configuration "([^\"]*)")? is loaded in the (?:(retina|non-retina) )?(?:(iphone|ipad) )?simulator(?: with SDK ([0-9.]+))?$/ do |target, project, configuration, retina, platform, sdk_version|
44
+ if sdk_version
45
+ ICuke::SDK.use(sdk_version)
46
+ elsif platform
47
+ ICuke::SDK.use_latest(platform.downcase.to_sym)
48
+ else
49
+ ICuke::SDK.use_latest
50
+ end
51
+ attrs = { :target => target,
52
+ :platform => platform,
53
+ :env => {
54
+ 'DYLD_INSERT_LIBRARIES' => ICuke::SDK.dylib_fullpath
55
+ }
56
+ }
57
+ attrs.merge!(:retina => !(retina =~ /non/)) if retina
58
+ attrs.merge!(:build_configuration => configuration) if configuration
59
+ icuke_driver.launch(File.expand_path(project), attrs)
60
+ end
61
+
62
+ Given /^the module "([^\"]*)" is loaded in the simulator$/ do |path|
63
+ path.sub!(/#{File.basename(path)}$/, ICuke::SDK.dylib(File.basename(path)))
64
+ simulator.load_module(File.expand_path(path))
65
+ end
66
+
67
+ ##
68
+ # :section: Seeing What's on the Screen
69
+ #
70
+ # The two following rules detect accessibility text on the screen:
71
+ #
72
+ # Then I should see "some text" within "some scope"
73
+ # Then I should not see "some text" within "some scope"
74
+ #
75
+ Then /^I should see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, scope|
76
+ raise %Q{Content "#{text}" not found in: #{screen.xml}} unless icuke_driver.screen.visible?(text, scope)
77
+ end
78
+
79
+ Then /^I should not see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, scope|
80
+ raise %Q{Content "#{text}" was found but was not expected in: #{screen.xml}} if icuke_driver.screen.visible?(text, scope)
81
+ end
82
+
83
+ ##
84
+ # :section: Sending Input to the App
85
+ #
86
+ # The following rules are available:
87
+ #
88
+ # When I tap "some label"
89
+ # When I type "some text" in "some field label"
90
+ # When I drag from <source> to <destination>
91
+ # When I select the "some label" slider and drag <distance> pixels <direction>
92
+ # When I move the "label" slider to <n> percent
93
+ # When I scroll <direction> to "some text"
94
+ # When I suspend the application
95
+ # When I resume the application
96
+ #
97
+ When /^I tap "([^\"]*)"$/ do |label|
98
+ icuke_driver.tap(label)
99
+ end
100
+
101
+ When /^I type "([^\"]*)" in "([^\"]*)"$/ do |text, textfield|
102
+ icuke_driver.type(textfield, text)
103
+ end
104
+
105
+ When /^I drag from (.*) to (.*)$/ do |source, destination|
106
+ icuke_driver.drag_with_source(source, destination)
107
+ end
108
+
109
+ When /^I select the "(.*)" slider and drag (.*) pixels (down|up|left|right)$/ do |label, distance, direction|
110
+ icuke_driver.drag_slider_to(label, direction.to_sym, distance.to_i)
111
+ end
112
+
113
+ When /^I move the "([^\"]*)" slider to (.*) percent$/ do |label, percent|
114
+ icuke_driver.drag_slider_to_percentage(label, percent.to_i)
115
+ end
116
+
117
+ When /^I scroll (down|up|left|right)(?: to "([^\"]*)")?$/ do |direction, text|
118
+ if text
119
+ icuke_driver.scroll_to(text, :direction => direction.to_sym)
120
+ else
121
+ icuke_driver.scroll(direction.to_sym)
122
+ end
123
+ end
124
+
125
+ When /^I suspend the application/ do
126
+ icuke_driver.suspend
127
+ end
128
+
129
+ When /^I resume the application/ do
130
+ icuke_driver.resume
131
+ end
132
+
133
+ ##
134
+ # :section: Debugging Tools
135
+ #
136
+ # Then I put the phone into recording mode
137
+ #
138
+ # Then show me the screen
139
+ #
140
+ # "show me the screen" is the quintessential step used for debugging tests. It dumps
141
+ # the raw XML received from the iOS app.
142
+ #
143
+ Then /^I put the phone into recording mode$/ do
144
+ icuke_driver.record
145
+ end
146
+
147
+ Then /^show me the screen$/ do
148
+ puts icuke_driver.screen.xml.to_s
149
+ end