site_prism 3.4.1 → 3.7.1

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