appium_lib 9.3.8 → 9.4.0

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