site_prism 3.4.1 → 3.7.1

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.
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
+ # [SitePrism::ElementChecker]
5
+ #
6
+ # This allows users to run `#all_there?` checks on an instance.
7
+ #
8
+ # NB: This functionality is being removed in v4 in favour of the all_there gem
4
9
  module ElementChecker
5
10
  # Runnable in the scope of any SitePrism::Page or Section.
6
11
  # Returns +true+ when "every item" that is being checked is
@@ -21,10 +26,9 @@ module SitePrism
21
26
  # Override: 'one' => Perform one recursive dive into all section/sections
22
27
  # items and call #all_there? on all of those items too.
23
28
  def all_there?(recursion: :none)
24
- if recursion == :none
25
- elements_to_check.all? { |name| there?(name) }
26
- elsif recursion == :one
27
- all_there_with_recursion
29
+ case recursion
30
+ when :none; then elements_to_check.all? { |name| there?(name) }
31
+ when :one; then all_there_with_recursion
28
32
  else
29
33
  SitePrism.logger.debug("Input value '#{recursion}'. Valid values are :none or :one.")
30
34
  SitePrism.logger.error('Invalid recursion setting, Will not run #all_there?.')
@@ -35,6 +39,10 @@ module SitePrism
35
39
  _mapped_items.select { |name| there?(name) }
36
40
  end
37
41
 
42
+ def elements_missing
43
+ elements_to_check.reject { |name| there?(name) }
44
+ end
45
+
38
46
  private
39
47
 
40
48
  def all_there_with_recursion
@@ -25,14 +25,6 @@ module SitePrism
25
25
  # Formerly known as `NoSelectorForElement`
26
26
  class InvalidElementError < SitePrismError; end
27
27
 
28
- # A tool like Timecop is being used to "freeze time" by overriding Time.now
29
- # and similar methods. In this case, our waiter functions won't work, because
30
- # Time.now does not change.
31
- # If you encounter this issue, check that you are not doing Timecop.freeze without
32
- # an accompanying Timecop.return.
33
- # Also check out Timecop.safe_mode https://github.com/travisjeffery/timecop#timecopsafe_mode
34
- class FrozenInTimeError < SitePrismError; end
35
-
36
28
  # The condition that was being evaluated inside the block did not evaluate
37
29
  # to true within the time limit
38
30
  # Formerly known as `TimeoutException`
@@ -1,6 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
+ # [SitePrism::Loadable]
5
+ #
6
+ # SitePrism Loadable's are defined as checks or waiters which "must" pass before
7
+ # the rest of the loading logic can be performed on a class or section.
8
+ #
9
+ # Loadable's are primarily used with the `#load` method which will auto-execute them all
10
+ # in their defined order. But they can be used dynamically wherever desired.
4
11
  module Loadable
5
12
  module ClassMethods
6
13
  # The list of load_validations.
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'site_prism/loadable'
4
-
5
3
  module SitePrism
6
- # rubocop:disable Metrics/ClassLength
7
4
  class Page
8
5
  include Capybara::DSL
9
6
  include ElementChecker
@@ -27,11 +24,7 @@ module SitePrism
27
24
  end
28
25
 
29
26
  def page
30
- if defined?(@page)
31
- @page
32
- else
33
- Capybara.current_session
34
- end
27
+ (defined?(@page) && @page) || Capybara.current_session
35
28
  end
36
29
 
37
30
  # Loads the page.
@@ -73,24 +66,19 @@ module SitePrism
73
66
  raise SitePrism::NoUrlMatcherForPageError unless url_matcher
74
67
 
75
68
  expected_mappings = args.last.is_a?(::Hash) ? args.pop : {}
76
- seconds = args&.first || wait_time
69
+ seconds = args&.first || Capybara.default_max_wait_time
77
70
  Waiter.wait_until_true(seconds) { url_matches?(expected_mappings) }
78
71
  end
79
72
 
80
- def url_matches(seconds = wait_time)
73
+ def url_matches(seconds = Capybara.default_max_wait_time)
81
74
  return unless displayed?(seconds)
75
+ return regexp_backed_matches if url_matcher.is_a?(Regexp)
82
76
 
83
- if url_matcher.is_a?(Regexp)
84
- regexp_backed_matches
85
- else
86
- template_backed_matches
87
- end
77
+ template_backed_matches
88
78
  end
89
79
 
90
80
  def url(expansion = {})
91
- return nil if self.class.url.nil?
92
-
93
- Addressable::Template.new(self.class.url).expand(expansion).to_s
81
+ self.class.url && Addressable::Template.new(self.class.url).expand(expansion).to_s
94
82
  end
95
83
 
96
84
  def url_matcher
@@ -103,22 +91,6 @@ module SitePrism
103
91
 
104
92
  private
105
93
 
106
- def _find(*find_args)
107
- page.find(*find_args)
108
- end
109
-
110
- def _all(*find_args)
111
- page.all(*find_args)
112
- end
113
-
114
- def element_exists?(*find_args)
115
- page.has_selector?(*find_args)
116
- end
117
-
118
- def element_does_not_exist?(*find_args)
119
- page.has_no_selector?(*find_args)
120
- end
121
-
122
94
  def regexp_backed_matches
123
95
  url_matcher.match(page.current_url)
124
96
  end
@@ -167,5 +139,4 @@ module SitePrism
167
139
  end
168
140
  end
169
141
  end
170
- # rubocop:enable Metrics/ClassLength
171
142
  end
@@ -3,6 +3,7 @@
3
3
  module SitePrism
4
4
  class RecursionChecker
5
5
  attr_reader :instance
6
+
6
7
  private :instance
7
8
 
8
9
  def initialize(instance)
@@ -28,7 +29,7 @@ module SitePrism
28
29
  expected(mapped_items, :elements),
29
30
  expected(mapped_items, :section),
30
31
  expected(mapped_items, :sections),
31
- expected(mapped_items, :iframe),
32
+ expected(mapped_items, :iframe)
32
33
  ]
33
34
  end
34
35
 
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SitePrism
4
+ class RspecMatchers
5
+ attr_reader :element_name
6
+
7
+ def initialize(element_name)
8
+ @element_name = element_name
9
+ end
10
+
11
+ def _create_rspec_existence_matchers
12
+ SitePrism.logger.debug('Including all relevant matcher names / warnings in RSpec scope.')
13
+ create_rspec_existence_matchers(matcher, object_method, negated_object_method, warning)
14
+ end
15
+
16
+ private
17
+
18
+ def create_rspec_existence_matchers(matcher, object_method, negated_object_method, warning)
19
+ RSpec::Matchers.define(matcher) do |*args|
20
+ match { |actual| actual.public_send(object_method, *args) }
21
+ match_when_negated do |actual|
22
+ return actual.public_send(negated_object_method, *args) if actual.respond_to?(negated_object_method)
23
+
24
+ SitePrism.logger.debug(warning)
25
+ !actual.public_send(object_method, *args)
26
+ end
27
+ end
28
+ end
29
+
30
+ def matcher
31
+ "have_#{element_name}"
32
+ end
33
+
34
+ def object_method
35
+ "has_#{element_name}?"
36
+ end
37
+
38
+ def negated_object_method
39
+ "has_no_#{element_name}?"
40
+ end
41
+
42
+ def warning
43
+ "The RSpec matcher '#{matcher}' was added by SitePrism, but the object under test "\
44
+ "does not respond to '#{negated_object_method}' and is probably not a SitePrism object. "\
45
+ 'Falling back to the default RSpec matcher.'
46
+ end
47
+ end
48
+ end
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'site_prism/loadable'
4
-
5
3
  module SitePrism
6
4
  class Section
7
- include Capybara::DSL
8
5
  include ElementChecker
9
6
  include Loadable
10
7
  include DSL
@@ -12,44 +9,67 @@ module SitePrism
12
9
 
13
10
  attr_reader :root_element, :parent
14
11
 
15
- def self.set_default_search_arguments(*args)
16
- @default_search_arguments = args
17
- end
12
+ class << self
13
+ def set_default_search_arguments(*args)
14
+ @default_search_arguments = args
15
+ end
16
+
17
+ def default_search_arguments
18
+ return @default_search_arguments if @default_search_arguments
19
+
20
+ superclass.respond_to?(:default_search_arguments) && superclass.default_search_arguments
21
+ end
18
22
 
19
- def self.default_search_arguments
20
- @default_search_arguments ||
21
- (
22
- superclass.respond_to?(:default_search_arguments) &&
23
- superclass.default_search_arguments
24
- ) ||
25
- nil
23
+ private
24
+
25
+ def root_element_methods
26
+ ::Capybara::Session::NODE_METHODS + %i[native visible?]
27
+ end
28
+
29
+ def session_methods
30
+ ::Capybara::Session::DSL_METHODS - root_element_methods
31
+ end
26
32
  end
27
33
 
28
- def initialize(parent, root_element)
34
+ def initialize(parent, root_element, &block)
29
35
  @parent = parent
30
36
  @root_element = root_element
31
- Capybara.within(@root_element) { yield(self) } if block_given?
37
+ within(&block) if block_given?
32
38
  end
33
39
 
34
- # Capybara::DSL module "delegates" Capybara methods to the "page" method
35
- # as such we need to overload this method so that the correct scoping
36
- # occurs and calls within a section (For example section.find(element))
37
- # correctly scope to look within the section only
38
- def page
39
- return root_element if root_element
40
+ # Send all root_element methods through `#root_element`
41
+ # NB: This requires a method called `#to_capybara_node` being created and
42
+ # then set to this value (Capybara agnostic API)
43
+ root_element_methods.each do |method|
44
+ def_delegators :root_element, method
45
+ end
46
+
47
+ # Send all methods that previously acted on the `#page` method that existed previously
48
+ # through to the same location - But directly as `Capybara.current_session`
49
+ session_methods.each do |method|
50
+ def_delegators :capybara_session, method
51
+ end
40
52
 
41
- SitePrism.logger.warn('Root Element not found; Falling back to `super`')
42
- super
53
+ # This scopes our calls inside Section correctly to the `Capybara::Node::Element`
54
+ def to_capybara_node
55
+ root_element
43
56
  end
44
57
 
45
- def visible?
46
- page.visible?
58
+ # This allows us to return anything thats passed in as a block to the section at
59
+ # creation time, so that an anonymous section or such-like will have the extra methods
60
+ def within
61
+ Capybara.within(root_element) { yield(self) }
47
62
  end
48
63
 
49
- def_delegators :capybara_session,
50
- :execute_script,
51
- :evaluate_script,
52
- :within_frame
64
+ # This was the old API-style of delegating through the Capybara.page call and over-loading
65
+ # the method so we always went through our correct `root_element`
66
+ def page
67
+ SitePrism::Deprecator.deprecate('Using page inside section')
68
+ return root_element if root_element
69
+
70
+ SitePrism.logger.warn('Root Element not found; Falling back to Capybara.current_session')
71
+ capybara_session
72
+ end
53
73
 
54
74
  def capybara_session
55
75
  Capybara.current_session
@@ -60,27 +80,5 @@ module SitePrism
60
80
  candidate = candidate.parent until candidate.is_a?(SitePrism::Page)
61
81
  candidate
62
82
  end
63
-
64
- def native
65
- root_element.native
66
- end
67
-
68
- private
69
-
70
- def _find(*find_args)
71
- page.find(*find_args)
72
- end
73
-
74
- def _all(*find_args)
75
- page.all(*find_args)
76
- end
77
-
78
- def element_exists?(*find_args)
79
- page.has_selector?(*find_args)
80
- end
81
-
82
- def element_does_not_exist?(*find_args)
83
- page.has_no_selector?(*find_args)
84
- end
85
83
  end
86
84
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SitePrism
4
+ class Timer
5
+ attr_reader :wait_time
6
+
7
+ def self.run(wait_time, &block)
8
+ new(wait_time).run(&block)
9
+ end
10
+
11
+ def initialize(wait_time)
12
+ @wait_time = wait_time
13
+ @done = false
14
+ end
15
+
16
+ def done?
17
+ @done == true
18
+ end
19
+
20
+ def run
21
+ start
22
+ yield self
23
+ ensure
24
+ stop
25
+ end
26
+
27
+ def start
28
+ stop
29
+ return if wait_time.zero?
30
+
31
+ @done = false
32
+ @thread = Thread.start do
33
+ sleep wait_time
34
+ @done = true
35
+ end
36
+ end
37
+
38
+ def stop
39
+ if @thread
40
+ @thread.kill
41
+ @thread.join
42
+ @thread = nil
43
+ end
44
+ @done = true
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
- VERSION = '3.4.1'
4
+ VERSION = '3.7.1'
5
5
  end
@@ -2,33 +2,20 @@
2
2
 
3
3
  module SitePrism
4
4
  class Waiter
5
- class << self
6
- def wait_until_true(wait_time = Capybara.default_max_wait_time)
7
- start_time = Time.now
5
+ def self.sleep_duration
6
+ 0.05
7
+ end
8
8
 
9
+ def self.wait_until_true(wait_time = Capybara.default_max_wait_time)
10
+ Timer.run(wait_time) do |timer|
9
11
  loop do
10
12
  return true if yield
11
- break if Time.now - start_time > wait_time
12
-
13
- sleep(0.05)
13
+ break if timer.done?
14
14
 
15
- check_for_time_stopped!(start_time)
15
+ sleep(sleep_duration)
16
16
  end
17
-
18
17
  raise SitePrism::TimeoutError, "Timed out after #{wait_time}s."
19
18
  end
20
-
21
- private
22
-
23
- def check_for_time_stopped!(start_time)
24
- return unless start_time == Time.now
25
-
26
- raise(
27
- SitePrism::FrozenInTimeError,
28
- 'Time appears to be frozen. For more info, see ' \
29
- 'https://github.com/site-prism/site_prism/blob/master/lib/site_prism/error.rb'
30
- )
31
- end
32
19
  end
33
20
  end
34
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: site_prism
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.1
4
+ version: 3.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luke Hill
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-09-26 00:00:00.000000000 Z
12
+ date: 2021-02-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: addressable
@@ -31,126 +31,152 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '3.3'
34
+ version: '3.8'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '3.3'
41
+ version: '3.8'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: site_prism-all_there
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 0.3.1
49
+ - - "<"
47
50
  - !ruby/object:Gem::Version
48
- version: '0.3'
51
+ version: '1.0'
49
52
  type: :runtime
50
53
  prerelease: false
51
54
  version_requirements: !ruby/object:Gem::Requirement
52
55
  requirements:
53
- - - "~>"
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 0.3.1
59
+ - - "<"
54
60
  - !ruby/object:Gem::Version
55
- version: '0.3'
61
+ version: '1.0'
56
62
  - !ruby/object:Gem::Dependency
57
63
  name: cucumber
58
64
  requirement: !ruby/object:Gem::Requirement
59
65
  requirements:
60
66
  - - "~>"
61
67
  - !ruby/object:Gem::Version
62
- version: '3.1'
68
+ version: '4.0'
63
69
  type: :development
64
70
  prerelease: false
65
71
  version_requirements: !ruby/object:Gem::Requirement
66
72
  requirements:
67
73
  - - "~>"
68
74
  - !ruby/object:Gem::Version
69
- version: '3.1'
75
+ version: '4.0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: pry-byebug
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
70
90
  - !ruby/object:Gem::Dependency
71
91
  name: rake
72
92
  requirement: !ruby/object:Gem::Requirement
73
93
  requirements:
74
94
  - - "~>"
75
95
  - !ruby/object:Gem::Version
76
- version: '12.3'
96
+ version: '13.0'
77
97
  type: :development
78
98
  prerelease: false
79
99
  version_requirements: !ruby/object:Gem::Requirement
80
100
  requirements:
81
101
  - - "~>"
82
102
  - !ruby/object:Gem::Version
83
- version: '12.3'
103
+ version: '13.0'
84
104
  - !ruby/object:Gem::Dependency
85
105
  name: rspec
86
106
  requirement: !ruby/object:Gem::Requirement
87
107
  requirements:
88
108
  - - "~>"
89
109
  - !ruby/object:Gem::Version
90
- version: '3.8'
110
+ version: '3.9'
91
111
  type: :development
92
112
  prerelease: false
93
113
  version_requirements: !ruby/object:Gem::Requirement
94
114
  requirements:
95
115
  - - "~>"
96
116
  - !ruby/object:Gem::Version
97
- version: '3.8'
117
+ version: '3.9'
98
118
  - !ruby/object:Gem::Dependency
99
119
  name: rubocop
100
120
  requirement: !ruby/object:Gem::Requirement
101
121
  requirements:
102
122
  - - "~>"
103
123
  - !ruby/object:Gem::Version
104
- version: 0.73.0
124
+ version: 0.90.0
105
125
  type: :development
106
126
  prerelease: false
107
127
  version_requirements: !ruby/object:Gem::Requirement
108
128
  requirements:
109
129
  - - "~>"
110
130
  - !ruby/object:Gem::Version
111
- version: 0.73.0
131
+ version: 0.90.0
112
132
  - !ruby/object:Gem::Dependency
113
133
  name: rubocop-performance
114
134
  requirement: !ruby/object:Gem::Requirement
115
135
  requirements:
116
136
  - - "~>"
117
137
  - !ruby/object:Gem::Version
118
- version: 1.4.0
138
+ version: 1.8.1
119
139
  type: :development
120
140
  prerelease: false
121
141
  version_requirements: !ruby/object:Gem::Requirement
122
142
  requirements:
123
143
  - - "~>"
124
144
  - !ruby/object:Gem::Version
125
- version: 1.4.0
145
+ version: 1.8.1
126
146
  - !ruby/object:Gem::Dependency
127
147
  name: rubocop-rspec
128
148
  requirement: !ruby/object:Gem::Requirement
129
149
  requirements:
130
150
  - - "~>"
131
151
  - !ruby/object:Gem::Version
132
- version: 1.33.0
152
+ version: 1.38.0
133
153
  type: :development
134
154
  prerelease: false
135
155
  version_requirements: !ruby/object:Gem::Requirement
136
156
  requirements:
137
157
  - - "~>"
138
158
  - !ruby/object:Gem::Version
139
- version: 1.33.0
159
+ version: 1.38.0
140
160
  - !ruby/object:Gem::Dependency
141
161
  name: selenium-webdriver
142
162
  requirement: !ruby/object:Gem::Requirement
143
163
  requirements:
144
- - - "~>"
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '3.11'
167
+ - - "<"
145
168
  - !ruby/object:Gem::Version
146
- version: '3.7'
169
+ version: '4.1'
147
170
  type: :development
148
171
  prerelease: false
149
172
  version_requirements: !ruby/object:Gem::Requirement
150
173
  requirements:
151
- - - "~>"
174
+ - - ">="
152
175
  - !ruby/object:Gem::Version
153
- version: '3.7'
176
+ version: '3.11'
177
+ - - "<"
178
+ - !ruby/object:Gem::Version
179
+ version: '4.1'
154
180
  - !ruby/object:Gem::Dependency
155
181
  name: simplecov
156
182
  requirement: !ruby/object:Gem::Requirement
@@ -171,18 +197,16 @@ dependencies:
171
197
  requirements:
172
198
  - - "~>"
173
199
  - !ruby/object:Gem::Version
174
- version: '4.0'
200
+ version: '4.3'
175
201
  type: :development
176
202
  prerelease: false
177
203
  version_requirements: !ruby/object:Gem::Requirement
178
204
  requirements:
179
205
  - - "~>"
180
206
  - !ruby/object:Gem::Version
181
- version: '4.0'
182
- description: |-
183
- SitePrism gives you a simple,
184
- clean and semantic DSL for describing your site.
185
- SitePrism implements the Page Object Model pattern on top of Capybara.
207
+ version: '4.3'
208
+ description: SitePrism gives you a simple, clean and semantic DSL for describing your
209
+ site. SitePrism implements the Page Object Model pattern on top of Capybara.
186
210
  email:
187
211
  - lukehill_uk@hotmail.com
188
212
  - nat@natontesting.com
@@ -202,7 +226,9 @@ files:
202
226
  - lib/site_prism/logger.rb
203
227
  - lib/site_prism/page.rb
204
228
  - lib/site_prism/recursion_checker.rb
229
+ - lib/site_prism/rspec_matchers.rb
205
230
  - lib/site_prism/section.rb
231
+ - lib/site_prism/timer.rb
206
232
  - lib/site_prism/version.rb
207
233
  - lib/site_prism/waiter.rb
208
234
  homepage: https://github.com/site-prism/site_prism
@@ -210,15 +236,9 @@ licenses:
210
236
  - BSD-3-Clause
211
237
  metadata:
212
238
  bug_tracker_uri: https://github.com/site-prism/site_prism/issues
213
- changelog_uri: https://github.com/site-prism/site_prism/blob/master/CHANGELOG.md
239
+ changelog_uri: https://github.com/site-prism/site_prism/blob/main/CHANGELOG.md
214
240
  source_code_uri: https://github.com/site-prism/site_prism
215
- post_install_message: |-
216
- site_prism has now moved to a new organisation to facilitate better
217
- management of the codebase. The new organisation link is available at www.github.com/site-prism
218
- and will house the site_prism gem plus new associated co-dependent gems.
219
-
220
- NB: The old repo will soon be discontinued and all existing issues will be moved over to the new
221
- repo.
241
+ post_install_message:
222
242
  rdoc_options: []
223
243
  require_paths:
224
244
  - lib
@@ -226,15 +246,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
226
246
  requirements:
227
247
  - - ">="
228
248
  - !ruby/object:Gem::Version
229
- version: '2.3'
249
+ version: '2.4'
230
250
  required_rubygems_version: !ruby/object:Gem::Requirement
231
251
  requirements:
232
252
  - - ">="
233
253
  - !ruby/object:Gem::Version
234
254
  version: '0'
235
255
  requirements: []
236
- rubyforge_project:
237
- rubygems_version: 2.7.8
256
+ rubygems_version: 3.0.8
238
257
  signing_key:
239
258
  specification_version: 4
240
259
  summary: A Page Object Model DSL for Capybara