iCuke 0.6.3 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +1 -1
- data/Gemfile +12 -0
- data/Gemfile.lock +41 -0
- data/README.markdown +126 -0
- data/Rakefile +34 -12
- data/VERSION +1 -1
- data/bin/icuke +12 -10
- data/ext/Rakefile +6 -0
- data/ext/iCuke/{sdk3.1/DefaultsResponse.h → DefaultsResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/DefaultsResponse.m → DefaultsResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/EventResponse.h → EventResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/EventResponse.m → EventResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/ModuleResponse.h → ModuleResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/ModuleResponse.m → ModuleResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/QuitResponse.h → QuitResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/QuitResponse.m → QuitResponse.m} +0 -0
- data/ext/iCuke/Rakefile +14 -13
- data/ext/iCuke/{sdk3.1/Recorder.h → Recorder.h} +0 -0
- data/ext/iCuke/{sdk3.1/Recorder.m → Recorder.m} +0 -0
- data/ext/iCuke/{sdk3.1/RecorderResponse.h → RecorderResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/RecorderResponse.m → RecorderResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/SynthesizeSingleton.h → SynthesizeSingleton.h} +0 -0
- data/ext/iCuke/{sdk3.1/ViewResponse.h → ViewResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/ViewResponse.m → ViewResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/Viewer.h → Viewer.h} +0 -0
- data/ext/iCuke/{sdk4.0/Viewer.m → Viewer.m} +0 -0
- data/ext/iCuke/{sdk3.1/iCukeHTTPResponseHandler.h → iCukeHTTPResponseHandler.h} +0 -0
- data/ext/iCuke/{sdk3.1/iCukeHTTPResponseHandler.m → iCukeHTTPResponseHandler.m} +0 -0
- data/ext/iCuke/{sdk3.1/iCukeHTTPServer.h → iCukeHTTPServer.h} +0 -0
- data/ext/iCuke/{sdk4.0/iCukeHTTPServer.m → iCukeHTTPServer.m} +4 -2
- data/ext/iCuke/{sdk3.1/iCukeServer.h → iCukeServer.h} +0 -0
- data/ext/iCuke/{sdk3.1/iCukeServer.m → iCukeServer.m} +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/JSON.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/NSObject+SBJSON.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/NSObject+SBJSON.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/NSString+SBJSON.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/NSString+SBJSON.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJSON.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJSON.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonBase.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonBase.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonParser.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonParser.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonWriter.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonWriter.m +0 -0
- data/features/starting_project.feature +18 -0
- data/features/step_definitions/shell.rb +41 -0
- data/features/support/env.rb +2 -0
- data/features/support/environment.rb +40 -0
- data/features/supported_sdks.feature +12 -0
- data/iCuke.gemspec +149 -161
- data/lib/icuke/configuration.rb +19 -0
- data/lib/icuke/core_ext.rb +27 -0
- data/lib/icuke/cucumber.rb +29 -265
- data/lib/icuke/cucumber_compat.rb +4 -0
- data/lib/icuke/icuke_world.rb +149 -0
- data/lib/icuke/sdk.rb +5 -13
- data/lib/icuke/simulator_driver.rb +201 -0
- data/lib/icuke/waxsim.rb +47 -9
- data/spec/cucumber_spec.rb +130 -0
- data/spec/fixtures/controls_page.xml +252 -0
- data/spec/process_spec.rb +76 -0
- data/spec/screen_spec.rb +173 -0
- data/spec/simulate_spec.rb +75 -0
- data/spec/simulator_spec.rb +28 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +67 -0
- metadata +222 -121
- data/.gitignore +0 -15
- data/README.rdoc +0 -68
- data/ext/WaxSim/Simulator.h +0 -31
- data/ext/WaxSim/Simulator.m +0 -131
- data/ext/WaxSim/WaxSim.m +0 -110
- data/ext/WaxSim/WaxSim.xcodeproj/project.pbxproj +0 -238
- data/ext/WaxSim/WaxSim_Prefix.pch +0 -7
- data/ext/WaxSim/build/Release/waxsim +0 -0
- data/ext/WaxSim/build/Release/waxsim.dSYM/Contents/Info.plist +0 -20
- data/ext/WaxSim/build/Release/waxsim.dSYM/Contents/Resources/DWARF/waxsim +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/Simulator.o +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/WaxSim.o +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/waxsim.LinkFileList +0 -2
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/WaxSim.dep +0 -6
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/WaxSim~.dep +0 -6
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/build-state.dat +0 -227
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/build-state~.dat +0 -227
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-all-target-headers.hmap +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-generated-files.hmap +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-own-target-headers.hmap +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-project-headers.hmap +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim.hmap +0 -0
- data/ext/WaxSim/iPhoneSimulatorRemoteClient/iPhoneSimulatorRemoteClient.h +0 -126
- data/ext/iCuke/sdk3.1/Rakefile +0 -20
- data/ext/iCuke/sdk3.1/Viewer.m +0 -203
- data/ext/iCuke/sdk3.1/iCukeHTTPServer.m +0 -365
- data/ext/iCuke/sdk4.0/DefaultsResponse.h +0 -5
- data/ext/iCuke/sdk4.0/DefaultsResponse.m +0 -66
- data/ext/iCuke/sdk4.0/EventResponse.h +0 -5
- data/ext/iCuke/sdk4.0/EventResponse.m +0 -130
- data/ext/iCuke/sdk4.0/ModuleResponse.h +0 -5
- data/ext/iCuke/sdk4.0/ModuleResponse.m +0 -76
- data/ext/iCuke/sdk4.0/QuitResponse.h +0 -5
- data/ext/iCuke/sdk4.0/QuitResponse.m +0 -23
- data/ext/iCuke/sdk4.0/Rakefile +0 -20
- data/ext/iCuke/sdk4.0/Recorder.h +0 -17
- data/ext/iCuke/sdk4.0/Recorder.m +0 -90
- data/ext/iCuke/sdk4.0/RecorderResponse.h +0 -6
- data/ext/iCuke/sdk4.0/RecorderResponse.m +0 -68
- data/ext/iCuke/sdk4.0/SynthesizeSingleton.h +0 -68
- data/ext/iCuke/sdk4.0/ViewResponse.h +0 -5
- data/ext/iCuke/sdk4.0/ViewResponse.m +0 -84
- data/ext/iCuke/sdk4.0/Viewer.h +0 -8
- data/ext/iCuke/sdk4.0/iCukeHTTPResponseHandler.h +0 -50
- data/ext/iCuke/sdk4.0/iCukeHTTPResponseHandler.m +0 -381
- data/ext/iCuke/sdk4.0/iCukeHTTPServer.h +0 -53
- data/ext/iCuke/sdk4.0/iCukeServer.h +0 -14
- data/ext/iCuke/sdk4.0/iCukeServer.m +0 -65
- data/ext/iCuke/sdk4.0/json/JSON.h +0 -50
- data/ext/iCuke/sdk4.0/json/NSObject+SBJSON.h +0 -68
- data/ext/iCuke/sdk4.0/json/NSObject+SBJSON.m +0 -53
- data/ext/iCuke/sdk4.0/json/NSString+SBJSON.h +0 -58
- data/ext/iCuke/sdk4.0/json/NSString+SBJSON.m +0 -55
- data/ext/iCuke/sdk4.0/json/SBJSON.h +0 -75
- data/ext/iCuke/sdk4.0/json/SBJSON.m +0 -212
- data/ext/iCuke/sdk4.0/json/SBJsonBase.h +0 -86
- data/ext/iCuke/sdk4.0/json/SBJsonBase.m +0 -78
- data/ext/iCuke/sdk4.0/json/SBJsonParser.h +0 -87
- data/ext/iCuke/sdk4.0/json/SBJsonParser.m +0 -475
- data/ext/iCuke/sdk4.0/json/SBJsonWriter.h +0 -129
- data/ext/iCuke/sdk4.0/json/SBJsonWriter.m +0 -228
data/lib/icuke/core_ext.rb
CHANGED
@@ -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
|
data/lib/icuke/cucumber.rb
CHANGED
@@ -1,269 +1,33 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
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,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
|