ae_page_objects 1.1.3 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6be4cfb96f4b15a435ce587e4821dd6e1c1f6165
4
- data.tar.gz: e866450111689a5edcd99a61c514494b8791980b
3
+ metadata.gz: e5eeebecb74ccaec9739afd6183c3d8906ce2b9e
4
+ data.tar.gz: 6752901420af4fe99325e9735cbc3a5e9ddf68de
5
5
  SHA512:
6
- metadata.gz: 472aa891add7f3d89473045b128d6d179c99593434099af085a533e049ad762e64207528ceb2eba6b6d5e8be97f2e327c96bb790f2c7d4933f386cbde1fa7147
7
- data.tar.gz: 400a3f13461bcda18bbe715d9ce1286bea2dfc5ff7ff191f28bd1988fffdb4a532b21c51e797294e4c66581ccb3860d55a5ebfec960753d92eccd96e0f7e3d60
6
+ metadata.gz: 4b420a7c14fcde32afb609815550643a84b828f58654ebee477e4ef3bbf762ef70ff01ad16d09f174a68eddaa881cb706e3656fc7153a2ed1df401cb409f28ea
7
+ data.tar.gz: 25adc0b0e01e95ed700ee6a1bae61544662441b877778609db2449c091e36bb419c45ed5459a68e7a435b3ddd1d2391d9ab392cd5a41d9c6d3ba8cf60dba818c
@@ -16,10 +16,24 @@ module AePageObjects
16
16
  class Rails23 < Base
17
17
  def recognizes?(path, url)
18
18
  ["GET", "PUT", "POST", "DELETE", "PATCH"].map(&:downcase).map(&:to_sym).each do |method|
19
- route = ActionController::Routing::Routes.named_routes[path]
20
- route.recognize(url, {:method => method})
19
+ path_route_result = ActionController::Routing::Routes.named_routes[path].requirements
20
+ recognized_result = nil
21
+
22
+ begin
23
+ recognized_result = ActionController::Routing::Routes.recognize_path(url, {:method => method}).select do
24
+ |key, _|
25
+ key.to_s.match(/(controller|action)/)
26
+ end
27
+ rescue ActionController::MethodNotAllowed
28
+ end
21
29
 
22
- return true if route && route.recognize(url, {:method => method})
30
+ # Only the first recognized path returned by Rails is considered,
31
+ # which means, we only want highest prioritized route.
32
+ if recognized_result && path_route_result == Hash[recognized_result]
33
+ return true
34
+ else
35
+ next
36
+ end
23
37
  end
24
38
 
25
39
  false
@@ -44,14 +58,18 @@ module AePageObjects
44
58
 
45
59
  ["GET", "PUT", "POST", "DELETE", "PATCH"].each do |method|
46
60
  router.recognize(request_for(url, method)) do |route, matches, params|
47
- return true if route.name.to_s == path.to_s
61
+ if route.name.to_s == path.to_s
62
+ return true
63
+ else
64
+ # We break the inner loop here because only the first recognized path returned by Rails is considered,
65
+ # which means, we only want highest prioritized route.
66
+ break
67
+ end
48
68
  end
49
69
  end
50
-
51
70
  false
52
71
  end
53
72
 
54
-
55
73
  private
56
74
 
57
75
  def request_for(url, method)
@@ -86,6 +104,7 @@ module AePageObjects
86
104
  class Rails32 < Rails3
87
105
 
88
106
  private
107
+
89
108
  def url_and_router(url)
90
109
  url = Journey::Router::Utils.normalize_path(url) unless url =~ %r{://}
91
110
  router = ::Rails.application.routes.router
@@ -96,7 +115,8 @@ module AePageObjects
96
115
 
97
116
  class Rails4 < Rails32
98
117
 
99
- private
118
+ private
119
+
100
120
  def url_and_router(url)
101
121
  require 'action_dispatch/journey'
102
122
  url = ActionDispatch::Journey::Router::Utils.normalize_path(url) unless url =~ %r{://}
@@ -105,7 +125,6 @@ module AePageObjects
105
125
  [url, router]
106
126
  end
107
127
  end
108
-
109
128
  end
110
129
 
111
130
  def path_recognizes_url?(path, url)
@@ -143,14 +143,14 @@ module AePageObjects
143
143
 
144
144
  item_class = options.delete(:contains) || options[:is].item_class
145
145
  if block_given?
146
- item_class = item_class.new_subclass(&block).tap do |new_item_class|
146
+ item_class = Class.new(item_class, &block).tap do |new_item_class|
147
147
  new_item_class.element_attributes.merge!(item_class.element_attributes)
148
148
  end
149
149
  end
150
150
 
151
151
  # since we are creating a new item class, we need to subclass the collection class
152
152
  # so we can parameterize the collection class with an item class
153
- options[:is] = options[:is].new_subclass
153
+ options[:is] = Class.new(options[:is])
154
154
  options[:is].item_class = item_class
155
155
 
156
156
  element(name, options)
@@ -162,7 +162,7 @@ module AePageObjects
162
162
  raise ArgumentError, ":is option not supported" if options[:is]
163
163
  raise ArgumentError, "Block required." if block.nil?
164
164
 
165
- klass = ::AePageObjects::Form.new_subclass(&block)
165
+ klass = Class.new(::AePageObjects::Form, &block)
166
166
 
167
167
  options = options.dup
168
168
  options[:is] = klass
@@ -186,7 +186,7 @@ module AePageObjects
186
186
  klass = options.delete(:is) || ::AePageObjects::Element
187
187
 
188
188
  if block_given?
189
- klass.new_subclass(&block)
189
+ Class.new(klass, &block)
190
190
  else
191
191
  klass
192
192
  end
@@ -1,5 +1,3 @@
1
- require 'timeout'
2
-
3
1
  module AePageObjects
4
2
  class ElementProxy
5
3
 
@@ -14,6 +12,8 @@ module AePageObjects
14
12
  def initialize(element_class, *args)
15
13
  @element_class = element_class
16
14
  @args = args
15
+
16
+ @loaded_element = nil
17
17
  end
18
18
 
19
19
  # Provided so that visible? can be asked without
@@ -33,21 +33,45 @@ module AePageObjects
33
33
  end
34
34
 
35
35
  def present?
36
- ! presence.nil?
36
+ wait_for_presence
37
+ true
38
+ rescue ElementNotPresent
39
+ false
37
40
  end
38
41
 
39
42
  def not_present?
40
- Waiter.wait_for do
41
- ! present?
42
- end
43
+ wait_for_absence
44
+ true
45
+ rescue ElementNotAbsent
46
+ false
43
47
  end
44
48
 
45
49
  def presence
46
- element
47
- rescue AePageObjects::LoadingElementFailed
50
+ implicit_element
51
+ rescue LoadingElementFailed
48
52
  nil
49
53
  end
50
54
 
55
+ def wait_for_presence(timeout = nil)
56
+ is_present = Waiter.wait_for(timeout) do
57
+ ! presence.nil?
58
+ end
59
+
60
+ unless is_present
61
+ raise ElementNotPresent, "element_class: #{@element_class}, options: #{@options.inspect}"
62
+ end
63
+ end
64
+
65
+ def wait_for_absence(timeout = nil)
66
+ is_absent = Waiter.wait_for(timeout) do
67
+ check_absence
68
+ end
69
+
70
+ unless is_absent
71
+ raise ElementNotAbsent, "element_class: #{@element_class}, options: #{@options.inspect}"
72
+ end
73
+ end
74
+
51
75
  def is_a?(type)
52
76
  type == @element_class || type == ElementProxy
53
77
  end
@@ -61,7 +85,7 @@ module AePageObjects
61
85
  return @element_class
62
86
  end
63
87
 
64
- element.__send__(name, *args, &block)
88
+ implicit_element.__send__(name, *args, &block)
65
89
  end
66
90
 
67
91
  def respond_to?(*args)
@@ -70,8 +94,28 @@ module AePageObjects
70
94
 
71
95
  private
72
96
 
73
- def element
74
- @element ||= @element_class.new(*@args)
97
+ def load_element
98
+ @element_class.new(*@args)
99
+ end
100
+
101
+ def implicit_element
102
+ @loaded_element ||= load_element
103
+ end
104
+
105
+ def check_absence
106
+ load_element
107
+
108
+ false
109
+ rescue LoadingElementFailed
110
+ true
111
+ rescue => e
112
+ if Capybara.current_session.driver.is_a?(Capybara::Selenium::Driver) &&
113
+ e.is_a?(Selenium::WebDriver::Error::StaleElementReferenceError)
114
+ # ignore and spin around for another check
115
+ false
116
+ else
117
+ raise
118
+ end
75
119
  end
76
120
  end
77
121
  end
@@ -13,6 +13,12 @@ module AePageObjects
13
13
  class LoadingElementFailed < LoadingFailed
14
14
  end
15
15
 
16
+ class ElementNotPresent < Error
17
+ end
18
+
19
+ class ElementNotAbsent < Error
20
+ end
21
+
16
22
  class PathNotResolvable < Error
17
23
  end
18
24
 
@@ -21,4 +27,7 @@ module AePageObjects
21
27
 
22
28
  class CastError < Error
23
29
  end
30
+
31
+ class WindowNotFound < Error
32
+ end
24
33
  end
@@ -13,6 +13,13 @@ module AePageObjects
13
13
  else
14
14
  browser.window_handle
15
15
  end
16
+ rescue => e
17
+ if Capybara.current_session.driver.is_a?(Capybara::Selenium::Driver) &&
18
+ e.is_a?(Selenium::WebDriver::Error::NoSuchWindowError)
19
+ raise WindowNotFound
20
+ end
21
+
22
+ raise
16
23
  end
17
24
 
18
25
  def self.switch_to(handle)
@@ -15,14 +15,21 @@ module AePageObjects
15
15
 
16
16
  def opened
17
17
  WindowHandleManager.all.map do |handle|
18
- find(handle)
18
+ window_for(handle)
19
19
  end
20
20
  end
21
21
 
22
22
  def current_window
23
23
  current_handle = WindowHandleManager.current
24
24
 
25
- find(current_handle) if current_handle
25
+ window_for(current_handle) if current_handle
26
+ rescue WindowNotFound
27
+ synchronize_windows
28
+
29
+ if current_window = @windows[@windows.keys.sort.first]
30
+ current_window.switch_to
31
+ current_window
32
+ end
26
33
  end
27
34
 
28
35
  def close_all
@@ -31,12 +38,22 @@ module AePageObjects
31
38
 
32
39
  private
33
40
 
34
- def find(handle)
35
- @windows[handle] || create_window(handle)
41
+ def synchronize_windows
42
+ existence_unverified_window_handles = @windows.keys
43
+
44
+ WindowHandleManager.all.map do |handle|
45
+ # If it exists in the browser, it's been verified
46
+ existence_unverified_window_handles.delete(handle)
47
+ end
48
+
49
+ # Remove the windows that no longer exist.
50
+ existence_unverified_window_handles.each do |non_existing_window_handle|
51
+ @windows.delete(non_existing_window_handle)
52
+ end
36
53
  end
37
54
 
38
- def create_window(handle)
39
- Window.new(self, handle)
55
+ def window_for(handle)
56
+ @windows[handle] ||= Window.new(self, handle)
40
57
  end
41
58
  end
42
59
  end
@@ -26,6 +26,8 @@ module AePageObjects
26
26
  class_eval <<-RUBY
27
27
  def #{m}(*args, &block)
28
28
  node.send(:#{m}, *args, &block)
29
+ rescue Capybara::ElementNotFound
30
+ raise AePageObjects::LoadingElementFailed
29
31
  end
30
32
  RUBY
31
33
  end
@@ -51,12 +53,6 @@ module AePageObjects
51
53
  def current_url_without_params
52
54
  current_url.sub(/\?.*/, '')
53
55
  end
54
-
55
- def new_subclass(&block)
56
- klass = Class.new(self)
57
- klass.class_eval(&block) if block
58
- klass
59
- end
60
56
  end
61
57
 
62
58
  extend Dsl
@@ -1,7 +1,7 @@
1
1
  module AePageObjects
2
2
  module Waiter
3
- def self.wait_for(&block)
4
- seconds_to_wait = Capybara.default_wait_time
3
+ def self.wait_for(wait_time = nil, &block)
4
+ seconds_to_wait = wait_time || Capybara.default_wait_time
5
5
  start_time = Time.now
6
6
 
7
7
  until result = Capybara.using_wait_time(0, &block)
@@ -17,4 +17,4 @@ module AePageObjects
17
17
  result
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module AePageObjects
2
- VERSION = '1.1.3'.freeze
2
+ VERSION = '1.2.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,33 +1,33 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ae_page_objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Donnie Tognazzini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-30 00:00:00.000000000 Z
11
+ date: 2014-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.1'
20
- - - "<"
20
+ - - <
21
21
  - !ruby/object:Gem::Version
22
22
  version: '2.3'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ">="
27
+ - - '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '1.1'
30
- - - "<"
30
+ - - <
31
31
  - !ruby/object:Gem::Version
32
32
  version: '2.3'
33
33
  description: Capybara Page Objects pattern
@@ -85,17 +85,17 @@ require_paths:
85
85
  - lib
86
86
  required_ruby_version: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - ">="
88
+ - - '>='
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - ">="
93
+ - - '>='
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
96
  requirements: []
97
97
  rubyforge_project:
98
- rubygems_version: 2.2.2
98
+ rubygems_version: 2.1.11
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: Capybara Page Objects pattern