testautoi 0.9.127 → 0.9.133
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/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
|
+
|