appium_lib 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Rakefile +1 -1
- data/lib/appium_lib.rb +5 -5
- data/lib/appium_lib/android/patch.rb +11 -7
- data/lib/appium_lib/common/helper.rb +5 -3
- data/lib/appium_lib/common/patch.rb +9 -5
- data/lib/appium_lib/common/version.rb +2 -2
- data/lib/appium_lib/driver.rb +29 -13
- data/lib/appium_lib/ios/element/generic.rb +21 -7
- data/lib/appium_lib/ios/patch.rb +14 -10
- data/readme.md +4 -0
- data/release_notes.md +9 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YTA5MjVhYjAyZWEwMGM5NzQzYmI5OGRlZGU5NTkxMGM5YjY4ZDNmMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTg3MDQxYjBmZTEzZDhkNjYyODg2ZDIzYTY3YWRkMzVmMTc4NDFiZg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OGYyMzJlNGE1NWY3YWI4OWU1ZGY4Y2U2OWUzODljMzc2YzRjZDJlM2JhZTc2
|
10
|
+
OWU4Yzc3MmQzZGFiMjFiYjJmNjZmYTdkOWE3NzdlMjg5YjQwMDhlZGViNjMz
|
11
|
+
NjEwNzJlZGFkOGM3YTMzYWJlYjJkZWY3ZGQ1ZmUzOWY2MjA5NmM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTNjYmE5OTU1YzVlM2EwNjcxNzFiOTY5ZmVkYzZkY2JmMTc3YzA0MzUzZDUz
|
14
|
+
ODg2N2VmMjJkZTU4YjU2MGM4NzJhOTdjZGY2MDZkYjJhN2JhYjRhNmY5YzA5
|
15
|
+
ZTgwMjVlNmI1NzM2OGY0NjExMTdjZTdjODVlODFhZmQwM2M0ZmQ=
|
data/Rakefile
CHANGED
data/lib/appium_lib.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
$
|
3
|
+
$driver = nil
|
4
4
|
|
5
5
|
# Invoke top level methods on last created Appium driver.
|
6
6
|
def self.method_missing method, *args, &block
|
7
|
-
raise "driver is nil. called #{method}" if $
|
7
|
+
raise "driver is nil. called #{method}" if $driver == nil
|
8
8
|
|
9
|
-
$
|
10
|
-
|
11
|
-
|
9
|
+
$driver.respond_to?(method) ?
|
10
|
+
$driver.send( method, *args, &block ) :
|
11
|
+
super
|
12
12
|
end
|
13
13
|
|
14
14
|
module Appium
|
@@ -1,10 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Appium::Android
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
# class_eval inside a method because class Selenium::WebDriver::Element
|
4
|
+
# will trigger as soon as the file is required. in contrast a method
|
5
|
+
# will trigger only when invoked.
|
6
|
+
def patch_webdriver_element
|
7
|
+
Selenium::WebDriver::Element.class_eval do
|
8
|
+
# Cross platform way of entering text into a textfield
|
9
|
+
def type text
|
10
|
+
self.send_keys text
|
11
|
+
end
|
12
|
+
end
|
8
13
|
end
|
9
|
-
end
|
10
|
-
end
|
14
|
+
end
|
@@ -20,12 +20,14 @@ module Appium::Common
|
|
20
20
|
|
21
21
|
# Check every 0.5 seconds to see if block.call is true.
|
22
22
|
# Give up after 30 seconds.
|
23
|
+
# @param max_wait [Integer] the maximum time in seconds to wait for
|
24
|
+
# @param interval [Float] the time in seconds to wait after calling the block
|
23
25
|
# @param block [Block] the block to call
|
24
26
|
# @return [Object] the result of block.call
|
25
|
-
def wait &block
|
27
|
+
def wait max_wait=30, interval=0.5, &block
|
26
28
|
# Rescue Timeout::Error: execution expired
|
27
29
|
result = nil
|
28
|
-
timeout(
|
30
|
+
timeout(max_wait) { until (result = begin; block.call; rescue; end) do; sleep interval end }
|
29
31
|
result
|
30
32
|
end
|
31
33
|
|
@@ -158,4 +160,4 @@ module Appium::Common
|
|
158
160
|
def find_names name
|
159
161
|
find_elements :name, name
|
160
162
|
end
|
161
|
-
end # module Appium::Common
|
163
|
+
end # module Appium::Common
|
@@ -52,11 +52,11 @@ require 'selenium/webdriver/remote/http/default'
|
|
52
52
|
# Show http calls to the Selenium server.
|
53
53
|
#
|
54
54
|
# Invaluable for debugging.
|
55
|
-
|
56
|
-
|
55
|
+
def patch_webdriver_bridge
|
56
|
+
Selenium::WebDriver::Remote::Bridge.class_eval do
|
57
57
|
# Code from lib/selenium/webdriver/remote/bridge.rb
|
58
58
|
def raw_execute(command, opts = {}, command_hash = nil)
|
59
|
-
verb, path = COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}")
|
59
|
+
verb, path = Selenium::WebDriver::Remote::COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}")
|
60
60
|
path = path.dup
|
61
61
|
|
62
62
|
path[':session_id'] = @session_id if path.include?(':session_id')
|
@@ -75,12 +75,16 @@ module Selenium::WebDriver::Remote
|
|
75
75
|
path_str = path.sub(path_match[0], '') unless path_match.nil?
|
76
76
|
|
77
77
|
puts "#{verb} #{path_str}"
|
78
|
-
|
78
|
+
unless command_hash.nil? || command_hash.length == 0
|
79
|
+
print_command = command_hash.clone
|
80
|
+
print_command.delete :args if print_command[:args] == []
|
81
|
+
ap print_command
|
82
|
+
end
|
79
83
|
# puts "verb: #{verb}, path #{path}, command_hash #{command_hash.to_json}"
|
80
84
|
http.call verb, path, command_hash
|
81
85
|
end # def
|
82
86
|
end # class
|
83
|
-
end
|
87
|
+
end # def
|
84
88
|
|
85
89
|
# Print Appium's origValue error messages.
|
86
90
|
class Selenium::WebDriver::Remote::Response
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Appium
|
3
3
|
# Version and Date are defined on the 'Appium' module, not 'Appium::Common'
|
4
|
-
VERSION = '0.3.
|
5
|
-
DATE = '2013-04-
|
4
|
+
VERSION = '0.3.4' unless defined? ::Appium::VERSION
|
5
|
+
DATE = '2013-04-30' unless defined? ::Appium::DATE
|
6
6
|
end
|
data/lib/appium_lib/driver.rb
CHANGED
@@ -37,32 +37,42 @@ module Appium
|
|
37
37
|
attr_reader :app_path, :app_name, :app_package, :app_activity,
|
38
38
|
:app_wait_activity, :sauce_username, :sauce_access_key,
|
39
39
|
:port, :os, :ios_js
|
40
|
-
def initialize
|
40
|
+
def initialize options={}
|
41
|
+
# quit last driver
|
42
|
+
$driver.driver_quit if $driver
|
43
|
+
|
44
|
+
opts = {}
|
45
|
+
# convert to downcased symbols
|
46
|
+
options.each_pair { |k,v| opts[k.to_s.downcase.strip.intern] = v }
|
47
|
+
|
41
48
|
opts = {} if opts.nil?
|
42
49
|
# Path to the .apk, .app or .app.zip.
|
43
50
|
# The path can be local or remote for Sauce.
|
44
|
-
@app_path = opts.fetch
|
51
|
+
@app_path = opts.fetch :app_path, ENV['APP_PATH']
|
45
52
|
raise 'APP_PATH must be set.' if @app_path.nil?
|
46
53
|
|
47
54
|
# The name to use for the test run on Sauce.
|
48
|
-
@app_name = opts.fetch
|
55
|
+
@app_name = opts.fetch :app_name, ENV['APP_NAME']
|
56
|
+
|
57
|
+
# If key or env is defined, use selendroid else nil
|
58
|
+
@selendroid = opts.key?(:selendroid) || ENV['SELENDROID'] ? 'selendroid' : nil
|
49
59
|
|
50
60
|
# Android app package
|
51
|
-
@app_package = opts.fetch
|
61
|
+
@app_package = opts.fetch :app_package, ENV['APP_PACKAGE']
|
52
62
|
|
53
63
|
# Android app starting activity.
|
54
|
-
@app_activity = opts.fetch
|
64
|
+
@app_activity = opts.fetch :app_activity, ENV['APP_ACTIVITY']
|
55
65
|
|
56
66
|
# Android app waiting activity
|
57
|
-
@app_wait_activity = opts.fetch
|
67
|
+
@app_wait_activity = opts.fetch :app_wait_activity, ENV['APP_WAIT_ACTIVITY']
|
58
68
|
|
59
69
|
# Sauce Username
|
60
|
-
@sauce_username = opts.fetch
|
70
|
+
@sauce_username = opts.fetch :sauce_username, ENV['SAUCE_USERNAME']
|
61
71
|
|
62
72
|
# Sauce Key
|
63
|
-
@sauce_access_key = opts.fetch
|
73
|
+
@sauce_access_key = opts.fetch :sauce_access_key, ENV['SAUCE_ACCESS_KEY']
|
64
74
|
|
65
|
-
@port = opts.fetch
|
75
|
+
@port = opts.fetch :port, ENV['PORT'] || 4723
|
66
76
|
|
67
77
|
@os = :ios
|
68
78
|
@os = :android if @app_path.end_with?('.apk') || @app_path.end_with?('.apk.zip')
|
@@ -81,18 +91,24 @@ module Appium
|
|
81
91
|
extend Appium::Ios
|
82
92
|
end
|
83
93
|
|
94
|
+
# apply os specific patches
|
95
|
+
patch_webdriver_element
|
96
|
+
|
97
|
+
# enable debug patch
|
98
|
+
patch_webdriver_bridge if opts.fetch :debug, defined?(Pry)
|
99
|
+
|
84
100
|
# Save global reference to last created Appium driver for top level methods.
|
85
|
-
$
|
101
|
+
$driver = self
|
86
102
|
|
87
103
|
# Promote exactly once the first time the driver is created.
|
88
104
|
# Subsequent drivers do not trigger promotion.
|
89
105
|
unless @@loaded
|
90
106
|
@@loaded = true
|
91
107
|
# Promote Appium driver methods to Object instance methods.
|
92
|
-
$
|
108
|
+
$driver.public_methods(false).each do | m |
|
93
109
|
Object.class_eval do
|
94
110
|
define_method m do | *args, &block |
|
95
|
-
$
|
111
|
+
$driver.send m, *args, &block
|
96
112
|
end
|
97
113
|
end
|
98
114
|
end
|
@@ -106,7 +122,7 @@ module Appium
|
|
106
122
|
browserName: 'Android',
|
107
123
|
platform: 'LINUX',
|
108
124
|
version: '4.1',
|
109
|
-
device: 'Android',
|
125
|
+
device: @selendroid || 'Android',
|
110
126
|
name: @app_name || 'Ruby Console Android Appium',
|
111
127
|
app: absolute_app_path,
|
112
128
|
:'app-package' => @app_package,
|
@@ -31,22 +31,35 @@ module Appium::Ios
|
|
31
31
|
# execute_script 'au.mainApp.getNameContains("sign")'
|
32
32
|
# execute_script 'au.mainApp.getNameContains("zzz")'
|
33
33
|
# must check .isVisible or a hidden element may be returned.
|
34
|
-
# .tap()
|
34
|
+
# .tap() may error on invisible elements.
|
35
|
+
# if there are no visible elements though, then it's useful
|
36
|
+
# to .tap() on an invisible element.
|
35
37
|
<<-JS
|
36
38
|
UIAElement.prototype.getNameContains = function(targetName) {
|
37
39
|
var target = UIATarget.localTarget();
|
38
40
|
target.pushTimeout(0);
|
39
|
-
var search = "
|
41
|
+
var search = "name contains[c] '" + targetName + "' || label contains[c] '" + targetName + "'";
|
42
|
+
var result = {};
|
43
|
+
result.type = function() { return 'UIAElementNil'; };
|
44
|
+
result.isVisible = function() { return -1; };
|
45
|
+
|
40
46
|
var searchElements = function(element) {
|
41
47
|
var children = element.elements();
|
42
|
-
var
|
43
|
-
|
44
|
-
|
48
|
+
var results = children.withPredicate(search);
|
49
|
+
|
50
|
+
for (var resIdx = 0, resLen = results.length; resIdx < resLen; resIdx++) {
|
51
|
+
var tmp = results[resIdx];
|
52
|
+
if (tmp.type() !== 'UIAElementNil') {
|
53
|
+
result = tmp;
|
54
|
+
if (tmp.isVisible() === 1) {
|
55
|
+
return tmp;
|
56
|
+
}
|
57
|
+
}
|
45
58
|
}
|
46
59
|
|
47
60
|
for ( var a = 0, len = children.length; a < len; a++) {
|
48
|
-
|
49
|
-
if (result.type() !== 'UIAElementNil') {
|
61
|
+
searchElements(children[a]);
|
62
|
+
if (result.type() !== 'UIAElementNil' && result.isVisible() === 1) {
|
50
63
|
return result;
|
51
64
|
}
|
52
65
|
}
|
@@ -63,6 +76,7 @@ module Appium::Ios
|
|
63
76
|
};
|
64
77
|
}
|
65
78
|
|
79
|
+
console.log("Match is visible? " + result.isVisible())
|
66
80
|
return {
|
67
81
|
status: 0,
|
68
82
|
value: {ELEMENT: au.getId(result)}
|
data/lib/appium_lib/ios/patch.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Appium::Ios
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
# class_eval inside a method because class Selenium::WebDriver::Element
|
4
|
+
# will trigger as soon as the file is required. in contrast a method
|
5
|
+
# will trigger only when invoked.
|
6
|
+
def patch_webdriver_element
|
7
|
+
Selenium::WebDriver::Element.class_eval do
|
8
|
+
# Cross platform way of entering text into a textfield
|
9
|
+
def type text
|
10
|
+
# enter text then tap window to hide the keyboard.
|
11
|
+
js = <<-JS
|
12
|
+
au.getElement('#{self.ref}').setValue('#{text}');
|
13
|
+
au.lookup('window')[0].tap();
|
14
|
+
JS
|
15
|
+
@driver.execute_script js
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
data/readme.md
CHANGED
@@ -8,6 +8,10 @@ Helper methods for writing cross platform (iPad, iPhone, Android) tests in Ruby
|
|
8
8
|
|
9
9
|
Make sure you're using Ruby 1.9.3+ with upgraded rubygems and bundler.
|
10
10
|
|
11
|
+
#### Start appium server
|
12
|
+
|
13
|
+
`node server.js -V --fast-reset --without-delay`
|
14
|
+
|
11
15
|
#### Install / Upgrade
|
12
16
|
|
13
17
|
Update rubygems and bundler.
|
data/release_notes.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
#### v0.3.3 2013-04-27
|
2
|
+
|
3
|
+
- [b0ca37c](https://github.com/appium/ruby_lib/commit/b0ca37cfe47318f029e1f2ad498a5c08338016d7) Release 0.3.3
|
4
|
+
- [e7f55d9](https://github.com/appium/ruby_lib/commit/e7f55d92181660ea188a5123e6e4f447389c8d6d) Add driver method
|
5
|
+
- [6d381fe](https://github.com/appium/ruby_lib/commit/6d381fe029bd9a5c11aa4d1a322d6afb603c6434) Update readme.md
|
6
|
+
- [07da208](https://github.com/appium/ruby_lib/commit/07da208973ea4de64ec9605ef5dd38884771e8c6) Add troubleshooting steps
|
7
|
+
- [7df8ddc](https://github.com/appium/ruby_lib/commit/7df8ddcd0edb294abaddd2424f0f6b45f086fb53) Update release notes
|
8
|
+
|
9
|
+
|
1
10
|
#### v0.3.2 2013-04-26
|
2
11
|
|
3
12
|
- [eee6632](https://github.com/appium/ruby_lib/commit/eee6632251c40c8b2d6be9a361f429d7c89762f8) Release 0.3.2
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appium_lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- code@bootstraponline.com
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-04-
|
11
|
+
date: 2013-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: selenium-webdriver
|