testautoi 0.9.127 → 0.9.133
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/CalabashSetup +0 -0
- data/bin/GetIPAddress.js +5 -0
- data/bin/LaunchApp.js +5 -0
- data/bin/calabash-ios-build.rb +7 -21
- data/bin/calabash-ios-generate.rb +0 -3
- data/bin/calabash-ios-setup.rb +11 -14
- data/bin/devicedetect +0 -0
- data/bin/fruitstrap +0 -0
- data/bin/testautoi +643 -0
- data/calabash-cucumber.gemspec +5 -4
- data/features/step_definitions/calabash_steps.rb +16 -4
- data/lib/calabash-cucumber/core.rb +41 -9
- data/lib/calabash-cucumber/version.rb +1 -1
- data/lib/calabash-cucumber/wait_helpers.rb +3 -1
- data/{features-skeleton → scripts}/.irbrc +3 -1
- metadata +172 -144
- data/features-skeleton/irb_ios4.sh +0 -2
- data/features-skeleton/irb_ios5.sh +0 -2
data/bin/CalabashSetup
CHANGED
Binary file
|
data/bin/GetIPAddress.js
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
UIATarget.localTarget().delay(1);
|
2
|
+
var textField = UIATarget.localTarget().frontMostApp().mainWindow().textFields()[1].value();
|
3
|
+
UIATarget.localTarget().host().performTaskWithPathArgumentsTimeout("/usr/bin/sed", ["-i", "", "s/^IPAddress=.*$/IPAddress="+ textField +"/1", "./Device.cfg"], 2);
|
4
|
+
|
5
|
+
|
data/bin/LaunchApp.js
ADDED
data/bin/calabash-ios-build.rb
CHANGED
@@ -44,28 +44,14 @@ def build(options={:build_dir=>"Calabash",
|
|
44
44
|
res
|
45
45
|
end
|
46
46
|
|
47
|
-
def console
|
48
|
-
path =
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
if old_str != new_str
|
53
|
-
puts "Moving old .irbrc file to .irbrc.old"
|
54
|
-
FileUtils.mv(".irbrc", ".irbrc.old")
|
55
|
-
puts "Copying calabash-ios .irbrc file to current directory..."
|
56
|
-
FileUtils.cp(path, ".")
|
57
|
-
end
|
58
|
-
else
|
59
|
-
puts "Copying calabash-ios .irbrc file to current directory..."
|
60
|
-
FileUtils.cp(path, ".")
|
61
|
-
end
|
62
|
-
|
63
|
-
if !File.exists?(options[:script])
|
64
|
-
puts "Copying calabash-ios #{options[:script]} file to current directory..."
|
65
|
-
FileUtils.cp(File.join(@source_dir,options[:script]), ".")
|
47
|
+
def console
|
48
|
+
path = ENV['CALABASH_IRBRC']
|
49
|
+
unless path
|
50
|
+
path = File.expand_path(File.join(@script_dir,".irbrc"))
|
51
|
+
ENV['IRBRC'] = path
|
66
52
|
end
|
67
|
-
puts "Running irb
|
68
|
-
|
53
|
+
puts "Running irb..."
|
54
|
+
exec("irb")
|
69
55
|
end
|
70
56
|
|
71
57
|
|
@@ -13,9 +13,6 @@ def calabash_scaffold
|
|
13
13
|
exit 2 unless STDIN.gets.chomp == ''
|
14
14
|
|
15
15
|
FileUtils.cp_r(@source_dir, @features_dir)
|
16
|
-
FileUtils.mv "#{@features_dir}/.irbrc", "."
|
17
|
-
FileUtils.mv "#{@features_dir}/irb_ios4.sh", "."
|
18
|
-
FileUtils.mv "#{@features_dir}/irb_ios5.sh", "."
|
19
16
|
|
20
17
|
msg("Info") do
|
21
18
|
puts "Features subdirectory created. \n"
|
data/bin/calabash-ios-setup.rb
CHANGED
@@ -174,28 +174,25 @@ def setup_project(project_name, project_path, path)
|
|
174
174
|
exit 1
|
175
175
|
end
|
176
176
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
177
|
+
FileUtils.cd project_path do
|
178
|
+
##Backup
|
179
|
+
if File.exists? "#{proj_file}.bak"
|
180
|
+
msg("Error") do
|
181
|
+
puts "Backup file already exists. #{proj_file}.bak"
|
182
|
+
puts "For safety, I won't overwrite this file."
|
183
|
+
puts "You must manually move this file, if you want to"
|
184
|
+
puts "Run calabash-ios setup again."
|
185
|
+
end
|
186
|
+
exit 1
|
186
187
|
end
|
187
|
-
exit 1
|
188
188
|
end
|
189
189
|
|
190
|
-
|
190
|
+
download_calabash(project_path)
|
191
191
|
|
192
192
|
msg("Info") do
|
193
193
|
puts "Setting up project file for calabash-ios."
|
194
194
|
end
|
195
195
|
|
196
|
-
|
197
|
-
FileUtils.cd pwd
|
198
|
-
|
199
196
|
##Backup
|
200
197
|
msg("Info") do
|
201
198
|
puts "Making backup of project file: #{proj_file}"
|
data/bin/devicedetect
ADDED
Binary file
|
data/bin/fruitstrap
ADDED
Binary file
|
data/bin/testautoi
ADDED
@@ -0,0 +1,643 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'json'
|
5
|
+
require 'tmpdir'
|
6
|
+
require 'zip/zip'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
require File.join(File.dirname(__FILE__),"calabash-ios-sim")
|
10
|
+
|
11
|
+
@settings_file = File.join(FileUtils.pwd, ".testautoi_settings")
|
12
|
+
|
13
|
+
def print_usage
|
14
|
+
puts <<EOF
|
15
|
+
Usage: testautoi <command-name> [parameters] [options]
|
16
|
+
<command-name> can be one of
|
17
|
+
setup
|
18
|
+
Set up test automation configurations
|
19
|
+
run
|
20
|
+
Start test automation
|
21
|
+
build <Source Dir>
|
22
|
+
Build the instrumented app.
|
23
|
+
Use getsource command first to download source to <Source Dir>
|
24
|
+
install
|
25
|
+
Install the app
|
26
|
+
install tools
|
27
|
+
Download and install tools from Subversion.
|
28
|
+
launch
|
29
|
+
Launch the app
|
30
|
+
getip
|
31
|
+
Get the device's IP address
|
32
|
+
gen
|
33
|
+
Generate the skeleton of features directory
|
34
|
+
sim run
|
35
|
+
Start an iOS Simulator
|
36
|
+
sim quit
|
37
|
+
Quit the iOS Simulator
|
38
|
+
devices
|
39
|
+
List connected iOS Devices
|
40
|
+
getsource list
|
41
|
+
List of source branches
|
42
|
+
getsource <Branch>
|
43
|
+
Download a branch of app source
|
44
|
+
getsouce trunk
|
45
|
+
Download the trunk of app source
|
46
|
+
getbuild list
|
47
|
+
List available builds in the build drop
|
48
|
+
getbuild <Version>
|
49
|
+
Download the build with <Version>.
|
50
|
+
getbuild trunk
|
51
|
+
Download the trunk build
|
52
|
+
getscript list
|
53
|
+
List available scripts
|
54
|
+
getscript <Script>
|
55
|
+
Download the specified script
|
56
|
+
record start
|
57
|
+
Start recording
|
58
|
+
record stop
|
59
|
+
Stop recording
|
60
|
+
version
|
61
|
+
prints the gem version
|
62
|
+
|
63
|
+
<options> can be
|
64
|
+
-v, --verbose
|
65
|
+
Turns on verbose logging
|
66
|
+
EOF
|
67
|
+
end
|
68
|
+
|
69
|
+
def is_windows?
|
70
|
+
(RUBY_PLATFORM =~ /mswin|mingw|cygwin/)
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_ip_from_device_cfg
|
74
|
+
IO.read("Device.cfg").scan(/^IPAddress=(\S*)$/)[0][0]
|
75
|
+
end
|
76
|
+
|
77
|
+
def gen
|
78
|
+
STDOUT.sync = true
|
79
|
+
cmd = "calabash-ios gen"
|
80
|
+
result = system(cmd)
|
81
|
+
sleep(1)
|
82
|
+
result
|
83
|
+
end
|
84
|
+
|
85
|
+
def run(option)
|
86
|
+
app_bundle = @settings["app_bundle"].to_s.strip
|
87
|
+
app_bundle_id = app_bundle_id(File.join(FileUtils.pwd, app_bundle))
|
88
|
+
app_url = app_bundle_url_schemes(File.join(FileUtils.pwd, app_bundle))
|
89
|
+
device_ipaddr = @settings["device_ipaddr"].to_s.strip
|
90
|
+
device_udid = @settings["device_udid"].to_s.strip
|
91
|
+
STDOUT.sync = true
|
92
|
+
arguments = ARGV
|
93
|
+
if option == 'console'
|
94
|
+
cmd = "calabash-ios console"
|
95
|
+
else
|
96
|
+
cmd = "cucumber #{arguments.join(" ")}"
|
97
|
+
end
|
98
|
+
env = {}
|
99
|
+
env["APP_BUNDLE_PATH"] = File.join(FileUtils.pwd, app_bundle)
|
100
|
+
if device_udid == ''
|
101
|
+
# Use Simulator
|
102
|
+
else
|
103
|
+
env["NO_LAUNCH"] = "1"
|
104
|
+
get_device_ip
|
105
|
+
if ENV["NO_INSTALL"] != "1"
|
106
|
+
uninstall_app(app_bundle_id)
|
107
|
+
install_app(File.join(FileUtils.pwd, app_bundle))
|
108
|
+
end
|
109
|
+
launch_app(app_url)
|
110
|
+
sleep(5)
|
111
|
+
device_ipaddr = get_ip_from_device_cfg
|
112
|
+
end
|
113
|
+
if device_ipaddr != ''
|
114
|
+
env["DEVICE_ENDPOINT"] = "http://#{device_ipaddr}:37265"
|
115
|
+
end
|
116
|
+
result = system(env, cmd)
|
117
|
+
sleep(1)
|
118
|
+
result
|
119
|
+
end
|
120
|
+
|
121
|
+
def setup
|
122
|
+
read_settings
|
123
|
+
puts "Settings for Test Automation"
|
124
|
+
|
125
|
+
ask_for_setting("svn_location", "Please enter svn location of test source", @settings["svn_location"])
|
126
|
+
ask_for_setting("svn_location_tools", "Please enter svn location of tools", @settings["svn_location_tools"])
|
127
|
+
ask_for_setting("svn_location_app", "Please enter svn location of app source", @settings["svn_location_app"])
|
128
|
+
ask_for_setting("svn_username", "Please enter svn username", @settings["svn_username"])
|
129
|
+
ask_for_setting("svn_password", "Please enter svn password", @settings["svn_password"])
|
130
|
+
|
131
|
+
ask_for_setting("build_drop_location", "Please enter build drop location", @settings["build_drop_location"])
|
132
|
+
ask_for_setting("build_drop_username", "Please enter the username", @settings["build_drop_username"])
|
133
|
+
ask_for_setting("build_drop_password", "Please enter the password", @settings["build_drop_password"])
|
134
|
+
|
135
|
+
ask_for_setting("app_bundle", "Please enter the name of app bundle", @settings["app_bundle"])
|
136
|
+
ask_for_setting("device_udid", "Please enter the unique device ID of the device", @settings["device_udid"])
|
137
|
+
|
138
|
+
@settings["build_drop_branch_dir"] = "Mobile/iPhone/branch"
|
139
|
+
@settings["build_drop_trunk_dir"] = "Mobile/iPhone/trunk"
|
140
|
+
|
141
|
+
open(@settings_file, 'w') do |f|
|
142
|
+
f.puts @settings.to_json
|
143
|
+
end
|
144
|
+
puts "Saved your settings to #{@settings_file}. You can edit the settings manually or run this setup script again"
|
145
|
+
end
|
146
|
+
|
147
|
+
def ask_for_setting(key, msg, def_value)
|
148
|
+
puts (def_value.to_s.empty? ? msg : "#{msg} (#{def_value})")
|
149
|
+
input = STDIN.gets.chomp
|
150
|
+
if input.empty?
|
151
|
+
@settings[key] = def_value
|
152
|
+
elsif input.strip.empty?
|
153
|
+
@settings[key] = ''
|
154
|
+
else
|
155
|
+
@settings[key] = input
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def read_settings
|
160
|
+
if File.exist? @settings_file
|
161
|
+
@settings = JSON.parse(IO.read(@settings_file))
|
162
|
+
else
|
163
|
+
@settings = {}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def smb_connect_win(location,username,password)
|
168
|
+
mount_node = location.tr('/', '\\')
|
169
|
+
username = username.tr('/', '\\')
|
170
|
+
|
171
|
+
cmd = "net use"
|
172
|
+
output=`#{cmd}` ; result=$?.success?
|
173
|
+
|
174
|
+
if output.include?(mount_node)
|
175
|
+
cmd = "net use #{mount_node} /delete"
|
176
|
+
output=`#{cmd}` ; result=$?.success?
|
177
|
+
end
|
178
|
+
|
179
|
+
cmd = "net use #{mount_node} #{password} /user:#{username}"
|
180
|
+
output=`#{cmd}` ; result=$?.success?
|
181
|
+
raise "the command '#{cmd}' failed" if result == false
|
182
|
+
|
183
|
+
mount_node
|
184
|
+
end
|
185
|
+
|
186
|
+
def smb_disconnect_win(mount_node)
|
187
|
+
cmd = "net use #{mount_node} /delete"
|
188
|
+
output=`#{cmd}` ; result=$?.success?
|
189
|
+
end
|
190
|
+
|
191
|
+
def smb_connect_mac(location,username,password)
|
192
|
+
# create mount node
|
193
|
+
mount_node = "/Volumes/build_drop_temp"
|
194
|
+
if File.exists?(mount_node)
|
195
|
+
cmd = "umount #{mount_node}"
|
196
|
+
output=`#{cmd}` ; result=$?.success?
|
197
|
+
FileUtils.rm_rf(mount_node) if result == false
|
198
|
+
end
|
199
|
+
cmd = "mkdir #{mount_node}"
|
200
|
+
output=`#{cmd}` ; result=$?.success?
|
201
|
+
raise "the command '#{cmd}' failed" if result == false
|
202
|
+
|
203
|
+
# mount smbfs
|
204
|
+
location = location.tr('\\','/')
|
205
|
+
username = username.tr('\\',';').tr('/',';')
|
206
|
+
raise "The build drop location is incorrect" if not location.start_with?("//")
|
207
|
+
cmd = "mount -t smbfs //'#{username}':#{password}@#{location[2..-1]} #{mount_node}"
|
208
|
+
output=`#{cmd}` ; result=$?.success?
|
209
|
+
raise "the command '#{cmd}' failed" if result == false
|
210
|
+
mount_node
|
211
|
+
end
|
212
|
+
|
213
|
+
def smb_disconnect_mac(mount_node)
|
214
|
+
# unmount fs
|
215
|
+
cmd = "umount -f #{mount_node}"
|
216
|
+
output=`#{cmd}` ; result=$?.success?
|
217
|
+
raise "the command '#{cmd}' failed" if result == false
|
218
|
+
end
|
219
|
+
|
220
|
+
def smb_connect(location,username,password)
|
221
|
+
if is_windows?
|
222
|
+
smb_connect_win(location,username,password)
|
223
|
+
else
|
224
|
+
smb_connect_mac(location,username,password)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def smb_disconnect(mount_node)
|
229
|
+
if is_windows?
|
230
|
+
smb_disconnect_win(mount_node)
|
231
|
+
else
|
232
|
+
smb_disconnect_mac(mount_node)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def unzip_file (file, destination)
|
237
|
+
Zip::ZipFile.open(file) { |zip_file|
|
238
|
+
zip_file.each { |f|
|
239
|
+
f_path=File.join(destination, f.name)
|
240
|
+
FileUtils.mkdir_p(File.dirname(f_path))
|
241
|
+
zip_file.extract(f, f_path){ true }
|
242
|
+
}
|
243
|
+
}
|
244
|
+
end
|
245
|
+
|
246
|
+
def get_build
|
247
|
+
mount_node = smb_connect(@settings["build_drop_location"],
|
248
|
+
@settings["build_drop_username"],
|
249
|
+
@settings["build_drop_password"])
|
250
|
+
if ARGV.first == 'list'
|
251
|
+
# list build versions
|
252
|
+
branch_path = File.join(mount_node, @settings["build_drop_branch_dir"])
|
253
|
+
Dir.entries(branch_path).sort_by{|c| File.stat(File.join(branch_path,c)).ctime}.each do |d|
|
254
|
+
m = d.match(/^iPhone(\S+)$/)
|
255
|
+
if m != nil
|
256
|
+
puts m[1]
|
257
|
+
end
|
258
|
+
end
|
259
|
+
else
|
260
|
+
app_bundle = @settings["app_bundle"]
|
261
|
+
version = ARGV.shift
|
262
|
+
sim = (ARGV.shift == 'sim')?"Emulator":"Device"
|
263
|
+
if version == 'trunk'
|
264
|
+
# copy the trunk build
|
265
|
+
release_path = File.join(mount_node, @settings["build_drop_trunk_dir"], "ConcurMobile", sim)
|
266
|
+
else
|
267
|
+
# copy the version build
|
268
|
+
release_path = File.join(mount_node, @settings["build_drop_branch_dir"], "iPhone#{version}", "ConcurMobile", sim, "Release")
|
269
|
+
end
|
270
|
+
build_dir = Dir.entries(release_path).reject{|d|d.start_with?('.')}.sort_by{|c| File.stat(File.join(release_path,c)).ctime}.last
|
271
|
+
zip_file = build_dir + ".zip"
|
272
|
+
source = File.join(release_path, build_dir, zip_file)
|
273
|
+
raise "the file '#{source}' does not exist" if not File.exists?(source)
|
274
|
+
dest = File.join(FileUtils.pwd, zip_file)
|
275
|
+
FileUtils.copy(source, dest)
|
276
|
+
puts "Copy the build from #{source}"
|
277
|
+
FileUtils.rm_rf(File.join(FileUtils.pwd, (sim=='Emulator')?"Debug-iphonesimulator":"Release-iphoneos"))
|
278
|
+
unzip_file(dest, FileUtils.pwd)
|
279
|
+
FileUtils.rm_rf(File.join(FileUtils.pwd, app_bundle))
|
280
|
+
FileUtils.cp_r(File.join(FileUtils.pwd, (sim=='Emulator')?"Debug-iphonesimulator":"Release-iphoneos", app_bundle),
|
281
|
+
FileUtils.pwd)
|
282
|
+
end
|
283
|
+
|
284
|
+
smb_disconnect(mount_node)
|
285
|
+
end
|
286
|
+
|
287
|
+
def get_script
|
288
|
+
svn_location = @settings["svn_location"]
|
289
|
+
svn_location += '/' unless svn_location.end_with?('/')
|
290
|
+
username = @settings["svn_username"]
|
291
|
+
password = @settings["svn_password"]
|
292
|
+
uri = URI.join(svn_location, "Mobile/", "BVT/", "CTE/")
|
293
|
+
|
294
|
+
if ARGV.first == 'list'
|
295
|
+
puts `svn list #{uri} --username #{username} --password #{password}`
|
296
|
+
else
|
297
|
+
feature = ARGV.first
|
298
|
+
feature += '/' unless ARGV.first.end_with?('/')
|
299
|
+
uri = URI.join(uri, feature)
|
300
|
+
puts `svn export --force #{uri} features --username #{username} --password #{password}`
|
301
|
+
|
302
|
+
#uri = URI.join(@settings["svn_location"], "_support/", "support/")
|
303
|
+
#puts `svn export --force #{uri} features/support --username #{username} --password #{password}`
|
304
|
+
uri = URI.join(svn_location, "_support/", "step_definition/")
|
305
|
+
puts `svn export --force #{uri} features/step_definitions --username #{username} --password #{password}`
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def get_source
|
310
|
+
username = @settings["svn_username"]
|
311
|
+
password = @settings["svn_password"]
|
312
|
+
location = @settings["svn_location_app"]
|
313
|
+
raise "Error: No SVN settings." if username.to_s.empty? or password.to_s.empty? or location.to_s.empty?
|
314
|
+
location += '/' unless location.end_with?('/')
|
315
|
+
uri_base = URI(location)
|
316
|
+
|
317
|
+
if ARGV.first == 'list'
|
318
|
+
uri = URI.join(uri_base, "branches/")
|
319
|
+
output = `svn list #{uri} --username #{username} --password #{password}`
|
320
|
+
ios_branches = output.scan(/^(iPhone\S*)$/)
|
321
|
+
ios_branches.each {|i| puts i[0]}
|
322
|
+
else
|
323
|
+
# calabash_setup want Xcode to be closed.
|
324
|
+
res = `ps x -o pid,command | grep -v grep | grep Contents/MacOS/Xcode`
|
325
|
+
if res != ""
|
326
|
+
puts "Xcode is running. We'll be changing the project file so we'd better stop it."
|
327
|
+
puts "Please stop XCode and run setup again"
|
328
|
+
exit(0)
|
329
|
+
end
|
330
|
+
|
331
|
+
branch = ARGV.first
|
332
|
+
branch += '/' unless branch.end_with?('/')
|
333
|
+
|
334
|
+
# remove the directory if it exists
|
335
|
+
FileUtils.rm_rf(File.join(FileUtils.pwd, branch))
|
336
|
+
|
337
|
+
if branch == 'trunk/'
|
338
|
+
uri_iphone = URI.join(uri_base, "trunk/", "iPhone/")
|
339
|
+
uri_images = URI.join(uri_base, "trunk/", "images/")
|
340
|
+
else
|
341
|
+
uri_iphone = URI.join(uri_base, "branches/", branch, "iPhone/")
|
342
|
+
uri_images = URI.join(uri_base, "branches/", branch, "images/")
|
343
|
+
end
|
344
|
+
|
345
|
+
# get the source
|
346
|
+
system("svn export --force #{uri_iphone} #{branch}iPhone --username #{username} --password #{password}")
|
347
|
+
system("svn export --force #{uri_images} #{branch}images --username #{username} --password #{password}")
|
348
|
+
setup_target(branch)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def setup_target(branch_dir)
|
353
|
+
system("echo ConcurMobile|calabash-ios setup #{branch_dir}/iPhone")
|
354
|
+
end
|
355
|
+
|
356
|
+
def fruitstrap_path
|
357
|
+
File.join(File.dirname(__FILE__), "fruitstrap")
|
358
|
+
end
|
359
|
+
|
360
|
+
def launcher_path
|
361
|
+
File.join(FileUtils.pwd, "tools", "AppLaunch", "AppLaunch.app")
|
362
|
+
end
|
363
|
+
|
364
|
+
def app_bundle_path
|
365
|
+
raise "No app bundle setting" if @settings["app_bundle"].to_s.empty?
|
366
|
+
File.join(FileUtils.pwd, @settings["app_bundle"])
|
367
|
+
end
|
368
|
+
|
369
|
+
def app_bundle_id(app_bundle)
|
370
|
+
plist = CFPropertyList::List.new(:file => File.join(app_bundle, "Info.plist"))
|
371
|
+
hash = CFPropertyList.native_types(plist.value)
|
372
|
+
hash['CFBundleURLTypes'][0]["CFBundleIdentifier"]
|
373
|
+
end
|
374
|
+
|
375
|
+
def app_bundle_url_schemes(app_bundle)
|
376
|
+
plist = CFPropertyList::List.new(:file => File.join(app_bundle, "Info.plist"))
|
377
|
+
hash = CFPropertyList.native_types(plist.value)
|
378
|
+
hash['CFBundleURLTypes'][0]["CFBundleURLSchemes"][0] + ":"
|
379
|
+
end
|
380
|
+
|
381
|
+
def install_app(app_bundle)
|
382
|
+
udid = @settings["device_udid"].to_s.strip
|
383
|
+
arg_udid = (udid == "" ? "" : "--id=#{udid}")
|
384
|
+
result = system("#{fruitstrap_path} install #{arg_udid} -t 10 --bundle=#{app_bundle}")
|
385
|
+
raise "Failed to install the app" if result == false
|
386
|
+
end
|
387
|
+
|
388
|
+
def uninstall_app(app_bundle_id)
|
389
|
+
udid = @settings["device_udid"].to_s.strip
|
390
|
+
arg_udid = (udid == "" ? "" : "--id=#{udid}")
|
391
|
+
result = system("#{fruitstrap_path} uninstall #{arg_udid} -t 10 --bundle-id=#{app_bundle_id}")
|
392
|
+
raise "Failed to install the app" if result == false
|
393
|
+
end
|
394
|
+
|
395
|
+
def launch_app(app_url)
|
396
|
+
udid = @settings["device_udid"].to_s
|
397
|
+
udids = Device.detect
|
398
|
+
raise "No device is connected" if udids.length <= 0
|
399
|
+
raise "There are two or more devices. Please provide unique device ID." if udids.length > 1 and udid == ''
|
400
|
+
if udid == ''
|
401
|
+
udid = udids.first
|
402
|
+
end
|
403
|
+
raise "The device #{udid} is not found." if not udids.include?(udid)
|
404
|
+
tracetempl = "/Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate"
|
405
|
+
launcher = "./AppLaunch.app"
|
406
|
+
script = 'LaunchApp.js'
|
407
|
+
text = File.read(File.join(File.dirname(__FILE__), script))
|
408
|
+
File.open(File.join(FileUtils.pwd, script), "w") {|file| file.puts text.gsub(/\[%app%\]/, app_url)}
|
409
|
+
script = File.join(FileUtils.pwd, script)
|
410
|
+
cmd = `instruments -w #{udid} -t #{tracetempl} #{launcher_path} -e UIASCRIPT #{script}`
|
411
|
+
end
|
412
|
+
|
413
|
+
def get_device_ip
|
414
|
+
app_url = app_bundle_url_schemes(app_bundle_path)
|
415
|
+
udid = @settings["device_udid"].to_s
|
416
|
+
udids = Device.detect
|
417
|
+
raise "No device is connected" if udids.length <= 0
|
418
|
+
raise "There are two or more devices. Please provide unique device ID." if udids.length > 1 and udid == ''
|
419
|
+
if udid == ''
|
420
|
+
udid = udids.first
|
421
|
+
end
|
422
|
+
raise "The device #{udid} is not found." if not udids.include?(udid)
|
423
|
+
tracetempl = "/Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate"
|
424
|
+
launcher = "./AppLaunch.app"
|
425
|
+
script = 'GetIPAddress.js'
|
426
|
+
text = File.read(File.join(File.dirname(__FILE__), script))
|
427
|
+
File.open(File.join(FileUtils.pwd, script), "w") {|file| file.puts text}
|
428
|
+
script = File.join(FileUtils.pwd, script)
|
429
|
+
File.open(File.join(FileUtils.pwd, "Device.cfg"), "w") {|file| file.puts "IPAddress="}
|
430
|
+
cmd = `instruments -w #{udid} -t #{tracetempl} #{launcher_path} -e UIASCRIPT #{script}`
|
431
|
+
puts File.read(File.join(FileUtils.pwd, "Device.cfg"))
|
432
|
+
end
|
433
|
+
|
434
|
+
def start_sim
|
435
|
+
quit_sim
|
436
|
+
pid = spawn("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone\\ Simulator.app/Contents/MacOS/iPhone\\ Simulator")
|
437
|
+
end
|
438
|
+
|
439
|
+
def reset_sim
|
440
|
+
calabash_sim_reset
|
441
|
+
end
|
442
|
+
|
443
|
+
class Device
|
444
|
+
def self.call_device_detect(udid = nil)
|
445
|
+
udid_arg = (udid == nil) ? "" : "-i #{udid}"
|
446
|
+
`#{File.join(File.dirname(__FILE__), 'devicedetect')} #{udid_arg}`
|
447
|
+
end
|
448
|
+
|
449
|
+
def self.detect
|
450
|
+
udid_array = []
|
451
|
+
output = self.call_device_detect
|
452
|
+
foundDevReg = /^Found device \(([[:xdigit:]]*)\).*$/
|
453
|
+
output.split(/\r?\n/).select{ |i| i =~ foundDevReg }.each{ |foundDev| udid_array << foundDev.match(foundDevReg)[1] }
|
454
|
+
udid_array
|
455
|
+
end
|
456
|
+
|
457
|
+
attr_accessor :udid, :name, :wifi_address, :serial_number, :product_version, :product_type, :device_class, :model_number
|
458
|
+
|
459
|
+
def initialize(udid)
|
460
|
+
@udid = udid
|
461
|
+
output = self.class.call_device_detect(@udid)
|
462
|
+
raise "The device (#{@udid})is not found." if output == ""
|
463
|
+
@name = output.match(/^Device Name: (.*)$/)[1]
|
464
|
+
@wifi_address = output.match(/^WiFi Address: (.*)$/)[1]
|
465
|
+
@serial_number = output.match(/^Serial Number: (.*)$/)[1]
|
466
|
+
@product_version = output.match(/^Product Version: (.*)$/)[1]
|
467
|
+
@product_type = output.match(/^Product Type: (.*)$/)[1]
|
468
|
+
@device_class = output.match(/^Device Class: (.*)$/)[1]
|
469
|
+
@model_number = output.match(/^Model Number: (.*)$/)[1]
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
def list_devices
|
474
|
+
Device.detect.each{ |id| puts id }
|
475
|
+
end
|
476
|
+
|
477
|
+
def device_info(udid)
|
478
|
+
device = Device.new(udid)
|
479
|
+
puts "Unique Device ID: #{device.udid}"
|
480
|
+
puts "Device Name: #{device.name}"
|
481
|
+
puts "Serial Number: #{device.serial_number}"
|
482
|
+
puts "Model Number: #{device.model_number}"
|
483
|
+
puts "Product Version: #{device.product_version}"
|
484
|
+
puts "Product Type: #{device.product_type}"
|
485
|
+
puts "Device Class: #{device.device_class}"
|
486
|
+
puts "WiFi Address: #{device.wifi_address}"
|
487
|
+
end
|
488
|
+
|
489
|
+
def build_app(branch_dir,sim)
|
490
|
+
if sim == 'sim'
|
491
|
+
sdk = "iphonesimulator"
|
492
|
+
else
|
493
|
+
sdk = "iphoneos"
|
494
|
+
end
|
495
|
+
project = File.join(FileUtils.pwd, branch_dir, "iPhone", "ConcurMobile.xcodeproj")
|
496
|
+
target = "ConcurMobile-cal"
|
497
|
+
configuration = "Release"
|
498
|
+
system("/usr/bin/xcodebuild -project #{project} -target #{target} -configuration #{configuration} -sdk #{sdk} clean build")
|
499
|
+
app_bundle = @settings["app_bundle"]
|
500
|
+
source = File.join(FileUtils.pwd, branch_dir, "iPhone", "build", "#{configuration}-#{sdk}", app_bundle)
|
501
|
+
target = File.join(FileUtils.pwd, app_bundle)
|
502
|
+
FileUtils.rm_rf(target)
|
503
|
+
FileUtils.cp_r(source, target)
|
504
|
+
end
|
505
|
+
|
506
|
+
def install_tools
|
507
|
+
raise "Please configure Subversion location for tools, username, and password first by running setup" if @settings["svn_location_tools"].to_s.empty? or @settings["svn_username"].to_s.empty? or @settings["svn_password"].to_s.empty?
|
508
|
+
|
509
|
+
location = @settings["svn_location_tools"]
|
510
|
+
location += '/' unless location.end_with?('/')
|
511
|
+
username = @settings["svn_username"]
|
512
|
+
password = @settings["svn_password"]
|
513
|
+
|
514
|
+
# delete tools directory
|
515
|
+
FileUtils.rm_rf(File.join(FileUtils.pwd, "tools"))
|
516
|
+
|
517
|
+
system("svn export --force #{location} tools/ --username #{username} --password #{password}")
|
518
|
+
tools = `svn list #{location} -R --username #{username} --password #{password}`.split(/\n/).select{|i| i.end_with?('.zip')}
|
519
|
+
tools.each do |tool|
|
520
|
+
tool_zip = File.join(FileUtils.pwd, "tools", tool)
|
521
|
+
unzip_file(tool_zip, File.dirname(tool_zip))
|
522
|
+
tool_app = tool_zip.chomp(File.extname(tool_zip)) + ".app"
|
523
|
+
puts "Installing #{tool_app}"
|
524
|
+
install_app(tool_app)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
def record_start
|
529
|
+
launch_app('concurrecorder://record')
|
530
|
+
end
|
531
|
+
|
532
|
+
def record_stop
|
533
|
+
launch_app('concurrecorder://stop')
|
534
|
+
end
|
535
|
+
|
536
|
+
if (ARGV.length == 0)
|
537
|
+
print_usage
|
538
|
+
exit 0
|
539
|
+
end
|
540
|
+
|
541
|
+
cmd = ARGV.shift
|
542
|
+
|
543
|
+
if cmd == 'help'
|
544
|
+
print_usage
|
545
|
+
exit 0
|
546
|
+
|
547
|
+
elsif cmd == 'setup'
|
548
|
+
setup
|
549
|
+
exit 0
|
550
|
+
|
551
|
+
elsif cmd == 'getbuild'
|
552
|
+
read_settings
|
553
|
+
File.open("#{Dir.tmpdir}/testauto.lock", 'w') { |f|
|
554
|
+
f.flock(File::LOCK_EX)
|
555
|
+
get_build
|
556
|
+
}
|
557
|
+
exit 0
|
558
|
+
|
559
|
+
elsif cmd == 'getscript'
|
560
|
+
read_settings
|
561
|
+
get_script
|
562
|
+
exit 0
|
563
|
+
|
564
|
+
elsif cmd == 'getsource'
|
565
|
+
read_settings
|
566
|
+
get_source
|
567
|
+
exit 0
|
568
|
+
|
569
|
+
elsif cmd == 'install'
|
570
|
+
read_settings
|
571
|
+
option = ARGV.shift
|
572
|
+
if option == 'tools'
|
573
|
+
install_tools
|
574
|
+
else
|
575
|
+
install_app(app_bundle_path)
|
576
|
+
end
|
577
|
+
exit 0
|
578
|
+
|
579
|
+
elsif cmd == 'uninstall'
|
580
|
+
read_settings
|
581
|
+
uninstall_app(app_bundle_id(app_bundle_path))
|
582
|
+
|
583
|
+
elsif cmd == 'launch'
|
584
|
+
read_settings
|
585
|
+
launch_app(app_bundle_url_schemes(app_bundle_path))
|
586
|
+
exit 0
|
587
|
+
|
588
|
+
elsif cmd == 'getip'
|
589
|
+
read_settings
|
590
|
+
get_device_ip
|
591
|
+
exit 0
|
592
|
+
|
593
|
+
elsif cmd == 'devices'
|
594
|
+
list_devices
|
595
|
+
exit 0
|
596
|
+
|
597
|
+
elsif cmd == 'sim'
|
598
|
+
option = ARGV.shift
|
599
|
+
read_settings
|
600
|
+
if option == 'start'
|
601
|
+
start_sim
|
602
|
+
elsif option == 'quit'
|
603
|
+
quit_sim
|
604
|
+
elsif option == 'build'
|
605
|
+
branch_dir = ARGV.shift
|
606
|
+
build_app(branch_dir, 'sim')
|
607
|
+
end
|
608
|
+
exit 0
|
609
|
+
|
610
|
+
elsif cmd == 'run' or cmd == 'console'
|
611
|
+
read_settings
|
612
|
+
run(cmd)
|
613
|
+
|
614
|
+
elsif cmd == 'build'
|
615
|
+
read_settings
|
616
|
+
branch_dir = ARGV.shift
|
617
|
+
sim = ARGV.shift
|
618
|
+
build_app(branch_dir, sim)
|
619
|
+
|
620
|
+
elsif cmd == 'gen'
|
621
|
+
gen
|
622
|
+
|
623
|
+
elsif cmd == 'go'
|
624
|
+
go
|
625
|
+
|
626
|
+
elsif cmd == 'record'
|
627
|
+
read_settings
|
628
|
+
option = ARGV.shift
|
629
|
+
if option == 'start'
|
630
|
+
record_start
|
631
|
+
elsif option == 'stop'
|
632
|
+
record_stop
|
633
|
+
end
|
634
|
+
|
635
|
+
elsif cmd == 'version'
|
636
|
+
require 'calabash-cucumber'
|
637
|
+
puts Calabash::Cucumber::VERSION
|
638
|
+
exit 0
|
639
|
+
|
640
|
+
else
|
641
|
+
print_usage
|
642
|
+
end
|
643
|
+
|