appium_lib_core 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +11 -0
- data/lib/appium_lib_core/android/device/clipboard.rb +4 -4
- data/lib/appium_lib_core/android/device/screen.rb +1 -1
- data/lib/appium_lib_core/android/uiautomator2/device/battery.rb +2 -2
- data/lib/appium_lib_core/common/base.rb +17 -0
- data/lib/appium_lib_core/common/base/bridge.rb +1 -0
- data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +15 -0
- data/lib/appium_lib_core/common/base/bridge/w3c.rb +19 -0
- data/lib/appium_lib_core/common/base/driver.rb +599 -1
- data/lib/appium_lib_core/common/base/screenshot.rb +18 -0
- data/lib/appium_lib_core/common/device/app_management.rb +87 -0
- data/lib/appium_lib_core/common/device/app_state.rb +30 -0
- data/lib/appium_lib_core/common/device/battery_status.rb +25 -0
- data/lib/appium_lib_core/common/device/clipboard_content_type.rb +11 -0
- data/lib/appium_lib_core/common/device/context.rb +38 -0
- data/lib/appium_lib_core/common/device/device.rb +19 -0
- data/lib/appium_lib_core/common/device/device_lock.rb +22 -0
- data/lib/appium_lib_core/common/device/file_management.rb +26 -0
- data/lib/appium_lib_core/common/device/image_comparison.rb +168 -0
- data/lib/appium_lib_core/common/device/ime_actions.rb +29 -0
- data/lib/appium_lib_core/common/device/keyboard.rb +22 -0
- data/lib/appium_lib_core/common/device/keyevent.rb +38 -0
- data/lib/appium_lib_core/common/device/screen_record.rb +54 -0
- data/lib/appium_lib_core/common/device/setting.rb +17 -0
- data/lib/appium_lib_core/common/device/touch_actions.rb +21 -0
- data/lib/appium_lib_core/common/device/value.rb +19 -0
- data/lib/appium_lib_core/device.rb +24 -547
- data/lib/appium_lib_core/driver.rb +14 -9
- data/lib/appium_lib_core/element/image.rb +1 -1
- data/lib/appium_lib_core/ios/device/clipboard.rb +4 -4
- data/lib/appium_lib_core/ios/xcuitest/device/battery.rb +2 -2
- data/lib/appium_lib_core/ios/xcuitest/device/performance.rb +1 -3
- data/lib/appium_lib_core/ios/xcuitest/device/screen.rb +1 -1
- data/lib/appium_lib_core/ios_xcuitest.rb +0 -2
- data/lib/appium_lib_core/version.rb +2 -2
- data/release_notes.md +10 -0
- metadata +18 -17
- data/lib/appium_lib_core/device/app_management.rb +0 -113
- data/lib/appium_lib_core/device/app_state.rb +0 -32
- data/lib/appium_lib_core/device/battery_status.rb +0 -23
- data/lib/appium_lib_core/device/clipboard_content_type.rb +0 -9
- data/lib/appium_lib_core/device/context.rb +0 -48
- data/lib/appium_lib_core/device/device_lock.rb +0 -28
- data/lib/appium_lib_core/device/file_management.rb +0 -32
- data/lib/appium_lib_core/device/image_comparison.rb +0 -178
- data/lib/appium_lib_core/device/ime_actions.rb +0 -43
- data/lib/appium_lib_core/device/keyboard.rb +0 -26
- data/lib/appium_lib_core/device/keyevent.rb +0 -44
- data/lib/appium_lib_core/device/screen_record.rb +0 -56
- data/lib/appium_lib_core/device/setting.rb +0 -21
- data/lib/appium_lib_core/device/touch_actions.rb +0 -22
- data/lib/appium_lib_core/device/value.rb +0 -23
@@ -77,6 +77,24 @@ module Appium
|
|
77
77
|
raise Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
|
78
78
|
end
|
79
79
|
end
|
80
|
+
|
81
|
+
# @since 1.3.4
|
82
|
+
# @!method save_viewport_screenshot
|
83
|
+
# Save screenshot except for status bar while `@driver.save_screenshot` save entire screen.
|
84
|
+
#
|
85
|
+
# @example
|
86
|
+
#
|
87
|
+
# @driver.save_viewport_screenshot 'path/to/save.png' #=> Get the File instance of viewport_screenshot
|
88
|
+
#
|
89
|
+
def save_viewport_screenshot(png_path)
|
90
|
+
extension = File.extname(png_path).downcase
|
91
|
+
if extension != '.png'
|
92
|
+
::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
|
93
|
+
'It should end with .png extension'
|
94
|
+
end
|
95
|
+
viewport_screenshot_encode64 = bridge.take_viewport_screenshot
|
96
|
+
File.open(png_path, 'wb') { |f| f << viewport_screenshot_encode64.unpack('m')[0] }
|
97
|
+
end
|
80
98
|
end
|
81
99
|
end
|
82
100
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Appium
|
2
|
+
module Core
|
3
|
+
class Base
|
4
|
+
module Device
|
5
|
+
module AppManagement
|
6
|
+
def launch_app
|
7
|
+
execute :launch_app
|
8
|
+
end
|
9
|
+
|
10
|
+
def close_app
|
11
|
+
execute :close_app
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
execute :reset
|
16
|
+
end
|
17
|
+
|
18
|
+
def app_strings(language = nil)
|
19
|
+
opts = language ? { language: language } : {}
|
20
|
+
execute :app_strings, {}, opts
|
21
|
+
end
|
22
|
+
|
23
|
+
def background_app(duration = 0)
|
24
|
+
execute :background_app, {}, seconds: duration
|
25
|
+
end
|
26
|
+
|
27
|
+
def install_app(path,
|
28
|
+
replace: nil,
|
29
|
+
timeout: nil,
|
30
|
+
allow_test_packages: nil,
|
31
|
+
use_sdcard: nil,
|
32
|
+
grant_permissions: nil)
|
33
|
+
args = { appPath: path }
|
34
|
+
|
35
|
+
args[:options] = {} unless options?(replace, timeout, allow_test_packages, use_sdcard, grant_permissions)
|
36
|
+
|
37
|
+
args[:options][:replace] = replace unless replace.nil?
|
38
|
+
args[:options][:timeout] = timeout unless timeout.nil?
|
39
|
+
args[:options][:allowTestPackages] = allow_test_packages unless allow_test_packages.nil?
|
40
|
+
args[:options][:useSdcard] = use_sdcard unless use_sdcard.nil?
|
41
|
+
args[:options][:grantPermissions] = grant_permissions unless grant_permissions.nil?
|
42
|
+
|
43
|
+
execute :install_app, {}, args
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove_app(id, keep_data: nil, timeout: nil)
|
47
|
+
# required: [['appId'], ['bundleId']]
|
48
|
+
args = { appId: id }
|
49
|
+
|
50
|
+
args[:options] = {} unless keep_data.nil? || timeout.nil?
|
51
|
+
args[:options][:keepData] = keep_data unless keep_data.nil?
|
52
|
+
args[:options][:timeout] = timeout unless timeout.nil?
|
53
|
+
|
54
|
+
execute :remove_app, {}, args
|
55
|
+
end
|
56
|
+
|
57
|
+
def app_installed?(app_id)
|
58
|
+
# required: [['appId'], ['bundleId']]
|
59
|
+
execute :app_installed?, {}, bundleId: app_id
|
60
|
+
end
|
61
|
+
|
62
|
+
def activate_app(app_id)
|
63
|
+
# required: [['appId'], ['bundleId']]
|
64
|
+
execute :activate_app, {}, bundleId: app_id
|
65
|
+
end
|
66
|
+
|
67
|
+
def terminate_app(app_id, timeout: nil)
|
68
|
+
# required: [['appId'], ['bundleId']]
|
69
|
+
#
|
70
|
+
args = { appId: app_id }
|
71
|
+
|
72
|
+
args[:options] = {} unless timeout.nil?
|
73
|
+
args[:options][:timeout] = timeout unless timeout.nil?
|
74
|
+
|
75
|
+
execute :terminate_app, {}, args
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def options?(replace, timeout, allow_test_packages, use_sdcard, grant_permissions)
|
81
|
+
replace.nil? || timeout.nil? || allow_test_packages.nil? || use_sdcard.nil? || grant_permissions.nil?
|
82
|
+
end
|
83
|
+
end # module AppManagement
|
84
|
+
end # module Device
|
85
|
+
end # class Base
|
86
|
+
end # module Core
|
87
|
+
end # module Appium
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Appium
|
2
|
+
module Core
|
3
|
+
class Base
|
4
|
+
module Device
|
5
|
+
module AppState
|
6
|
+
STATUS = [
|
7
|
+
:not_installed, # 0
|
8
|
+
:not_running, # 1
|
9
|
+
:running_in_background_suspended, # 2
|
10
|
+
:running_in_background, # 3
|
11
|
+
:running_in_foreground # 4
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
def app_state(app_id)
|
15
|
+
# required: [['appId'], ['bundleId']]
|
16
|
+
response = execute :app_state, {}, appId: app_id
|
17
|
+
|
18
|
+
case response
|
19
|
+
when 0, 1, 2, 3, 4
|
20
|
+
STATUS[response]
|
21
|
+
else
|
22
|
+
::Appium::Logger.debug("Unexpected status in app_state: #{response}")
|
23
|
+
response
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end # module AppState
|
27
|
+
end # module Device
|
28
|
+
end # class Base
|
29
|
+
end # module Core
|
30
|
+
end # module Appium
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Appium
|
2
|
+
module Core
|
3
|
+
class Base
|
4
|
+
module Device
|
5
|
+
module BatteryStatus
|
6
|
+
ANDROID = [
|
7
|
+
:undefined, # 0, dummy
|
8
|
+
:unknown, # 1
|
9
|
+
:charging, # 2
|
10
|
+
:discharging, # 3
|
11
|
+
:not_charging, # 4
|
12
|
+
:full # 5
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
IOS = [
|
16
|
+
:unknown, # 0
|
17
|
+
:unplugged, # 1
|
18
|
+
:charging, # 2
|
19
|
+
:full # 3
|
20
|
+
].freeze
|
21
|
+
end # module BatteryStatus
|
22
|
+
end # module Device
|
23
|
+
end # class Base
|
24
|
+
end # module Core
|
25
|
+
end # module Appium
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Appium
|
2
|
+
module Core
|
3
|
+
class Base
|
4
|
+
module Device
|
5
|
+
module Context
|
6
|
+
def within_context(context)
|
7
|
+
existing_context = current_context
|
8
|
+
set_context context
|
9
|
+
if block_given?
|
10
|
+
result = yield
|
11
|
+
set_context existing_context
|
12
|
+
result
|
13
|
+
else
|
14
|
+
set_context existing_context
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def switch_to_default_context
|
19
|
+
set_context nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def current_context
|
23
|
+
execute :current_context
|
24
|
+
end
|
25
|
+
|
26
|
+
def available_contexts
|
27
|
+
# return empty array instead of nil on failure
|
28
|
+
execute(:available_contexts, {}) || []
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_context(context = null)
|
32
|
+
execute :set_context, {}, name: context
|
33
|
+
end
|
34
|
+
end # module ImeActions
|
35
|
+
end # module Device
|
36
|
+
end # class Base
|
37
|
+
end # module Core
|
38
|
+
end # module Appium
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Appium
|
2
|
+
module Core
|
3
|
+
class Base
|
4
|
+
module Device
|
5
|
+
module Device
|
6
|
+
def shake
|
7
|
+
execute :shake
|
8
|
+
end
|
9
|
+
|
10
|
+
def device_time(format = nil)
|
11
|
+
arg = {}
|
12
|
+
arg[:format] = format unless format.nil?
|
13
|
+
execute :device_time, {}, arg
|
14
|
+
end
|
15
|
+
end # module Device
|
16
|
+
end # module Device
|
17
|
+
end # class Base
|
18
|
+
end # module Core
|
19
|
+
end # module Appium
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Appium
|
2
|
+
module Core
|
3
|
+
class Base
|
4
|
+
module Device
|
5
|
+
module DeviceLock
|
6
|
+
def lock(duration = nil)
|
7
|
+
opts = duration ? { seconds: duration } : {}
|
8
|
+
execute :lock, {}, opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def device_locked?
|
12
|
+
execute :device_locked?
|
13
|
+
end
|
14
|
+
|
15
|
+
def unlock
|
16
|
+
execute :unlock
|
17
|
+
end
|
18
|
+
end # module DeviceLock
|
19
|
+
end # module Device
|
20
|
+
end # class Base
|
21
|
+
end # module Core
|
22
|
+
end # module Appium
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Appium
|
4
|
+
module Core
|
5
|
+
class Base
|
6
|
+
module Device
|
7
|
+
module FileManagement
|
8
|
+
def push_file(path, filedata)
|
9
|
+
encoded_data = Base64.encode64 filedata
|
10
|
+
execute :push_file, {}, path: path, data: encoded_data
|
11
|
+
end
|
12
|
+
|
13
|
+
def pull_file(path)
|
14
|
+
data = execute :pull_file, {}, path: path
|
15
|
+
Base64.decode64 data
|
16
|
+
end
|
17
|
+
|
18
|
+
def pull_folder(path)
|
19
|
+
data = execute :pull_folder, {}, path: path
|
20
|
+
Base64.decode64 data
|
21
|
+
end
|
22
|
+
end # module FileManagement
|
23
|
+
end # module Device
|
24
|
+
end # class Base
|
25
|
+
end # module Core
|
26
|
+
end # module Appium
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Appium
|
4
|
+
module Core
|
5
|
+
class Base
|
6
|
+
module Device
|
7
|
+
module ImageComparison
|
8
|
+
MODE = [:matchFeatures, :getSimilarity, :matchTemplate].freeze
|
9
|
+
|
10
|
+
MATCH_FEATURES = {
|
11
|
+
detector_name: %w(AKAZE AGAST BRISK FAST GFTT KAZE MSER SIFT ORB),
|
12
|
+
match_func: %w(FlannBased BruteForce BruteForceL1 BruteForceHamming BruteForceHammingLut BruteForceSL2),
|
13
|
+
goodMatchesFactor: nil, # Integer
|
14
|
+
visualize: [true, false]
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
MATCH_TEMPLATE = {
|
18
|
+
visualize: [true, false]
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
GET_SIMILARITY = {
|
22
|
+
visualize: [true, false]
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
# @!method match_images_features(first_image:, second_image:, detector_name: 'ORB',
|
26
|
+
# match_func: 'BruteForce', good_matches_factor: 100, visualize: false)
|
27
|
+
# Performs images matching by features with default options. Read https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.html
|
28
|
+
# for more details on this topic.
|
29
|
+
#
|
30
|
+
# @param [String] first_image An image data. All image formats, that OpenCV library itself accepts, are supported.
|
31
|
+
# @param [String] second_image An image data. All image formats, that OpenCV library itself accepts, are supported.
|
32
|
+
# @param [String] detector_name Sets the detector name for features matching
|
33
|
+
# algorithm. Some of these detectors (FAST, AGAST, GFTT, FAST, SIFT and MSER) are
|
34
|
+
# not available in the default OpenCV installation and have to be enabled manually
|
35
|
+
# before library compilation. The default detector name is 'ORB'.
|
36
|
+
# @param [String] match_func The name of the matching function. The default one is 'BruteForce'.
|
37
|
+
# @param [String] good_matches_factor The maximum count of "good" matches (e. g. with minimal distances).
|
38
|
+
# The default one is nil.
|
39
|
+
# @param [Bool] visualise Makes the endpoint to return an image, which contains the visualized result of
|
40
|
+
# the corresponding picture matching operation. This option is disabled by default.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# @driver.match_images_features first_image: "image data 1", second_image: "image data 2"
|
44
|
+
#
|
45
|
+
# visual = @@driver.match_images_features first_image: image1, second_image: image2, visualize: true
|
46
|
+
# File.write 'match_images_visual.png', Base64.decode64(visual['visualization']) # if the image is PNG
|
47
|
+
#
|
48
|
+
|
49
|
+
# @!method find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil)
|
50
|
+
# Performs images matching by template to find possible occurrence of the partial image
|
51
|
+
# in the full image with default options. Read https://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
|
52
|
+
# for more details on this topic.
|
53
|
+
#
|
54
|
+
# @param [String] full_image: A full image data.
|
55
|
+
# @param [String] partial_image: A partial image data. All image formats, that OpenCV library itself accepts,
|
56
|
+
# are supported.
|
57
|
+
# @param [Bool] visualise: Makes the endpoint to return an image, which contains the visualized result of
|
58
|
+
# the corresponding picture matching operation. This option is disabled by default.
|
59
|
+
# @param [Float] threshold: [0.5] At what normalized threshold to reject
|
60
|
+
#
|
61
|
+
# @example
|
62
|
+
# @driver.find_image_occurrence full_image: "image data 1", partial_image: "image data 2"
|
63
|
+
#
|
64
|
+
# visual = @@driver.find_image_occurrence full_image: image1, partial_image: image2, visualize: true
|
65
|
+
# File.write 'find_result_visual.png', Base64.decode64(visual['visualization']) # if the image is PNG
|
66
|
+
#
|
67
|
+
|
68
|
+
# @!method get_images_similarity(first_image:, second_image:, detector_name: 'ORB', visualize: false)
|
69
|
+
# Performs images matching to calculate the similarity score between them
|
70
|
+
# with default options. The flow there is similar to the one used in `find_image_occurrence`
|
71
|
+
# but it is mandatory that both images are of equal size.
|
72
|
+
#
|
73
|
+
# @param [String] first_image: An image data. All image formats, that OpenCV library itself accepts, are supported.
|
74
|
+
# @param [String] second_image: An image data. All image formats, that OpenCV library itself accepts, are supported.
|
75
|
+
# @param [Bool] visualise: Makes the endpoint to return an image, which contains the visualized result of
|
76
|
+
# the corresponding picture matching operation. This option is disabled by default.
|
77
|
+
#
|
78
|
+
# @example
|
79
|
+
# @driver.get_images_similarity first_image: "image data 1", second_image: "image data 2"
|
80
|
+
#
|
81
|
+
# visual = @@driver.get_images_similarity first_image: image1, second_image: image2, visualize: true
|
82
|
+
# File.write 'images_similarity_visual.png', Base64.decode64(visual['visualization']) # if the image is PNG
|
83
|
+
#
|
84
|
+
|
85
|
+
# @!method compare_images(mode:, first_image:, second_image:, options:)
|
86
|
+
#
|
87
|
+
# Performs images comparison using OpenCV framework features.
|
88
|
+
# It is expected that both OpenCV framework and opencv4nodejs
|
89
|
+
# module are installed on the machine where Appium server is running.
|
90
|
+
#
|
91
|
+
# @param [Symbol] mode: One of possible comparison modes: `:matchFeatures`, `:getSimilarity`, `:matchTemplate`.
|
92
|
+
# `:matchFeatures is by default.
|
93
|
+
# @param [String] first_image: An image data. All image formats, that OpenCV library itself accepts, are supported.
|
94
|
+
# @param [String] second_image: An image data. All image formats, that OpenCV library itself accepts, are supported.
|
95
|
+
# @param [Hash] options: The content of this dictionary depends on the actual `mode` value.
|
96
|
+
# See the documentation on `appium-support` module for more details.
|
97
|
+
# @returns [Hash] The content of the resulting dictionary depends on the actual `mode` and `options` values.
|
98
|
+
# See the documentation on `appium-support` module for more details.
|
99
|
+
#
|
100
|
+
|
101
|
+
####
|
102
|
+
## class << self
|
103
|
+
####
|
104
|
+
|
105
|
+
def match_images_features(first_image:,
|
106
|
+
second_image:,
|
107
|
+
detector_name: 'ORB',
|
108
|
+
match_func: 'BruteForce',
|
109
|
+
good_matches_factor: nil,
|
110
|
+
visualize: false)
|
111
|
+
unless MATCH_FEATURES[:detector_name].member?(detector_name.to_s)
|
112
|
+
raise "detector_name should be #{MATCH_FEATURES[:detector_name]}"
|
113
|
+
end
|
114
|
+
unless MATCH_FEATURES[:match_func].member?(match_func.to_s)
|
115
|
+
raise "match_func should be #{MATCH_FEATURES[:match_func]}"
|
116
|
+
end
|
117
|
+
unless MATCH_FEATURES[:visualize].member?(visualize)
|
118
|
+
raise "visualize should be #{MATCH_FEATURES[:visualize]}"
|
119
|
+
end
|
120
|
+
|
121
|
+
options = {}
|
122
|
+
options[:detectorName] = detector_name.to_s.upcase
|
123
|
+
options[:matchFunc] = match_func.to_s
|
124
|
+
options[:goodMatchesFactor] = good_matches_factor.to_i unless good_matches_factor.nil?
|
125
|
+
options[:visualize] = visualize
|
126
|
+
|
127
|
+
compare_images(mode: :matchFeatures, first_image: first_image, second_image: second_image, options: options)
|
128
|
+
end
|
129
|
+
|
130
|
+
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil)
|
131
|
+
unless MATCH_TEMPLATE[:visualize].member?(visualize)
|
132
|
+
raise "visualize should be #{MATCH_TEMPLATE[:visualize]}"
|
133
|
+
end
|
134
|
+
|
135
|
+
options = {}
|
136
|
+
options[:visualize] = visualize
|
137
|
+
options[:threshold] = threshold unless threshold.nil?
|
138
|
+
|
139
|
+
compare_images(mode: :matchTemplate, first_image: full_image, second_image: partial_image, options: options)
|
140
|
+
end
|
141
|
+
|
142
|
+
def get_images_similarity(first_image:, second_image:, visualize: false)
|
143
|
+
unless GET_SIMILARITY[:visualize].member?(visualize)
|
144
|
+
raise "visualize should be #{GET_SIMILARITY[:visualize]}"
|
145
|
+
end
|
146
|
+
|
147
|
+
options = {}
|
148
|
+
options[:visualize] = visualize
|
149
|
+
|
150
|
+
compare_images(mode: :getSimilarity, first_image: first_image, second_image: second_image, options: options)
|
151
|
+
end
|
152
|
+
|
153
|
+
def compare_images(mode: :matchFeatures, first_image:, second_image:, options: nil)
|
154
|
+
raise "content_type should be #{MODE}" unless MODE.member?(mode)
|
155
|
+
|
156
|
+
params = {}
|
157
|
+
params[:mode] = mode
|
158
|
+
params[:firstImage] = Base64.encode64 first_image
|
159
|
+
params[:secondImage] = Base64.encode64 second_image
|
160
|
+
params[:options] = options if options
|
161
|
+
|
162
|
+
execute(:compare_images, {}, params)
|
163
|
+
end
|
164
|
+
end # module ImageComparison
|
165
|
+
end # module Device
|
166
|
+
end # class Base
|
167
|
+
end # module Core
|
168
|
+
end # module Appium
|