iCuke 0.6.3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|