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/sdk.rb
CHANGED
|
@@ -6,7 +6,7 @@ module ICuke
|
|
|
6
6
|
|
|
7
7
|
def self.all
|
|
8
8
|
@all ||= begin
|
|
9
|
-
`xcodebuild -showsdks`.grep(/iphonesimulator/).map do |s|
|
|
9
|
+
`xcodebuild -showsdks`.split(/\n/).grep(/iphonesimulator/).map do |s|
|
|
10
10
|
s.sub(/.* iphonesimulator([0-9.]+).*/, '\1').chomp
|
|
11
11
|
end.sort
|
|
12
12
|
end
|
|
@@ -83,14 +83,10 @@ module ICuke
|
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def self.dylib(name = 'libicuke')
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"#{name}-sdk#{minor_version}.dylib"
|
|
86
|
+
"#{name}.dylib"
|
|
89
87
|
end
|
|
90
88
|
|
|
91
89
|
def self.dylib_fullpath(name = 'libicuke')
|
|
92
|
-
require_sdk
|
|
93
|
-
|
|
94
90
|
File.join(ICUKE_EXT_DIR, dylib(name))
|
|
95
91
|
end
|
|
96
92
|
|
|
@@ -98,26 +94,22 @@ module ICuke
|
|
|
98
94
|
ICUKE_EXT_DIR
|
|
99
95
|
end
|
|
100
96
|
|
|
101
|
-
def self.sdk_ext_dir
|
|
102
|
-
File.join(ext_dir, "sdk#{minor_version}")
|
|
103
|
-
end
|
|
104
|
-
|
|
105
97
|
def self.cflags
|
|
106
|
-
"#{CFLAGS} -isysroot #{root} -F/System/Library/PrivateFrameworks -D__IPHONE_OS_VERSION_MIN_REQUIRED
|
|
98
|
+
"#{CFLAGS} -isysroot #{root} -F/System/Library/PrivateFrameworks -D__IPHONE_OS_VERSION_MIN_REQUIRED=30000"
|
|
107
99
|
end
|
|
108
100
|
|
|
109
101
|
def self.gcc
|
|
110
102
|
if major_version == '4'
|
|
111
103
|
abi_flags = "-fobjc-abi-version=2 -fobjc-legacy-dispatch"
|
|
112
104
|
end
|
|
113
|
-
"xcrun -sdk #{fullname} gcc -I. -I#{
|
|
105
|
+
"xcrun -sdk #{fullname} gcc -I. -I#{ext_dir} -I#{ext_dir}/json #{cflags} -x objective-c #{abi_flags}"
|
|
114
106
|
end
|
|
115
107
|
|
|
116
108
|
def self.ld
|
|
117
109
|
if major_version == '4'
|
|
118
110
|
abi_flags = "-Xlinker -objc_abi_version -Xlinker 2"
|
|
119
111
|
end
|
|
120
|
-
"xcrun -sdk #{fullname} gcc -I. -I#{
|
|
112
|
+
"xcrun -sdk #{fullname} gcc -I. -I#{ext_dir} -I#{ext_dir}/json #{cflags} #{abi_flags}"
|
|
121
113
|
end
|
|
122
114
|
|
|
123
115
|
def self.launch(application, family, environment = {})
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
require 'icuke/simulator'
|
|
2
|
+
require 'icuke/simulate'
|
|
3
|
+
require 'icuke/screen'
|
|
4
|
+
require 'icuke/configuration'
|
|
5
|
+
|
|
6
|
+
module ICuke
|
|
7
|
+
class SimulatorDriver
|
|
8
|
+
|
|
9
|
+
DSL_METHODS = [:launch, :quit, :suspend, :resume, :screen,
|
|
10
|
+
:response, :record, :tap, :swipe, :drag,
|
|
11
|
+
:drag_with_source, :drag_slider_to,
|
|
12
|
+
:drag_slider_to_percentage, :type, :scroll_to,
|
|
13
|
+
:scroll, :set_application_defaults]
|
|
14
|
+
|
|
15
|
+
include ICuke::Simulate::Gestures
|
|
16
|
+
|
|
17
|
+
def initialize(simulator, configuration)
|
|
18
|
+
@simulator = simulator
|
|
19
|
+
@configuration = configuration
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.default_driver(configuration)
|
|
23
|
+
new(ICuke::Simulator.new, configuration)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def launch(application, options = {})
|
|
27
|
+
default_options = {:build_configuration => configuration[:build_configuration]}
|
|
28
|
+
process = ICuke::Simulator::Process.new(application, default_options.merge(options))
|
|
29
|
+
@simulator.launch(process)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def quit
|
|
33
|
+
@simulator.quit
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def suspend
|
|
37
|
+
@simulator.suspend
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def resume
|
|
41
|
+
@simulator.resume
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def screen
|
|
45
|
+
@screen ||= Screen.new(response)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def response
|
|
49
|
+
@response ||= @simulator.view
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def record
|
|
53
|
+
@simulator.record
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def tap(label, options = {}, &block)
|
|
57
|
+
options = {
|
|
58
|
+
:pause => true
|
|
59
|
+
}.merge(options)
|
|
60
|
+
|
|
61
|
+
element = screen.first_tappable_element(label)
|
|
62
|
+
x, y = screen.element_center(element)
|
|
63
|
+
|
|
64
|
+
@simulator.fire_event(Tap.new(x, y, options))
|
|
65
|
+
|
|
66
|
+
sleep(options[:pause] ? 2 : 0.2)
|
|
67
|
+
|
|
68
|
+
refresh
|
|
69
|
+
|
|
70
|
+
yield element if block_given?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def swipe(direction, options = {})
|
|
74
|
+
x, y, x2, y2 = screen.swipe_coordinates(direction)
|
|
75
|
+
@simulator.fire_event(Swipe.new(x, y, x2, y2, 0.015, options))
|
|
76
|
+
sleep(1)
|
|
77
|
+
refresh
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def drag(source_x, source_y, dest_x, dest_y, options = {})
|
|
81
|
+
@simulator.fire_event(Drag.new(source_x, source_y, dest_x, dest_y, 0.15, options))
|
|
82
|
+
sleep(1)
|
|
83
|
+
refresh
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def drag_with_source(source, destination)
|
|
87
|
+
sources = source.split(',').collect {|val| val.strip.to_i}
|
|
88
|
+
destinations = destination.split(',').collect {|val| val.strip.to_i}
|
|
89
|
+
drag(sources[0], sources[1], destinations[0], destinations[1])
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def drag_slider_to(label, direction, distance)
|
|
93
|
+
element = screen.first_slider_element(label)
|
|
94
|
+
x, y = screen.find_slider_button(element)
|
|
95
|
+
|
|
96
|
+
dest_x, dest_y = x, y
|
|
97
|
+
modifier = direction_modifier(direction)
|
|
98
|
+
|
|
99
|
+
if [:up, :down].include?(direction)
|
|
100
|
+
dest_y += modifier * distance
|
|
101
|
+
else
|
|
102
|
+
dest_x += modifier * distance
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
drag(x, y, dest_x, dest_y)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def drag_slider_to_percentage(label, percentage)
|
|
109
|
+
element = screen.first_slider_element(label)
|
|
110
|
+
x, y = screen.find_slider_button(element)
|
|
111
|
+
dest_x, dest_y = screen.find_slider_percentage_location(element, percentage)
|
|
112
|
+
drag(x, y, dest_x, dest_y)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def type(textfield, text, options = {})
|
|
116
|
+
tap(textfield, :hold_for => 0.75) do |field|
|
|
117
|
+
if field['value']
|
|
118
|
+
tap('Select All')
|
|
119
|
+
tap('Delete')
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Without this sleep fields which have auto-capitilisation/correction can
|
|
124
|
+
# miss the first keystroke for some reason.
|
|
125
|
+
sleep(0.5)
|
|
126
|
+
|
|
127
|
+
text.split('').each do |c|
|
|
128
|
+
begin
|
|
129
|
+
tap(c == ' ' ? 'space' : c, :pause => false)
|
|
130
|
+
rescue Exception => e
|
|
131
|
+
try_keyboards =
|
|
132
|
+
case c
|
|
133
|
+
when /[a-zA-Z]/
|
|
134
|
+
['more, letters', 'shift']
|
|
135
|
+
when /[0-9]/
|
|
136
|
+
['more, numbers']
|
|
137
|
+
else
|
|
138
|
+
['more, numbers', 'more, symbols']
|
|
139
|
+
end
|
|
140
|
+
until try_keyboards.empty?
|
|
141
|
+
begin
|
|
142
|
+
tap(try_keyboards.shift, :pause => false)
|
|
143
|
+
retry
|
|
144
|
+
rescue
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
raise e
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# From UIReturnKeyType
|
|
152
|
+
# Should probably sort these in rough order of likelyhood?
|
|
153
|
+
return_keys = ['return', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency call']
|
|
154
|
+
return_keys.each do |key|
|
|
155
|
+
begin
|
|
156
|
+
tap(key)
|
|
157
|
+
return
|
|
158
|
+
rescue
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def scroll_to(text, options = {})
|
|
164
|
+
x, y, x2, y2 = screen.swipe_coordinates(swipe_direction(options[:direction]))
|
|
165
|
+
previous_response = response.dup
|
|
166
|
+
until screen.visible?(text) do
|
|
167
|
+
@simulator.fire_event(Swipe.new(x, y, x2, y2, 0.15, options))
|
|
168
|
+
refresh
|
|
169
|
+
raise %Q{Content "#{text}" not found in: #{screen}} if response == previous_response
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def scroll(direction)
|
|
174
|
+
swipe(swipe_direction(direction))
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def set_application_defaults(defaults)
|
|
178
|
+
@simulator.set_defaults(defaults)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def refresh
|
|
182
|
+
@response = nil
|
|
183
|
+
@screen = nil
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
private
|
|
187
|
+
|
|
188
|
+
def swipe_direction(direction)
|
|
189
|
+
swipe_directions = { :up => :down, :down => :up, :left => :right, :right => :left }
|
|
190
|
+
swipe_directions[direction]
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def direction_modifier(direction)
|
|
194
|
+
[:up, :left].include?(direction) ? -1 : 1
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def configuration
|
|
198
|
+
@configuration
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
data/lib/icuke/waxsim.rb
CHANGED
|
@@ -6,14 +6,19 @@ module ICuke
|
|
|
6
6
|
include Timeout
|
|
7
7
|
|
|
8
8
|
attr_accessor :current_process
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
def launch(process)
|
|
11
|
-
process = process.
|
|
12
|
-
:configuration => 'Debug',
|
|
11
|
+
process = process.with_launch_options({
|
|
13
12
|
:env => {
|
|
14
13
|
'CFFIXED_USER_HOME' => Dir.mktmpdir
|
|
15
14
|
}
|
|
16
15
|
})
|
|
16
|
+
|
|
17
|
+
process.setup_commands.each do |cmd|
|
|
18
|
+
fail "Unable to run setup command #{cmd}" if !system(cmd)
|
|
19
|
+
fail "Setup command #{cmd} failed with exit status #{$?}" if $? != 0
|
|
20
|
+
end
|
|
21
|
+
|
|
17
22
|
@simulator = BackgroundProcess.run(process.command)
|
|
18
23
|
self.current_process = process
|
|
19
24
|
|
|
@@ -28,6 +33,7 @@ module ICuke
|
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
def quit
|
|
36
|
+
return unless @simulator
|
|
31
37
|
get '/quit' rescue nil # results in a hard exit(0)
|
|
32
38
|
@simulator.wait
|
|
33
39
|
self.current_process = nil
|
|
@@ -44,28 +50,60 @@ module ICuke
|
|
|
44
50
|
end
|
|
45
51
|
|
|
46
52
|
class Process
|
|
53
|
+
DEFAULT_CONFIGURATION = 'Debug'
|
|
54
|
+
|
|
55
|
+
attr_reader :launch_options
|
|
56
|
+
|
|
47
57
|
def initialize(project_file, launch_options = {})
|
|
48
58
|
@project_file = project_file
|
|
49
59
|
@launch_options = launch_options
|
|
50
60
|
end
|
|
51
61
|
|
|
52
62
|
# returns a new Process, treat Process as an immutable value object
|
|
53
|
-
def
|
|
54
|
-
self.class.new(@project_file,
|
|
63
|
+
def with_launch_options(options = {})
|
|
64
|
+
self.class.new(@project_file, @launch_options.deep_merge(options))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def setup_commands
|
|
68
|
+
cmds = []
|
|
69
|
+
cmds << simulate_device_command if @launch_options.has_key?(:retina)
|
|
70
|
+
cmds
|
|
55
71
|
end
|
|
56
72
|
|
|
57
73
|
def command
|
|
58
|
-
ICuke::SDK.launch("#{directory}/#{
|
|
74
|
+
ICuke::SDK.launch("#{directory}/#{target}.app", @launch_options[:platform], @launch_options[:env])
|
|
59
75
|
end
|
|
60
76
|
|
|
61
77
|
private
|
|
78
|
+
|
|
79
|
+
def simulate_device_command
|
|
80
|
+
"defaults write com.apple.iphonesimulator SimulateDevice '\"#{simulate_device}\"'"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def simulate_device
|
|
84
|
+
case @launch_options[:platform]
|
|
85
|
+
when :ipad
|
|
86
|
+
"iPad"
|
|
87
|
+
else
|
|
88
|
+
"iPhone"
|
|
89
|
+
end +
|
|
90
|
+
if @launch_options[:retina]
|
|
91
|
+
" (Retina)"
|
|
92
|
+
else
|
|
93
|
+
""
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def target
|
|
98
|
+
@launch_options[:target] || File.basename(@project_file, '.xcodeproj')
|
|
99
|
+
end
|
|
62
100
|
|
|
63
|
-
def
|
|
64
|
-
|
|
101
|
+
def build_configuration
|
|
102
|
+
@launch_options[:build_configuration] || DEFAULT_CONFIGURATION
|
|
65
103
|
end
|
|
66
104
|
|
|
67
105
|
def directory
|
|
68
|
-
"#{File.dirname(@project_file)}/build/#{
|
|
106
|
+
"#{File.dirname(@project_file)}/build/#{build_configuration}-iphonesimulator"
|
|
69
107
|
end
|
|
70
108
|
end
|
|
71
109
|
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require 'spec/spec_helper'
|
|
2
|
+
require 'icuke'
|
|
3
|
+
require 'cucumber/step_mother'
|
|
4
|
+
require 'icuke/cucumber'
|
|
5
|
+
require 'icuke/simulate'
|
|
6
|
+
|
|
7
|
+
describe ICukeWorld do
|
|
8
|
+
|
|
9
|
+
before(:each) do
|
|
10
|
+
@simulator = []
|
|
11
|
+
@simulator.stub(:view)
|
|
12
|
+
@simulator.stub(:fire_event)
|
|
13
|
+
@cuke_world = ICuke::SimulatorDriver.new @simulator, ICuke::Configuration.new({
|
|
14
|
+
:build_configuration => 'Debug'
|
|
15
|
+
})
|
|
16
|
+
@cuke_world.stub!(:sleep)
|
|
17
|
+
|
|
18
|
+
xml = File.read('spec/fixtures/controls_page.xml')
|
|
19
|
+
@cuke_world.stub(:response).and_return(xml)
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "when performing a swipe" do
|
|
24
|
+
|
|
25
|
+
before(:each) do
|
|
26
|
+
@simulator.should_receive(:fire_event)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should begin swipe at center of screen" do
|
|
30
|
+
center_x, center_y = 160, 240
|
|
31
|
+
ICuke::Simulate::Gestures::Swipe.should_receive(:new).
|
|
32
|
+
with(center_x, center_y, 160, 480, 0.015, {})
|
|
33
|
+
@cuke_world.swipe(:down)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should swipe to the bottom of the screen when swiping down" do
|
|
37
|
+
bottom_y = 480
|
|
38
|
+
ICuke::Simulate::Gestures::Swipe.should_receive(:new).
|
|
39
|
+
with(160, 240, 160, bottom_y, 0.015, {})
|
|
40
|
+
@cuke_world.swipe(:down)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should swipe to the top of the screen when swiping up" do
|
|
44
|
+
top_y = 0
|
|
45
|
+
ICuke::Simulate::Gestures::Swipe.should_receive(:new).
|
|
46
|
+
with(160, 240, 160, top_y, 0.015, {})
|
|
47
|
+
@cuke_world.swipe(:up)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should swipe to the left of the screen when swipping left" do
|
|
51
|
+
min_x = 0
|
|
52
|
+
ICuke::Simulate::Gestures::Swipe.should_receive(:new).
|
|
53
|
+
with(160, 240, min_x, 240, 0.015, {})
|
|
54
|
+
@cuke_world.swipe(:left)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should swipe to the right of the screen when swipping right" do
|
|
58
|
+
max_x = 320
|
|
59
|
+
ICuke::Simulate::Gestures::Swipe.should_receive(:new).
|
|
60
|
+
with(160, 240, max_x, 240, 0.015, {})
|
|
61
|
+
@cuke_world.swipe(:right)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context "when performing a drag" do
|
|
67
|
+
|
|
68
|
+
it "should fire an event" do
|
|
69
|
+
@simulator.should_receive(:fire_event)
|
|
70
|
+
@cuke_world.drag(1,2,3,4,{})
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should simulate a swipe from source to destination" do
|
|
74
|
+
sx, sy, dx, dy = 10, 20, 30, 40
|
|
75
|
+
ICuke::Simulate::Gestures::Drag.should_receive(:new).
|
|
76
|
+
with(sx, sy, dx, dy, 0.15, {})
|
|
77
|
+
@cuke_world.drag(sx, sy, dx, dy, {})
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "when performing a drag with a source" do
|
|
83
|
+
|
|
84
|
+
it "should parse the input values" do
|
|
85
|
+
ICuke::Simulate::Gestures::Drag.should_receive(:new).
|
|
86
|
+
with(12, 24, 34, 44, 0.15, {})
|
|
87
|
+
@cuke_world.drag_with_source("12,24", "34,44")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "when draging a slider" do
|
|
93
|
+
|
|
94
|
+
before(:each) do
|
|
95
|
+
@screen = []
|
|
96
|
+
@screen.should_receive(:first_slider_element).at_least(:once)
|
|
97
|
+
@screen.should_receive(:find_slider_button).at_least(:once).and_return([244, 287])
|
|
98
|
+
Screen.should_receive(:new).at_least(:once).and_return(@screen)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "should set the destination properly" do
|
|
102
|
+
{:up=>[244,267], :down=>[244,307], :right=>[264,287], :left=>[224,287]}.each do |d|
|
|
103
|
+
ICuke::Simulate::Gestures::Drag.should_receive(:new).
|
|
104
|
+
with(244, 287, d[1][0], d[1][1], 0.15, {})
|
|
105
|
+
@cuke_world.drag_slider_to('Label', d[0], 20)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context "when draging a slider to a percentage value" do
|
|
112
|
+
|
|
113
|
+
before(:each) do
|
|
114
|
+
@element = []
|
|
115
|
+
@screen = []
|
|
116
|
+
@screen.should_receive(:first_slider_element).and_return(@element)
|
|
117
|
+
@screen.should_receive(:find_slider_button).and_return([244, 287])
|
|
118
|
+
Screen.should_receive(:new).and_return(@screen)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "should identify the destination on the screen" do
|
|
122
|
+
@screen.should_receive(:find_slider_percentage_location).with(@element, 30).
|
|
123
|
+
and_return([230, 287])
|
|
124
|
+
ICuke::Simulate::Gestures::Drag.should_receive(:new).
|
|
125
|
+
with(244, 287, 230, 287, 0.15, {})
|
|
126
|
+
@cuke_world.drag_slider_to_percentage("label", 30)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
end
|