appium_lib 0.24.1 → 1.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.
- checksums.yaml +4 -4
- data/Rakefile +17 -8
- data/android_tests/Gemfile +1 -0
- data/android_tests/LICENSE-2.0.txt +202 -0
- data/android_tests/Rakefile +61 -0
- data/android_tests/api.apk +0 -0
- data/android_tests/appium.txt +3 -0
- data/android_tests/flaky.txt +1 -0
- data/android_tests/lib/android/specs/android/dynamic.rb +5 -0
- data/android_tests/lib/android/specs/android/element/alert.rb +41 -0
- data/android_tests/lib/android/specs/android/element/button.rb +55 -0
- data/android_tests/lib/android/specs/android/element/generic.rb +48 -0
- data/android_tests/lib/android/specs/android/element/text.rb +39 -0
- data/android_tests/lib/android/specs/android/element/textfield.rb +60 -0
- data/android_tests/lib/android/specs/android/helper.rb +80 -0
- data/android_tests/lib/android/specs/android/patch.rb +14 -0
- data/android_tests/lib/android/specs/common/device.rb +117 -0
- data/android_tests/lib/android/specs/common/element/window.rb +9 -0
- data/android_tests/lib/android/specs/common/helper.rb +112 -0
- data/android_tests/lib/android/specs/common/patch.rb +69 -0
- data/android_tests/lib/android/specs/common/version.rb +9 -0
- data/android_tests/lib/android/specs/driver.rb +174 -0
- data/android_tests/lib/format.rb +49 -0
- data/android_tests/lib/run.rb +72 -0
- data/android_tests/readme.md +27 -0
- data/appium_lib.gemspec +8 -5
- data/docs/android_docs.md +1052 -716
- data/docs/ios_docs.md +657 -834
- data/docs_gen/make_docs.rb +1 -3
- data/ios_tests/Gemfile +1 -0
- data/ios_tests/LICENSE-2.0.txt +202 -0
- data/ios_tests/Rakefile +47 -0
- data/ios_tests/UICatalog.app.zip +0 -0
- data/ios_tests/UICatalog.app/12-6AM.png +0 -0
- data/ios_tests/UICatalog.app/12-6PM.png +0 -0
- data/ios_tests/UICatalog.app/6-12AM.png +0 -0
- data/ios_tests/UICatalog.app/6-12PM.png +0 -0
- data/ios_tests/UICatalog.app/Default-568h@2x.png +0 -0
- data/ios_tests/UICatalog.app/Default@2x.png +0 -0
- data/ios_tests/UICatalog.app/Info.plist +0 -0
- data/ios_tests/UICatalog.app/PkgInfo +1 -0
- data/ios_tests/UICatalog.app/UIButton_custom.png +0 -0
- data/ios_tests/UICatalog.app/UICatalog +0 -0
- data/ios_tests/UICatalog.app/blueButton.png +0 -0
- data/ios_tests/UICatalog.app/bookmarkImage.png +0 -0
- data/ios_tests/UICatalog.app/bookmarkImageHighlighted.png +0 -0
- data/ios_tests/UICatalog.app/divider.png +0 -0
- data/ios_tests/UICatalog.app/en.lproj/AlertsViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/ButtonsViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/ControlsViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/ImagesViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/Localizable.strings +0 -0
- data/ios_tests/UICatalog.app/en.lproj/MainWindow.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/PickerViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/SearchBarController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/SegmentViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/TextFieldController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/TextViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/ToolbarViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/TransitionViewController.nib +0 -0
- data/ios_tests/UICatalog.app/en.lproj/WebViewController.nib +0 -0
- data/ios_tests/UICatalog.app/orangeslide.png +0 -0
- data/ios_tests/UICatalog.app/scene1.jpg +0 -0
- data/ios_tests/UICatalog.app/scene2.jpg +0 -0
- data/ios_tests/UICatalog.app/scene3.jpg +0 -0
- data/ios_tests/UICatalog.app/scene4.jpg +0 -0
- data/ios_tests/UICatalog.app/scene5.jpg +0 -0
- data/ios_tests/UICatalog.app/searchBarBackground.png +0 -0
- data/ios_tests/UICatalog.app/segment_check.png +0 -0
- data/ios_tests/UICatalog.app/segment_search.png +0 -0
- data/ios_tests/UICatalog.app/segment_tools.png +0 -0
- data/ios_tests/UICatalog.app/segmentedBackground.png +0 -0
- data/ios_tests/UICatalog.app/slider_ball.png +0 -0
- data/ios_tests/UICatalog.app/toolbarBackground.png +0 -0
- data/ios_tests/UICatalog.app/whiteButton.png +0 -0
- data/ios_tests/UICatalog.app/yellowslide.png +0 -0
- data/ios_tests/appium.txt +3 -0
- data/ios_tests/flaky.txt +1 -0
- data/ios_tests/lib/format.rb +25 -0
- data/ios_tests/lib/ios/specs/common/element/window.rb +15 -0
- data/ios_tests/lib/ios/specs/common/helper.rb +204 -0
- data/ios_tests/lib/ios/specs/common/patch.rb +50 -0
- data/ios_tests/lib/ios/specs/common/version.rb +17 -0
- data/ios_tests/lib/ios/specs/device/device.rb +82 -0
- data/ios_tests/lib/ios/specs/device/multi_touch.rb +12 -0
- data/ios_tests/lib/ios/specs/device/touch_actions.rb +15 -0
- data/ios_tests/lib/ios/specs/driver.rb +203 -0
- data/ios_tests/lib/ios/specs/ios/element/alert.rb +48 -0
- data/ios_tests/lib/ios/specs/ios/element/button.rb +58 -0
- data/ios_tests/lib/ios/specs/ios/element/generic.rb +35 -0
- data/ios_tests/lib/ios/specs/ios/element/text.rb +54 -0
- data/ios_tests/lib/ios/specs/ios/element/textfield.rb +123 -0
- data/ios_tests/lib/ios/specs/ios/helper.rb +27 -0
- data/ios_tests/lib/ios/specs/ios/patch.rb +30 -0
- data/ios_tests/lib/run.rb +106 -0
- data/ios_tests/readme.md +30 -0
- data/ios_tests/upload/sauce_storage.rb +64 -0
- data/ios_tests/upload/upload.rb +6 -0
- data/lib/appium_lib.rb +4 -14
- data/lib/appium_lib/android/dynamic.rb +30 -32
- data/lib/appium_lib/android/element/alert.rb +34 -33
- data/lib/appium_lib/android/element/button.rb +91 -0
- data/lib/appium_lib/android/element/generic.rb +51 -146
- data/lib/appium_lib/android/element/text.rb +54 -0
- data/lib/appium_lib/android/element/textfield.rb +46 -41
- data/lib/appium_lib/android/helper.rb +248 -417
- data/lib/appium_lib/android/mobile_methods.rb +17 -0
- data/lib/appium_lib/android/patch.rb +9 -8
- data/lib/appium_lib/awesome_print/ostruct.rb +33 -0
- data/lib/appium_lib/common/element/window.rb +9 -8
- data/lib/appium_lib/common/helper.rb +182 -243
- data/lib/appium_lib/common/patch.rb +65 -79
- data/lib/appium_lib/common/version.rb +2 -3
- data/lib/appium_lib/device/device.rb +339 -0
- data/lib/appium_lib/device/multi_touch.rb +94 -0
- data/lib/appium_lib/device/touch_actions.rb +142 -0
- data/lib/appium_lib/driver.rb +217 -306
- data/lib/appium_lib/ios/element/alert.rb +16 -92
- data/lib/appium_lib/ios/element/button.rb +55 -0
- data/lib/appium_lib/ios/element/generic.rb +27 -160
- data/lib/appium_lib/ios/element/text.rb +54 -0
- data/lib/appium_lib/ios/element/textfield.rb +78 -65
- data/lib/appium_lib/ios/helper.rb +300 -190
- data/lib/appium_lib/ios/mobile_methods.rb +17 -0
- data/lib/appium_lib/ios/patch.rb +55 -41
- data/lib/appium_lib/logger.rb +13 -0
- data/lib/appium_lib/rails/duplicable.rb +116 -0
- data/readme.md +6 -1
- data/release_notes.md +118 -0
- metadata +170 -12
- data/lib/appium_lib/common/element/button.rb +0 -83
- data/lib/appium_lib/common/element/text.rb +0 -61
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# rake ios['ios/element/generic']
|
|
2
|
+
describe 'ios/element/generic' do
|
|
3
|
+
def before_first
|
|
4
|
+
screen.must_equal catalog
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def uibutton_text
|
|
8
|
+
'Buttons, Various uses of UIButton'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def verify element
|
|
12
|
+
element = element.first if element.is_a? Array
|
|
13
|
+
element.name.must_equal uibutton_text
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
t 'before_first' do
|
|
17
|
+
before_first
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
t 'find' do
|
|
21
|
+
verify find 'tons'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
t 'finds' do
|
|
25
|
+
verify finds 'tons'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
t 'find_exact' do
|
|
29
|
+
verify find_exact uibutton_text
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
t 'finds_exact' do
|
|
33
|
+
verify finds_exact uibutton_text
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# rake ios['ios/element/text']
|
|
2
|
+
describe 'ios/element/text' do
|
|
3
|
+
def ui_catalog
|
|
4
|
+
'UICatalog'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def before_first
|
|
8
|
+
screen.must_equal catalog
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
t 'before_first' do
|
|
12
|
+
before_first
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
t 'e_s_texts' do
|
|
16
|
+
e_s_texts.length.must_equal 13
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
t 'first_s_text' do
|
|
20
|
+
first_s_text.text.must_equal ui_catalog
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
t 'last_s_text' do
|
|
24
|
+
last_s_text.text.must_equal ''
|
|
25
|
+
last_s_text.name.must_equal 'Transitions, Shows UIViewAnimationTransitions'
|
|
26
|
+
end
|
|
27
|
+
|
|
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
|
|
35
|
+
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
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
t 's_text_exact' do
|
|
41
|
+
# should fail
|
|
42
|
+
set_wait 0
|
|
43
|
+
act = begin; s_text_exact 'mos'; rescue; end
|
|
44
|
+
act.must_be_nil
|
|
45
|
+
set_wait
|
|
46
|
+
|
|
47
|
+
# should pass
|
|
48
|
+
s_text_exact(ui_catalog).text.must_equal ui_catalog
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
t 's_texts_exact' do
|
|
52
|
+
s_texts_exact('UICatalog').length.must_equal 1
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# rake ios[ios/element/textfield]
|
|
2
|
+
describe 'ios/element/textfield' do
|
|
3
|
+
def enter_text
|
|
4
|
+
'<enter text>'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def enter_password
|
|
8
|
+
'<enter password>'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def before_first
|
|
12
|
+
go_to_textfields
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def after_last
|
|
16
|
+
set_wait 30
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
t 'before_first' do
|
|
20
|
+
before_first
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
t 'textfield' do
|
|
24
|
+
textfield(1).text.must_equal(enter_text)
|
|
25
|
+
textfield(enter_text).text.must_equal(enter_text)
|
|
26
|
+
textfield('word').text.must_equal enter_password
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
t 'textfields' do
|
|
30
|
+
values = textfields('enter').map { |e| e.value }
|
|
31
|
+
values.include?('<enter text>').must_equal true
|
|
32
|
+
values.include?('<enter password>').must_equal true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
t 'first_textfield' do
|
|
36
|
+
first_textfield.text.must_equal enter_text
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
t 'last_textfield' do
|
|
40
|
+
last_textfield.text.must_equal enter_password
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
t 'textfield_exact' do
|
|
44
|
+
textfield_exact(enter_password).text.must_equal enter_password
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
t 'textfields_exact' do
|
|
48
|
+
textfields_exact(enter_password).first.text.must_equal enter_password
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
t 'e_textfields' do
|
|
52
|
+
e_textfields.length.must_equal 4
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def keyboard_exists?
|
|
56
|
+
!!ignore { wait_true(3) { execute_script 'au.mainApp().keyboard().type() !== "UIAElementNil"' } }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def keyboard_must_not_exist
|
|
60
|
+
keyboard_exists?.must_equal false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def keyboard_must_exist
|
|
64
|
+
keyboard_exists?.must_equal true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
t 'textfield type' do
|
|
68
|
+
# Regular send keys triggers the keyboard and doesn't dismiss
|
|
69
|
+
keyboard_must_not_exist
|
|
70
|
+
textfield(1).send_keys 'ok'
|
|
71
|
+
keyboard_must_exist
|
|
72
|
+
|
|
73
|
+
# type will dismiss the keyboard
|
|
74
|
+
message = 'type test type'
|
|
75
|
+
textfield(1).type message
|
|
76
|
+
keyboard_must_not_exist
|
|
77
|
+
textfield(1).text.must_equal message
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def must_raise_no_element &block
|
|
81
|
+
proc { block.call }.must_raise Selenium::WebDriver::Error::NoSuchElementError
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# test textfield methods with no textfields
|
|
85
|
+
|
|
86
|
+
t 'leave textfields' do
|
|
87
|
+
set_wait 1
|
|
88
|
+
leave_textfields
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
t 'no textfield' do
|
|
92
|
+
must_raise_no_element { textfield(1) }
|
|
93
|
+
must_raise_no_element { textfield('does not exist') }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
t 'no textfields' do
|
|
97
|
+
textfields('does not exist').length.must_equal 0
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
t 'no first_textfield' do
|
|
101
|
+
must_raise_no_element { first_textfield }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
t 'no last_textfield' do
|
|
105
|
+
must_raise_no_element { last_textfield }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
t 'no textfield_exact' do
|
|
109
|
+
must_raise_no_element { textfield_exact('does not exist') }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
t 'no textfields_exact' do
|
|
113
|
+
textfields_exact('does not exist').length.must_equal 0
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
t 'no e_textfields' do
|
|
117
|
+
e_textfields.length.must_equal 0
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
t 'after_last' do
|
|
121
|
+
after_last
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# rake ios[ios/helper]
|
|
2
|
+
describe 'ios/helper' do
|
|
3
|
+
def before_first
|
|
4
|
+
screen.must_equal catalog
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
t 'before_first' do
|
|
8
|
+
before_first
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
t 'ios_password' do
|
|
12
|
+
ios_password.must_equal '•'
|
|
13
|
+
ios_password(2).must_equal '•' * 2
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# todo: t 'get_page' do
|
|
17
|
+
|
|
18
|
+
# t 'page' do # writes to std out
|
|
19
|
+
|
|
20
|
+
t 'source_window' do
|
|
21
|
+
source_window.length.must_equal 11
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# todo: t 'page_window' do
|
|
25
|
+
# todo: t 'id' do
|
|
26
|
+
# todo: t 'ios_version' do
|
|
27
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# rake ios[ios/patch]
|
|
2
|
+
describe 'ios/patch' do
|
|
3
|
+
def before_first
|
|
4
|
+
screen.must_equal catalog
|
|
5
|
+
go_to_textfields
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def after_last
|
|
9
|
+
leave_textfields
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
t 'before_first' do
|
|
13
|
+
before_first
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# todo: test 'label'
|
|
17
|
+
|
|
18
|
+
t 'type' do
|
|
19
|
+
# nav to textfield
|
|
20
|
+
s_text('textfields').click
|
|
21
|
+
|
|
22
|
+
ele = first_textfield
|
|
23
|
+
ele.type 'ok'
|
|
24
|
+
ele.text.must_equal 'ok'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
t 'after_last' do
|
|
28
|
+
after_last
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'spec'
|
|
3
|
+
require 'hashdiff'
|
|
4
|
+
|
|
5
|
+
require_relative '../../lib/appium_lib'
|
|
6
|
+
|
|
7
|
+
=begin
|
|
8
|
+
Run all Android tests:
|
|
9
|
+
ruby run.rb android
|
|
10
|
+
|
|
11
|
+
Run only the view album test:
|
|
12
|
+
ruby run.rb ios view_album
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# Sanity check
|
|
16
|
+
a = OpenStruct.new x: 'ok'
|
|
17
|
+
raise 'x issue' unless a.x == 'ok'
|
|
18
|
+
|
|
19
|
+
# common methods
|
|
20
|
+
def back_click(opts={})
|
|
21
|
+
opts ||= {}
|
|
22
|
+
search_wait = opts.fetch(:wait, 60 * 1.7)
|
|
23
|
+
# iOS may have multiple 'back' buttons
|
|
24
|
+
# select the first displayed? back button.
|
|
25
|
+
wait(search_wait) do
|
|
26
|
+
button_exact('Back').click
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def leave_textfields
|
|
31
|
+
back_click
|
|
32
|
+
screen.must_equal catalog
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def go_to_textfields
|
|
36
|
+
screen.must_equal catalog
|
|
37
|
+
wait_true { s_text('textfield').click; screen == 'TextFields' } # wait for screen transition
|
|
38
|
+
screen.must_equal 'TextFields'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def screen
|
|
42
|
+
$driver.find_element(:class, 'UIANavigationBar').name
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def catalog
|
|
46
|
+
'UICatalog'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
|
|
51
|
+
caps = Appium.load_appium_txt file: File.expand_path('..', __FILE__), verbose: true
|
|
52
|
+
caps = caps.merge({ appium_lib: { debug: true, wait: 30 } })
|
|
53
|
+
|
|
54
|
+
dir = File.expand_path '..', __FILE__
|
|
55
|
+
device = ARGV[0].downcase.strip
|
|
56
|
+
devices = %w[ android selendroid ios ]
|
|
57
|
+
raise 'Expected android, selendroid or ios as first argument' unless devices.include? device
|
|
58
|
+
|
|
59
|
+
one_test = ARGV[1]
|
|
60
|
+
test_dir = "/#{device}/"
|
|
61
|
+
|
|
62
|
+
caps[:app] = ENV['SAUCE_PATH'] if ENV['SAUCE_USERNAME'] && ENV['SAUCE_ACCESS_KEY']
|
|
63
|
+
|
|
64
|
+
trace_files = []
|
|
65
|
+
|
|
66
|
+
if one_test
|
|
67
|
+
unless File.exists? one_test
|
|
68
|
+
# ensure ext is .rb
|
|
69
|
+
one_test = File.join(File.dirname(one_test),
|
|
70
|
+
File.basename(one_test, '.*') + '.rb')
|
|
71
|
+
one_test = File.join(dir, test_dir + 'specs/', one_test)
|
|
72
|
+
else
|
|
73
|
+
one_test = File.expand_path one_test
|
|
74
|
+
end
|
|
75
|
+
raise "\nTest #{one_test} does not exist.\n" unless File.exists?(one_test)
|
|
76
|
+
Appium::Driver.new(caps).start_driver
|
|
77
|
+
# require support (common.rb)
|
|
78
|
+
Dir.glob(File.join dir, test_dir + '/*.rb') do |test|
|
|
79
|
+
require test
|
|
80
|
+
trace_files << test
|
|
81
|
+
end
|
|
82
|
+
puts "Loading one test: #{one_test}"
|
|
83
|
+
require one_test
|
|
84
|
+
trace_files << one_test
|
|
85
|
+
else
|
|
86
|
+
# require all
|
|
87
|
+
Dir.glob(File.join dir, test_dir + '**/*.rb') do |test|
|
|
88
|
+
# load all tests
|
|
89
|
+
trace_files << test
|
|
90
|
+
puts " #{File.basename(test, '.*')}"
|
|
91
|
+
require test
|
|
92
|
+
end
|
|
93
|
+
Appium::Driver.new(caps).start_driver
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
trace_files.map! do |f|
|
|
97
|
+
f = File.expand_path f
|
|
98
|
+
# ensure all traced files end in .rb
|
|
99
|
+
f = File.join(File.dirname(f), File.basename(f, '.*') + '.rb')
|
|
100
|
+
f
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Exit after tests.
|
|
104
|
+
Minitest.after_run { $driver.x if $driver }
|
|
105
|
+
# Run Minitest. Provide test file array for tracing.
|
|
106
|
+
Minitest.run_specs({ :trace => trace_files })
|
data/ios_tests/readme.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
ruby_lib_ios
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
ruby_lib's iOS tests. Requires `Ruby 1.9.3` or better.
|
|
5
|
+
|
|
6
|
+
- `rake install` Install gems required to run the tests.
|
|
7
|
+
- `rake ios` Run all tests.
|
|
8
|
+
- `rake` Run all the test. Same as `rake ios`
|
|
9
|
+
- `rake ios['ios/element/generic']` Run a single test.
|
|
10
|
+
- `arc` Opens the Appium Ruby Console (arc). Enables interactive testing.
|
|
11
|
+
- `gem install appium_console` if it's not installed already.
|
|
12
|
+
|
|
13
|
+
`UICatalog6.1` is from [appium/appium](https://github.com/appium/appium/blob/master/assets/UICatalog6.1.app.zip)
|
|
14
|
+
|
|
15
|
+
The tests are now run against `iPhone Simulator 7.0.3 (11B508)`
|
|
16
|
+
|
|
17
|
+
#### Documentation
|
|
18
|
+
|
|
19
|
+
- [Installing Appium on OS X](https://github.com/appium/ruby_console/blob/master/osx.md)
|
|
20
|
+
- [Overview](https://github.com/appium/ruby_lib/blob/master/docs/docs.md)
|
|
21
|
+
- [iOS methods](https://github.com/appium/ruby_lib/blob/master/docs/ios_docs.md)
|
|
22
|
+
- [Minitest Expectations](http://ruby-doc.org/stdlib-1.9.3/libdoc/minitest/spec/rdoc/MiniTest/Expectations.html)
|
|
23
|
+
|
|
24
|
+
--
|
|
25
|
+
|
|
26
|
+
```java
|
|
27
|
+
Finished in 1 min 49 secs
|
|
28
|
+
|
|
29
|
+
101 runs, 130 assertions, 0 failures, 0 errors, 0 skips
|
|
30
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
See docs @ http://saucelabs.com/docs/rest#storage
|
|
3
|
+
|
|
4
|
+
s = SauceStorage.new username: 'my_user_name', key: '00', debug: true
|
|
5
|
+
|
|
6
|
+
# or if you have SAUCE_USERNAME and SAUCE_ACCESS_KEY in env already
|
|
7
|
+
|
|
8
|
+
s = SauceStorage.new debug: true
|
|
9
|
+
|
|
10
|
+
# list all files
|
|
11
|
+
s.files
|
|
12
|
+
|
|
13
|
+
# upload a file
|
|
14
|
+
s.upload '/tmp/sauce/test.zip'
|
|
15
|
+
|
|
16
|
+
> s.files
|
|
17
|
+
=> [{"size"=>8,
|
|
18
|
+
"mtime"=>1367700857.1011374,
|
|
19
|
+
"name"=>"test.zip",
|
|
20
|
+
"md5"=>"d8064dccc0b399d37c73ffa9661a79b6"}]
|
|
21
|
+
> s.upload '/tmp/sauce/test.zip'
|
|
22
|
+
Uploaded /tmp/sauce/test.zip
|
|
23
|
+
local_md5: 764efa883dda1e11db47671c4a3bbd9e
|
|
24
|
+
remote_md5: 764efa883dda1e11db47671c4a3bbd9e
|
|
25
|
+
=end
|
|
26
|
+
require 'rubygems'
|
|
27
|
+
require 'restclient'
|
|
28
|
+
require 'json'
|
|
29
|
+
|
|
30
|
+
class SauceStorage
|
|
31
|
+
attr_reader :username, :key, :url, :debug
|
|
32
|
+
def initialize opts
|
|
33
|
+
@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
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def upload file_path
|
|
40
|
+
file_name = File.basename file_path
|
|
41
|
+
file = File.new file_path
|
|
42
|
+
local_md5 = Digest::MD5.hexdigest File.read file_path
|
|
43
|
+
|
|
44
|
+
self.files.each do |file|
|
|
45
|
+
if file['md5'] == local_md5
|
|
46
|
+
puts 'File already uploaded' if @debug
|
|
47
|
+
return true
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
url = "#{@url}/#{file_name}?overwrite=plz"
|
|
52
|
+
remote_md5 = JSON.parse( RestClient.post url, file, content_type: 'application/octet-stream' )['md5']
|
|
53
|
+
if @debug
|
|
54
|
+
puts "Uploaded #{file_path}"
|
|
55
|
+
puts " local_md5: #{local_md5}"
|
|
56
|
+
puts "remote_md5: #{remote_md5}"
|
|
57
|
+
end
|
|
58
|
+
local_md5 == remote_md5
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def files
|
|
62
|
+
JSON.parse( RestClient.get @url )['files']
|
|
63
|
+
end
|
|
64
|
+
end
|