Module: Appium::Device

Extended by:
Forwardable
Defined in:
lib/appium_lib/device/device.rb

Constant Summary collapse

NoArgMethods =
{
  post: {
    open_notifications:   'session/:session_id/appium/device/open_notifications',
    shake:                'session/:session_id/appium/device/shake',
    launch_app:           'session/:session_id/appium/app/launch',
    close_app:            'session/:session_id/appium/app/close',
    reset:                'session/:session_id/appium/app/reset',
    toggle_airplane_mode: 'session/:session_id/appium/device/toggle_airplane_mode',
    device_locked?:       'session/:session_id/appium/device/is_locked'
  },
  get:  {
    device_time:            'session/:session_id/appium/device/system_time',
    current_activity:       'session/:session_id/appium/device/current_activity',
    current_context:        'session/:session_id/context',
    get_network_connection: 'session/:session_id/network_connection'
  }
}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.accessiblity_id_findObject

find_element/s with their accessibility_id

“‘ruby

find_elements :accessibility_id, 'Animation'

“‘



352
353
354
355
356
# File 'lib/appium_lib/device/device.rb', line 352

def extend_search_contexts
  Selenium::WebDriver::SearchContext.class_eval do
    Selenium::WebDriver::SearchContext::FINDERS[:accessibility_id] = 'accessibility id'
  end
end

.add_endpoint_method(method, path, verb = :post) ⇒ Object



302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/appium_lib/device/device.rb', line 302

def add_endpoint_method(method, path, verb = :post)
  if block_given?
    # &Proc.new with no args passes the passed_in block
    # Because creating Procs from blocks is slow
    create_bridge_command method, verb, path, &Proc.new
  else
    create_bridge_command method, verb, path
  end

  delegate_driver_method method
  delegate_from_appium_driver method
end

.add_touch_actionsObject



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/appium_lib/device/device.rb', line 358

def add_touch_actions
  add_endpoint_method(:touch_actions, 'session/:session_id/touch/perform') do
    def touch_actions(actions)
      actions = { actions: [actions].flatten }
      execute :touch_actions, {}, actions
    end
  end

  add_endpoint_method(:multi_touch, 'session/:session_id/touch/multi/perform') do
    def multi_touch(actions)
      execute :multi_touch, {}, actions: actions
    end
  end

  actions = Appium::TouchAction::COMPLEX_ACTIONS
  actions.each do |method|
    delegate_from_appium_driver(method, Appium::TouchAction)
  end

  delegate_from_appium_driver(:pinch, Appium::MultiTouch)
  delegate_from_appium_driver(:zoom, Appium::MultiTouch)
end

.create_bridge_command(method, verb, path) ⇒ Object



335
336
337
338
339
340
341
342
343
344
# File 'lib/appium_lib/device/device.rb', line 335

def create_bridge_command(method, verb, path)
  Selenium::WebDriver::Remote::Bridge.class_eval do
    command method, verb, path
    if block_given?
      class_eval(&Proc.new)
    else
      define_method(method) { execute method }
    end
  end
end

.delegate_driver_method(method) ⇒ Object



324
325
326
327
# File 'lib/appium_lib/device/device.rb', line 324

def delegate_driver_method(method)
  return if Selenium::WebDriver::Driver.method_defined? method
  Selenium::WebDriver::Driver.class_eval { def_delegator :@bridge, method }
end

.delegate_from_appium_driver(method, delegation_target = :driver) ⇒ Object



330
331
332
# File 'lib/appium_lib/device/device.rb', line 330

def delegate_from_appium_driver(method, delegation_target = :driver)
  def_delegator delegation_target, method
end

.extend_search_contextsObject



352
353
354
355
356
# File 'lib/appium_lib/device/device.rb', line 352

def extend_search_contexts
  Selenium::WebDriver::SearchContext.class_eval do
    Selenium::WebDriver::SearchContext::FINDERS[:accessibility_id] = 'accessibility id'
  end
end

.extend_webdriver_with_forwardableObject



316
317
318
319
320
321
# File 'lib/appium_lib/device/device.rb', line 316

def extend_webdriver_with_forwardable
  return if Selenium::WebDriver::Driver.is_a? Forwardable
  Selenium::WebDriver::Driver.class_eval do
    extend Forwardable
  end
end

.extended(_mod) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/appium_lib/device/device.rb', line 108

def extended(_mod)
  extend_webdriver_with_forwardable

  NoArgMethods.each_pair do |verb, pair|
    pair.each_pair { |command, path| add_endpoint_method command, path, verb }
  end

  add_endpoint_method(:available_contexts, 'session/:session_id/contexts', :get) do
    def available_contexts
      # return empty array instead of nil on failure
      execute(:available_contexts, {}) || []
    end
  end

  add_endpoint_method(:app_strings, 'session/:session_id/appium/app/strings') do
    def app_strings(language = nil)
      opts = language ? { language: language } : {}
      execute :app_strings, {}, opts
    end
  end

  add_endpoint_method(:lock, 'session/:session_id/appium/device/lock') do
    def lock(duration)
      execute :lock, {}, seconds: duration
    end
  end

  add_endpoint_method(:install_app, 'session/:session_id/appium/device/install_app') do
    def install_app(path)
      execute :install_app, {}, appPath: path
    end
  end

  add_endpoint_method(:remove_app, 'session/:session_id/appium/device/remove_app') do
    def remove_app(id)
      execute :remove_app, {}, appId: id
    end
  end

  add_endpoint_method(:app_installed?, 'session/:session_id/appium/device/app_installed') do
    def app_installed?(app_id)
      execute :app_installed?, {}, bundleId: app_id
    end
  end

  add_endpoint_method(:background_app, 'session/:session_id/appium/app/background') do
    def background_app(duration)
      execute :background_app, {}, seconds: duration
    end
  end

  # @!method start_activity
  #   Start a new activity within the current app or launch a new app and start the target activity.
  #
  #   Android only.
  #   @param [String] The package owning the activity [required]
  #   @param [String] The target activity [required]
  #   @param [String] The package to start before the target package [optional]
  #   @param [String] The activity to start before the target activity [optional]
  #
  #   ```ruby
  #   start_activity app_package: 'io.appium.android.apis',
  #     app_activity: '.accessibility.AccessibilityNodeProviderActivity'
  #   ```
  add_endpoint_method(:start_activity, 'session/:session_id/appium/device/start_activity') do
    def start_activity(opts)
      fail 'opts must be a hash' unless opts.is_a? Hash
      app_package = opts[:app_package]
      fail 'app_package is required' unless app_package
      app_activity = opts[:app_activity]
      fail 'app_activity is required' unless opts[:app_activity]
      app_wait_package  = opts.fetch(:app_wait_package, '')
      app_wait_activity = opts.fetch(:app_wait_activity, '')

      unknown_opts = opts.keys - [:app_package, :app_activity, :app_wait_package, :app_wait_activity]
      fail "Unknown options #{unknown_opts}" unless unknown_opts.empty?

      execute :start_activity, {}, appPackage: app_package,
                                   appActivity: app_activity,
                                   appWaitPackage: app_wait_package,
                                   appWaitActivity: app_wait_activity
    end
  end

  add_endpoint_method(:set_context, 'session/:session_id/context') do
    def set_context(context = null)
      execute :set_context, {}, name: context
    end
  end

  add_endpoint_method(:hide_keyboard, 'session/:session_id/appium/device/hide_keyboard') do
    def hide_keyboard(close_key = nil)
      # Android can only tapOutside.
      if $driver.device_is_android?
        return execute :hide_keyboard, {}, strategy: :tapOutside
      end

      close_key ||= 'Done' # default to Done key.
      $driver.hide_ios_keyboard close_key
    end
  end

  add_endpoint_method(:press_keycode, 'session/:session_id/appium/device/press_keycode') do
    def press_keycode(key, metastate = nil)
      args             = { keycode: key }
      args[:metastate] = metastate if metastate
      execute :press_keycode, {}, args
    end
  end

  add_endpoint_method(:long_press_keycode, 'session/:session_id/appium/device/long_press_keycode') do
    def long_press_keycode(key, metastate = nil)
      args             = { keycode: key }
      args[:metastate] = metastate if metastate
      execute :long_press_keycode, {}, args
    end
  end

  # TODO: TEST ME
  add_endpoint_method(:set_immediate_value, 'session/:session_id/appium/element/:id/value') do
    def set_immediate_value(element, value)
      execute :set_immediate_value, { id: element.ref }, value: value
    end
  end

  add_endpoint_method(:push_file, 'session/:session_id/appium/device/push_file') do
    def push_file(path, filedata)
      encoded_data = Base64.encode64 filedata
      execute :push_file, {}, path: path, data: encoded_data
    end
  end

  add_endpoint_method(:pull_file, 'session/:session_id/appium/device/pull_file') do
    def pull_file(path)
      data = execute :pull_file, {}, path: path
      Base64.decode64 data
    end
  end

  # TODO: TEST ME
  add_endpoint_method(:pull_folder, 'session/:session_id/appium/device/pull_folder') do
    def pull_folder(path)
      data = execute :pull_folder, {}, path: path
      Base64.decode64 data
    end
  end

  # TODO: TEST ME
  add_endpoint_method(:end_coverage, 'session/:session_id/appium/app/end_test_coverage') do
    def end_coverage(path, intent)
      execute :end_coverage, {}, path: path, intent: intent
    end
  end

  add_endpoint_method(:get_settings, 'session/:session_id/appium/settings', :get) do
    def get_settings
      execute :get_settings, {}
    end
  end

  add_endpoint_method(:update_settings, 'session/:session_id/appium/settings') do
    def update_settings(settings)
      execute :update_settings, {}, settings: settings
    end
  end

  # @!method get_network_connection
  #   Get the device network connection current status
  #   See set_network_connection method for return value

  # @!method set_network_connection
  #   Set the device network connection mode
  #   @param path (String) Bit mask that represent the network mode
  #   Value (Alias)      | Data | Wifi | Airplane Mode
  #   -------------------------------------------------
  #   1 (Airplane Mode)  | 0    | 0    | 1
  #   6 (All network on) | 1    | 1    | 0
  #   4 (Data only)      | 1    | 0    | 0
  #   2 (Wifi only)      | 0    | 1    | 0
  #   0 (None)           | 0    | 0    | 0
  #
  add_endpoint_method(:set_network_connection, 'session/:session_id/network_connection') do
    def set_network_connection(mode)
      execute :set_network_connection, {}, type: mode
    end
  end

  add_touch_actions
  extend_search_contexts
end

Instance Method Details

#app_stringsObject

Return the hash of all localization strings. “‘ruby app_strings #=> “TransitionsTitle”=>“Transitions”, “WebTitle”=>“Web” “`



# File 'lib/appium_lib/device/device.rb', line 25

#available_contextsArray<String>

Returns All usable contexts, as an array of strings.

Returns:

  • (Array<String>)

    All usable contexts, as an array of strings.



# File 'lib/appium_lib/device/device.rb', line 393

#background_appObject

Backgrounds the app for a set number of seconds. This is a blocking application



# File 'lib/appium_lib/device/device.rb', line 31

#current_activityObject



# File 'lib/appium_lib/device/device.rb', line 36

#current_contextString

Returns The context currently being used.

Returns:

  • (String)

    The context currently being used.



# File 'lib/appium_lib/device/device.rb', line 390

#device_locked?Object



# File 'lib/appium_lib/device/device.rb', line 50

#end_coverageObject

Android only; Ends the test coverage and writes the results to the given path on device.

Parameters:

  • path (String)

    Path on the device to write too.

  • intent (String)

    Intent to broadcast when ending coverage.



# File 'lib/appium_lib/device/device.rb', line 96

#get_settingsObject

Get appium Settings for current test session



# File 'lib/appium_lib/device/device.rb', line 101

#hide_keyboardObject

Hide the onscreen keyboard

Parameters:

  • close_key (String)

    the name of the key which closes the keyboard. Defaults to ‘Done’.



# File 'lib/appium_lib/device/device.rb', line 52

#launch_appObject

Start the simulator and application configured with desired capabilities



# File 'lib/appium_lib/device/device.rb', line 38

#long_press_keycodeObject

Parameters:

  • key (integer)

    The key to long press.

  • metastate (String)

    The state the metakeys should be in when long pressing the key.



# File 'lib/appium_lib/device/device.rb', line 67

#press_keycodeObject

Parameters:

  • key (integer)

    The key to press.

  • metastate (String)

    The state the metakeys should be in when pressing the key.



# File 'lib/appium_lib/device/device.rb', line 61

#pull_fileObject

Retrieve a file from the device. This can retrieve an absolute path or a path relative to the installed app (iOS only). “‘ruby pull_file ’/local/data/some/path’ #=> Get the file at that path pull_file ‘Shenanigans.app/some/file’ #=> Get ‘some/file’ from the install location of Shenanigans.app “‘

Parameters:

  • path (String)

    Either an absolute path OR, for iOS devices, a path relative to the app, as described.



# File 'lib/appium_lib/device/device.rb', line 78

#pull_folderObject

Retrieve a folder from the device. “‘ruby pull_folder ’/data/local/tmp’ #=> Get the folder at that path “‘

Parameters:

  • path (String)

    absolute path to the folder



# File 'lib/appium_lib/device/device.rb', line 88

#push_fileObject

Place a file in a specific location on the device.

Parameters:

  • path (String)

    The absolute path on the device to store data at.

  • data (String)

    Raw file data to be sent to the device.



# File 'lib/appium_lib/device/device.rb', line 73

#resetObject

Reset the device, relaunching the application.



# File 'lib/appium_lib/device/device.rb', line 41

#set_contextObject

Change the context to the given context. “‘ruby set_context “NATIVE_APP” “`

Parameters:

  • The (String)

    context to change to



# File 'lib/appium_lib/device/device.rb', line 382

#shakeObject

Cause the device to shake



# File 'lib/appium_lib/device/device.rb', line 44

#switch_to_default_contextObject

Change to the default context. This is equivalent to ‘set_context nil`.



411
412
413
# File 'lib/appium_lib/device/device.rb', line 411

def switch_to_default_context
  set_context nil
end

#toggle_flight_modeObject

Toggle flight mode on or off



# File 'lib/appium_lib/device/device.rb', line 47

#within_context(context) ⇒ Object

Perform a block within the given context, then switch back to the starting context. “‘ruby within_context(’NATIVE_APP’) do

find_element [:tag, "button"]

“‘

Parameters:

  • context (String)

    The context to switch to for the duration of the block.



403
404
405
406
407
408
# File 'lib/appium_lib/device/device.rb', line 403

def within_context(context)
  existing_context = current_context
  set_context context
  yield if block_given?
  set_context existing_context
end