ae_page_objects 1.4.1 → 1.5.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: 62a7c4ae245bff142532db643f26fd8d86cbeec5
4
- data.tar.gz: 7f08f9ba3ee29135124a6002eee99235e19854ea
3
+ metadata.gz: bdbc7b1c3cc7929e18cae25d6b5a0073bc941d85
4
+ data.tar.gz: 0767bbea656f6a123d00c2dae7c00673714272d3
5
5
  SHA512:
6
- metadata.gz: 360cc60ce2ff2ce7b5f4a4ca67ccc2c840df1a2aea9ca16fdad34629a3e9aba0d153c17514287b5be2756c12289d1f924f2f12477d7b2f4f9c6597dd8bb79213
7
- data.tar.gz: 16c0429209abafbccdc3e699d41426455ae54adf340ac9398cfa885b11768c77a3223583be15e016b12ae5adba359153fae0a619aacb441dff3730c99c95c11f
6
+ metadata.gz: 12c29ba3329811692f161d16a46dc95bf187492c49585295e183f2d63bc356420a3ea76a4cb158b77f49db322517f18b674020741424389427f975c7189d3fb9
7
+ data.tar.gz: fa23580da483d787a283c96ac7495780ff52b17dd7563892aa4e89bed21205e15a97b64de1a547aafeb373f3391496fce569bf1f933d443b241e9e15eeca5d63
@@ -18,12 +18,6 @@ module AePageObjects
18
18
  autoload :Inflector, 'ae_page_objects/util/inflector'
19
19
  autoload :Waiter, 'ae_page_objects/util/waiter'
20
20
 
21
- module Concerns
22
- autoload :LoadEnsuring, 'ae_page_objects/concerns/load_ensuring'
23
- autoload :Staleable, 'ae_page_objects/concerns/staleable'
24
- autoload :Visitable, 'ae_page_objects/concerns/visitable'
25
- end
26
-
27
21
  module MultipleWindows
28
22
  autoload :Browser, 'ae_page_objects/multiple_windows/browser'
29
23
  autoload :Window, 'ae_page_objects/multiple_windows/window'
@@ -66,6 +60,24 @@ module AePageObjects
66
60
  end
67
61
  end
68
62
  end
63
+
64
+ def self.wait_until(seconds_to_wait = nil, error_message = nil)
65
+ seconds_to_wait ||= Capybara.default_wait_time
66
+ start_time = Time.now
67
+
68
+ until result = yield
69
+ delay = seconds_to_wait - (Time.now - start_time)
70
+
71
+ if delay <= 0
72
+ raise WaitTimeoutError, error_message || "Timed out waiting for condition"
73
+ end
74
+
75
+ sleep(0.05)
76
+ raise FrozenInTime, "Time appears to be frozen" if Time.now == start_time
77
+ end
78
+
79
+ result
80
+ end
69
81
  end
70
82
 
71
83
  require 'ae_page_objects/core_ext/module'
@@ -1,6 +1,46 @@
1
1
  module AePageObjects
2
2
  class Document < Node
3
- include Concerns::Visitable
3
+ class << self
4
+ def can_load_from_current_url?
5
+ return true if paths.empty?
6
+
7
+ url = current_url_without_params
8
+
9
+ paths.any? do |path|
10
+ site.path_recognizes_url?(path, url)
11
+ end
12
+ end
13
+
14
+ def visit(*args)
15
+ args = args.dup
16
+ inner_options = args.last.is_a?(::Hash)? args.last : {}
17
+
18
+ path = inner_options.delete(:via) || paths.first
19
+
20
+ full_path = site.generate_path(path, *args)
21
+ raise PathNotResolvable, "#{self.name} not visitable via #{paths.first}(#{args.inspect})" unless full_path
22
+
23
+ Capybara.current_session.visit(full_path)
24
+
25
+ new
26
+ end
27
+
28
+ private
29
+
30
+ def paths
31
+ @paths ||= []
32
+ end
33
+
34
+ def path(path_method)
35
+ raise ArgumentError, "path must be a symbol or string" if ! path_method.is_a?(Symbol) && ! path_method.is_a?(String)
36
+
37
+ paths << path_method
38
+ end
39
+
40
+ def site
41
+ @site ||= Site.from(self)
42
+ end
43
+ end
4
44
 
5
45
  attr_reader :window
6
46
 
@@ -19,10 +59,19 @@ module AePageObjects
19
59
  self
20
60
  end
21
61
 
22
- class << self
23
62
  private
24
- def site
25
- @site ||= Site.from(self)
63
+
64
+ def ensure_loaded!
65
+ begin
66
+ AePageObjects.wait_until { self.class.can_load_from_current_url? }
67
+ rescue WaitTimeoutError
68
+ raise LoadingPageFailed, "#{self.class.name} cannot be loaded with url '#{current_url_without_params}'"
69
+ end
70
+
71
+ begin
72
+ super
73
+ rescue LoadingElementFailed => e
74
+ raise LoadingPageFailed, e.message
26
75
  end
27
76
  end
28
77
  end
@@ -1,19 +1,26 @@
1
+ require 'ae_page_objects/util/page_polling'
2
+
1
3
  module AePageObjects
2
4
  class DocumentLoader
5
+ include AePageObjects::PagePolling
6
+
3
7
  def initialize(query, strategy)
4
8
  @query = query
5
9
  @strategy = strategy
6
10
  end
7
11
 
8
12
  def load
9
- Waiter.wait_until do
10
- @query.conditions.each do |document_condition|
11
- if document = @strategy.load_document_with_condition(document_condition)
12
- return document
13
+ begin
14
+ poll_until do
15
+ @query.conditions.each do |document_condition|
16
+ if document = @strategy.load_document_with_condition(document_condition)
17
+ return document
18
+ end
13
19
  end
14
- end
15
20
 
16
- nil
21
+ nil
22
+ end
23
+ rescue AePageObjects::WaitTimeoutError
17
24
  end
18
25
 
19
26
  raise DocumentLoadError, @strategy.document_not_loaded_error_message(@query)
@@ -1,6 +1,7 @@
1
+ require 'ae_page_objects/util/page_polling'
2
+
1
3
  module AePageObjects
2
4
  class ElementProxy
3
-
4
5
  # Remove all instance methods so even things like class()
5
6
  # get handled by method_missing(). <lifted from activerecord>
6
7
  instance_methods.each do |m|
@@ -9,6 +10,8 @@ module AePageObjects
9
10
  end
10
11
  end
11
12
 
13
+ include AePageObjects::PagePolling
14
+
12
15
  def initialize(element_class, *args)
13
16
  @element_class = element_class
14
17
  @args = args
@@ -61,35 +64,30 @@ module AePageObjects
61
64
  end
62
65
 
63
66
  def wait_until_visible(timeout = nil)
64
- is_visible = Waiter.wait_until(timeout) do
65
- inst = presence
66
- ! inst.nil? && inst.visible?
67
+ with_reloaded_element(timeout) do
68
+ !@loaded_element.nil? && @loaded_element.visible?
67
69
  end
68
70
 
69
- unless is_visible
70
- raise ElementNotVisible, "element_class: #{@element_class}, options: #{@options.inspect}"
71
- end
71
+ rescue AePageObjects::WaitTimeoutError
72
+ raise ElementNotVisible, "element_class: #{@element_class}, options: #{@options.inspect}"
72
73
  end
73
74
 
74
75
  def wait_until_hidden(timeout = nil)
75
- is_hidden = Waiter.wait_until(timeout) do
76
- inst = presence
77
- inst.nil? || ! inst.visible?
76
+ with_reloaded_element(timeout) do
77
+ @loaded_element.nil? || !@loaded_element.visible?
78
78
  end
79
79
 
80
- unless is_hidden
81
- raise ElementNotHidden, "element_class: #{@element_class}, options: #{@options.inspect}"
82
- end
80
+ rescue AePageObjects::WaitTimeoutError
81
+ raise ElementNotHidden, "element_class: #{@element_class}, options: #{@options.inspect}"
83
82
  end
84
83
 
85
84
  def wait_until_present(timeout = nil)
86
- is_present = Waiter.wait_until(timeout) do
87
- ! presence.nil?
85
+ with_reloaded_element(timeout) do
86
+ !@loaded_element.nil?
88
87
  end
89
88
 
90
- unless is_present
91
- raise ElementNotPresent, "element_class: #{@element_class}, options: #{@options.inspect}"
92
- end
89
+ rescue AePageObjects::WaitTimeoutError
90
+ raise ElementNotPresent, "element_class: #{@element_class}, options: #{@options.inspect}"
93
91
  end
94
92
 
95
93
  def wait_for_presence(timeout = nil)
@@ -98,13 +96,12 @@ module AePageObjects
98
96
  end
99
97
 
100
98
  def wait_until_absent(timeout = nil)
101
- is_absent = Waiter.wait_until(timeout) do
102
- check_absence
99
+ with_reloaded_element(timeout) do
100
+ @loaded_element.nil?
103
101
  end
104
102
 
105
- unless is_absent
106
- raise ElementNotAbsent, "element_class: #{@element_class}, options: #{@options.inspect}"
107
- end
103
+ rescue AePageObjects::WaitTimeoutError
104
+ raise ElementNotAbsent, "element_class: #{@element_class}, options: #{@options.inspect}"
108
105
  end
109
106
 
110
107
  def wait_for_absence(timeout = nil)
@@ -132,7 +129,7 @@ module AePageObjects
132
129
  super || @element_class.allocate.respond_to?(*args)
133
130
  end
134
131
 
135
- private
132
+ private
136
133
 
137
134
  def load_element
138
135
  @element_class.new(*@args)
@@ -142,20 +139,30 @@ module AePageObjects
142
139
  @loaded_element ||= load_element
143
140
  end
144
141
 
145
- def check_absence
146
- load_element
142
+ def reload_element
143
+ @loaded_element = load_element
147
144
 
148
- false
145
+ true
149
146
  rescue LoadingElementFailed
147
+ @loaded_element = nil
148
+
150
149
  true
151
150
  rescue => e
152
151
  if Capybara.current_session.driver.is_a?(Capybara::Selenium::Driver) &&
153
152
  e.is_a?(Selenium::WebDriver::Error::StaleElementReferenceError)
154
- # ignore and spin around for another check
153
+
154
+ # Inconclusive. Leave the handling up to the caller
155
155
  false
156
156
  else
157
157
  raise
158
158
  end
159
159
  end
160
+
161
+ def with_reloaded_element(timeout)
162
+ poll_until(timeout) do
163
+ reload_conclusive = reload_element
164
+ reload_conclusive && yield
165
+ end
166
+ end
160
167
  end
161
168
  end
@@ -1,66 +1,86 @@
1
1
  module AePageObjects
2
2
  class Node
3
- module Methods
4
- def initialize(capybara_node)
5
- @node = capybara_node
6
- end
7
-
8
- def node
9
- @node
10
- end
11
-
12
- def document
13
- raise "Must implement!"
14
- end
3
+ extend Dsl
15
4
 
5
+ class << self
16
6
  def current_url
17
- self.class.current_url
7
+ Capybara.current_session.current_url.sub(/^https?:\/\/[^\/]*/, '')
18
8
  end
19
9
 
20
10
  def current_url_without_params
21
- self.class.current_url_without_params
11
+ current_url.sub(/(\?|\#).*/, '')
22
12
  end
13
+ end
14
+
15
+ def initialize(capybara_node)
16
+ @node = capybara_node
17
+ @stale = false
23
18
 
24
- METHODS_TO_DELEGATE_TO_NODE = [:find, :all, :value, :set, :text, :visible?]
25
- METHODS_TO_DELEGATE_TO_NODE.each do |m|
26
- class_eval <<-RUBY
27
- def #{m}(*args, &block)
28
- node.send(:#{m}, *args, &block)
29
- rescue Capybara::ElementNotFound => e
30
- raise LoadingElementFailed, e.message
31
- end
32
- RUBY
19
+ ensure_loaded!
20
+ end
21
+
22
+ def node
23
+ if stale?
24
+ raise StalePageObject, "Can't access stale page object '#{self}'"
33
25
  end
34
26
 
35
- private
27
+ @node
28
+ end
36
29
 
37
- def eval_locator(locator)
38
- return [] unless locator
30
+ def stale?
31
+ @stale
32
+ end
39
33
 
40
- if locator.respond_to?(:call)
41
- locator = instance_eval(&locator)
42
- end
34
+ def stale!
35
+ @stale = true
36
+ end
43
37
 
44
- locator.is_a?(Array) ? locator : [locator.to_s]
45
- end
38
+ def document
39
+ raise "Must implement!"
46
40
  end
47
41
 
48
- module ClassMethods
49
- def current_url
50
- Capybara.current_session.current_url.sub(/^https?:\/\/[^\/]*/, '')
51
- end
42
+ def current_url
43
+ self.class.current_url
44
+ end
52
45
 
53
- def current_url_without_params
54
- current_url.sub(/(\?|\#).*/, '')
46
+ def current_url_without_params
47
+ self.class.current_url_without_params
48
+ end
49
+
50
+ METHODS_TO_DELEGATE_TO_NODE = [:find, :all, :value, :set, :text, :visible?]
51
+ METHODS_TO_DELEGATE_TO_NODE.each do |m|
52
+ class_eval <<-RUBY
53
+ def #{m}(*args, &block)
54
+ node.send(:#{m}, *args, &block)
55
+ rescue Capybara::ElementNotFound => e
56
+ raise LoadingElementFailed, e.message
57
+ end
58
+ RUBY
59
+ end
60
+
61
+ private
62
+
63
+ def eval_locator(locator)
64
+ return [] unless locator
65
+
66
+ if locator.respond_to?(:call)
67
+ locator = instance_eval(&locator)
55
68
  end
69
+
70
+ locator.is_a?(Array) ? locator : [locator.to_s]
56
71
  end
57
72
 
58
- extend Dsl
73
+ def loaded_locator
74
+ end
59
75
 
60
- include Methods
61
- extend ClassMethods
76
+ def ensure_loaded!
77
+ if locator = loaded_locator
78
+ find(*eval_locator(locator))
79
+ end
62
80
 
63
- include Concerns::LoadEnsuring
64
- include Concerns::Staleable
81
+ self
82
+ rescue Capybara::ElementNotFound => e
83
+ raise LoadingElementFailed, e.message
84
+ end
65
85
  end
66
86
  end
@@ -8,7 +8,7 @@ module AePageObjects
8
8
  end
9
9
 
10
10
  def current_document=(document)
11
- @current_document.send(:stale!) if @current_document
11
+ @current_document.stale! if @current_document
12
12
  @current_document = document
13
13
  end
14
14
 
@@ -0,0 +1,12 @@
1
+ module AePageObjects
2
+ module PagePolling
3
+
4
+ private
5
+
6
+ def poll_until(timeout = nil, &block)
7
+ AePageObjects.wait_until(timeout) do
8
+ Capybara.using_wait_time(0, &block)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,38 +1,32 @@
1
+ require 'ae_page_objects/util/page_polling'
2
+
1
3
  module AePageObjects
2
4
  module Waiter
3
- def self.wait_until(timeout = nil, &block)
4
- seconds_to_wait = timeout || Capybara.default_wait_time
5
- start_time = Time.now
6
-
7
- until result = Capybara.using_wait_time(0, &block)
8
- delay = seconds_to_wait - (Time.now - start_time)
9
-
10
- if delay <= 0
11
- return false
12
- end
5
+ class << self
6
+ include AePageObjects::PagePolling
13
7
 
14
- sleep(0.05)
15
- raise FrozenInTime, "Time appears to be frozen" if Time.now == start_time
8
+ def wait_until(timeout = nil, &block)
9
+ warn "[DEPRECATION WARNING]: AePageObjects::Waiter.wait_until is deprecated and will be removed in version 2.0.0. Use AePageObjects.wait_until instead."
10
+ wait_until_return_false(timeout, &block)
16
11
  end
17
12
 
18
- result
19
- end
20
-
21
- def self.wait_for(*args, &block)
22
- warn "[DEPRECATION WARNING]: AePageObjects::Waiter.wait_for is deprecated and will be removed in version 2.0.0. Use AePageObjects::Waiter.wait_until instead."
23
- wait_until(*args, &block)
24
- end
25
-
26
- def self.wait_until!(timeout = nil)
27
- result = wait_until(timeout) do
28
- yield
13
+ def wait_for(timeout = nil, &block)
14
+ warn "[DEPRECATION WARNING]: AePageObjects::Waiter.wait_for is deprecated and will be removed in version 2.0.0. Use AePageObjects.wait_until instead."
15
+ wait_until_return_false(timeout, &block)
29
16
  end
30
17
 
31
- unless result
32
- raise WaitTimeoutError, "Timed out waiting for condition"
18
+ def wait_until!(timeout = nil, &block)
19
+ warn "[DEPRECATION WARNING]: AePageObjects::Waiter.wait_until! is deprecated and will be removed in version 2.0.0. Use AePageObjects.wait_until instead."
20
+ poll_until(timeout, &block)
33
21
  end
34
22
 
35
- result
23
+ private
24
+
25
+ def wait_until_return_false(timeout, &block)
26
+ poll_until(timeout, &block)
27
+ rescue WaitTimeoutError
28
+ false
29
+ end
36
30
  end
37
31
  end
38
32
  end
@@ -1,3 +1,3 @@
1
1
  module AePageObjects
2
- VERSION = '1.4.1'.freeze
2
+ VERSION = '1.5.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ae_page_objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.5.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: 2015-08-28 00:00:00.000000000 Z
11
+ date: 2016-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '1.1'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '2.3'
22
+ version: '2.8'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '1.1'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '2.3'
32
+ version: '2.8'
33
33
  description: Capybara Page Objects pattern
34
34
  email:
35
35
  - engineering@appfolio.com
@@ -38,9 +38,6 @@ extensions: []
38
38
  extra_rdoc_files: []
39
39
  files:
40
40
  - lib/ae_page_objects.rb
41
- - lib/ae_page_objects/concerns/load_ensuring.rb
42
- - lib/ae_page_objects/concerns/staleable.rb
43
- - lib/ae_page_objects/concerns/visitable.rb
44
41
  - lib/ae_page_objects/core/application_router.rb
45
42
  - lib/ae_page_objects/core/basic_router.rb
46
43
  - lib/ae_page_objects/core/dsl.rb
@@ -71,6 +68,7 @@ files:
71
68
  - lib/ae_page_objects/util/hash_symbolizer.rb
72
69
  - lib/ae_page_objects/util/inflector.rb
73
70
  - lib/ae_page_objects/util/internal_helpers.rb
71
+ - lib/ae_page_objects/util/page_polling.rb
74
72
  - lib/ae_page_objects/util/singleton.rb
75
73
  - lib/ae_page_objects/util/waiter.rb
76
74
  - lib/ae_page_objects/version.rb
@@ -1,26 +0,0 @@
1
- module AePageObjects
2
- module Concerns
3
- module LoadEnsuring
4
-
5
- def initialize(*args)
6
- super
7
- ensure_loaded!
8
- end
9
-
10
- private
11
-
12
- def loaded_locator
13
- end
14
-
15
- def ensure_loaded!
16
- if locator = loaded_locator
17
- find(*eval_locator(locator))
18
- end
19
-
20
- self
21
- rescue Capybara::ElementNotFound => e
22
- raise LoadingElementFailed, e.message
23
- end
24
- end
25
- end
26
- end
@@ -1,25 +0,0 @@
1
- module AePageObjects
2
- module Concerns
3
- module Staleable
4
-
5
- def stale?
6
- !!@stale
7
- end
8
-
9
- def node
10
- if stale?
11
- raise StalePageObject, "Can't access stale page object '#{self}'"
12
- end
13
-
14
- super
15
- end
16
-
17
- private
18
-
19
- def stale!
20
- @stale = true
21
- end
22
-
23
- end
24
- end
25
- end
@@ -1,66 +0,0 @@
1
- module AePageObjects
2
- module Concerns
3
- module Visitable
4
-
5
- def self.included(target)
6
- target.extend ClassMethods
7
- end
8
-
9
- private
10
-
11
- def ensure_loaded!
12
- unless Waiter.wait_until { self.class.can_load_from_current_url? }
13
- raise LoadingPageFailed, "#{self.class.name} cannot be loaded with url '#{current_url_without_params}'"
14
- end
15
-
16
- begin
17
- super
18
- rescue LoadingElementFailed => e
19
- raise LoadingPageFailed, e.message
20
- end
21
- end
22
-
23
- module VisitMethod
24
- def visit(*args)
25
- args = args.dup
26
- inner_options = args.last.is_a?(::Hash)? args.last : {}
27
-
28
- path = inner_options.delete(:via) || paths.first
29
-
30
- full_path = site.generate_path(path, *args)
31
- raise PathNotResolvable, "#{self.name} not visitable via #{paths.first}(#{args.inspect})" unless full_path
32
-
33
- Capybara.current_session.visit(full_path)
34
- new
35
- end
36
- end
37
-
38
- module ClassMethods
39
-
40
- def can_load_from_current_url?
41
- return true if paths.empty?
42
-
43
- url = current_url_without_params
44
-
45
- paths.any? do |path|
46
- site.path_recognizes_url?(path, url)
47
- end
48
- end
49
-
50
- private
51
-
52
- def paths
53
- @paths ||= []
54
- end
55
-
56
- def path(path_method)
57
- raise ArgumentError, "path must be a symbol or string" if ! path_method.is_a?(Symbol) && ! path_method.is_a?(String)
58
-
59
- paths << path_method
60
-
61
- extend VisitMethod
62
- end
63
- end
64
- end
65
- end
66
- end