Class: Appium::TouchAction

Inherits:
Object
  • Object
show all
Defined in:
lib/appium_lib/core/device/touch_actions.rb

Overview

Perform a series of gestures, one after another. Gestures are chained together and only performed when `perform()` is called. Default is conducted by global driver.

Each method returns the object itself, so calls can be chained.

“`ruby action = TouchAction.new.press(x: 45, y: 100).wait(5).release action.perform action = TouchAction.new.swipe(.…) action.perform “`

Or each methods can call without `TouchAction.new` as the following. In this case, `perform` is called automatically. “`ruby # called `swipe(…).perform` in this method. swipe(start_x: 75, start_y: 500, offset_x: 75, offset_y: 20, duration: 500) “`

If you'd like to perform the chain with an arbitrary driver: “`ruby driver = Appium::Driver.new(opts, false).start_driver action = TouchAction.new.press(x: 45, y: 100).wait(5).release action.perform(@driver) action = TouchAction.new.swipe(.…) action.perform(@driver) “`

Constant Summary

ACTIONS =
[:move_to, :long_press, :double_tap, :two_finger_tap, :press, :release, :tap, :wait, :perform].freeze
COMPLEX_ACTIONS =
[:swipe].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTouchAction

Returns a new instance of TouchAction



47
48
49
# File 'lib/appium_lib/core/device/touch_actions.rb', line 47

def initialize
  @actions = []
end

Instance Attribute Details

#actionsObject (readonly)

Returns the value of attribute actions



45
46
47
# File 'lib/appium_lib/core/device/touch_actions.rb', line 45

def actions
  @actions
end

Instance Method Details

#cancel(driver = $driver) ⇒ Object

Does nothing, currently.



194
195
196
197
198
# File 'lib/appium_lib/core/device/touch_actions.rb', line 194

def cancel(driver = $driver)
  @actions << { action: cancel }
  driver.touch_actions @actions
  self
end

#double_tap(opts) ⇒ Object

Double tap an element on the screen

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :element (WebDriver::Element) — default: Optional

    Element to restrict scope too.

  • :x (integer)

    x co-ordinate to tap

  • :y (integer)

    y co-ordinate to tap



120
121
122
123
124
# File 'lib/appium_lib/core/device/touch_actions.rb', line 120

def double_tap(opts)
  args = opts.select { |k, _v| [:element, :x, :y].include? k }
  args = args_with_ele_ref(args)
  chain_method(:doubleTap, args) # doubleTap is what the appium server expects
end

#long_press(opts) ⇒ Object

Press down for a specific duration. Alternatively, you can use `press(…).wait(…).release()` instead of `long_press` if duration doesn't work well. github.com/appium/ruby_lib/issues/231#issuecomment-269895512 e.g. Appium::TouchAction.new.press(x: 280, y: 530).wait(2000).release.perform

Parameters:

  • element (Hash)

    a customizable set of options

  • x (Hash)

    a customizable set of options

  • y (Hash)

    a customizable set of options

  • duration (Hash)

    a customizable set of options



72
73
74
75
76
# File 'lib/appium_lib/core/device/touch_actions.rb', line 72

def long_press(opts)
  args = opts.select { |k, _v| [:element, :x, :y, :duration].include? k }
  args = args_with_ele_ref(args)
  chain_method(:longPress, args) # longPress is what the appium server expects
end

#move_to(opts) ⇒ Object

Move to the given co-ordinates.

`move_to`'s `x` and `y` have two case. One is working as coordinate, the other is working as offset.

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :x (integer)

    x co-ordinate to move to if element isn't set. Works as an offset if x is set with Element.

  • :y (integer)

    y co-ordinate to move to if element isn't set. Works as an offset if y is set with Element.

  • Element (WebDriver::Element)

    to scope this move within.



58
59
60
61
# File 'lib/appium_lib/core/device/touch_actions.rb', line 58

def move_to(opts)
  opts = args_with_ele_ref(opts)
  chain_method(:moveTo, opts)
end

#perform(driver = $driver) ⇒ Object

Ask the driver to perform all actions in this action chain.



187
188
189
190
191
# File 'lib/appium_lib/core/device/touch_actions.rb', line 187

def perform(driver = $driver)
  driver.touch_actions @actions
  @actions.clear
  self
end

#press(opts) ⇒ Object

Press a finger onto the screen. Finger will stay down until you call `release`.

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :element (WebDriver::Element) — default: Optional

    Element to press within.

  • :x (integer)

    x co-ordinate to press on

  • :y (integer)

    y co-ordinate to press on



84
85
86
87
88
# File 'lib/appium_lib/core/device/touch_actions.rb', line 84

def press(opts)
  args = opts.select { |k, _v| [:element, :x, :y].include? k }
  args = args_with_ele_ref(args)
  chain_method(:press, args)
end

#release(opts = nil) ⇒ Object

Remove a finger from the screen.

Parameters:

  • opts (Hash) (defaults to: nil)

    a customizable set of options

Options Hash (opts):

  • :element (WebDriver::Element) — default: Optional

    Element to release from.

  • :x (integer)

    x co-ordinate to release from

  • :y (integer)

    y co-ordinate to release from



95
96
97
98
# File 'lib/appium_lib/core/device/touch_actions.rb', line 95

def release(opts = nil)
  args = args_with_ele_ref(opts) if opts
  chain_method(:release, args)
end

#swipe(opts, ele = nil) ⇒ Object

Convenience method to peform a swipe.

Note that iOS 7 simulators have broken swipe.

For iOS: Use `offset_x` and `offset_y` to define the end point.

For Android: Use `end_x` and `end_y` to define the end point.

If you'd like more details, please read tests and its log samples in `ios_tests/lib/ios/specs/device/touch_actions.rb` and `ios_tests/lib/ios/specs/device/touch_actions.rb`

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :start_x (int)

    Where to start swiping, on the x axis. Default 0.

  • :start_y (int)

    Where to start swiping, on the y axis. Default 0.

  • :offset_x (int)

    For iOS. Offset, on the x axis. Default 0.

  • :offset_y (int)

    For iOS. Offset, on the y axis. Default 0.

  • :end_x (int)

    For Android. Where to end swiping, on the x axis. Default 0.

  • :end_y (int)

    For Android. Where to end swiping, on the y axis. Default 0.

  • :duration (int)

    How long the actual swipe takes to complete in milliseconds. Default 200.



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/appium_lib/core/device/touch_actions.rb', line 162

def swipe(opts, ele = nil)
  start_x  = opts.fetch :start_x, 0
  start_y  = opts.fetch :start_y, 0
  offset_x = opts.fetch :offset_x, nil
  offset_y = opts.fetch :offset_y, nil
  end_x    = opts.fetch :end_x, nil
  end_y    = opts.fetch :end_y, nil
  duration = opts.fetch :duration, 200

  coordinates = swipe_coordinates(end_x: end_x, end_y: end_y, offset_x: offset_x, offset_y: offset_y)

  if ele # pinch/zoom for XCUITest
    press x: start_x, y: start_y, element: ele
    move_to x: coordinates[:offset_x], y: coordinates[:offset_y], element: ele
  else
    press x: start_x, y: start_y
    wait(duration) if duration
    move_to x: coordinates[:offset_x], y: coordinates[:offset_y]
  end
  release

  self
end

#swipe_coordinates(end_x: nil, end_y: nil, offset_x: nil, offset_y: nil, driver: $driver) ⇒ Object

Visible for testing



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/appium_lib/core/device/touch_actions.rb', line 201

def swipe_coordinates(end_x: nil, end_y: nil, offset_x: nil, offset_y: nil, driver: $driver)
  if driver.device_is_android?
    puts 'end_x and end_y are used for Android. Not offset_x and offset_y.' if end_x.nil? || end_y.nil?
    end_x ||= 0
    end_y ||= 0
    return { offset_x: end_x, offset_y: end_y }
  elsif offset_x.nil? || offset_y.nil?
    puts 'offset_x and offset_y are used for iOS. Not end_x and end_y point.'
  end

  offset_x ||= 0
  offset_y ||= 0

  { offset_x: offset_x, offset_y: offset_y }
end

#tap(opts) ⇒ Object

Touch a point on the screen. Alternatively, you can use `press(…).release.perform` instead of `tap(…).perform`.

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :element (WebDriver::Element) — default: Optional

    Element to restrict scope too.

  • :x (integer)

    x co-ordinate to tap

  • :y (integer)

    y co-ordinate to tap

  • :fingers (integer)

    how many fingers to tap with (Default 1)



107
108
109
110
111
112
# File 'lib/appium_lib/core/device/touch_actions.rb', line 107

def tap(opts)
  opts[:count] = opts.delete(:fingers) if opts[:fingers]
  opts[:count] ||= 1
  args = args_with_ele_ref opts
  chain_method(:tap, args)
end

#two_finger_tap(opts) ⇒ Object

Two finger tap an element on the screen

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :element (WebDriver::Element) — default: Optional

    Element to restrict scope too.

  • :x (integer)

    x co-ordinate to tap

  • :y (integer)

    y co-ordinate to tap



131
132
133
134
135
# File 'lib/appium_lib/core/device/touch_actions.rb', line 131

def two_finger_tap(opts)
  args = opts.select { |k, _v| [:element, :x, :y].include? k }
  args = args_with_ele_ref(args)
  chain_method(:twoFingerTap, args) # twoFingerTap is what the appium server expects
end

#wait(milliseconds) ⇒ Object

Pause for a number of milliseconds before the next action

Parameters:

  • milliseconds (integer)

    Number of milliseconds to pause for



139
140
141
142
# File 'lib/appium_lib/core/device/touch_actions.rb', line 139

def wait(milliseconds)
  args = { ms: milliseconds }
  chain_method(:wait, args)
end