appium_lib 9.3.8 → 9.4.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.
@@ -79,5 +79,12 @@ finds_exact(value) # Return any elements include `value` as its name attributes.
79
79
  xpaths("//some xpaths")
80
80
  ```
81
81
 
82
+ ## Gesture
83
+ - `mobile:` commands are provided by WDA.
84
+ - Documentations
85
+ - https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ios-xctest-mobile-gestures.md
86
+ - Specs by test code
87
+ - https://github.com/appium/appium-xcuitest-driver/blob/master/test/functional/basic/gesture-e2e-specs.js
88
+
82
89
  ## Other actions
83
90
  Basically, other actions such as `type` are compatible with `automationName = Appium`.
@@ -0,0 +1,61 @@
1
+ # rake ios[ios/xcuitest_gestures]
2
+ describe 'ios/xcuitest_gestures' do
3
+ def before_first
4
+ screen.must_equal catalog
5
+ end
6
+
7
+ def after_last
8
+ screen.must_equal catalog
9
+ end
10
+
11
+ t 'before_first' do
12
+ before_first
13
+ end
14
+
15
+ t 'tap' do
16
+ element = text('controls')
17
+ tap(x: 0, y: 0, element: element)
18
+ end
19
+
20
+ t 'double_tap' do
21
+ element = button('Tinted')
22
+ double_tap(element: element)
23
+ end
24
+
25
+ t 'scroll' do
26
+ scroll direction: 'down'
27
+ text('Style Default').displayed?.must_be true
28
+ end
29
+
30
+ t 'swipe' do
31
+ swipe direction: 'down'
32
+ swipe direction: 'down'
33
+
34
+ proc { text('Style Default') }.must_raise ::Selenium::WebDriver::Error::NoSuchElementError
35
+ end
36
+
37
+ t 'pinch' do
38
+ pinch(scale: 0.5, velocity: -1)
39
+ end
40
+
41
+ t 'back to top' do
42
+ back_click
43
+ end
44
+
45
+ t 'select_picker_wheel' do
46
+ element = text('pickers')
47
+ tap(x: 0, y: 0, element: element)
48
+
49
+ e = find_element :name, 'John Appleseed'
50
+ select_picker_wheel(element: e, order: 'next')
51
+
52
+ e.displayed?.must_be false
53
+ find_element(:name, 'Serena Auroux').displayed?.must_be true
54
+
55
+ back_click
56
+ end
57
+
58
+ t 'after_last' do
59
+ after_last
60
+ end
61
+ end
@@ -7,31 +7,20 @@ module Appium
7
7
  private
8
8
 
9
9
  # @private
10
- def _button_visible_selectors(opts = {})
11
- button_index = opts.fetch :button_index, false
12
- image_button_index = opts.fetch :image_button_index, false
13
-
14
- if button_index && image_button_index
15
- "new UiSelector().className(#{Button}).instance(#{button_index});" \
16
- "new UiSelector().className(#{ImageButton}).instance(#{image_button_index});"
17
- else
18
- "new UiSelector().className(#{Button});" \
19
- "new UiSelector().className(#{ImageButton});"
20
- end
10
+ def _button_visible_selectors
11
+ "//#{Button}|#{ImageButton}"
21
12
  end
22
13
 
23
14
  # @private
24
15
  def _button_exact_string(value)
25
- button = string_visible_exact Button, value
26
- image_button = string_visible_exact ImageButton, value
27
- button + image_button
16
+ string_visible_exact(Button, value) +
17
+ string_visible_exact(ImageButton, value).sub(/\A\/\//, '|')
28
18
  end
29
19
 
30
20
  # @private
31
21
  def _button_contains_string(value)
32
- button = string_visible_contains Button, value
33
- image_button = string_visible_contains ImageButton, value
34
- button + image_button
22
+ string_visible_contains(Button, value) +
23
+ string_visible_contains(ImageButton, value).sub(/\A\/\//, '|')
35
24
  end
36
25
 
37
26
  public
@@ -47,10 +36,12 @@ module Appium
47
36
  index = value
48
37
  raise "#{index} is not a valid index. Must be >= 1" if index <= 0
49
38
 
50
- return find_element :uiautomator, _button_visible_selectors(index: index)
39
+ result = find_elements(:xpath, _button_visible_selectors)[value - 1]
40
+ raise Selenium::WebDriver::Error::NoSuchElementError unless result
41
+ return result
51
42
  end
52
43
 
53
- find_element :uiautomator, _button_contains_string(value)
44
+ find_element :xpath, _button_contains_string(value)
54
45
  end
55
46
 
56
47
  # Find all buttons containing value.
@@ -58,43 +49,36 @@ module Appium
58
49
  # @param value [String] the value to search for
59
50
  # @return [Array<Button>]
60
51
  def buttons(value = false)
61
- return find_elements :uiautomator, _button_visible_selectors unless value
62
- find_elements :uiautomator, _button_contains_string(value)
52
+ return find_elements :xpath, _button_visible_selectors unless value
53
+ find_elements :xpath, _button_contains_string(value)
63
54
  end
64
55
 
65
56
  # Find the first button.
66
57
  # @return [Button]
67
58
  def first_button
68
- find_element :uiautomator, _button_visible_selectors(button_index: 0, image_button_index: 0)
59
+ find_element :xpath, _button_visible_selectors
69
60
  end
70
61
 
71
62
  # Find the last button.
72
63
  # @return [Button]
73
64
  def last_button
74
- # uiautomator index doesn't support last
75
- # and it's 0 indexed
76
- button_index = tags(Button).length
77
- button_index -= 1 if button_index > 0
78
- image_button_index = tags(ImageButton).length
79
- image_button_index -= 1 if image_button_index > 0
80
-
81
- find_element :uiautomator,
82
- _button_visible_selectors(button_index: button_index,
83
- image_button_index: image_button_index)
65
+ result = find_elements(:xpath, _button_visible_selectors).last
66
+ raise Selenium::WebDriver::Error::NoSuchElementError unless result
67
+ result
84
68
  end
85
69
 
86
70
  # Find the first button that exactly matches value.
87
71
  # @param value [String] the value to match exactly
88
72
  # @return [Button]
89
73
  def button_exact(value)
90
- find_element :uiautomator, _button_exact_string(value)
74
+ find_element :xpath, _button_exact_string(value)
91
75
  end
92
76
 
93
77
  # Find all buttons that exactly match value.
94
78
  # @param value [String] the value to match exactly
95
79
  # @return [Array<Button>]
96
80
  def buttons_exact(value)
97
- find_elements :uiautomator, _button_exact_string(value)
81
+ find_elements :xpath, _button_exact_string(value)
98
82
  end
99
83
  end # module Android
100
84
  end # module Appium
@@ -286,19 +286,15 @@ module Appium
286
286
  # @param value [String] the value to search for
287
287
  # @return [String]
288
288
  def string_visible_contains(class_name, value)
289
- value = %("#{value}")
289
+ r_id = resource_id(value, " or @resource-id='#{value}'")
290
290
 
291
291
  if class_name == '*'
292
- return (resource_id(value, "new UiSelector().resourceId(#{value});") +
293
- "new UiSelector().descriptionContains(#{value});" \
294
- "new UiSelector().textContains(#{value});")
292
+ return "//*[contains(translate(@text,'#{value.upcase}', '#{value}'), '#{value}')" \
293
+ " or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
295
294
  end
296
295
 
297
- class_name = %("#{class_name}")
298
-
299
- resource_id(value, "new UiSelector().className(#{class_name}).resourceId(#{value});") +
300
- "new UiSelector().className(#{class_name}).descriptionContains(#{value});" \
301
- "new UiSelector().className(#{class_name}).textContains(#{value});"
296
+ "//#{class_name}[contains(translate(@text,'#{value.upcase}', '#{value}'), '#{value}')" \
297
+ " or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
302
298
  end
303
299
 
304
300
  # Find the first element that contains value
@@ -306,7 +302,7 @@ module Appium
306
302
  # @param value [String] the value to search for
307
303
  # @return [Element]
308
304
  def complex_find_contains(element, value)
309
- find_element :uiautomator, string_visible_contains(element, value)
305
+ find_element :xpath, string_visible_contains(element, value)
310
306
  end
311
307
 
312
308
  # Find all elements containing value
@@ -314,7 +310,7 @@ module Appium
314
310
  # @param value [String] the value to search for
315
311
  # @return [Array<Element>]
316
312
  def complex_finds_contains(element, value)
317
- find_elements :uiautomator, string_visible_contains(element, value)
313
+ find_elements :xpath, string_visible_contains(element, value)
318
314
  end
319
315
 
320
316
  # @private
@@ -323,19 +319,13 @@ module Appium
323
319
  # @param value [String] the value to search for
324
320
  # @return [String]
325
321
  def string_visible_exact(class_name, value)
326
- value = %("#{value}")
322
+ r_id = resource_id(value, " or @resource-id='#{value}'")
327
323
 
328
324
  if class_name == '*'
329
- return (resource_id(value, "new UiSelector().resourceId(#{value});") +
330
- "new UiSelector().description(#{value});" \
331
- "new UiSelector().text(#{value});")
325
+ return "//*[@text='#{value}' or @content-desc='#{value}'" + r_id + ']'
332
326
  end
333
327
 
334
- class_name = %("#{class_name}")
335
-
336
- resource_id(value, "new UiSelector().className(#{class_name}).resourceId(#{value});") +
337
- "new UiSelector().className(#{class_name}).description(#{value});" \
338
- "new UiSelector().className(#{class_name}).text(#{value});"
328
+ "//#{class_name}[@text='#{value}' or @content-desc='#{value}'" + r_id + ']'
339
329
  end
340
330
 
341
331
  # Find the first element exactly matching value
@@ -343,7 +333,7 @@ module Appium
343
333
  # @param value [String] the value to search for
344
334
  # @return [Element]
345
335
  def complex_find_exact(class_name, value)
346
- find_element :uiautomator, string_visible_exact(class_name, value)
336
+ find_element :xpath, string_visible_exact(class_name, value)
347
337
  end
348
338
 
349
339
  # Find all elements exactly matching value
@@ -351,7 +341,7 @@ module Appium
351
341
  # @param value [String] the value to search for
352
342
  # @return [Element]
353
343
  def complex_finds_exact(class_name, value)
354
- find_elements :uiautomator, string_visible_exact(class_name, value)
344
+ find_elements :xpath, string_visible_exact(class_name, value)
355
345
  end
356
346
 
357
347
  # Returns XML string for the current page
@@ -1,5 +1,5 @@
1
1
  module Appium
2
2
  # Version and Date are defined on the 'Appium' module, not 'Appium::Common'
3
- VERSION = '9.3.8'.freeze unless defined? ::Appium::VERSION
4
- DATE = '2017-04-13'.freeze unless defined? ::Appium::DATE
3
+ VERSION = '9.4.0'.freeze unless defined? ::Appium::VERSION
4
+ DATE = '2017-04-17'.freeze unless defined? ::Appium::DATE
5
5
  end
@@ -24,6 +24,7 @@ require_relative 'ios/element/generic'
24
24
  require_relative 'ios/element/textfield'
25
25
  require_relative 'ios/element/text'
26
26
  require_relative 'ios/mobile_methods'
27
+ require_relative 'ios/xcuitest_gestures'
27
28
 
28
29
  # android
29
30
  require_relative 'android/helper'
@@ -411,6 +412,7 @@ module Appium
411
412
  else
412
413
  # load iOS specific methods
413
414
  extend Appium::Ios
415
+ extend Appium::Ios::XcuitestGesture if automation_name_is_xcuitest? # Override touch actions
414
416
  end
415
417
 
416
418
  # apply os specific patches
@@ -0,0 +1,144 @@
1
+ module Appium
2
+ module Ios
3
+ module XcuitestGesture
4
+ # @param [string] direction Either 'up', 'down', 'left' or 'right'.
5
+ # @option opts [Element] :element Element to swipe on
6
+ #
7
+ # ```ruby
8
+ # swipe direction: "down"
9
+ # ```
10
+ def swipe(direction:, element: nil)
11
+ return unless %w(up down left right).include?(direction)
12
+
13
+ args = { direction: direction }
14
+ args[:element] = element.ref if element
15
+
16
+ execute_script 'mobile: swipe', args
17
+ end
18
+
19
+ # @param [string] direction Either 'up', 'down', 'left' or 'right'.
20
+ # @option opts [String] :name the accessibility id of the child element, to which scrolling is performed.
21
+ # @option opts [Element] :element Element id to long tap on.
22
+ # @option opts [bool] :to_visible Boolean parameter. If set to true then asks to scroll to the first visible
23
+ # element in the parent container. Has no effect if element is not set
24
+ # @option opts [String] :predicate_string the NSPredicate locator of the child element,
25
+ # to which the scrolling should be performed. Has no effect if element is not a container
26
+ #
27
+ # ```ruby
28
+ # scroll direction: "down"
29
+ # ```
30
+ def scroll(direction:, name: nil, element: nil, to_visible: nil, predicate_string: nil)
31
+ return 'Set "up", "down", "left" or "right" for :direction' unless %w(up down left right).include?(direction)
32
+
33
+ args = { direction: direction }
34
+ args[:element] = element.ref if element
35
+ args[:name] = name if name
36
+ args[:toVisible] = to_visible if to_visible
37
+ args[:predicateString] = predicate_string if predicate_string
38
+
39
+ execute_script 'mobile: scroll', args
40
+ end
41
+
42
+ # @param scale [scale] X tap coordinate of type float. Mandatory parameter
43
+ # @param velocity [float] Y tap coordinate of type float. Mandatory parameter
44
+ # @option opts [Element] :element Element id to long tap on.
45
+ #
46
+ # ```ruby
47
+ # pinch scale: 0.5, velocity: -1
48
+ # ```
49
+ def pinch(scale:, velocity: 1.0, element: nil)
50
+ return unless automation_name_is_xcuitest?
51
+
52
+ args = { scale: scale, velocity: velocity }
53
+ args[:element] = element.ref if element
54
+
55
+ execute_script 'mobile: pinch', args
56
+ end
57
+
58
+ # @param x [float] X Screen x tap coordinate of type float. Mandatory parameter only if element is not set
59
+ # @param y [float] Y Screen y tap coordinate of type float. Mandatory parameter only if element is not set
60
+ # @option opts [Element] :element Element to long tap on.
61
+ #
62
+ # ```ruby
63
+ # double_tap x: 100, y: 100
64
+ # double_tap element: find_element(:accessibility_id, "some item")
65
+ # ```
66
+ def double_tap(x: nil, y: nil, element: nil)
67
+ return 'require XCUITest(WDA)' unless automation_name_is_xcuitest?
68
+ return 'Set x, y or element' if (x.nil? || y.nil?) && element.nil?
69
+
70
+ args = element.nil? ? { x: x, y: y } : { element: element.ref }
71
+ execute_script 'mobile: doubleTap', args
72
+ end
73
+
74
+ # @param [Element] :element Element to long tap on.
75
+ #
76
+ # ```ruby
77
+ # two_finger_tap element: find_element(:accessibility_id, "some item")
78
+ # ```
79
+ def two_finger_tap(element:)
80
+ return 'require XCUITest(WDA)' unless automation_name_is_xcuitest?
81
+
82
+ args = { element: element.ref }
83
+ execute_script 'mobile: twoFingerTap', args
84
+ end
85
+
86
+ # @param x [float] X tap coordinate of type float. Mandatory parameter
87
+ # @param y [float] Y tap coordinate of type float. Mandatory parameter
88
+ # @option opts [Element] :element Element id to long tap on. x and y tap coordinates will be calculated
89
+ # relatively to the current element position on the screen if this argument is provided.
90
+ # Otherwise they should be calculated relatively to screen borders.
91
+ #
92
+ # ```ruby
93
+ # tap x: 100, y: 100
94
+ # tap x: 100, y: 100, element: find_element(:accessibility_id, "some item")
95
+ # ```
96
+ def tap(x:, y:, element: nil)
97
+ return 'require XCUITest(WDA)' unless automation_name_is_xcuitest?
98
+
99
+ args = { x: x, y: y }
100
+ args[:element] = element.ref
101
+ execute_script 'mobile: tap', args
102
+ end
103
+
104
+ # rubocop:disable Metrics/ParameterLists
105
+ # @param duration [float] Float number of seconds in range [0.5, 60]. How long the tap gesture at starting
106
+ # drag point should be before to start dragging. Mandatory parameter
107
+ # @param from_x [float] The x coordinate of starting drag point (type float). Mandatory parameter
108
+ # @param from_y [float] The y coordinate of starting drag point (type float). Mandatory parameter
109
+ # @param to_x [float] The x coordinate of ending drag point (type float). Mandatory parameter
110
+ # @param to_y [float] The y coordinate of ending drag point (type float). Mandatory parameter
111
+ # @option opts [Element] :element Element id to perform drag on. All the coordinates will be calculated
112
+ # relatively this this element position on the screen. Absolute screen coordinates are expected
113
+ # if this argument is not set
114
+ #
115
+ # ```ruby
116
+ # drag_from_to_for_duration from_x: 100, from_y: 100, to_x: 150, to_y: 150
117
+ # ```
118
+ def drag_from_to_for_duration(from_x:, from_y:, to_x:, to_y:, duration: 1.0, element: nil)
119
+ return 'require XCUITest(WDA)' unless automation_name_is_xcuitest?
120
+
121
+ args = { from_x: from_x, from_y: from_y, to_x: to_x, to_y: to_y, duration: duration }
122
+ args[:element] = element if element
123
+ execute_script 'mobile: dragFromToForDuration', args
124
+ end
125
+ # rubocop:enable Metrics/ParameterLists
126
+
127
+ # https://github.com/facebook/WebDriverAgent/pull/523
128
+ # https://github.com/appium/appium-xcuitest-driver/pull/420
129
+ # @param order [String] The order to move picker to. "next" or "previous".
130
+ # @param element [Element] Element id to perform select picker wheel on.
131
+ #
132
+ # ```ruby
133
+ # select_picker_wheel order: "next", element: find_element(:accessibility_id, "some picker")
134
+ # ```
135
+ def select_picker_wheel(element:, order:)
136
+ return 'require XCUITest(WDA)' unless automation_name_is_xcuitest?
137
+ return 'Set "next" or "previous" for :order' unless %w(next previous).include?(order)
138
+
139
+ args = { element: element.ref, order: order }
140
+ execute_script 'mobile: selectPickerWheelValue', args
141
+ end
142
+ end # module XcuitestGesture
143
+ end # module Ios
144
+ end # module Appium
@@ -1,3 +1,10 @@
1
+ #### v9.3.8 2017-04-13
2
+
3
+ - [7a7cf44](https://github.com/appium/ruby_lib/commit/7a7cf44c3cb11a90142285b8e8d731dc452b89eb) Release 9 3 8 (#540)
4
+ - [5e67b88](https://github.com/appium/ruby_lib/commit/5e67b8813950148661bc4491811a696edeffc63c) allow using TestObject server (#538)
5
+ - [9fdf89f](https://github.com/appium/ruby_lib/commit/9fdf89f9c3993730aabf1b8e25f03a773e565d98) add link to mobile gesture for XCUITets (#536)
6
+
7
+
1
8
  #### v9.3.7 2017-04-09
2
9
 
3
10
  - [8daf6f7](https://github.com/appium/ruby_lib/commit/8daf6f773c9b8acd7a89e2a9225fd834de5b4e2e) Release 9 3 7 (#535)
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: 9.3.8
4
+ version: 9.4.0
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: 2017-04-13 00:00:00.000000000 Z
11
+ date: 2017-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: selenium-webdriver
@@ -333,6 +333,7 @@ files:
333
333
  - ios_tests/lib/ios/specs/ios/helper.rb
334
334
  - ios_tests/lib/ios/specs/ios/mobile_methods.rb
335
335
  - ios_tests/lib/ios/specs/ios/patch.rb
336
+ - ios_tests/lib/ios/specs/ios/xcuitest_gestures.rb
336
337
  - ios_tests/lib/run.rb
337
338
  - ios_tests/readme.md
338
339
  - ios_tests/upload/sauce_storage.rb
@@ -368,6 +369,7 @@ files:
368
369
  - lib/appium_lib/ios/helper.rb
369
370
  - lib/appium_lib/ios/mobile_methods.rb
370
371
  - lib/appium_lib/ios/patch.rb
372
+ - lib/appium_lib/ios/xcuitest_gestures.rb
371
373
  - lib/appium_lib/logger.rb
372
374
  - lib/appium_lib/rails/duplicable.rb
373
375
  - readme.md