testautoa 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/bin/testautoa +18 -6
- data/lib/calabash-android.rb +2 -1
- data/lib/calabash-android/abase.rb +89 -0
- data/lib/calabash-android/helpers.rb +29 -15
- data/lib/calabash-android/lib/TestServer.apk +0 -0
- data/lib/calabash-android/lib/screenshotTaker.jar +0 -0
- data/lib/calabash-android/operations.rb +80 -23
- data/lib/calabash-android/steps/additions_manual_steps.rb +1 -1
- data/lib/calabash-android/version.rb +1 -1
- data/test-server/calabash-js/src/calabash.js +4 -0
- data/test-server/calabash-js/src/set_text.js +62 -56
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/CalabashInstrumentationTestRunner.java +2 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/InstrumentationBackend.java +7 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/Actions.java +2 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForScreen.java +2 -2
- metadata +4 -3
- data/lib/calabash-android/lib/screenShotTaker.jar +0 -0
data/Rakefile
CHANGED
data/bin/testautoa
CHANGED
@@ -165,8 +165,8 @@ def setup
|
|
165
165
|
ask_for_setting("avd_cpu", "Please enter the CPU of Android emulator", @settings["avd_cpu"] ||= "armeabi-v7a")
|
166
166
|
ask_for_setting("avd_sdcard_size", "Please enter the SD card size of Android emulator", @settings["avd_sdcard_size"] ||= "64M")
|
167
167
|
ask_for_setting("avd_ram_size", "Please enter the RAM size of Android emulator", @settings["avd_ram_size"] ||= "1024")
|
168
|
-
@settings["build_drop_branch_dir"] = "Mobile/Android/branch"
|
169
|
-
@settings["build_drop_trunk_dir"] = "Mobile/Android/trunk"
|
168
|
+
@settings["build_drop_branch_dir"] = "Mobile/Android/branch/Corp"
|
169
|
+
@settings["build_drop_trunk_dir"] = "Mobile/Android/trunk/Corp"
|
170
170
|
|
171
171
|
open('.testautoa_settings', 'w') do |f|
|
172
172
|
f.puts @settings.to_json
|
@@ -234,6 +234,12 @@ def smb_connect_mac(location,username,password)
|
|
234
234
|
location = location.tr('\\','/')
|
235
235
|
username = username.tr('\\',';').tr('/',';')
|
236
236
|
raise "The build drop location is incorrect" if not location.start_with?("//")
|
237
|
+
paths = location.split('/')
|
238
|
+
if paths.size > 4
|
239
|
+
location = paths.shift(4).join('/')
|
240
|
+
@settings["build_drop_branch_dir"] = [paths.join('/'), @settings["build_drop_branch_dir"]].join('/')
|
241
|
+
@settings["build_drop_trunk_dir"] = [paths.join('/'), @settings["build_drop_trunk_dir"]].join('/')
|
242
|
+
end
|
237
243
|
cmd = "mount -t smbfs //'#{username}':#{password}@#{location[2..-1]} #{mount_node}"
|
238
244
|
output=`#{cmd}` ; result=$?.success?
|
239
245
|
raise "the command '#{cmd}' failed" if result == false
|
@@ -286,7 +292,9 @@ def get_build
|
|
286
292
|
# copy the version build
|
287
293
|
release_path = File.join(mount_node, @settings["build_drop_branch_dir"], "Android#{ARGV.first}/Release")
|
288
294
|
end
|
295
|
+
raise "No builds found in #{release_path}" unless File.directory?(release_path)
|
289
296
|
build_dir = Dir.entries(release_path).reject{|d|d.start_with?('.')}.sort_by{|c| File.stat(File.join(release_path,c)).ctime}.last
|
297
|
+
raise "No builds found in #{release_path}" if build_dir == nil
|
290
298
|
apk_file = "ConcurMobile.apk"
|
291
299
|
source = File.join(release_path, build_dir, apk_file)
|
292
300
|
raise "the file '#{source}' does not exist" if not File.exists?(source)
|
@@ -311,8 +319,8 @@ def get_script
|
|
311
319
|
uri = URI.join(uri, feature)
|
312
320
|
puts `svn export --force #{uri} features --username #{username} --password #{password}`
|
313
321
|
|
314
|
-
|
315
|
-
|
322
|
+
uri = URI.join(@settings["svn_location"], "_support/", "support/")
|
323
|
+
puts `svn export --force #{uri} features/support --username #{username} --password #{password}`
|
316
324
|
uri = URI.join(@settings["svn_location"], "_support/", "step_definition/")
|
317
325
|
puts `svn export --force #{uri} features/step_definitions --username #{username} --password #{password}`
|
318
326
|
end
|
@@ -326,8 +334,12 @@ end
|
|
326
334
|
def adb_path_w_sn
|
327
335
|
raise_if_android_home_not_set
|
328
336
|
serial_number = @settings["device_serialno"].to_s.strip
|
329
|
-
serial_number = "-s #{serial_number}" unless serial_number.empty?
|
330
|
-
|
337
|
+
serial_number = " -s #{serial_number}" unless serial_number.empty?
|
338
|
+
adb_path + serial_number
|
339
|
+
end
|
340
|
+
|
341
|
+
def adb_shell(command)
|
342
|
+
system("#{adb_path_w_sn} shell #{command}")
|
331
343
|
end
|
332
344
|
|
333
345
|
def android_path
|
data/lib/calabash-android.rb
CHANGED
@@ -0,0 +1,89 @@
|
|
1
|
+
class Calabash::ABase
|
2
|
+
include Calabash::Android::Operations
|
3
|
+
|
4
|
+
|
5
|
+
attr_accessor :world, :transition_duration
|
6
|
+
|
7
|
+
def initialize(world, transition_duration=0.5)
|
8
|
+
self.world = world
|
9
|
+
self.transition_duration = transition_duration
|
10
|
+
end
|
11
|
+
|
12
|
+
def trait
|
13
|
+
raise "You should define a trait method or a title method" unless respond_to?(:title)
|
14
|
+
"* marked:'#{self.title}'"
|
15
|
+
end
|
16
|
+
|
17
|
+
def current_page?
|
18
|
+
element_exists(trait)
|
19
|
+
end
|
20
|
+
|
21
|
+
def page(clz, *args)
|
22
|
+
clz.new(world, *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def await(wait_opts={})
|
26
|
+
wait_for_elements_exist([trait], wait_opts)
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Performs a transition from receiver page to another by performing a +:tap+ gesture
|
32
|
+
# or a user specified +:action+.
|
33
|
+
# Caller must supply a hash of options +transition_options+ to describe the transition.
|
34
|
+
# Transition options may have the following keys
|
35
|
+
#
|
36
|
+
# +:tap+: A uiquery used to perform a tap gesture to begin transition
|
37
|
+
# +:action+: A proc to use begin transition (either :tap or :action must be supplied)
|
38
|
+
# +:page+: A page object or page object class to transition to (target page). If a class is provided this
|
39
|
+
# is instantiated using the +page+ method of self. If no +:page+ is supplied, +self+ is used.
|
40
|
+
# +:await+: If specified and truthy will await the +:page+ after performing gesture (usually to wait
|
41
|
+
# for animation to finish)
|
42
|
+
# +:tap_options+: If +:tap+ is provided used to pass as options to touch
|
43
|
+
# +:wait_options+: When awaiting target page, pass these options to the +await+ method
|
44
|
+
#
|
45
|
+
# Returns the transition target page
|
46
|
+
#
|
47
|
+
# Note it is assumed that the target page is a Calabash::ABase (or acts accordingly)
|
48
|
+
def transition(transition_options={})
|
49
|
+
uiquery = transition_options[:tap]
|
50
|
+
action = transition_options[:action]
|
51
|
+
page_arg = transition_options[:page]
|
52
|
+
should_await = transition_options.has_key?(:await) ? transition_options[:await] : true
|
53
|
+
|
54
|
+
if action.nil? && uiquery.nil?
|
55
|
+
raise "Called transition without providing a gesture (:tap or :action) #{transition_options}"
|
56
|
+
end
|
57
|
+
|
58
|
+
if uiquery
|
59
|
+
tap_options = transition_options[:tap_options] || {}
|
60
|
+
touch(uiquery, tap_options)
|
61
|
+
else
|
62
|
+
action.call()
|
63
|
+
end
|
64
|
+
|
65
|
+
page_obj = page_arg.is_a?(Class) ? page(page_arg) : page_arg
|
66
|
+
page_obj ||= self
|
67
|
+
|
68
|
+
if should_await
|
69
|
+
unless page_obj == self
|
70
|
+
wait_opts = transition_options[:wait_options] || {}
|
71
|
+
page_obj.await(wait_opts)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
page_obj
|
76
|
+
end
|
77
|
+
|
78
|
+
def await_screenshot(wait_opts={}, screenshot_opts={})
|
79
|
+
await(wait_opts)
|
80
|
+
screenshot_embed(screenshot_opts)
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
protected
|
85
|
+
def method_missing(name, *args, &block)
|
86
|
+
world.send(name, *args, &block)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -81,17 +81,37 @@ def sign_apk(app_path, dest_path)
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def read_keystore_info
|
84
|
+
keystore = default_keystore
|
85
|
+
|
84
86
|
if File.exist? ".calabash_settings"
|
85
87
|
keystore = JSON.parse(IO.read(".calabash_settings"))
|
86
|
-
keystore
|
87
|
-
keystore
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
fail_if_key_missing(keystore, "keystore_location")
|
89
|
+
fail_if_key_missing(keystore, "keystore_password")
|
90
|
+
fail_if_key_missing(keystore, "keystore_alias")
|
91
|
+
keystore["keystore_location"] = File.expand_path(keystore["keystore_location"])
|
92
|
+
end
|
93
|
+
keystore["keystore_location"] = put_in_quotes(remove_quotes(keystore["keystore_location"]))
|
94
|
+
keystore
|
95
|
+
end
|
96
|
+
|
97
|
+
def default_keystore
|
98
|
+
{
|
99
|
+
"keystore_location" => File.expand_path(File.join(ENV["HOME"], "/.android/debug.keystore")),
|
91
100
|
"keystore_password" => "android",
|
92
101
|
"keystore_alias" => "androiddebugkey",
|
93
|
-
|
94
|
-
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def fail_if_key_missing(map, key)
|
106
|
+
raise "Found .calabash_settings but no #{key} defined." unless map[key]
|
107
|
+
end
|
108
|
+
|
109
|
+
def remove_quotes(s)
|
110
|
+
s.gsub(/"/, "")
|
111
|
+
end
|
112
|
+
|
113
|
+
def put_in_quotes(s)
|
114
|
+
%Q{"#{s}"}
|
95
115
|
end
|
96
116
|
|
97
117
|
def keytool_path
|
@@ -104,7 +124,7 @@ end
|
|
104
124
|
|
105
125
|
def fingerprint_from_keystore
|
106
126
|
keystore_info = read_keystore_info
|
107
|
-
cmd = "#{keytool_path} -v -list -alias #{keystore_info["keystore_alias"]} -keystore
|
127
|
+
cmd = "#{keytool_path} -v -list -alias #{keystore_info["keystore_alias"]} -keystore #{keystore_info["keystore_location"]} -storepass #{keystore_info["keystore_password"]}"
|
108
128
|
|
109
129
|
log cmd
|
110
130
|
fingerprints = `#{cmd}`
|
@@ -138,13 +158,7 @@ end
|
|
138
158
|
def extract_md5_fingerprint(fingerprints)
|
139
159
|
log fingerprints
|
140
160
|
|
141
|
-
|
142
|
-
if fingerprints.encoding.name == "CP850"
|
143
|
-
fingerprints = fingerprints.gsub("\xA0".force_encoding("CP850"),"")
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
m = fingerprints.scan(/MD5\s*:\s*((?:[a-fA-F\d]{2}:){15}[a-fA-F\d]{2})/).flatten
|
161
|
+
m = fingerprints.scan(/MD5.*((?:[a-fA-F\d]{2}:){15}[a-fA-F\d]{2})/).flatten
|
148
162
|
raise "No MD5 fingerprint found:\n #{fingerprints}" if m.empty?
|
149
163
|
m.first
|
150
164
|
end
|
Binary file
|
Binary file
|
@@ -19,6 +19,10 @@ module Operations
|
|
19
19
|
include Calabash::Android::WaitHelpers
|
20
20
|
include Calabash::Android::TouchHelpers
|
21
21
|
|
22
|
+
def current_activity
|
23
|
+
`#{default_device.adb_command} shell dumpsys window windows`.each_line.grep(/mFocusedApp.+[\.\/]([^.\/\}]+)\}/){$1}.first
|
24
|
+
end
|
25
|
+
|
22
26
|
def log(message)
|
23
27
|
$stdout.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} - #{message}" if (ARGV.include? "-v" or ARGV.include? "--verbose")
|
24
28
|
end
|
@@ -71,8 +75,16 @@ module Operations
|
|
71
75
|
default_device.clear_app_data
|
72
76
|
end
|
73
77
|
|
78
|
+
def pull(remote, local)
|
79
|
+
default_device.pull(remote, local)
|
80
|
+
end
|
81
|
+
|
82
|
+
def push(local, remote)
|
83
|
+
default_device.push(local, remote)
|
84
|
+
end
|
85
|
+
|
74
86
|
def start_test_server_in_background(options={})
|
75
|
-
default_device.start_test_server_in_background()
|
87
|
+
default_device.start_test_server_in_background(options)
|
76
88
|
end
|
77
89
|
|
78
90
|
def shutdown_test_server
|
@@ -104,6 +116,10 @@ module Operations
|
|
104
116
|
default_device.press_back_key
|
105
117
|
end
|
106
118
|
|
119
|
+
def switch_wifi(on)
|
120
|
+
default_device.switch_wifi(on)
|
121
|
+
end
|
122
|
+
|
107
123
|
#def wait_for(timeout, &block)
|
108
124
|
# value = nil
|
109
125
|
# begin
|
@@ -152,6 +168,14 @@ module Operations
|
|
152
168
|
|
153
169
|
###
|
154
170
|
|
171
|
+
### simple page object helper
|
172
|
+
|
173
|
+
def page(clz, *args)
|
174
|
+
clz.new(self, *args)
|
175
|
+
end
|
176
|
+
|
177
|
+
###
|
178
|
+
|
155
179
|
### app life cycle
|
156
180
|
def connect_to_test_server
|
157
181
|
puts "Explicit calls to connect_to_test_server should be removed."
|
@@ -277,12 +301,7 @@ module Operations
|
|
277
301
|
@@screenshot_count ||= 0
|
278
302
|
path = "#{prefix}#{name}_#{@@screenshot_count}.png"
|
279
303
|
|
280
|
-
if ENV["SCREENSHOT_VIA_USB"] == "
|
281
|
-
device_args = "-s #{@serial}" if @serial
|
282
|
-
screenshot_cmd = "java -jar #{File.join(File.dirname(__FILE__), 'lib', 'screenShotTaker.jar')} #{path} #{device_args}"
|
283
|
-
log screenshot_cmd
|
284
|
-
raise "Could not take screenshot" unless system(screenshot_cmd)
|
285
|
-
else
|
304
|
+
if ENV["SCREENSHOT_VIA_USB"] == "false"
|
286
305
|
begin
|
287
306
|
res = http("/screenshot")
|
288
307
|
rescue EOFError
|
@@ -291,31 +310,48 @@ module Operations
|
|
291
310
|
File.open(path, 'wb') do |f|
|
292
311
|
f.write res
|
293
312
|
end
|
313
|
+
else
|
314
|
+
screenshot_cmd = "java -jar #{File.join(File.dirname(__FILE__), 'lib', 'screenshotTaker.jar')} #{serial} #{path}"
|
315
|
+
log screenshot_cmd
|
316
|
+
raise "Could not take screenshot" unless system(screenshot_cmd)
|
294
317
|
end
|
295
318
|
|
296
|
-
|
297
319
|
@@screenshot_count += 1
|
298
320
|
path
|
299
321
|
end
|
300
322
|
|
301
323
|
def adb_command
|
324
|
+
"#{adb} -s #{serial}"
|
325
|
+
end
|
326
|
+
|
327
|
+
def adb
|
302
328
|
if is_windows?
|
303
|
-
%Q("#{ENV["ANDROID_HOME"]}\\platform-tools\\adb.exe"
|
329
|
+
%Q("#{ENV["ANDROID_HOME"]}\\platform-tools\\adb.exe")
|
304
330
|
else
|
305
|
-
%Q("#{ENV["ANDROID_HOME"]}/platform-tools/adb"
|
331
|
+
%Q("#{ENV["ANDROID_HOME"]}/platform-tools/adb")
|
306
332
|
end
|
307
333
|
end
|
308
334
|
|
309
|
-
def
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
335
|
+
def serial
|
336
|
+
@serial || default_serial
|
337
|
+
end
|
338
|
+
|
339
|
+
def default_serial
|
340
|
+
devices = connected_devices
|
341
|
+
log "connected_devices: #{devices}"
|
342
|
+
raise "No connected devices" if devices.empty?
|
343
|
+
raise "More than one device connected. Specify device serial using ADB_DEVICE_ARG" if devices.length > 1
|
344
|
+
devices.first
|
315
345
|
end
|
316
346
|
|
347
|
+
def connected_devices
|
348
|
+
lines = `#{adb} devices`.split("\n")
|
349
|
+
lines.shift
|
350
|
+
lines.collect { |l| l.split("\t").first}
|
351
|
+
end
|
352
|
+
|
317
353
|
def wake_up
|
318
|
-
wake_up_cmd = "#{adb_command} shell am start -a android.intent.action.MAIN -n
|
354
|
+
wake_up_cmd = "#{adb_command} shell am start -a android.intent.action.MAIN -n #{package_name(@test_server_path)}/sh.calaba.instrumentationbackend.WakeUp"
|
319
355
|
log "Waking up device using:"
|
320
356
|
log wake_up_cmd
|
321
357
|
raise "Could not wake up the device" unless system(wake_up_cmd)
|
@@ -326,10 +362,20 @@ module Operations
|
|
326
362
|
end
|
327
363
|
|
328
364
|
def clear_app_data
|
329
|
-
cmd = "#{adb_command} shell am instrument
|
365
|
+
cmd = "#{adb_command} shell am instrument #{package_name(@test_server_path)}/sh.calaba.instrumentationbackend.ClearAppData"
|
330
366
|
raise "Could not clear data" unless system(cmd)
|
331
367
|
end
|
332
368
|
|
369
|
+
def pull(remote, local)
|
370
|
+
cmd = "#{adb_command} pull #{remote} #{local}"
|
371
|
+
raise "Could not pull #{remote} to #{local}" unless system(cmd)
|
372
|
+
end
|
373
|
+
|
374
|
+
def push(local, remote)
|
375
|
+
cmd = "#{adb_command} push #{local} #{remote}"
|
376
|
+
raise "Could not push #{local} to #{remote}" unless system(cmd)
|
377
|
+
end
|
378
|
+
|
333
379
|
def start_test_server_in_background(options={})
|
334
380
|
raise "Will not start test server because of previous failures." if ::Cucumber.wants_to_quit
|
335
381
|
|
@@ -337,12 +383,13 @@ module Operations
|
|
337
383
|
wake_up
|
338
384
|
end
|
339
385
|
|
340
|
-
|
341
|
-
|
342
|
-
:main_activity => options[:main_activity] || main_activity(@app_path),
|
386
|
+
env_options = {:target_package => package_name(@app_path),
|
387
|
+
:main_activity => main_activity(@app_path),
|
343
388
|
:test_server_port => @test_server_port,
|
344
|
-
:debug =>
|
345
|
-
:class =>
|
389
|
+
:debug => false,
|
390
|
+
:class => "sh.calaba.instrumentationbackend.InstrumentationBackend"}
|
391
|
+
|
392
|
+
env_options = env_options.merge(options)
|
346
393
|
|
347
394
|
cmd_arr = [adb_command, "shell am instrument"]
|
348
395
|
|
@@ -413,6 +460,11 @@ module Operations
|
|
413
460
|
def shutdown_test_server
|
414
461
|
begin
|
415
462
|
http("/kill")
|
463
|
+
Timeout::timeout(3) do
|
464
|
+
sleep 0.3 while app_running?
|
465
|
+
end
|
466
|
+
rescue Timeout::Error
|
467
|
+
log ("Could not kill app. Waited to 3 seconds.")
|
416
468
|
rescue EOFError
|
417
469
|
log ("Could not kill app. App is most likely not running anymore.")
|
418
470
|
end
|
@@ -440,6 +492,11 @@ module Operations
|
|
440
492
|
def press_back_key
|
441
493
|
input_keyevent(4)
|
442
494
|
end
|
495
|
+
|
496
|
+
def switch_wifi(on)
|
497
|
+
cmd = "#{adb_command} shell am start -n com.concur.wifiswitch/." + (on ? "On" : "Off") + "Activity"
|
498
|
+
result = `#{cmd}`
|
499
|
+
end
|
443
500
|
end
|
444
501
|
|
445
502
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
Then /^I compare the current screen with the reference image "([^\"]*) manually
|
1
|
+
Then /^I compare the current screen with the reference image "([^\"]*)" manually$/ do |name|
|
2
2
|
# TODO: once test artifacts directory is configurable, the image location
|
3
3
|
# will need to be either a fully qualified path somewhere (webserver?) or
|
4
4
|
# be relative to the output HTML file
|
@@ -1,49 +1,49 @@
|
|
1
1
|
(function () {
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
2
|
+
function simulateKeyEvent(elem, character) {
|
3
|
+
var ch = character.charCodeAt(0);
|
4
|
+
|
5
|
+
var evt;
|
6
|
+
evt = document.createEvent('KeyboardEvent');
|
7
|
+
evt.initKeyboardEvent('keydown', true, true, window, 0, 0, 0, 0, 0, ch);
|
8
|
+
elem.dispatchEvent(evt);
|
9
|
+
|
10
|
+
evt = document.createEvent('KeyboardEvent');
|
11
|
+
evt.initKeyboardEvent('keyup', true, true, window, 0, 0, 0, 0, 0, ch);
|
12
|
+
elem.dispatchEvent(evt);
|
13
|
+
evt = document.createEvent('KeyboardEvent');
|
14
|
+
evt.initKeyboardEvent('keypress', true, true, window, 0, 0, 0, 0, 0, ch);
|
15
|
+
elem.dispatchEvent(evt);
|
16
|
+
}
|
17
|
+
|
18
|
+
|
19
|
+
function enterTextIntoInputField(elem, text) {
|
20
|
+
elem.value = "";
|
21
|
+
for (var i = 0; i < text.length; i++) {
|
22
|
+
var ch = text.charAt(i);
|
23
|
+
elem.value += ch;
|
24
|
+
simulateKeyEvent(elem, ch);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
|
29
|
+
function fireHTMLEvent(elem, eventName) {
|
30
|
+
var evt = document.createEvent("HTMLEvents");
|
31
|
+
evt.initEvent(eventName, true, true );
|
32
|
+
return !elem.dispatchEvent(evt);
|
33
|
+
}
|
34
|
+
|
35
|
+
function selectInputField(elem) {
|
36
|
+
elem.click();
|
37
|
+
elem.focus();
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
function deselectInputField(elem) {
|
42
|
+
fireHTMLEvent(elem, 'change');
|
43
|
+
fireHTMLEvent(elem, 'blur');
|
44
|
+
}
|
45
|
+
|
46
|
+
|
47
47
|
/** David Mark's isHostMethod function,
|
48
48
|
* http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
|
49
49
|
* Modified to use strict equality
|
@@ -72,7 +72,7 @@
|
|
72
72
|
}
|
73
73
|
else if (object instanceof Node)//TODO: support for frames!
|
74
74
|
{
|
75
|
-
res = {}
|
75
|
+
res = {};
|
76
76
|
if (isHostMethod(object,'getBoundingClientRect'))
|
77
77
|
{
|
78
78
|
res['rect'] = object.getBoundingClientRect();
|
@@ -81,6 +81,9 @@
|
|
81
81
|
res.nodeName = object.nodeName;
|
82
82
|
res.id = object.id || '';
|
83
83
|
res['class'] = object.className || '';
|
84
|
+
if (object.hasOwnProperty('value')) {
|
85
|
+
res.value = object.value;
|
86
|
+
}
|
84
87
|
res.html = object.outerHTML || '';
|
85
88
|
res.nodeValue = object.nodeValue;
|
86
89
|
}
|
@@ -102,23 +105,26 @@
|
|
102
105
|
}
|
103
106
|
return res;
|
104
107
|
}
|
105
|
-
|
108
|
+
|
106
109
|
///TODO: no support for now frames
|
107
110
|
//idea would be map XPath across window.frames
|
108
111
|
//must take care of visibility questions
|
109
112
|
|
110
113
|
try
|
111
|
-
{
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
114
|
+
{
|
115
|
+
var exp = JSON.parse('%@')/* dynamic */,
|
116
|
+
el,
|
117
|
+
text = '%@',
|
118
|
+
i,N;
|
119
|
+
|
117
120
|
el=document.elementFromPoint(exp.rect.left, exp.rect.top);
|
121
|
+
if(exp.id){
|
122
|
+
el = document.getElementById(exp.id);
|
123
|
+
}
|
118
124
|
if (/input/i.test(el.tagName))
|
119
125
|
{
|
120
|
-
|
121
|
-
|
126
|
+
selectInputField(el);
|
127
|
+
enterTextIntoInputField(el, text);
|
122
128
|
}
|
123
129
|
else
|
124
130
|
{
|
@@ -130,4 +136,4 @@
|
|
130
136
|
return JSON.stringify({error:'Exception while running query: '+exp, details:e.toString()})
|
131
137
|
}
|
132
138
|
return JSON.stringify(toJSON(el));
|
133
|
-
})();
|
139
|
+
})();
|
@@ -9,7 +9,7 @@ import sh.calaba.instrumentationbackend.actions.HttpServer;
|
|
9
9
|
|
10
10
|
public class CalabashInstrumentationTestRunner extends InstrumentationTestRunner {
|
11
11
|
@Override
|
12
|
-
public void onCreate(Bundle arguments) {
|
12
|
+
public void onCreate(Bundle arguments) {
|
13
13
|
try {
|
14
14
|
Context context = getTargetContext ();
|
15
15
|
Class<?> c = Class.forName("mono.MonoPackageManager");
|
@@ -24,6 +24,7 @@ public class CalabashInstrumentationTestRunner extends InstrumentationTestRunner
|
|
24
24
|
HttpServer.instantiate(Integer.parseInt(arguments.getString("test_server_port")));
|
25
25
|
|
26
26
|
InstrumentationBackend.testPackage = arguments.getString("target_package");
|
27
|
+
InstrumentationBackend.extras = arguments;
|
27
28
|
|
28
29
|
try {
|
29
30
|
InstrumentationBackend.mainActivity = Class.forName(arguments.getString("main_activity"));
|
@@ -1,5 +1,7 @@
|
|
1
1
|
package sh.calaba.instrumentationbackend;
|
2
2
|
|
3
|
+
import android.content.Intent;
|
4
|
+
import android.os.Bundle;
|
3
5
|
import sh.calaba.instrumentationbackend.actions.Actions;
|
4
6
|
import sh.calaba.instrumentationbackend.actions.HttpServer;
|
5
7
|
import android.Manifest;
|
@@ -17,6 +19,7 @@ import com.jayway.android.robotium.solo.SoloEnhanced;
|
|
17
19
|
public class InstrumentationBackend extends ActivityInstrumentationTestCase2 {
|
18
20
|
public static String testPackage;
|
19
21
|
public static Class mainActivity;
|
22
|
+
public static Bundle extras;
|
20
23
|
|
21
24
|
private static final String TAG = "InstrumentationBackend";
|
22
25
|
|
@@ -32,7 +35,10 @@ public class InstrumentationBackend extends ActivityInstrumentationTestCase2 {
|
|
32
35
|
@Override
|
33
36
|
protected void setUp() throws Exception {
|
34
37
|
super.setUp();
|
35
|
-
|
38
|
+
Intent i = new Intent();
|
39
|
+
i.setClassName(testPackage, mainActivity.getName());
|
40
|
+
i.putExtras(extras);
|
41
|
+
setActivityIntent(i);
|
36
42
|
solo = new SoloEnhanced(getInstrumentation(), this.getActivity());
|
37
43
|
viewFetcher = new PublicViewFetcher(getInstrumentation(), this.getActivity());
|
38
44
|
actions = new Actions(getInstrumentation(), this);
|
@@ -16,7 +16,7 @@ public class WaitForScreen implements Action {
|
|
16
16
|
if (InstrumentationBackend.solo.waitForActivity(args[0], DEFAULT_TIMEOUT)) {
|
17
17
|
return Result.successResult();
|
18
18
|
} else {
|
19
|
-
String currentActivity = InstrumentationBackend.solo.getCurrentActivity().
|
19
|
+
String currentActivity = InstrumentationBackend.solo.getCurrentActivity().getClass().getSimpleName();
|
20
20
|
Result result = new Result(false, "Screen " + args[0] + " not found. Current activity is " + currentActivity);
|
21
21
|
result.addBonusInformation(currentActivity);
|
22
22
|
return result;
|
@@ -35,7 +35,7 @@ public class WaitForScreen implements Action {
|
|
35
35
|
if (InstrumentationBackend.solo.waitForActivity(args[0], timeout)) {
|
36
36
|
return Result.successResult();
|
37
37
|
} else {
|
38
|
-
String currentActivity = InstrumentationBackend.solo.getCurrentActivity().
|
38
|
+
String currentActivity = InstrumentationBackend.solo.getCurrentActivity().getClass().getSimpleName();
|
39
39
|
Result result = new Result(false, "Screen " + args[0] + " not found. Current activity is " + currentActivity);
|
40
40
|
result.addBonusInformation(currentActivity);
|
41
41
|
return result;
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: testautoa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cucumber
|
@@ -155,6 +155,7 @@ files:
|
|
155
155
|
- features-skeleton/support/hooks.rb
|
156
156
|
- irbrc
|
157
157
|
- lib/calabash-android.rb
|
158
|
+
- lib/calabash-android/abase.rb
|
158
159
|
- lib/calabash-android/calabash_steps.rb
|
159
160
|
- lib/calabash-android/canned_steps.md
|
160
161
|
- lib/calabash-android/color_helper.rb
|
@@ -162,7 +163,7 @@ files:
|
|
162
163
|
- lib/calabash-android/helpers.rb
|
163
164
|
- lib/calabash-android/lib/AXMLPrinter2.jar
|
164
165
|
- lib/calabash-android/lib/manifest_extractor.jar
|
165
|
-
- lib/calabash-android/lib/
|
166
|
+
- lib/calabash-android/lib/screenshotTaker.jar
|
166
167
|
- lib/calabash-android/lib/unsign.jar
|
167
168
|
- lib/calabash-android/management/adb.rb
|
168
169
|
- lib/calabash-android/management/app_installation.rb
|
Binary file
|