appium_lib 1.0.0 → 2.0.0

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +48 -14
  3. data/android_tests/Rakefile +5 -2
  4. data/android_tests/api.apk +0 -0
  5. data/android_tests/lib/android/specs/android/element/alert.rb +1 -1
  6. data/android_tests/lib/android/specs/android/element/button.rb +1 -4
  7. data/android_tests/lib/android/specs/android/element/text.rb +15 -18
  8. data/android_tests/lib/android/specs/android/element/textfield.rb +1 -4
  9. data/android_tests/lib/android/specs/android/helper.rb +4 -6
  10. data/android_tests/lib/android/specs/common/device.rb +16 -6
  11. data/android_tests/lib/android/specs/common/helper.rb +6 -6
  12. data/android_tests/lib/android/specs/common/patch.rb +3 -3
  13. data/android_tests/lib/android/specs/driver.rb +1 -1
  14. data/appium_lib.gemspec +11 -11
  15. data/docs/android_docs.md +193 -210
  16. data/docs/ios_docs.md +505 -177
  17. data/docs/migration.md +27 -0
  18. data/docs_gen/make_docs.rb +17 -17
  19. data/ios_tests/Rakefile +6 -3
  20. data/ios_tests/lib/ios/specs/common/helper.rb +1 -1
  21. data/ios_tests/lib/ios/specs/common/patch.rb +2 -2
  22. data/ios_tests/lib/ios/specs/device/device.rb +3 -2
  23. data/ios_tests/lib/ios/specs/device/multi_touch.rb +1 -1
  24. data/ios_tests/lib/ios/specs/device/touch_actions.rb +2 -2
  25. data/ios_tests/lib/ios/specs/driver.rb +5 -5
  26. data/ios_tests/lib/ios/specs/ios/element/alert.rb +5 -5
  27. data/ios_tests/lib/ios/specs/ios/element/button.rb +2 -5
  28. data/ios_tests/lib/ios/specs/ios/element/text.rb +21 -21
  29. data/ios_tests/lib/ios/specs/ios/element/textfield.rb +1 -8
  30. data/ios_tests/lib/ios/specs/ios/helper.rb +2 -2
  31. data/ios_tests/lib/ios/specs/ios/patch.rb +1 -1
  32. data/ios_tests/lib/run.rb +1 -1
  33. data/ios_tests/upload/sauce_storage.rb +13 -12
  34. data/ios_tests/upload/upload.rb +1 -1
  35. data/lib/appium_lib/android/dynamic.rb +31 -30
  36. data/lib/appium_lib/android/element/button.rb +7 -11
  37. data/lib/appium_lib/android/element/generic.rb +5 -5
  38. data/lib/appium_lib/android/element/text.rb +8 -12
  39. data/lib/appium_lib/android/element/textfield.rb +3 -7
  40. data/lib/appium_lib/android/helper.rb +46 -10
  41. data/lib/appium_lib/common/helper.rb +4 -2
  42. data/lib/appium_lib/common/patch.rb +1 -1
  43. data/lib/appium_lib/common/version.rb +2 -2
  44. data/lib/appium_lib/device/device.rb +34 -27
  45. data/lib/appium_lib/device/multi_touch.rb +1 -1
  46. data/lib/appium_lib/device/touch_actions.rb +30 -28
  47. data/lib/appium_lib/driver.rb +3 -3
  48. data/lib/appium_lib/ios/element/button.rb +4 -8
  49. data/lib/appium_lib/ios/element/text.rb +8 -12
  50. data/lib/appium_lib/ios/element/textfield.rb +3 -7
  51. data/lib/appium_lib/ios/helper.rb +70 -40
  52. data/readme.md +6 -70
  53. data/release_notes.md +26 -0
  54. metadata +3 -2
data/docs/migration.md ADDED
@@ -0,0 +1,27 @@
1
+ ### Breaking Changes in 2.0
2
+
3
+ In 2.0, the e_* methods have been renamed.
4
+
5
+ Old | New
6
+ :--|:--
7
+ `e_buttons` | `buttons`
8
+ `e_s_texts` | `texts`
9
+ `e_textfields` | `textfields`
10
+
11
+ All s_texts methods have been renamed.
12
+
13
+ Old | New
14
+ :--|:--
15
+ `s_text` | `text`
16
+ `s_texts` | `texts`
17
+ `first_s_text` | `first_text`
18
+ `last_s_text` | `last_text`
19
+ `s_text_exact` | `text_exact`
20
+ `s_texts_exact` | `texts_exact`
21
+
22
+ Other changes:
23
+
24
+ Old | New
25
+ :--|:--
26
+ `press_for_duration` | `long_press`
27
+ `current_context=` | `set_context`
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'yard'
3
3
 
4
4
  def space amount
5
- ' ' * amount
5
+ ' ' * amount
6
6
  end
7
7
 
8
8
  def last_sha
@@ -17,18 +17,18 @@ def mobj_to_md obj
17
17
 
18
18
  # skip class vars
19
19
  if sig.start_with?('@@') ||
20
- # skip methods marked private
21
- obj.tag('private') ||
22
- # skip date and version from version.rb
23
- obj.name.match(/DATE|VERSION/)
24
- return out
20
+ # skip methods marked private
21
+ obj.tag('private') ||
22
+ # skip date and version from version.rb
23
+ obj.name.match(/DATE|VERSION/)
24
+ return out
25
25
  end
26
26
 
27
27
  method_path = obj.file.split('/lib/').last
28
- os = method_path.downcase.match /ios|android/
29
- out += "##### [#{obj.name.to_s}](https://github.com/appium/ruby_lib/blob/#{last_sha}/lib/#{method_path}#L#{obj.line}) #{os}\n\n"
30
- out += "> #{obj.signature}\n\n"
31
- out += "#{obj.docstring}\n\n"
28
+ os = method_path.downcase.match /ios|android/
29
+ out += "##### [#{obj.name.to_s}](https://github.com/appium/ruby_lib/blob/#{last_sha}/lib/#{method_path}#L#{obj.line}) #{os}\n\n"
30
+ out += "> #{obj.signature}\n\n"
31
+ out += "#{obj.docstring}\n\n"
32
32
 
33
33
 
34
34
  indent = space 5
@@ -56,12 +56,12 @@ def run out_file, globs
56
56
  puts "Globbing: #{globs}"
57
57
  puts "Writing: #{out_file}"
58
58
  YARD::Parser::SourceParser.parse globs
59
- File.open(out_file, 'w') do | file |
60
- entries = YARD::Registry.entries
59
+ File.open(out_file, 'w') do |file|
60
+ entries = YARD::Registry.entries
61
61
  entries_length = entries.length
62
62
  puts "Processing: #{entries_length} entries"
63
63
  raise 'No entries to process' if entries_length <= 0
64
- YARD::Registry.entries.each do | entry |
64
+ YARD::Registry.entries.each do |entry|
65
65
  file.write mobj_to_md entry
66
66
  end
67
67
  end
@@ -71,14 +71,14 @@ end
71
71
 
72
72
  def globs paths
73
73
  # Convert single string to array for map
74
- paths = [ paths ] unless paths.kind_of? Array
74
+ paths = [paths] unless paths.kind_of? Array
75
75
  # Adjust path based on system
76
76
  paths.map! { |path| "#{Dir.pwd}#{path}" }
77
77
  end
78
78
 
79
- common_globs = '/lib/appium_lib/*.rb', '/lib/appium_lib/device/*.rb', '/lib/appium_lib/common/**/*.rb'
80
- android_globs = common_globs + [ '/lib/appium_lib/android/**/*.rb' ]
81
- ios_globs = common_globs + [ '/lib/appium_lib/ios/**/*.rb' ]
79
+ common_globs = '/lib/appium_lib/*.rb', '/lib/appium_lib/device/*.rb', '/lib/appium_lib/common/**/*.rb'
80
+ android_globs = common_globs + ['/lib/appium_lib/android/**/*.rb']
81
+ ios_globs = common_globs + ['/lib/appium_lib/ios/**/*.rb']
82
82
 
83
83
  run 'docs/android_docs.md', globs(android_globs)
84
84
 
data/ios_tests/Rakefile CHANGED
@@ -5,7 +5,10 @@ task :default => :ios
5
5
 
6
6
  # Run sh and ignore exception
7
7
  def run_sh cmd
8
- begin; sh cmd; rescue; end
8
+ begin
9
+ sh cmd
10
+ rescue
11
+ end
9
12
  end
10
13
 
11
14
  # Run cmd. On failure run install and try again.
@@ -32,8 +35,8 @@ task :ios, :args, :test_file do |args, test_file|
32
35
  # rake android['ok']
33
36
  # args = android
34
37
  # test_file = {:args=>"ok"}
35
- test_file = test_file[:args]
36
- path = File.expand_path('appium.txt', Rake.application.original_dir)
38
+ test_file = test_file[:args]
39
+ path = File.expand_path('appium.txt', Rake.application.original_dir)
37
40
  ENV['APPIUM_TXT'] = path
38
41
  puts "Rake appium.txt path is: #{path}"
39
42
  cmd = 'bundle exec ruby ./lib/run.rb ios'
@@ -65,7 +65,7 @@ must_not_raise is a no-op.
65
65
  # start page
66
66
  tag('UIANavigationBar').name.must_equal 'UICatalog'
67
67
  # nav to new page.
68
- wait_true { s_text('buttons').click; tag('UIANavigationBar').name == 'Buttons' }
68
+ wait_true { text('buttons').click; tag('UIANavigationBar').name == 'Buttons' }
69
69
  tag('UIANavigationBar').name.must_equal 'Buttons'
70
70
  # go back
71
71
  back_click
@@ -19,13 +19,13 @@ describe 'common/patch.rb' do
19
19
  # todo: t 'value' do; end
20
20
 
21
21
  t 'name' do
22
- first_s_text.name.must_equal 'UICatalog'
22
+ first_text.name.must_equal 'UICatalog'
23
23
  end
24
24
 
25
25
  # t 'tag_name' do; end # Doesn't work on Android
26
26
 
27
27
  t 'location_rel' do
28
- loc = first_s_text.location_rel
28
+ loc = first_text.location_rel
29
29
  loc.x.class.must_equal String
30
30
  loc.y.class.must_equal String
31
31
  end
@@ -55,6 +55,7 @@ describe 'device/device' do
55
55
 
56
56
  t 'app_strings' do
57
57
  app_strings.must_include "SearchBarExplain"
58
+ app_strings('en').must_include "SearchBarExplain"
58
59
  end
59
60
 
60
61
  t 'action_chain' do
@@ -66,11 +67,11 @@ describe 'device/device' do
66
67
  end
67
68
 
68
69
  t 'swipe' do
69
- swipe start_x: 75, start_y: 500, end_x: 75, end_y: 0, duration: 0.8
70
+ swipe start_x: 75, start_y: 500, end_x: 75, end_y: 0, duration: 800
70
71
  end
71
72
 
72
73
  t 'pinch & zoom' do
73
- s_text('Images, Use of UIImageView').click
74
+ text('Images, Use of UIImageView').click
74
75
  zoom 200
75
76
  pinch 75
76
77
  end
@@ -1,5 +1,5 @@
1
1
  describe 'device/multi_touch' do
2
- t { } # place holder test
2
+ t {} # place holder test
3
3
  end
4
4
 
5
5
  # todo: write tests
@@ -1,10 +1,10 @@
1
1
  describe 'device/touch_actions' do
2
- t { } # place holder test
2
+ t {} # place holder test
3
3
  end
4
4
  # todo: write tests
5
5
  =begin
6
6
  move_to
7
- press_for_duration
7
+ long_press
8
8
  press
9
9
  release
10
10
  tap
@@ -44,8 +44,8 @@ describe 'driver' do
44
44
  debug: true }
45
45
 
46
46
  if actual != expected
47
- diff = HashDiff.diff expected, actual
48
- diff = "diff (expected, actual):\n#{diff}"
47
+ diff = HashDiff.diff expected, actual
48
+ diff = "diff (expected, actual):\n#{diff}"
49
49
  # example:
50
50
  # change :ios in expected to match 'ios' in actual
51
51
  # [["~", "caps.platformName", :ios, "ios"]]
@@ -56,8 +56,8 @@ describe 'driver' do
56
56
 
57
57
  t 'verify attributes are immutable' do
58
58
  driver_attributes[:caps][:app] = 'fake'
59
- actual = File.basename driver_attributes[:caps][:app]
60
- expected = 'UICatalog.app'
59
+ actual = File.basename driver_attributes[:caps][:app]
60
+ expected = 'UICatalog.app'
61
61
  actual.must_equal expected
62
62
  end
63
63
 
@@ -139,7 +139,7 @@ describe 'driver' do
139
139
 
140
140
  t 'restart' do
141
141
  restart
142
- s_text 'buttons'
142
+ text 'buttons'
143
143
  end
144
144
 
145
145
  t 'driver' do
@@ -2,7 +2,7 @@
2
2
  describe 'ios/element/alert' do
3
3
  def nav_once
4
4
  screen.must_equal catalog
5
- wait_true { s_text('alerts').click; tag('UIANavigationBar').name == 'Alerts' } # wait for true
5
+ wait_true { text('alerts').click; tag('UIANavigationBar').name == 'Alerts' } # wait for true
6
6
  tag('UIANavigationBar').name.must_equal 'Alerts'
7
7
 
8
8
  # redefine method as no-op after it's invoked once
@@ -10,7 +10,7 @@ describe 'ios/element/alert' do
10
10
  end
11
11
 
12
12
  def after_last
13
- alert_accept if exists { s_text('UIActionSheet <title>') }
13
+ alert_accept if exists { text('UIActionSheet <title>') }
14
14
  back_click
15
15
  screen.must_equal catalog
16
16
  sleep 1
@@ -23,9 +23,9 @@ describe 'ios/element/alert' do
23
23
 
24
24
  def open_alert
25
25
  wait_true do
26
- return true if exists { s_text('UIActionSheet <title>') }
27
- s_text('Show OK-Cancel').click
28
- s_text('UIActionSheet <title>').displayed?
26
+ return true if exists { text('UIActionSheet <title>') }
27
+ text('Show OK-Cancel').click
28
+ text('UIActionSheet <title>').displayed?
29
29
  end
30
30
  end
31
31
 
@@ -3,7 +3,7 @@ describe 'ios/element/button' do
3
3
  def before_first
4
4
  screen.must_equal catalog
5
5
  # nav to buttons activity
6
- wait { s_text('buttons').click }
6
+ wait { text('buttons').click }
7
7
  end
8
8
 
9
9
  def after_last
@@ -30,6 +30,7 @@ describe 'ios/element/button' do
30
30
  t 'buttons' do
31
31
  exp = ['Back', 'Gray', 'Right pointing arrow']
32
32
  buttons('a').map { |e| e.name }.must_equal exp
33
+ buttons.length.must_equal 4
33
34
  end
34
35
 
35
36
  t 'first_button' do
@@ -48,10 +49,6 @@ describe 'ios/element/button' do
48
49
  buttons_exact(gray).first.name.must_equal gray
49
50
  end
50
51
 
51
- t 'e_buttons' do
52
- e_buttons.length.must_equal 4
53
- end
54
-
55
52
  t 'after_last' do
56
53
  after_last
57
54
  end
@@ -12,43 +12,43 @@ describe 'ios/element/text' do
12
12
  before_first
13
13
  end
14
14
 
15
- t 'e_s_texts' do
16
- e_s_texts.length.must_equal 13
15
+ t 'first_text' do
16
+ first_text.text.must_equal ui_catalog
17
17
  end
18
18
 
19
- t 'first_s_text' do
20
- first_s_text.text.must_equal ui_catalog
19
+ t 'last_text' do
20
+ last_text.text.must_equal ''
21
+ last_text.name.must_equal 'Transitions, Shows UIViewAnimationTransitions'
21
22
  end
22
23
 
23
- t 'last_s_text' do
24
- last_s_text.text.must_equal ''
25
- last_s_text.name.must_equal 'Transitions, Shows UIViewAnimationTransitions'
24
+ t 'text' do
25
+ text('mat').text.must_equal ''
26
+ text(1).text.must_equal ui_catalog
27
+ text('mat').name.must_equal 'Transitions, Shows UIViewAnimationTransitions'
26
28
  end
27
29
 
28
- t 's_text' do
29
- s_text('mat').text.must_equal ''
30
- s_text(1).text.must_equal ui_catalog
31
- s_text('mat').name.must_equal 'Transitions, Shows UIViewAnimationTransitions'
32
- end
33
-
34
- t 's_texts' do
30
+ t 'texts' do
35
31
  exp = ['Controls, Various uses of UIControl', 'Segments, Various uses of UISegmentedControl']
36
- s_texts('trol').map { |e| e.name }.must_equal exp
37
- s_texts('uses').length.must_equal 7
32
+ texts.length.must_equal 13
33
+ texts('trol').map { |e| e.name }.must_equal exp
34
+ texts('uses').length.must_equal 7
38
35
  end
39
36
 
40
- t 's_text_exact' do
37
+ t 'text_exact' do
41
38
  # should fail
42
39
  set_wait 0
43
- act = begin; s_text_exact 'mos'; rescue; end
40
+ act = begin
41
+ text_exact 'mos'
42
+ rescue
43
+ end
44
44
  act.must_be_nil
45
45
  set_wait
46
46
 
47
47
  # should pass
48
- s_text_exact(ui_catalog).text.must_equal ui_catalog
48
+ text_exact(ui_catalog).text.must_equal ui_catalog
49
49
  end
50
50
 
51
- t 's_texts_exact' do
52
- s_texts_exact('UICatalog').length.must_equal 1
51
+ t 'texts_exact' do
52
+ texts_exact('UICatalog').length.must_equal 1
53
53
  end
54
54
  end
@@ -30,6 +30,7 @@ describe 'ios/element/textfield' do
30
30
  values = textfields('enter').map { |e| e.value }
31
31
  values.include?('<enter text>').must_equal true
32
32
  values.include?('<enter password>').must_equal true
33
+ textfields.length.must_equal 4
33
34
  end
34
35
 
35
36
  t 'first_textfield' do
@@ -48,10 +49,6 @@ describe 'ios/element/textfield' do
48
49
  textfields_exact(enter_password).first.text.must_equal enter_password
49
50
  end
50
51
 
51
- t 'e_textfields' do
52
- e_textfields.length.must_equal 4
53
- end
54
-
55
52
  def keyboard_exists?
56
53
  !!ignore { wait_true(3) { execute_script 'au.mainApp().keyboard().type() !== "UIAElementNil"' } }
57
54
  end
@@ -113,10 +110,6 @@ describe 'ios/element/textfield' do
113
110
  textfields_exact('does not exist').length.must_equal 0
114
111
  end
115
112
 
116
- t 'no e_textfields' do
117
- e_textfields.length.must_equal 0
118
- end
119
-
120
113
  t 'after_last' do
121
114
  after_last
122
115
  end
@@ -9,8 +9,8 @@ describe 'ios/helper' do
9
9
  end
10
10
 
11
11
  t 'ios_password' do
12
- ios_password.must_equal ''
13
- ios_password(2).must_equal '' * 2
12
+ ios_password.must_equal 8226.chr('UTF-8')
13
+ ios_password(2).must_equal 8226.chr('UTF-8') * 2
14
14
  end
15
15
 
16
16
  # todo: t 'get_page' do
@@ -17,7 +17,7 @@ describe 'ios/patch' do
17
17
 
18
18
  t 'type' do
19
19
  # nav to textfield
20
- s_text('textfields').click
20
+ text('textfields').click
21
21
 
22
22
  ele = first_textfield
23
23
  ele.type 'ok'
data/ios_tests/lib/run.rb CHANGED
@@ -34,7 +34,7 @@ end
34
34
 
35
35
  def go_to_textfields
36
36
  screen.must_equal catalog
37
- wait_true { s_text('textfield').click; screen == 'TextFields' } # wait for screen transition
37
+ wait_true { text('textfield').click; screen == 'TextFields' } # wait for screen transition
38
38
  screen.must_equal 'TextFields'
39
39
  end
40
40
 
@@ -26,30 +26,31 @@ remote_md5: 764efa883dda1e11db47671c4a3bbd9e
26
26
  require 'rubygems'
27
27
  require 'restclient'
28
28
  require 'json'
29
-
29
+
30
30
  class SauceStorage
31
31
  attr_reader :username, :key, :url, :debug
32
+
32
33
  def initialize opts
33
34
  @username = opts.fetch :username, ENV['SAUCE_USERNAME']
34
- @key = opts.fetch :key, ENV['SAUCE_ACCESS_KEY']
35
- @url = "https://#{@username}:#{@key}@saucelabs.com/rest/v1/storage/#{@username}"
36
- @debug = opts.fetch :debug, false
35
+ @key = opts.fetch :key, ENV['SAUCE_ACCESS_KEY']
36
+ @url = "https://#{@username}:#{@key}@saucelabs.com/rest/v1/storage/#{@username}"
37
+ @debug = opts.fetch :debug, false
37
38
  end
38
-
39
+
39
40
  def upload file_path
40
41
  file_name = File.basename file_path
41
- file = File.new file_path
42
+ file = File.new file_path
42
43
  local_md5 = Digest::MD5.hexdigest File.read file_path
43
-
44
+
44
45
  self.files.each do |file|
45
46
  if file['md5'] == local_md5
46
47
  puts 'File already uploaded' if @debug
47
48
  return true
48
49
  end
49
50
  end
50
-
51
- url = "#{@url}/#{file_name}?overwrite=plz"
52
- remote_md5 = JSON.parse( RestClient.post url, file, content_type: 'application/octet-stream' )['md5']
51
+
52
+ url = "#{@url}/#{file_name}?overwrite=plz"
53
+ remote_md5 = JSON.parse(RestClient.post url, file, content_type: 'application/octet-stream')['md5']
53
54
  if @debug
54
55
  puts "Uploaded #{file_path}"
55
56
  puts " local_md5: #{local_md5}"
@@ -57,8 +58,8 @@ class SauceStorage
57
58
  end
58
59
  local_md5 == remote_md5
59
60
  end
60
-
61
+
61
62
  def files
62
- JSON.parse( RestClient.get @url )['files']
63
+ JSON.parse(RestClient.get @url)['files']
63
64
  end
64
65
  end