site_prism 4.0.beta → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,7 +15,7 @@ module SitePrism
15
15
  warn("#{old} is being deprecated and should no longer be used.")
16
16
  end
17
17
 
18
- warn("#{old} will be removed in SitePrism v4. You have been warned!")
18
+ warn("#{old} will be removed in SitePrism v5. You have been warned!")
19
19
  end
20
20
 
21
21
  # @return SitePrism.logger.debug(msg)
@@ -27,9 +27,9 @@ module SitePrism
27
27
  # NB: As this is bubbled up at debug level, often users will not see this. So it will
28
28
  # never be a candidate for removal directly
29
29
  def soft_deprecate(old, reason, new = nil)
30
- debug("The #{old} method is changing, as is SitePrism, and is now configurable.")
30
+ debug("The #{old} method is changing, as is SitePrism, and is now advised to be changed.")
31
31
  debug("REASON: #{reason}.")
32
- debug('Moving forwards into SitePrism v4, the default behaviour will change.')
32
+ debug('Moving forwards into SitePrism v5, the default behaviour will change.')
33
33
  debug("We advise you change to using #{new}") if new
34
34
  end
35
35
 
@@ -16,7 +16,7 @@ module SitePrism
16
16
 
17
17
  private
18
18
 
19
- def raise_if_block(object, name, has_block, type)
19
+ def raise_if_runtime_block_supplied(object, name, has_block, type)
20
20
  return unless has_block
21
21
 
22
22
  SitePrism.logger.debug("Type passed in: #{type}")
@@ -24,25 +24,21 @@ module SitePrism
24
24
  raise SitePrism::UnsupportedBlockError
25
25
  end
26
26
 
27
- # Call `find` inside `to_capybara_node` context (Either Capybara::Session or Capybara::Node::Element)
28
27
  def _find(*find_args)
29
28
  kwargs = find_args.pop
30
29
  to_capybara_node.find(*find_args, **kwargs)
31
30
  end
32
31
 
33
- # Call `all` inside `to_capybara_node` context (Either Capybara::Session or Capybara::Node::Element)
34
32
  def _all(*find_args)
35
33
  kwargs = find_args.pop
36
34
  to_capybara_node.all(*find_args, **kwargs)
37
35
  end
38
36
 
39
- # Call `has_selector?` inside `to_capybara_node` context (Either Capybara::Session or Capybara::Node::Element)
40
37
  def element_exists?(*find_args)
41
38
  kwargs = find_args.pop
42
39
  to_capybara_node.has_selector?(*find_args, **kwargs)
43
40
  end
44
41
 
45
- # Call `has_no_selector?` inside `to_capybara_node` context (Either Capybara::Session or Capybara::Node::Element)
46
42
  def element_does_not_exist?(*find_args)
47
43
  kwargs = find_args.pop
48
44
  to_capybara_node.has_no_selector?(*find_args, **kwargs)
@@ -103,10 +99,10 @@ module SitePrism
103
99
  # Wait for the elements to be present or not -> @return [TrueClass, SitePrism::Error]
104
100
  # Validate certain properties about the element
105
101
  def element(name, *find_args)
106
- raise_if_block(self, name, block_given?, :element)
102
+ raise_if_build_time_block_supplied(self, name, block_given?, :element)
107
103
  build(:element, name, *find_args) do
108
104
  define_method(name) do |*runtime_args, &runtime_block|
109
- raise_if_block(self, name, runtime_block, :element)
105
+ raise_if_runtime_block_supplied(self, name, runtime_block, :element)
110
106
  _find(*merge_args(find_args, runtime_args))
111
107
  end
112
108
  end
@@ -118,10 +114,10 @@ module SitePrism
118
114
  # Wait for the elements to be present or not -> @return [TrueClass, SitePrism::Error]
119
115
  # Validate certain properties about the elements
120
116
  def elements(name, *find_args)
121
- raise_if_block(self, name, block_given?, :elements)
117
+ raise_if_build_time_block_supplied(self, name, block_given?, :elements)
122
118
  build(:elements, name, *find_args) do
123
119
  define_method(name) do |*runtime_args, &runtime_block|
124
- raise_if_block(self, name, runtime_block, :elements)
120
+ raise_if_runtime_block_supplied(self, name, runtime_block, :elements)
125
121
  _all(*merge_args(find_args, runtime_args))
126
122
  end
127
123
  end
@@ -151,7 +147,7 @@ module SitePrism
151
147
  section_class, find_args = extract_section_options(args, &block)
152
148
  build(:sections, name, *find_args) do
153
149
  define_method(name) do |*runtime_args, &runtime_block|
154
- raise_if_block(self, name, runtime_block, :sections)
150
+ raise_if_runtime_block_supplied(self, name, runtime_block, :sections)
155
151
  _all(*merge_args(find_args, runtime_args)).map do |element|
156
152
  section_class.new(self, element)
157
153
  end
@@ -160,7 +156,7 @@ module SitePrism
160
156
  end
161
157
 
162
158
  def iframe(name, klass, *args)
163
- SitePrism.logger.debug('Block passed into iFrame construct at build time') if block_given?
159
+ raise_if_build_time_block_supplied(self, name, block_given?, :elements)
164
160
  element_find_args = deduce_iframe_element_find_args(args)
165
161
  scope_find_args = deduce_iframe_scope_find_args(args)
166
162
  build(:iframe, name, *element_find_args) do
@@ -175,10 +171,10 @@ module SitePrism
175
171
  # Return a list of all mapped items on a SitePrism class instance (Page or Section)
176
172
  # If legacy is set to true (Default) -> @return [Array]
177
173
  # If legacy is set to false (New behaviour) -> @return [Hash]
178
- def mapped_items(legacy: true)
179
- return old_mapped_items if legacy
174
+ def mapped_items(legacy: false)
175
+ return legacy_mapped_items if legacy
180
176
 
181
- new_mapped_items
177
+ @mapped_items ||= { element: [], elements: [], section: [], sections: [], iframe: [] }
182
178
  end
183
179
 
184
180
  private
@@ -192,13 +188,13 @@ module SitePrism
192
188
  map_item(type, name)
193
189
  yield
194
190
  end
195
- add_helper_methods(name, *find_args)
191
+ add_helper_methods(name, type, *find_args)
196
192
  end
197
193
 
198
- def add_helper_methods(name, *find_args)
194
+ def add_helper_methods(name, _type, *find_args)
199
195
  create_existence_checker(name, *find_args)
200
196
  create_nonexistence_checker(name, *find_args)
201
- SitePrism::RspecMatchers.new(name)._create_rspec_existence_matchers if defined?(RSpec)
197
+ SitePrism::RSpecMatchers.new(name)._create_rspec_existence_matchers if defined?(RSpec)
202
198
  create_visibility_waiter(name, *find_args)
203
199
  create_invisibility_waiter(name, *find_args)
204
200
  end
@@ -254,15 +250,15 @@ module SitePrism
254
250
  end
255
251
 
256
252
  def create_error_method(name)
257
- SitePrism.logger.error("#{name} has come from an item with no locators.")
258
- SitePrism::Deprecator.soft_deprecate(
253
+ SitePrism::Deprecator.deprecate(
259
254
  'DSL definition with no find_args',
260
- 'All DSL elements should have find_args'
255
+ 'DSL definition with at least 1 find_arg'
261
256
  )
257
+ SitePrism.logger.error("#{name} has come from an item with no locators.")
262
258
  define_method(name) { raise SitePrism::InvalidElementError }
263
259
  end
264
260
 
265
- def raise_if_block(parent_object, name, has_block, type)
261
+ def raise_if_build_time_block_supplied(parent_object, name, has_block, type)
266
262
  return unless has_block
267
263
 
268
264
  SitePrism.logger.debug("Type passed in: #{type}")
@@ -270,22 +266,19 @@ module SitePrism
270
266
  raise SitePrism::UnsupportedBlockError
271
267
  end
272
268
 
273
- def old_mapped_items
274
- SitePrism::Deprecator.soft_deprecate(
275
- '.mapped_items on a class',
276
- 'To allow easier recursion through the items in conjunction with #all_there?',
277
- '.mapped_items(legacy: false)'
278
- )
279
- @old_mapped_items ||= []
280
- end
281
-
282
- def new_mapped_items
283
- @new_mapped_items ||= { element: [], elements: [], section: [], sections: [], iframe: [] }
269
+ def legacy_mapped_items
270
+ @legacy_mapped_items ||= begin
271
+ SitePrism::Deprecator.deprecate(
272
+ '.mapped_items structure (internally), on a class',
273
+ 'the new .mapped_items structure'
274
+ )
275
+ []
276
+ end
284
277
  end
285
278
 
286
279
  def map_item(type, name)
287
- old_mapped_items << { type => name }
288
- new_mapped_items[type] << name.to_sym
280
+ mapped_items(legacy: true) << { type => name }
281
+ mapped_items[type] << name.to_sym
289
282
  end
290
283
 
291
284
  def deduce_iframe_scope_find_args(args)
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
+ #
4
5
  # [SitePrism::ElementChecker]
5
6
  #
6
7
  # This allows users to run `#all_there?` checks on an instance.
7
8
  #
8
- # NB: This functionality is being removed in v4 in favour of the all_there gem
9
9
  module ElementChecker
10
10
  # Runnable in the scope of any SitePrism::Page or Section.
11
11
  # Returns +true+ when "every item" that is being checked is
@@ -13,10 +13,16 @@ module SitePrism
13
13
  # for how the definition of "every item" is derived.
14
14
  #
15
15
  # Example
16
- # @my_page.mapped_items
17
- # { element => :button_one, element => :button_two, section => :filters }
16
+ # @my_page.class.mapped_items
17
+ # {
18
+ # element => [:button_one, :button_two],
19
+ # elements => [:button_collection_one, :button_collection_two],
20
+ # section => [:filters],
21
+ # sections => [:search_result],
22
+ # iframe => []
23
+ # }
18
24
  # @my_page.all_there?
19
- # => true - If the three items above are all present
25
+ # => true - If the items above are all present
20
26
  #
21
27
  # Note that #elements_to_check will check the hash of mapped_items
22
28
  #
@@ -26,13 +32,7 @@ module SitePrism
26
32
  # Override: 'one' => Perform one recursive dive into all section/sections
27
33
  # items and call #all_there? on all of those items too.
28
34
  def all_there?(recursion: :none)
29
- case recursion
30
- when :none; then elements_to_check.all? { |name| there?(name) }
31
- when :one; then SitePrism::AllThere::RecursionChecker.new(self).all_there?
32
- else
33
- SitePrism.logger.debug("Input value '#{recursion}'. Valid values are :none or :one.")
34
- SitePrism.logger.error('Invalid recursion setting, Will not run #all_there?.')
35
- end
35
+ SitePrism::AllThere::RecursionChecker.new(self).all_there?(recursion: recursion)
36
36
  end
37
37
 
38
38
  # Returns each element that is currently present inside the scope being tested
@@ -51,8 +51,6 @@ module SitePrism
51
51
 
52
52
  private
53
53
 
54
- # If the page or section has expected_items set, return expected_items that are mapped
55
- # otherwise just return the list of all mapped_items
56
54
  def elements_to_check
57
55
  if _expected_items
58
56
  SitePrism.logger.debug('Expected Items has been set.')
@@ -63,7 +61,7 @@ module SitePrism
63
61
  end
64
62
 
65
63
  def _mapped_items
66
- self.class.mapped_items(legacy: false).values.flatten.uniq
64
+ self.class.mapped_items.values.flatten.uniq
67
65
  end
68
66
 
69
67
  def _expected_items
@@ -43,10 +43,11 @@ module SitePrism
43
43
 
44
44
  # Check if the page is loaded.
45
45
  #
46
- # On failure, if an error was reported by a failing validation,
47
- # it will be available via the `load_error` accessor.
46
+ # On failure, if an error was reported by a failing validation, it will be available via the `load_error` accessor
48
47
  #
49
- # @return [Boolean] True if the page loaded successfully; otherwise false.
48
+ # It will return true if the page has been loaded successfully; otherwise it returns false
49
+ #
50
+ # @return [Boolean]
50
51
  def loaded?
51
52
  self.load_error = nil
52
53
 
@@ -57,8 +58,6 @@ module SitePrism
57
58
 
58
59
  private
59
60
 
60
- # If any load validations from page subclasses returns false,
61
- # immediately return false.
62
61
  def load_validations_pass?
63
62
  self.class.load_validations.all? do |validation|
64
63
  passed, message = instance_eval(&validation)
@@ -9,7 +9,7 @@ module SitePrism
9
9
  # through clicking buttons or filling in fields, or verbosely loaded by using the `#load` method
10
10
  #
11
11
  # All method calls made whilst on a page are scoped using `#to_capybara_node` which defaults to the
12
- # current Capybara session
12
+ # current Capybara session or the `@page` that has been loaded in-line
13
13
  class Page
14
14
  include Capybara::DSL
15
15
  include ElementChecker
@@ -48,12 +48,17 @@ module SitePrism
48
48
  #
49
49
  # @return [Capybara::Node::Simple || Capybara::Session]
50
50
  def page
51
- (defined?(@page) && @page) || Capybara.current_session
51
+ @_page ||= begin
52
+ SitePrism::Deprecator.deprecate('Calling #page on a SitePrism::Page instance')
53
+ to_capybara_node
54
+ end
52
55
  end
53
56
 
54
57
  # This scopes our calls inside Page correctly to the `Capybara::Session`
58
+ #
59
+ # @return [Capybara::Node::Simple || Capybara::Session]
55
60
  def to_capybara_node
56
- page
61
+ (defined?(@page) && @page) || Capybara.current_session
57
62
  end
58
63
 
59
64
  # Loads the page.
@@ -85,12 +90,21 @@ module SitePrism
85
90
  return_yield || true
86
91
  end
87
92
 
93
+ # Returns true if the page is displayed within the requisite time
94
+ # Returns false if the page is not displayed within the requisite time
95
+ #
96
+ # @return [Boolean]
88
97
  def displayed?(*args)
89
98
  wait_until_displayed(*args)
90
99
  rescue SitePrism::TimeoutError
91
100
  false
92
101
  end
93
102
 
103
+ # Wait until the page is displayed according to input arguments
104
+ # If no url_matcher is provided we don't know how to determine if the page is displayed. So we return an error
105
+ # Then we wait until the url matches the expected mappings
106
+ #
107
+ # @return [Boolean]
94
108
  def wait_until_displayed(*args)
95
109
  raise SitePrism::NoUrlMatcherForPageError unless url_matcher
96
110
 
@@ -99,6 +113,13 @@ module SitePrism
99
113
  Waiter.wait_until_true(seconds) { url_matches?(expected_mappings) }
100
114
  end
101
115
 
116
+ # Return the matching information of a page
117
+ #
118
+ # Return nil if the page is not displayed correctly
119
+ # Return the regex matches if we have provided a regexp style url_matcher
120
+ # Otherwise fall back to an addressable-style template of matches
121
+ #
122
+ # @return [Nil || MatchData || Hash]
102
123
  def url_matches(seconds = Capybara.default_max_wait_time)
103
124
  return unless displayed?(seconds)
104
125
  return regexp_backed_matches if url_matcher.is_a?(Regexp)
@@ -106,14 +127,24 @@ module SitePrism
106
127
  template_backed_matches
107
128
  end
108
129
 
130
+ # Returns the templated url from the set_url property defined during the page definition
131
+ # Returns `nil` if there was not a property set (i.e. the page should not be directly loaded)
132
+ #
133
+ # @return [NilClass || String]
109
134
  def url(expansion = {})
110
135
  self.class.url && Addressable::Template.new(self.class.url).expand(expansion).to_s
111
136
  end
112
137
 
138
+ # Returns the url_matcher property defined during the page definition
139
+ #
140
+ # @return [Regexp]
113
141
  def url_matcher
114
142
  self.class.url_matcher
115
143
  end
116
144
 
145
+ # Returns true if the page is secure, otherwise returns false
146
+ #
147
+ # @return [Boolean]
117
148
  def secure?
118
149
  page.current_url.start_with?('https')
119
150
  end
@@ -4,13 +4,16 @@ module SitePrism
4
4
  #
5
5
  # @api private
6
6
  #
7
- class RspecMatchers
7
+ class RSpecMatchers
8
8
  attr_reader :element_name
9
9
 
10
10
  def initialize(element_name)
11
11
  @element_name = element_name
12
12
  end
13
13
 
14
+ # Create the positive and negative rspec matchers that will use the SitePrism boolean methods
15
+ #
16
+ # @return [Symbol]
14
17
  def _create_rspec_existence_matchers
15
18
  SitePrism.logger.debug('Including all relevant matcher names / warnings in RSpec scope.')
16
19
  create_rspec_existence_matchers(matcher, object_method, negated_object_method, warning)
@@ -43,8 +46,8 @@ module SitePrism
43
46
  end
44
47
 
45
48
  def warning
46
- "The RSpec matcher '#{matcher}' was added by SitePrism, but the object under test "\
47
- "does not respond to '#{negated_object_method}' and is probably not a SitePrism object. "\
49
+ "The RSpec matcher '#{matcher}' was added by SitePrism, but the object under test " \
50
+ "does not respond to '#{negated_object_method}' and is probably not a SitePrism object. " \
48
51
  'Falling back to the default RSpec matcher.'
49
52
  end
50
53
  end
@@ -72,13 +72,6 @@ module SitePrism
72
72
  Capybara.within(root_element) { yield(self) }
73
73
  end
74
74
 
75
- # This was the old API-style of delegating through the Capybara.page call and over-loading
76
- # the method so we always went through our correct `root_element`
77
- def page
78
- SitePrism.logger.fatal('This is not supposed to be used. All delegation now happens automatically!')
79
- raise SitePrism::SitePrismError
80
- end
81
-
82
75
  def capybara_session
83
76
  Capybara.current_session
84
77
  end
@@ -1,15 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
- # [SitePrism::Timer]
5
4
  #
6
- # Used to count asynchronously towards an overall desired duration or condition (Block)
5
+ # @api private
6
+ #
7
7
  class Timer
8
8
  attr_reader :wait_time
9
9
 
10
- # Return &block
11
- #
12
- # Count towards a specified time (Supplied)
13
10
  def self.run(wait_time, &block)
14
11
  new(wait_time).run(&block)
15
12
  end
@@ -19,16 +16,10 @@ module SitePrism
19
16
  @done = false
20
17
  end
21
18
 
22
- # Return Boolean
23
- #
24
- # Whether the timer has completed
25
19
  def done?
26
20
  @done == true
27
21
  end
28
22
 
29
- # Return &block
30
- #
31
- # Start the Timer and re-evaluate the block repeatedly
32
23
  def run
33
24
  start
34
25
  yield self
@@ -36,9 +27,8 @@ module SitePrism
36
27
  stop
37
28
  end
38
29
 
39
- # Return [Boolean, Nil]
40
- #
41
- # Start the Timer in a separate process
30
+ private
31
+
42
32
  def start
43
33
  stop
44
34
  return if wait_time.zero?
@@ -50,9 +40,6 @@ module SitePrism
50
40
  end
51
41
  end
52
42
 
53
- # Return True
54
- #
55
- # Forcibly stop the timer, and kill any threads created by it
56
43
  def stop
57
44
  if @thread
58
45
  @thread.kill
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
- VERSION = '4.0.beta'
4
+ VERSION = '4.0.1'
5
5
  end
@@ -3,10 +3,10 @@
3
3
  module SitePrism
4
4
  # [SitePrism::Waiter]
5
5
  class Waiter
6
- # @return Boolean
7
- #
8
6
  # A looper that will wait until the passed in block evaluates to true
9
7
  # Alternatively it will time out once the wait_time is exceeded
8
+ #
9
+ # @return [Boolean]
10
10
  def self.wait_until_true(wait_time = Capybara.default_max_wait_time, sleep_duration = 0.05)
11
11
  Timer.run(wait_time) do |timer|
12
12
  loop do
data/lib/site_prism.rb CHANGED
@@ -2,25 +2,25 @@
2
2
 
3
3
  require 'site_prism/error'
4
4
  require 'site_prism/all_there'
5
+
5
6
  require 'addressable/template'
6
7
  require 'forwardable'
7
8
 
8
- # [SitePrism] namespace
9
- # We autoload our files underneath here to provide a slightly more optimal load solution
10
- module SitePrism
11
- autoload :AddressableUrlMatcher, 'site_prism/addressable_url_matcher'
12
- autoload :DSL, 'site_prism/dsl'
13
- autoload :DSLValidator, 'site_prism/dsl_validator'
14
- autoload :Deprecator, 'site_prism/deprecator'
15
- autoload :ElementChecker, 'site_prism/element_checker'
16
- autoload :Loadable, 'site_prism/loadable'
17
- autoload :Logger, 'site_prism/logger'
18
- autoload :Page, 'site_prism/page'
19
- autoload :RspecMatchers, 'site_prism/rspec_matchers'
20
- autoload :Section, 'site_prism/section'
21
- autoload :Timer, 'site_prism/timer'
22
- autoload :Waiter, 'site_prism/waiter'
9
+ require 'site_prism/addressable_url_matcher'
10
+ require 'site_prism/dsl'
11
+ require 'site_prism/dsl_validator'
12
+ require 'site_prism/deprecator'
13
+ require 'site_prism/element_checker'
14
+ require 'site_prism/loadable'
15
+ require 'site_prism/logger'
16
+ require 'site_prism/page'
17
+ require 'site_prism/rspec_matchers'
18
+ require 'site_prism/section'
19
+ require 'site_prism/timer'
20
+ require 'site_prism/waiter'
23
21
 
22
+ # [SitePrism]
23
+ module SitePrism
24
24
  class << self
25
25
  def configure
26
26
  yield self