Module: Appium

Defined in:
lib/appium_lib/error.rb,
lib/appium_lib/appium.rb,
lib/appium_lib/driver.rb,
lib/appium_lib/ios/ios.rb,
lib/appium_lib/version.rb,
lib/appium_lib/common/log.rb,
lib/appium_lib/sauce_labs.rb,
lib/appium_lib/common/wait.rb,
lib/appium_lib/ios/xcuitest.rb,
lib/appium_lib/common/device.rb,
lib/appium_lib/common/helper.rb,
lib/appium_lib/common/command.rb,
lib/appium_lib/android/android.rb,
lib/appium_lib/android/espresso.rb,
lib/appium_lib/ios/element/text.rb,
lib/appium_lib/ios/common/errors.rb,
lib/appium_lib/ios/common/helper.rb,
lib/appium_lib/ios/element/alert.rb,
lib/appium_lib/common/http_client.rb,
lib/appium_lib/ios/element/button.rb,
lib/appium_lib/ios/element/generic.rb,
lib/appium_lib/ios/xcuitest/bridge.rb,
lib/appium_lib/ios/xcuitest/helper.rb,
lib/appium_lib/android/element/text.rb,
lib/appium_lib/android/uiautomator2.rb,
lib/appium_lib/ios/xcuitest/command.rb,
lib/appium_lib/ios/xcuitest/element.rb,
lib/appium_lib/android/common/helper.rb,
lib/appium_lib/android/element/alert.rb,
lib/appium_lib/ios/element/textfield.rb,
lib/appium_lib/android/element/button.rb,
lib/appium_lib/android/element/generic.rb,
lib/appium_lib/android/espresso/bridge.rb,
lib/appium_lib/android/espresso/helper.rb,
lib/appium_lib/android/espresso/element.rb,
lib/appium_lib/common/command/ws_logcat.rb,
lib/appium_lib/android/element/textfield.rb,
lib/appium_lib/ios/xcuitest/element/text.rb,
lib/appium_lib/android/uiautomator2/bridge.rb,
lib/appium_lib/android/uiautomator2/helper.rb,
lib/appium_lib/ios/xcuitest/command/source.rb,
lib/appium_lib/ios/xcuitest/element/button.rb,
lib/appium_lib/android/uiautomator2/element.rb,
lib/appium_lib/ios/xcuitest/element/generic.rb,
lib/appium_lib/ios/xcuitest/command/gestures.rb,
lib/appium_lib/android/common/command/command.rb,
lib/appium_lib/ios/xcuitest/element/textfield.rb,
lib/appium_lib/android/espresso/element/button.rb,
lib/appium_lib/ios/xcuitest/command/pasteboard.rb,
lib/appium_lib/android/espresso/element/generic.rb,
lib/appium_lib/ios/xcuitest/command/certificate.rb,
lib/appium_lib/ios/xcuitest/command/get_context.rb,
lib/appium_lib/android/uiautomator2/element/button.rb,
lib/appium_lib/ios/xcuitest/command/multi_app_handler.rb

Overview

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Defined Under Namespace

Modules: Android, Common, Device, Http, Ios Classes: ArgumentError, Driver, Error, NoDriverInstanceError, SauceLabs

Constant Summary collapse

VERSION =

Version and Date are defined on the ‘Appium’ module, not ‘Appium::Common’

'15.2.2'
DATE =
'2024-08-06'

Class Method Summary collapse

Class Method Details

.expand_required_files(base_dir, file_paths) ⇒ Array

Returns list of require files as an array, nil if require doesn’t exist.

Parameters:

  • base_dir (String)

    parent directory of loaded appium.txt (toml)

  • file_paths (String)

Returns:

  • (Array)

    list of require files as an array, nil if require doesn’t exist



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
# File 'lib/appium_lib/appium.rb', line 111

def expand_required_files(base_dir, file_paths)
  # ensure files are absolute
  Array(file_paths).map! do |f|
    file = File.exist?(f) ? f : File.join(base_dir, f)
    file = File.expand_path file

    File.exist?(file) ? file : nil
  end
  file_paths.compact! # remove nils

  files = []

  # now expand dirs
  file_paths.each do |item|
    unless File.directory? item
      # save file
      files << item
      next # only look inside folders
    end
    Dir.glob(File.expand_path(File.join(item, '**', '*.rb'))) do |f|
      # do not add folders to the file list
      files << File.expand_path(f) unless File.directory? f
    end
  end

  files
end

.load_settings(opts = {}) ⇒ hash Also known as: load_appium_txt

Load arbitrary text ([toml format](github.com/toml-lang/toml)) The toml is parsed by github.com/fbernier/tomlrb .

“‘

caps

app = “path/to/app”

appium_lib

port = 8080 “‘

:app is expanded :require is expanded all keys are converted to symbols

Parameters:

  • opts (Hash) (defaults to: {})

    file: ‘/path/to/appium.txt’, verbose: true

Returns:

  • (hash)

    the symbolized hash with updated :app and :require keys

Raises:



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/appium_lib/appium.rb', line 58

def load_settings(opts = {})
  raise ArgumentError, 'opts must be a hash' unless opts.is_a? Hash
  raise ArgumentError, 'opts must not be empty' if opts.empty?

  toml = opts[:file]
  raise ArgumentError, 'Must pass a capability file which has [caps] and [appium_lib]' unless toml

  verbose = opts.fetch :verbose, false

  Appium::Logger.info "appium settings path: #{toml}" if verbose

  toml_exists = File.exist? toml
  Appium::Logger.info "Exists? #{toml_exists}" if verbose

  raise ArgumentError, "toml doesn't exist #{toml}" unless toml_exists

  require 'tomlrb'
  Appium::Logger.info "Loading #{toml}" if verbose

  data = Tomlrb.load_file(toml, symbolize_keys: true)

  Appium::Logger.info data if verbose && !data.empty?

  # FIXME: Deprecated. Will remove when we remove 'Appium::Driver.absolute_app_path'
  if data
    if data['caps']
      if data['caps'][:app] && !data['caps'][:app].empty?
        data['caps'][:app] = Appium::Driver.absolute_app_path data
      elsif data['caps']['app'] && !data['caps']['app'].empty?
        data['caps']['app'] = Appium::Driver.absolute_app_path data
      end
    elsif data[:caps]
      if data[:caps][:app] && !data[:caps][:app].empty?
        data[:caps][:app] = Appium::Driver.absolute_app_path data
      elsif data[:caps]['app'] && !data[:caps]['app'].empty?
        data[:caps]['app'] = Appium::Driver.absolute_app_path data
      end
    end
  end

  if data && data[:appium_lib] && data[:appium_lib][:require]
    parent_dir = File.dirname toml
    data[:appium_lib][:require] = expand_required_files(parent_dir, data[:appium_lib][:require])
  end

  data
end

.promote_appium_methods(class_array, driver = $driver) ⇒ Object

Promote appium methods to class instance methods

To promote methods to all classes:

It’s better to promote on specific classes instead of Object

Examples:


Appium.promote_appium_methods Object

# promote on rspec
Appium.promote_appium_methods RSpec::Core::ExampleGroup

# promote on minispec
Appium.promote_appium_methods Minitest::Spec

Parameters:

  • class_array (Array<Class>)

    An array of classes

  • driver (Driver) (defaults to: $driver)

    A driver to extend for

Raises:



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
# File 'lib/appium_lib/appium.rb', line 207

def promote_appium_methods(class_array, driver = $driver)
  raise ArgumentError, 'Driver is nil' if driver.nil?

  # Wrap single class into an array
  class_array = [class_array] unless class_array.instance_of? Array
  # Promote Appium driver methods to class instance methods.
  class_array.each do |klass|
    driver.public_methods(false).each do |method|
      klass.class_eval do
        # NOTE: Do not skip re-definding methods to not keep old instance information.
        # Probably the global driver ($driver) stuff needs to override (re-defined)
        # every time to not keep unexpected state.
        # https://github.com/appium/ruby_lib/issues/917

        # Remove the method before adding it.
        remove_method method if method_defined? method

        define_method method do |*args, &block|
          # Prefer existing method.
          # super will invoke method missing on driver
          super(*args, &block)

          # minitest also defines a name method,
          # so rescue argument error
          # and call the name method on $driver
        rescue NoMethodError, ArgumentError
          if args.size == 1 && args.first.is_a?(Hash)
            # To prevent warnings by keyword arguments (for Ruby 2.7 and 3)
            driver.send method, **args.first, &block if driver.respond_to?(method)
          else
            ::Appium::Logger.warn "Should fix this '#{args}' for Ruby 2.7 (and 3)" if args.first.is_a?(Hash)

            driver.send method, *args, &block if driver.respond_to?(method)
          end
        end
      end
    end
  end
  nil # return nil
end

.promote_singleton_appium_methods(modules, driver = $driver) ⇒ Object

This method is intended to work with page objects that share a common module. For example, Page::HomePage, Page::SignIn those could be promoted on with Appium.promote_singleton_appium_methods Page

If you are promoting on an individual class then you should use Appium.promote_appium_methods instead. The singleton method is intended only for the shared module use case.

if modules is a module instead of an array, then the constants of that module are promoted on. otherwise, the array of modules will be used as the promotion target.

Parameters:

  • modules (Array<Module>)

    An array of modules

  • driver (Driver) (defaults to: $driver)

    A driver to extend for

Raises:



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
# File 'lib/appium_lib/appium.rb', line 153

def promote_singleton_appium_methods(modules, driver = $driver)
  raise ArgumentError, 'Global $driver is nil' if driver.nil?

  target_modules = []

  if modules.is_a? Module
    modules.constants.each do |sub_module|
      target_modules << modules.const_get(sub_module)
    end
  else
    raise ArgumentError, 'modules must be a module or an array' unless modules.is_a? Array

    target_modules = modules
  end

  target_modules.each do |const|
    # noinspection RubyResolve
    driver.public_methods(false).each do |m|
      # override unless there's an existing method with matching arity
      next if const.respond_to?(m) && const.method(m).arity == driver.method(m).arity

      const.send(:define_singleton_method, m) do |*args, &block|
        super(*args, &block) # promote.rb
      rescue NoMethodError, ArgumentError
        driver.send m, *args, &block if driver.respond_to?(m)
      end
    end
  end
end