Top Level Namespace

Defined Under Namespace

Modules: Appium, Minitest

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.method_missing(method, *args, &block) ⇒ Object

Invoke top level methods on last created Appium driver.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/appium_lib.rb', line 7

def self.method_missing method, *args, &block
  raise "driver is nil. called #{method}" if $driver == nil

  if $driver.respond_to?(method)
    # puts "[method_missing] Calling driver.send for #{method}"
    $driver.send(method, *args, &block)
  elsif self.respond_to?(method)
    # puts "[method_missing] Calling super with args for #{method}"
    super(*args, &block)
  else
    # puts "[method_missing] Calling super (no args) for #{method}"
    super
  end
end

Instance Method Details

#load_appium_txt(opts) ⇒ Array<String>

Load appium.txt (toml format) into system ENV the basedir of this file + appium.txt is what’s used

Parameters:

  • opts (Hash)

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

Returns:

  • (Array<String>)

    the require files. nil if require doesn’t exist



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/appium_lib/driver.rb', line 28

def load_appium_txt opts
  raise 'opts must be a hash' unless opts.kind_of? Hash
  opts.each_pair { |k,v| opts[k.to_s.downcase.strip.intern] = v }
  opts = {} if opts.nil?
  file = opts.fetch :file, nil
  raise 'Must pass file' unless file
  verbose = opts.fetch :verbose, false
  # Check for env vars in .txt
  parent_dir = File.dirname file
  toml = File.expand_path File.join parent_dir, 'appium.txt'
  puts "appium.txt path: #{toml}" if verbose
  # @private
  def update data, *args
    args.each do |name|
      var = data[name]
      ENV[name] = var if var
    end
  end

  toml_exists = File.exists? toml
  puts "Exists? #{toml_exists}" if verbose
  data = nil

  if toml_exists
    require 'toml'
    puts "Loading #{toml}" if verbose

    # bash requires A="OK"
    # toml requires A = "OK"
    #
    # A="OK" => A = "OK"
    data = File.read toml

    data = data.split("\n").map do |line|
      line.sub /([^\s])\=/, "\\1 = "
    end.join "\n"

    data = TOML::Parser.new(data).parsed
    ap data unless data.empty? if verbose

    update data, 'APP_PATH', 'APP_APK', 'APP_PACKAGE',
           'APP_ACTIVITY', 'APP_WAIT_ACTIVITY',
           'DEVICE'

    # Ensure app path is absolute
    ENV['APP_PATH'] = File.expand_path ENV['APP_PATH'] if ENV['APP_PATH'] &&
        !ENV['APP_PATH'].empty?

    # device is not case sensitive
    ENV['DEVICE'] = ENV['DEVICE'].strip.downcase if !ENV['DEVICE'].nil?
    if ! %w(ios android selendroid).include? ENV['DEVICE']
      raise %(DEVICE="#{ENV['DEVICE']}" must be ios, android,
or selendroid.)
    end
  end

  # return list of require files as an array
  # nil if require doesn't exist
  if data && data['require']
    r = data['require']
    r = r.kind_of?(Array) ? r : [ r ]
    # ensure files are absolute
    r.map! do |file|
      file = file.include?(File::Separator) ? file :
             File.join(parent_dir, file)
      file = File.expand_path file

      File.exists?(file) ? file : nil
    end
    r.compact! # remove nils

    files = []

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

    files
  end
end

#patch_webdriver_bridgeObject

Show http calls to the Selenium server.

Invaluable for debugging.



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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
# File 'lib/appium_lib/common/patch.rb', line 82

def patch_webdriver_bridge
  Selenium::WebDriver::Remote::Bridge.class_eval do
    # Code from lib/selenium/webdriver/remote/bridge.rb
    def raw_execute(command, opts = {}, command_hash = nil)
      verb, path = Selenium::WebDriver::Remote::COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}")
      path       = path.dup

      path[':session_id'] = @session_id if path.include?(':session_id')

      begin
        opts.each { |key, value| path[key.inspect] = escaper.escape(value.to_s) }
        rescue IndexError
        raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
      end

      # convert /// into /
      path.gsub! /\/+/, '/'

      # change path from session/efac972c-941a-499c-803c-d7d008749/execute
      # to /execute
      # path may be nil, session, or not have anything after the session_id.
      path_str = ''
      path_match = path.match /.*\h{8}-\h{4}-\h{4}-\h{4}-\h{12}/
      path_str = path.sub(path_match[0], '') unless path_match.nil?

      puts "#{verb} #{path_str}"
      unless command_hash.nil? || command_hash.length == 0
        print_command = command_hash.clone
        print_command.delete :args if print_command[:args] == []

        mobile_find = 'mobile: find'
        if print_command[:script] == mobile_find
          args = print_command[:args]
          puts "#{mobile_find}"#" #{args}"

          # [[[[3, "sign"]]]] => [[[3, "sign"]]]
          #
          # [[[[4, "android.widget.EditText"], [7, "z"]], [[4, "android.widget.EditText"], [3, "z"]]]]
          # => [[[4, "android.widget.EditText"], [7, "z"]], [[4, "android.widget.EditText"], [3, "z"]]]
          args = args[0]
          option = args[0].to_s.downcase
          has_option = ! option.match(/all|scroll/).nil?
          puts option if has_option

          start = has_option ? 1 : 0

          start.upto(args.length-1) do |selector_index|
            selectors = args[selector_index]
            selectors_size = selectors.length
            selectors.each_index do |pair_index|
              pair = selectors[pair_index]
              res = $driver.dynamic_code_to_string pair[0], pair[1]

              if selectors_size == 1 || pair_index >= selectors_size - 1
                puts res
              elsif selectors_size > 1 && pair_index < selectors_size
                print res + '.'
              end
            end
          end # start.upto
        else
          ap print_command
        end
      end
      delay = $driver.global_webdriver_http_sleep
      sleep delay if !delay.nil? && delay > 0
      # puts "verb: #{verb}, path #{path}, command_hash #{command_hash.to_json}"
      http.call verb, path, command_hash
    end # def
  end # class
end

#update(data, *args) ⇒ Object



40
41
42
43
44
45
# File 'lib/appium_lib/driver.rb', line 40

def update data, *args
  args.each do |name|
    var = data[name]
    ENV[name] = var if var
  end
end