automation_object 0.6.0 → 0.7.5

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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/automation_object/blue_print/hash_adapter/hook_action.rb +1 -1
  3. data/lib/automation_object/driver/appium_adapter/driver.rb +17 -1
  4. data/lib/automation_object/driver/driver.rb +7 -1
  5. data/lib/automation_object/driver/nokogiri_adapter/driver.rb +6 -0
  6. data/lib/automation_object/driver/selenium_adapter/driver.rb +16 -1
  7. data/lib/automation_object/dsl/_base.rb +6 -3
  8. data/lib/automation_object/dsl/_proxy.rb +2 -2
  9. data/lib/automation_object/dsl/element.rb +9 -3
  10. data/lib/automation_object/dsl/element_array.rb +9 -3
  11. data/lib/automation_object/dsl/element_hash.rb +9 -3
  12. data/lib/automation_object/dsl/modal.rb +9 -6
  13. data/lib/automation_object/dsl/screen.rb +5 -7
  14. data/lib/automation_object/dsl/top.rb +7 -3
  15. data/lib/automation_object/state/_base.rb +72 -0
  16. data/lib/automation_object/state/_common_element.rb +44 -0
  17. data/lib/automation_object/state/{error.rb → _error.rb} +4 -0
  18. data/lib/automation_object/state/element.rb +23 -0
  19. data/lib/automation_object/state/element_array.rb +26 -0
  20. data/lib/automation_object/state/element_hash.rb +34 -0
  21. data/lib/automation_object/state/element_proxy.rb +31 -0
  22. data/lib/automation_object/state/hook.rb +51 -0
  23. data/lib/automation_object/state/{composite/hook_action.rb → hook_action.rb} +11 -13
  24. data/lib/automation_object/state/hook_actions/action_loop.rb +43 -0
  25. data/lib/automation_object/state/hook_actions/change_screen.rb +23 -0
  26. data/lib/automation_object/state/hook_actions/change_to_previous_screen.rb +23 -0
  27. data/lib/automation_object/state/hook_actions/close_modal.rb +21 -0
  28. data/lib/automation_object/state/hook_actions/close_screen.rb +20 -0
  29. data/lib/automation_object/state/hook_actions/element_requirement.rb +30 -0
  30. data/lib/automation_object/state/hook_actions/new_screen.rb +49 -0
  31. data/lib/automation_object/state/hook_actions/possible_screen_changes.rb +23 -0
  32. data/lib/automation_object/state/{composite/hook_actions → hook_actions}/reset_screen.rb +4 -5
  33. data/lib/automation_object/state/hook_actions/show_modal.rb +18 -0
  34. data/lib/automation_object/state/hook_actions/sleep.rb +13 -0
  35. data/lib/automation_object/state/hook_actions/wait_for_elements.rb +18 -0
  36. data/lib/automation_object/state/modal.rb +47 -0
  37. data/lib/automation_object/state/screen.rb +70 -0
  38. data/lib/automation_object/state/top.rb +43 -0
  39. data/lib/automation_object/state.rb +3 -3
  40. data/lib/automation_object/version.rb +1 -1
  41. metadata +40 -43
  42. data/lib/automation_object/state/composite/_base.rb +0 -81
  43. data/lib/automation_object/state/composite/_common_element.rb +0 -38
  44. data/lib/automation_object/state/composite/element.rb +0 -24
  45. data/lib/automation_object/state/composite/element_array.rb +0 -27
  46. data/lib/automation_object/state/composite/element_hash.rb +0 -35
  47. data/lib/automation_object/state/composite/element_proxy.rb +0 -33
  48. data/lib/automation_object/state/composite/helpers/window.rb +0 -79
  49. data/lib/automation_object/state/composite/helpers/window_manager.rb +0 -59
  50. data/lib/automation_object/state/composite/hook.rb +0 -55
  51. data/lib/automation_object/state/composite/hook_actions/action_loop.rb +0 -45
  52. data/lib/automation_object/state/composite/hook_actions/change_screen.rb +0 -23
  53. data/lib/automation_object/state/composite/hook_actions/change_to_previous_screen.rb +0 -23
  54. data/lib/automation_object/state/composite/hook_actions/close_modal.rb +0 -29
  55. data/lib/automation_object/state/composite/hook_actions/close_screen.rb +0 -19
  56. data/lib/automation_object/state/composite/hook_actions/element_requirement.rb +0 -32
  57. data/lib/automation_object/state/composite/hook_actions/new_screen.rb +0 -31
  58. data/lib/automation_object/state/composite/hook_actions/possible_screen_changes.rb +0 -22
  59. data/lib/automation_object/state/composite/hook_actions/show_modal.rb +0 -23
  60. data/lib/automation_object/state/composite/hook_actions/sleep.rb +0 -15
  61. data/lib/automation_object/state/composite/hook_actions/wait_for_elements.rb +0 -20
  62. data/lib/automation_object/state/composite/modal.rb +0 -45
  63. data/lib/automation_object/state/composite/screen.rb +0 -64
  64. data/lib/automation_object/state/composite/top.rb +0 -51
  65. data/lib/automation_object/state/session.rb +0 -54
@@ -43,6 +43,10 @@ module AutomationObject
43
43
 
44
44
  # Modal isn't active error
45
45
  class ModalNotActiveError < StandardError
46
+ def initialize(modal)
47
+ message = "#{modal} is not currently active"
48
+ super(message)
49
+ end
46
50
  end
47
51
 
48
52
  # Modal parent error
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require_relative '_base'
3
+ require_relative '_common_element'
4
+
5
+ require_relative 'element_proxy'
6
+
7
+ module AutomationObject
8
+ module State
9
+ # Element composite for managing state
10
+ class Element < Base
11
+ include CommonElement
12
+
13
+ # @return [AutomationObject::State::ElementProxy] Selenium proxy
14
+ def utilize
15
+ # return self.cache if self.cache
16
+
17
+ element = driver.find_element(*blue_prints.selector_params)
18
+ @active = true
19
+ self.cache = ElementProxy.new(self, element)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ require_relative '_base'
3
+ require_relative '_common_element'
4
+
5
+ require_relative 'element_proxy'
6
+
7
+ module AutomationObject
8
+ module State
9
+ # Element array composite for managing state
10
+ class ElementArray < Base
11
+ include CommonElement
12
+
13
+ # @return [Array<AutomationObject::State::ElementProxy>] Selenium proxy
14
+ def utilize
15
+ # return self.cache if self.cache
16
+
17
+ elements = driver.find_elements(*blue_prints.selector_params)
18
+
19
+ @active = true
20
+ self.cache = elements.map do |element|
21
+ ElementProxy.new(self, element)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ require_relative '_base'
3
+ require_relative '_common_element'
4
+
5
+ require_relative 'element_proxy'
6
+
7
+ module AutomationObject
8
+ module State
9
+ # Element hash composite for managing state
10
+ class ElementHash < Base
11
+ include CommonElement
12
+
13
+ # @return [Hash<String, AutomationObject::State::ElementProxy>] Selenium proxy
14
+ def utilize
15
+ # return self.cache if self.cache
16
+
17
+ elements = driver.find_elements(*blue_prints.selector_params)
18
+ self.cache = {}
19
+
20
+ elements.each do |element|
21
+ # Want to wrap element, before sending for method!
22
+ # That will help us include custom methods, etc...
23
+ wrapped_element = ElementProxy.new(self, element)
24
+ hash_key = wrapped_element.send(blue_prints.define_elements_by) # Send to wrapped state proxy
25
+
26
+ cache[hash_key] = wrapped_element
27
+ end
28
+
29
+ @active = true
30
+ cache
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ require_relative '../proxy/proxy'
3
+
4
+ module AutomationObject
5
+ module State
6
+ # Proxy class to allow for usage of hooks
7
+ class ElementProxy < ::AutomationObject::Proxy::Proxy
8
+ def initialize(composite, element)
9
+ @composite = composite
10
+ @subject = element
11
+ end
12
+
13
+ # Overiding base method to run possible hooks
14
+ def method_missing(method_symbol, *args, &block)
15
+ # Run before hook if needed
16
+ @composite.method_hooks[method_symbol].before if @composite.method_hook?(method_symbol)
17
+
18
+ subject_return = @subject.send(method_symbol, *args, &block)
19
+
20
+ # Run after hook if needed
21
+ @composite.method_hooks[method_symbol].after if @composite.method_hook?(method_symbol)
22
+
23
+ subject_return
24
+ end
25
+
26
+ def respond_to_missing?(method, include_private = false)
27
+ @subject.respond_to_missing?(method, include_private)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ require_relative '_base'
3
+
4
+ require_relative 'hook_action'
5
+ require_relative 'hook_actions/element_requirement'
6
+
7
+ module AutomationObject
8
+ module State
9
+ # Hook composite for managing state
10
+ class Hook < Base
11
+ # @return [Boolean, nil] return nil if no live? check, otherwise boolean
12
+ def live?
13
+ before
14
+
15
+ return nil if blue_prints.live?.empty?
16
+
17
+ blue_prints.live?.each do |element_requirement_blueprints|
18
+ hook_element_requirement = ElementRequirement.new(self, driver, element_requirement_blueprints, 1)
19
+ return false unless hook_element_requirement.run
20
+ end
21
+
22
+ after
23
+
24
+ true
25
+ end
26
+
27
+ # Runs the before hook
28
+ # @return [Boolean, nil] return nil unless there is a hook, otherwise boolean depending on success of hook
29
+ def before
30
+ return nil if blue_prints.before.empty?
31
+
32
+ hook_action = HookAction.new(driver,
33
+ blue_prints.before,
34
+ :hook_action, self, location + '[hook_action]')
35
+
36
+ hook_action.run
37
+ end
38
+
39
+ # Runs the after hook
40
+ # @return [Boolean, nil] return nil unless there is a hook, otherwise boolean depending on success of hook
41
+ def after
42
+ return nil if blue_prints.after.empty?
43
+
44
+ hook_action = HookAction.new(driver,
45
+ blue_prints.after,
46
+ :hook_action, self, location + '[hook_action]')
47
+ hook_action.run
48
+ end
49
+ end
50
+ end
51
+ end
@@ -14,21 +14,19 @@ require_relative 'hook_actions/new_screen'
14
14
 
15
15
  module AutomationObject
16
16
  module State
17
- module Composite
18
- # Hook action composite for managing state
19
- class HookAction < Base
20
- # @return [Boolean] run success or not
21
- def run
22
- blue_prints.hook_order.each do |hook_name|
23
- hook_action_class = AutomationObject::State::Composite.const_get(hook_name.to_s.pascalize)
24
- blue_prints = self.blue_prints.send(hook_name)
17
+ # Hook action composite for managing state
18
+ class HookAction < Base
19
+ # @return [Boolean] run success or not
20
+ def run
21
+ blue_prints.hook_order.each do |hook_name|
22
+ hook_action_class = AutomationObject::State.const_get(hook_name.to_s.pascalize)
23
+ blue_prints = self.blue_prints.send(hook_name)
25
24
 
26
- hook_action = hook_action_class.new(self, driver, blue_prints)
27
- return false if hook_action.run == false # Use long form, can return nil!
28
- end
29
-
30
- true
25
+ hook_action = hook_action_class.new(self, driver, blue_prints)
26
+ return false if hook_action.run == false # Use long form, can return nil!
31
27
  end
28
+
29
+ true
32
30
  end
33
31
  end
34
32
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ module AutomationObject
3
+ module State
4
+ # Composite action loop base class
5
+ class ActionLoop
6
+ # @return [AutomationObject::State::Base]
7
+ attr_accessor :composite
8
+ # @return [AutomationObject::Driver::Driver]
9
+ attr_accessor :driver
10
+ # @return [AutomationObject::BluePrint::Composite::Base]
11
+ attr_accessor :blue_prints
12
+ # @return [Integer]
13
+ attr_accessor :loops
14
+
15
+ # @param composite [AutomationObject::State::Composite::Base]
16
+ # @param driver [AutomationObject::Driver::Driver]
17
+ # @param blue_prints [AutomationObject::BluePrint::Composite::Base]
18
+ # @param loops [Integer]
19
+ def initialize(composite, driver, blue_prints, loops = 30)
20
+ self.composite = composite
21
+ self.driver = driver
22
+ self.blue_prints = blue_prints
23
+ self.loops = loops
24
+ end
25
+
26
+ # @return [Boolean] run success or not
27
+ def run
28
+ loops.times do
29
+ # Sub classes implement single run
30
+ return true if single_run
31
+ end
32
+
33
+ false
34
+ end
35
+
36
+ # Abstract method, override
37
+ # @return [Boolean] success or not
38
+ def single_run
39
+ raise NotImplementedError
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'action_loop'
3
+
4
+ module AutomationObject
5
+ module State
6
+ # Change screen hook loop
7
+ class ChangeScreen < ActionLoop
8
+ def single_run
9
+ return false unless driver.document_complete?
10
+
11
+ new_screen = composite.top.screens[blue_prints]
12
+ return false if new_screen.load.live? == false # Need strict
13
+
14
+ new_screen.previous_screen_name = composite.screen.name
15
+
16
+ composite.screen.deactivate
17
+ new_screen.activate
18
+
19
+ true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'action_loop'
3
+
4
+ module AutomationObject
5
+ module State
6
+ # Change to previous screen hook loop
7
+ class ChangeToPreviousScreen < ActionLoop
8
+ def single_run
9
+ return false unless driver.document_complete?
10
+
11
+ new_screen = composite.top.screens[composite.screen.previous_screen_name]
12
+ # Need strict check, can be nil
13
+ return false if new_screen.load.live? == false
14
+
15
+ new_screen.previous_screen_name = composite.screen.name
16
+ composite.screen.deactivate
17
+ new_screen.activate
18
+
19
+ true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'action_loop'
3
+ require_relative '../_error'
4
+
5
+ module AutomationObject
6
+ module State
7
+ # Close modal hook loop
8
+ class CloseModal < ActionLoop
9
+ def single_run
10
+ return false unless driver.document_complete?
11
+
12
+ raise ModalParentExpected unless composite.parent.is_a?(Modal)
13
+
14
+ return false if modal.live? == false
15
+
16
+ modal.deactivate
17
+ true
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'action_loop'
3
+ require_relative '../_error'
4
+
5
+ module AutomationObject
6
+ module State
7
+ # Close screen hook loop
8
+ class CloseScreen < ActionLoop
9
+ def single_run
10
+ raise ScreenParentExpected unless composite.screen
11
+
12
+ return false unless composite.screen.closed?
13
+
14
+ composite.screen.deactivate
15
+
16
+ true
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'action_loop'
3
+
4
+ module AutomationObject
5
+ module State
6
+ # Element requirement hook loop
7
+ class ElementRequirement < ActionLoop
8
+ def element
9
+ @element ||= driver.find_element(*blue_prints.element_blueprints.selector_params)
10
+ end
11
+
12
+ def single_run
13
+ blue_prints.hook_order.each do |requirement_name|
14
+ next if blue_prints.requirement(requirement_name).nil?
15
+
16
+ requirement_value = blue_prints.requirement(requirement_name)
17
+
18
+ case requirement_name
19
+ when :exists?
20
+ return false if requirement_value != driver.exists?(*blue_prints.element_blueprints.selector_params)
21
+ else
22
+ return false if requirement_value != element.send(requirement_name)
23
+ end
24
+ end
25
+
26
+ true
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'action_loop'
3
+ require_relative '../_error'
4
+
5
+ module AutomationObject
6
+ module State
7
+ # New screen hook loop
8
+ class NewScreen < ActionLoop
9
+ # @param composite [AutomationObject::State::Base]
10
+ # @param driver [AutomationObject::Driver::Driver]
11
+ # @param blue_prints [AutomationObject::BluePrint::Composite::Base]
12
+ # @param loops [Integer]
13
+ def initialize(composite, driver, blue_prints, loops = 1)
14
+ self.composite = composite
15
+ self.driver = driver
16
+ self.blue_prints = blue_prints
17
+ self.loops = loops
18
+ end
19
+
20
+ def single_run
21
+ new_screen = composite.top.screens[blue_prints]
22
+ stored_window_handles = composite.top.screens.values
23
+ .each_with_object([]) do |screen, a|
24
+ a.push(screen.window_handle) unless screen.window_handle.nil?
25
+ a
26
+ end
27
+
28
+ driver_handles = driver.window_handles
29
+
30
+ return false if driver_handles.length <= stored_window_handles.length
31
+ raise MoreThenOneScreenCreated if (driver_handles.length - stored_window_handles.length) > 1
32
+
33
+ new_window_handle = (driver_handles - stored_window_handles)[0]
34
+ driver.window_handle = new_window_handle
35
+
36
+ 30.times do
37
+ next unless driver.document_complete?
38
+ next if new_screen.load.live? == false
39
+
40
+ new_screen.activate
41
+
42
+ return true
43
+ end
44
+
45
+ false
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'action_loop'
3
+
4
+ module AutomationObject
5
+ module State
6
+ # Possible screen changes hook loop
7
+ class PossibleScreenChanges < ActionLoop
8
+ def single_run
9
+ return false unless driver.document_complete?
10
+
11
+ blue_prints.each do |possible_screen_name|
12
+ new_screen = composite.top.screens[possible_screen_name]
13
+ next unless new_screen.load.live? != false
14
+ composite.screen.deactivate
15
+ new_screen.activate
16
+ return true
17
+ end
18
+
19
+ false
20
+ end
21
+ end
22
+ end
23
+ end