ae_page_objects 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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