testautoa 0.4.2 → 0.4.3
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/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
|