appium_lib 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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