appium_lib_core 1.7.2 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/CHANGELOG.md +11 -0
  4. data/lib/appium_lib_core/android/device/clipboard.rb +4 -4
  5. data/lib/appium_lib_core/android/device/screen.rb +1 -1
  6. data/lib/appium_lib_core/android/uiautomator2/device/battery.rb +2 -2
  7. data/lib/appium_lib_core/common/base.rb +17 -0
  8. data/lib/appium_lib_core/common/base/bridge.rb +1 -0
  9. data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +15 -0
  10. data/lib/appium_lib_core/common/base/bridge/w3c.rb +19 -0
  11. data/lib/appium_lib_core/common/base/driver.rb +599 -1
  12. data/lib/appium_lib_core/common/base/screenshot.rb +18 -0
  13. data/lib/appium_lib_core/common/device/app_management.rb +87 -0
  14. data/lib/appium_lib_core/common/device/app_state.rb +30 -0
  15. data/lib/appium_lib_core/common/device/battery_status.rb +25 -0
  16. data/lib/appium_lib_core/common/device/clipboard_content_type.rb +11 -0
  17. data/lib/appium_lib_core/common/device/context.rb +38 -0
  18. data/lib/appium_lib_core/common/device/device.rb +19 -0
  19. data/lib/appium_lib_core/common/device/device_lock.rb +22 -0
  20. data/lib/appium_lib_core/common/device/file_management.rb +26 -0
  21. data/lib/appium_lib_core/common/device/image_comparison.rb +168 -0
  22. data/lib/appium_lib_core/common/device/ime_actions.rb +29 -0
  23. data/lib/appium_lib_core/common/device/keyboard.rb +22 -0
  24. data/lib/appium_lib_core/common/device/keyevent.rb +38 -0
  25. data/lib/appium_lib_core/common/device/screen_record.rb +54 -0
  26. data/lib/appium_lib_core/common/device/setting.rb +17 -0
  27. data/lib/appium_lib_core/common/device/touch_actions.rb +21 -0
  28. data/lib/appium_lib_core/common/device/value.rb +19 -0
  29. data/lib/appium_lib_core/device.rb +24 -547
  30. data/lib/appium_lib_core/driver.rb +14 -9
  31. data/lib/appium_lib_core/element/image.rb +1 -1
  32. data/lib/appium_lib_core/ios/device/clipboard.rb +4 -4
  33. data/lib/appium_lib_core/ios/xcuitest/device/battery.rb +2 -2
  34. data/lib/appium_lib_core/ios/xcuitest/device/performance.rb +1 -3
  35. data/lib/appium_lib_core/ios/xcuitest/device/screen.rb +1 -1
  36. data/lib/appium_lib_core/ios_xcuitest.rb +0 -2
  37. data/lib/appium_lib_core/version.rb +2 -2
  38. data/release_notes.md +10 -0
  39. metadata +18 -17
  40. data/lib/appium_lib_core/device/app_management.rb +0 -113
  41. data/lib/appium_lib_core/device/app_state.rb +0 -32
  42. data/lib/appium_lib_core/device/battery_status.rb +0 -23
  43. data/lib/appium_lib_core/device/clipboard_content_type.rb +0 -9
  44. data/lib/appium_lib_core/device/context.rb +0 -48
  45. data/lib/appium_lib_core/device/device_lock.rb +0 -28
  46. data/lib/appium_lib_core/device/file_management.rb +0 -32
  47. data/lib/appium_lib_core/device/image_comparison.rb +0 -178
  48. data/lib/appium_lib_core/device/ime_actions.rb +0 -43
  49. data/lib/appium_lib_core/device/keyboard.rb +0 -26
  50. data/lib/appium_lib_core/device/keyevent.rb +0 -44
  51. data/lib/appium_lib_core/device/screen_record.rb +0 -56
  52. data/lib/appium_lib_core/device/setting.rb +0 -21
  53. data/lib/appium_lib_core/device/touch_actions.rb +0 -22
  54. 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,11 @@
1
+ module Appium
2
+ module Core
3
+ class Base
4
+ module Device
5
+ module Clipboard
6
+ CONTENT_TYPE = [:plaintext, :image, :url].freeze
7
+ end
8
+ end # module Clipboard
9
+ end # class Base
10
+ end # module Core
11
+ 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