testa_appium_driver 0.1.1 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,7 +3,7 @@ module TestaAppiumDriver
3
3
 
4
4
  private
5
5
  # @return [Array]
6
- def w3c_each(skip_scroll_to_start, &block)
6
+ def w3c_each(direction, &block)
7
7
  elements = []
8
8
  begin
9
9
  @driver.disable_wait_for_idle
@@ -13,7 +13,14 @@ module TestaAppiumDriver
13
13
  iterations = 0
14
14
 
15
15
 
16
- scroll_to_start unless skip_scroll_to_start
16
+ if direction.nil?
17
+ scroll_to_start
18
+ if @scrollable.scroll_orientation == :vertical
19
+ direction = :down
20
+ else
21
+ direction = :right
22
+ end
23
+ end
17
24
 
18
25
  until is_end_of_scroll?
19
26
  matches = @locator.execute(skip_cache: true)
@@ -27,6 +34,7 @@ module TestaAppiumDriver
27
34
  end
28
35
  iterations += 1
29
36
  break if !@max_scrolls.nil? && iterations == @max_scrolls
37
+ self.send("page_#{direction}")
30
38
  end
31
39
  rescue => e
32
40
  raise e
@@ -37,13 +45,13 @@ module TestaAppiumDriver
37
45
  elements
38
46
  end
39
47
 
40
- def w3c_align(with)
48
+ def w3c_align(with, scroll_to_find)
41
49
  @driver.disable_wait_for_idle
42
50
  default_deadzone!
43
51
 
44
52
 
45
53
 
46
- @locator.scroll_to unless @raise # called with !
54
+ @locator.scroll_to if scroll_to_find
47
55
 
48
56
  element = @locator.execute
49
57
  @driver.disable_implicit_wait
@@ -3,19 +3,24 @@ require_relative 'scroll_actions/w3c_scroll_actions'
3
3
 
4
4
 
5
5
  module TestaAppiumDriver
6
- #noinspection RubyResolve,RubyTooManyInstanceVariablesInspection
7
- class ScrollActions
8
6
 
7
+ # Class for handling scroll actions
8
+ class ScrollActions
9
+ # @param [TestaAppiumDriver::Locator, nil] scrollable container that will be used to determine the bounds for scrolling
10
+ # @param [Hash] params
11
+ # acceptable params
12
+ # - locator - element that should be found with scrolling actions
13
+ # - deadzone - [Hash] that stores top, bottom, left and right deadzone values. If deadzone[:top] is 200 then 200px from top of the scrollable container will not be used for scrolling
14
+ # - max_scrolls - [Integer] maximum number of scrolls before exception is thrown
15
+ # - default_scroll_strategy - defines which scroll strategy will be used if a scroll action is valid for multiple strategies
9
16
  def initialize(scrollable, params = {})
10
17
  @scrollable = scrollable
11
18
  @locator = params[:locator]
12
19
  @deadzone = params[:deadzone]
13
- @direction = params[:direction]
14
20
  @max_scrolls = params[:max_scrolls]
15
21
  @default_scroll_strategy = params[:default_scroll_strategy]
16
22
  @driver = @locator.driver
17
23
 
18
- @raise = params[:raise]
19
24
 
20
25
  if @scrollable.nil?
21
26
  # if we dont have a scrollable element or if we do have it, but it is not compatible with uiautomator
@@ -35,16 +40,33 @@ module TestaAppiumDriver
35
40
  end
36
41
 
37
42
 
38
- def align(with)
39
- w3c_align(with)
43
+ def align(with, scroll_to_find)
44
+ w3c_align(with, scroll_to_find)
40
45
  @locator
41
46
  end
42
47
 
43
48
  # @return [Array]
44
- def each(skip_scroll_to_start, &block)
45
- w3c_each(skip_scroll_to_start, &block)
49
+ def each(&block)
50
+ w3c_each(nil, &block)
51
+ end
52
+
53
+ def each_down(&block)
54
+ w3c_each(:down, &block)
55
+ end
56
+
57
+ def each_up(&block)
58
+ w3c_each(:up, &block)
46
59
  end
47
60
 
61
+ def each_right(&block)
62
+ w3c_each(:right, &block)
63
+ end
64
+
65
+ def each_left(&block)
66
+ w3c_each(:left, &block)
67
+ end
68
+
69
+
48
70
  def resolve_strategy
49
71
  if @strategy.nil?
50
72
  @default_scroll_strategy
@@ -1,19 +1,19 @@
1
1
  module Selenium
2
2
  module WebDriver
3
- #noinspection RubyClassVariableUsageInspection
4
3
  class Element
4
+ # sets the testa appium driver instance for the current phone
5
5
  def self.set_driver(driver, udid)
6
6
  udid = "unknown" if udid.nil?
7
7
  @@drivers ||= {}
8
8
  @@drivers[udid] = driver
9
9
  end
10
10
 
11
+ # @return [TestaAppiumDriver::Driver] testa appium driver instance for the current phone
11
12
  def get_driver
12
13
  udid = @bridge.capabilities.instance_variable_get(:@capabilities)["udid"]
13
14
  udid = "unknown" if udid.nil?
14
15
  @@drivers[udid]
15
16
  end
16
-
17
17
  end
18
18
  end
19
19
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'em/pure_ruby'
4
+ require 'appium_lib_core'
5
+
3
6
  require_relative 'common/bounds'
4
7
  require_relative 'common/exceptions/strategy_mix_exception'
5
8
  require_relative 'common/helpers'
@@ -10,18 +13,24 @@ require_relative 'common/selenium_element'
10
13
  module TestaAppiumDriver
11
14
  class Driver
12
15
  include Helpers
16
+
17
+ # @return [::Appium::Core::Base::Driver] the ruby_lib_core appium driver
13
18
  attr_accessor :driver
19
+
20
+ # @return [String] iOS or Android
14
21
  attr_reader :device
22
+
23
+ # @return [String] driver automation name (uiautomator2 or xcuitest)
15
24
  attr_reader :automation_name
16
25
 
17
26
  # custom options
18
- # - default_strategy: default strategy to be used for finding elements. Available strategies :uiautomator or :xpath
27
+ # - default_find_strategy: default strategy to be used for finding elements. Available strategies :uiautomator or :xpath
28
+ # - default_scroll_strategy: default strategy to be used for scrolling. Available strategies: :uiautomator(android only), :w3c
19
29
  def initialize(opts = {})
20
30
  @testa_opts = opts[:testa_appium_driver] || {}
21
31
 
22
32
 
23
-
24
- core = ::Appium::Core.for(opts)
33
+ core = Appium::Core.for(opts)
25
34
  extend_for(core.device, core.automation_name)
26
35
  @device = core.device
27
36
  @automation_name = core.automation_name
@@ -29,14 +38,15 @@ module TestaAppiumDriver
29
38
  handle_testa_opts
30
39
 
31
40
  @driver = core.start_driver
32
- invalidate_cache!
41
+ invalidate_cache
33
42
 
34
43
 
35
- ::Selenium::WebDriver::Element.set_driver(self, opts[:caps][:udid])
44
+ Selenium::WebDriver::Element.set_driver(self, opts[:caps][:udid])
36
45
  end
37
46
 
38
47
 
39
- def invalidate_cache!
48
+ # invalidates current find_element cache
49
+ def invalidate_cache
40
50
  @cache = {
41
51
  strategy: nil,
42
52
  selector: nil,
@@ -49,11 +59,13 @@ module TestaAppiumDriver
49
59
 
50
60
 
51
61
 
52
- #noinspection RubyScope
62
+ # Executes the find_element with the resolved locator strategy and selector. Find_element might be skipped if cache is hit.
63
+ # Cache stores last executed find_element with given selector, strategy and from_element. If given values are the same within
64
+ # last 5 seconds element is retrieved from cache.
53
65
  # @param [TestaAppiumDriver::Locator, TestaAppiumDriver::Driver] from_element element from which start the search
54
- # @param [String] selector resolved string of a [TestaAppiumDriver::Locator] selector xpath for xpath strategy, java UiSelectors for uiautomator
66
+ # @param [String] selector resolved string of a [TestaAppiumDriver::Locator] selector xpath for xpath strategy, java UiSelectors for uiautomator or id for ID strategy
55
67
  # @param [Boolean] single fetch single or multiple results
56
- # @param [Symbol, nil] strategy [TestaAppiumDriver:FIND_STRATEGY_UIAUTOMATOR] or [FIND_STRATEGY_XPATH]
68
+ # @param [Symbol, nil] strategy [TestaAppiumDriver::FIND_STRATEGY_UIAUTOMATOR], [TestaAppiumDriver::FIND_STRATEGY_XPATH] or [TestaAppiumDriver::FIND_STRATEGY_ID]
57
69
  # @param [Symbol] default_strategy if strategy is not enforced, default can be used
58
70
  # @param [Boolean] skip_cache to skip checking and storing cache
59
71
  # @return [Selenium::WebDriver::Element, Array] element is returned if single is true, array otherwise
@@ -107,21 +119,27 @@ module TestaAppiumDriver
107
119
 
108
120
 
109
121
  # method missing is used to forward methods to the actual appium driver
122
+ # after the method is executed, find element cache is invalidated
110
123
  def method_missing(method, *args, &block)
111
- @driver.send(method, *args, &block)
124
+ r = @driver.send(method, *args, &block)
125
+ invalidate_cache
126
+ r
112
127
  end
113
128
 
129
+ # disables implicit wait
114
130
  def disable_implicit_wait
115
131
  @implicit_wait_ms = @driver.get_timeouts["implicit"]
116
132
  @driver.manage.timeouts.implicit_wait = 0
117
133
  end
118
134
 
135
+ # enables implicit wait, can be called only after disabling implicit wait
119
136
  def enable_implicit_wait
120
137
  raise "Implicit wait is not disabled" if @implicit_wait_ms.nil?
121
138
  # get_timeouts always returns in milliseconds, but we should set in seconds
122
139
  @driver.manage.timeouts.implicit_wait = @implicit_wait_ms / 1000
123
140
  end
124
141
 
142
+ # disables wait for idle, only executed for android devices
125
143
  def disable_wait_for_idle
126
144
  if @device == :android
127
145
  @wait_for_idle_timeout = @driver.settings.get["waitForIdleTimeout"]
@@ -129,6 +147,7 @@ module TestaAppiumDriver
129
147
  end
130
148
  end
131
149
 
150
+ # enables wait for idle, only executed for android devices
132
151
  def enable_wait_for_idle
133
152
  if @device == :android
134
153
  raise "Wait for idle is not disabled" if @wait_for_idle_timeout.nil?
@@ -136,12 +155,15 @@ module TestaAppiumDriver
136
155
  end
137
156
  end
138
157
 
158
+
159
+ # @@return [String] current package under test
139
160
  def current_package
140
161
  @driver.current_package
141
162
  end
142
163
 
143
- def window_size(*args)
144
- @driver.window_size(*args)
164
+
165
+ def window_size
166
+ @driver.window_size
145
167
  end
146
168
 
147
169
  def back
@@ -166,6 +188,7 @@ module TestaAppiumDriver
166
188
  end
167
189
 
168
190
 
191
+ # @return [Array<Selenium::WebDriver::Element] array of 2 elements, the first element without children and the last element without children in the current page
169
192
  def first_and_last_leaf(from_element = @driver)
170
193
  disable_wait_for_idle
171
194
  disable_implicit_wait
@@ -7,6 +7,7 @@ module TestaAppiumDriver
7
7
  include TypeSelectors
8
8
 
9
9
 
10
+ private
10
11
  def handle_testa_opts
11
12
  if @testa_opts[:default_find_strategy].nil?
12
13
  @default_find_strategy = DEFAULT_IOS_FIND_STRATEGY
@@ -1,7 +1,5 @@
1
1
  module TestaAppiumDriver
2
- #noinspection RubyYardReturnMatch
3
- class Locator
4
-
2
+ module Attributes
5
3
 
6
4
  #noinspection RubyNilAnalysis
7
5
  def attribute(name, *args)
@@ -76,4 +74,8 @@ module TestaAppiumDriver
76
74
  alias_method :bounds, :rect
77
75
  alias_method :text, :label
78
76
  end
77
+ #noinspection RubyYardReturnMatch
78
+ class Locator
79
+ include TestaAppiumDriver::Attributes
80
+ end
79
81
  end
@@ -1,7 +1,6 @@
1
1
  require_relative 'locator/attributes'
2
2
 
3
3
  module TestaAppiumDriver
4
- #noinspection RubyTooManyInstanceVariablesInspection
5
4
  class Locator
6
5
  include TypeSelectors
7
6
 
@@ -24,6 +23,7 @@ module TestaAppiumDriver
24
23
  end
25
24
 
26
25
 
26
+ # @return [Array] returns 2 elements. The first is the resolved find element strategy and the second is the resolved selector
27
27
  def strategy_and_selector
28
28
  if @can_use_id_strategy
29
29
  return FIND_STRATEGY_NAME, @can_use_id_strategy
@@ -32,7 +32,8 @@ module TestaAppiumDriver
32
32
  end
33
33
 
34
34
 
35
- # @return [Locator] existing locator element
35
+
36
+ # @return [Locator] new child locator element
36
37
  def add_child_selector(params)
37
38
  params, selectors = extract_selectors_from_params(params)
38
39
  single = params[:single]
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- module TestaAppiumDriver
4
- VERSION = "0.1.1"
5
- end
1
+ # frozen_string_literal: true
2
+
3
+ module TestaAppiumDriver
4
+ VERSION = "0.1.5"
5
+ end
@@ -9,13 +9,14 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ["karlo.razumovic@gmail.com"]
10
10
 
11
11
  spec.summary = "Appium made easy"
12
- spec.description = "Testa appium driver is a wrapper around ruby_lib_core. It significantly reduces the amount of code need to achieve your goals."
12
+ spec.description = "Testa appium driver is a wrapper around ruby_lib_core. It leverages all driver features and makes them simple and easy to use, significantly reduces the amount of code needed and enables you to define locators that can be reused"
13
13
  spec.homepage = "https://github.com/Karazum/testa_appium_driver"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = ">= 2.4.0"
16
16
 
17
17
  #spec.metadata["allowed_push_host"] = "Set to 'https://mygemserver.com'"
18
18
 
19
+ spec.metadata["documentation_uri"] = "https://www.rubydoc.info/gems/testa_appium_driver"
19
20
  spec.metadata["homepage_uri"] = spec.homepage
20
21
  spec.metadata["source_code_uri"] = "https://github.com/Karazum/testa_appium_driver"
21
22
  spec.metadata["changelog_uri"] = "https://github.com/Karazum/testa_appium_driver"
@@ -30,7 +31,7 @@ Gem::Specification.new do |spec|
30
31
  spec.require_paths = ["lib"]
31
32
 
32
33
  spec.add_runtime_dependency "appium_lib_core", ["= 4.7.0"]
33
- spec.add_runtime_dependency "json", [">= 2.3.0"]
34
+ spec.add_runtime_dependency "json", ["~> 2.3"]
34
35
 
35
36
  spec.add_development_dependency "rubocop", ["= 1.19.0"]
36
37
  spec.add_development_dependency "rake", ["~> 13.0"]
@@ -11,7 +11,7 @@
11
11
  <orderEntry type="sourceFolder" forTests="false" />
12
12
  <orderEntry type="library" scope="PROVIDED" name="appium_lib_core (v4.7.0, ruby-2.6.5-p114) [gem]" level="application" />
13
13
  <orderEntry type="library" scope="PROVIDED" name="ast (v2.4.2, ruby-2.6.5-p114) [gem]" level="application" />
14
- <orderEntry type="library" scope="PROVIDED" name="bundler (v2.2.25, ruby-2.6.5-p114) [gem]" level="application" />
14
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v2.1.4, ruby-2.6.5-p114) [gem]" level="application" />
15
15
  <orderEntry type="library" scope="PROVIDED" name="childprocess (v3.0.0, ruby-2.6.5-p114) [gem]" level="application" />
16
16
  <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.4.4, ruby-2.6.5-p114) [gem]" level="application" />
17
17
  <orderEntry type="library" scope="PROVIDED" name="eventmachine (v1.2.7, ruby-2.6.5-p114) [gem]" level="application" />
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: testa_appium_driver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - karlo.razumovic
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-19 00:00:00.000000000 Z
11
+ date: 2021-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appium_lib_core
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.3.0
33
+ version: '2.3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.3.0
40
+ version: '2.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rubocop
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,8 +66,9 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '13.0'
69
- description: Testa appium driver is a wrapper around ruby_lib_core. It significantly
70
- reduces the amount of code need to achieve your goals.
69
+ description: Testa appium driver is a wrapper around ruby_lib_core. It leverages all
70
+ driver features and makes them simple and easy to use, significantly reduces the
71
+ amount of code needed and enables you to define locators that can be reused
71
72
  email:
72
73
  - karlo.razumovic@gmail.com
73
74
  executables: []
@@ -123,6 +124,7 @@ homepage: https://github.com/Karazum/testa_appium_driver
123
124
  licenses:
124
125
  - MIT
125
126
  metadata:
127
+ documentation_uri: https://www.rubydoc.info/gems/testa_appium_driver
126
128
  homepage_uri: https://github.com/Karazum/testa_appium_driver
127
129
  source_code_uri: https://github.com/Karazum/testa_appium_driver
128
130
  changelog_uri: https://github.com/Karazum/testa_appium_driver