site_prism 4.0.3 → 5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SitePrism
4
+ module DSL
5
+ # [SitePrism::DSL::Validator]
6
+ #
7
+ # This is the new validator module which will check all DSL items against a whitelist
8
+ # for any entries which break specific rules
9
+ #
10
+ # @api private
11
+ #
12
+ module Validator
13
+ attr_accessor :dsl_name_error
14
+
15
+ def name_invalid?(name)
16
+ prefix_invalid?(name) ||
17
+ suffix_invalid?(name) ||
18
+ characters_invalid?(name) ||
19
+ blacklisted?(name)
20
+ end
21
+
22
+ private
23
+
24
+ def prefix_invalid?(name)
25
+ return false unless prefix_blacklist.any? { |prefix| name.start_with?(prefix) }
26
+
27
+ log_failure(name, 'prefix')
28
+ end
29
+
30
+ def suffix_invalid?(name)
31
+ return false unless suffix_blacklist.any? { |prefix| name.end_with?(prefix) }
32
+
33
+ log_failure(name, 'suffix')
34
+ end
35
+
36
+ def characters_invalid?(name)
37
+ return false if name.match?(regex_permission)
38
+
39
+ log_failure(name, 'character(s)')
40
+ end
41
+
42
+ def blacklisted?(name)
43
+ return false unless blacklisted_names.include?(name)
44
+
45
+ log_failure(name, 'name (blacklisted entry)')
46
+ end
47
+
48
+ def regex_permission
49
+ /^[a-z]\w+$/
50
+ end
51
+
52
+ def prefix_blacklist
53
+ %w[
54
+ no_
55
+ _
56
+ ]
57
+ end
58
+
59
+ def suffix_blacklist
60
+ %w[
61
+ _
62
+ ?
63
+ ]
64
+ end
65
+
66
+ def blacklisted_names
67
+ %w[
68
+ attributes
69
+ html
70
+ no
71
+ title
72
+ element
73
+ elements
74
+ section
75
+ sections
76
+ iframe
77
+ ]
78
+ end
79
+
80
+ def log_failure(name, type)
81
+ self.dsl_name_error = "DSL item: #{name} has an invalid #{type}"
82
+ SitePrism.logger.debug(debug_error(type))
83
+ end
84
+
85
+ def debug_error(type)
86
+ case type
87
+ when 'prefix'; then "Invalid Prefixes: #{prefix_blacklist.join(', ')}."
88
+ when 'suffix'; then "Invalid Suffixes: #{suffix_blacklist.join(', ')}"
89
+ when 'character(s)'; then "Invalid DSL Names: #{blacklisted_names.join(', ')}"
90
+ else "DSL Charset REGEX: #{regex_permission.inspect}"
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,17 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'site_prism/dsl/builder'
4
+ require 'site_prism/dsl/methods'
5
+ require 'site_prism/dsl/locators'
6
+ require 'site_prism/dsl/validator'
7
+
3
8
  module SitePrism
4
9
  # [SitePrism::DSL]
5
10
  #
6
- # This is the core Module Namespace for all of the public-facing DSL methods
7
- # such as `element`. The code here is designed to be used through the defining
8
- # of said items, and not to be instantiated directly.
11
+ # This is the core internal workings of SitePrism. It consists of four moving parts - plus some generic methods included here
12
+ # Builder -> The way in which the .build method generates lots of instance-methods on a SitePrism::Page or SitePrism::Section instance
13
+ # Methods -> The public DSL metaprogram methods, such as `element` or `section`
14
+ # Locators -> Our locator scoping logic within capybara. By and large leaning on `#to_capybara_node`
15
+ # Validators -> EXPERIMENTAL: A new module that ensures names of all DSL items conform to certain rules
9
16
  #
10
- # The whole package here can be thought of as [@api private]
11
17
  module DSL
12
18
  def self.included(klass)
13
- klass.extend ClassMethods
14
- klass.extend DSLValidator
19
+ klass.extend Builder
20
+ klass.extend Methods
21
+ klass.include Locators
22
+ klass.extend Validator
15
23
  end
16
24
 
17
25
  private
@@ -23,326 +31,5 @@ module SitePrism
23
31
  SitePrism.logger.error("#{object.class}##{name} cannot accept runtime blocks")
24
32
  raise SitePrism::UnsupportedBlockError
25
33
  end
26
-
27
- def _find(*find_args)
28
- kwargs = find_args.pop
29
- to_capybara_node.find(*find_args, **kwargs)
30
- end
31
-
32
- def _all(*find_args)
33
- kwargs = find_args.pop
34
- to_capybara_node.all(*find_args, **kwargs)
35
- end
36
-
37
- def element_exists?(*find_args)
38
- kwargs = find_args.pop
39
- to_capybara_node.has_selector?(*find_args, **kwargs)
40
- end
41
-
42
- def element_does_not_exist?(*find_args)
43
- kwargs = find_args.pop
44
- to_capybara_node.has_no_selector?(*find_args, **kwargs)
45
- end
46
-
47
- # Sanitize method called before calling any SitePrism DSL method or
48
- # meta-programmed method. This ensures that the Capybara query is correct.
49
- #
50
- # Accepts any combination of arguments sent at DSL definition or runtime
51
- # and combines them in such a way that Capybara can operate with them.
52
- def merge_args(find_args, runtime_args, visibility_args = {})
53
- find_args = find_args.dup
54
- runtime_args = runtime_args.dup
55
- options = visibility_args.dup
56
- SitePrism.logger.debug("Initial args: #{find_args}, #{runtime_args}.")
57
-
58
- recombine_args(find_args, runtime_args, options)
59
-
60
- return [*find_args, *runtime_args, {}] if options.empty?
61
-
62
- [*find_args, *runtime_args, options]
63
- end
64
-
65
- # Options re-combiner. This takes the original inputs and combines
66
- # them such that there is only one hash passed as a final argument
67
- # to Capybara.
68
- #
69
- # If the hash is empty, then the hash is omitted from the payload sent
70
- # to Capybara, and the find / runtime arguments are sent alone.
71
- #
72
- # NB: If the +wait+ key is present in the options hash, even as false or 0, It will
73
- # be set as the user-supplied value (So user error can be the cause for issues).
74
- def recombine_args(find_args, runtime_args, options)
75
- options.merge!(find_args.pop) if find_args.last.is_a? Hash
76
- options.merge!(runtime_args.pop) if runtime_args.last.is_a? Hash
77
- options[:wait] = Capybara.default_max_wait_time unless options.key?(:wait)
78
- end
79
-
80
- # [SitePrism::DSL::ClassMethods]
81
- # This exposes all of the DSL definitions users will use when generating
82
- # their POM classes.
83
- #
84
- # Many of these methods will be used in-line to allow users to generate a multitude of
85
- # methods and locators for finding elements / sections on a page or section of a page
86
- module ClassMethods
87
- attr_reader :expected_items
88
-
89
- # Sets the `expected_items` iVar on a class. This property is used in conjunction with
90
- # `all_there?` to provide a way of granularising the check made to only interrogate a sub-set
91
- # of DSL defined items
92
- def expected_elements(*elements)
93
- @expected_items = elements
94
- end
95
-
96
- # Creates an instance of a SitePrism Element - This will create several methods designed to
97
- # Locate the element -> @return [Capybara::Node::Element]
98
- # Check the elements presence or non-presence -> @return [Boolean]
99
- # Wait for the elements to be present or not -> @return [TrueClass, SitePrism::Error]
100
- # Validate certain properties about the element
101
- def element(name, *find_args)
102
- raise_if_build_time_block_supplied(self, name, block_given?, :element)
103
- build(:element, name, *find_args) do
104
- define_method(name) do |*runtime_args, &runtime_block|
105
- raise_if_runtime_block_supplied(self, name, runtime_block, :element)
106
- _find(*merge_args(find_args, runtime_args))
107
- end
108
- end
109
- end
110
-
111
- # Creates a enumerable instance of a SitePrism Element - This will create several methods designed to
112
- # Locate the enumerable element -> @return [Capybara::Result]
113
- # Check the elements presence or non-presence -> @return [Boolean]
114
- # Wait for the elements to be present or not -> @return [TrueClass, SitePrism::Error]
115
- # Validate certain properties about the elements
116
- def elements(name, *find_args)
117
- raise_if_build_time_block_supplied(self, name, block_given?, :elements)
118
- build(:elements, name, *find_args) do
119
- define_method(name) do |*runtime_args, &runtime_block|
120
- raise_if_runtime_block_supplied(self, name, runtime_block, :elements)
121
- _all(*merge_args(find_args, runtime_args))
122
- end
123
- end
124
- end
125
-
126
- # Creates an instance of a SitePrism Section - This will create several methods designed to
127
- # Locate the section -> @return [SitePrism::Section]
128
- # Check the section presence or non-presence -> @return [Boolean]
129
- # Wait for the section to be present or not -> @return [TrueClass, SitePrism::Error]
130
- # Validate certain properties about the section
131
- def section(name, *args, &block)
132
- section_class, find_args = extract_section_options(args, &block)
133
- build(:section, name, *find_args) do
134
- define_method(name) do |*runtime_args, &runtime_block|
135
- section_element = _find(*merge_args(find_args, runtime_args))
136
- section_class.new(self, section_element, &runtime_block)
137
- end
138
- end
139
- end
140
-
141
- # Creates an enumerable instance of a SitePrism Section - This will create several methods designed to
142
- # Locate the sections -> @return [Array]
143
- # Check the sections presence or non-presence -> @return [Boolean]
144
- # Wait for the sections to be present or not -> @return [TrueClass, SitePrism::Error]
145
- # Validate certain properties about the section
146
- def sections(name, *args, &block)
147
- section_class, find_args = extract_section_options(args, &block)
148
- build(:sections, name, *find_args) do
149
- define_method(name) do |*runtime_args, &runtime_block|
150
- raise_if_runtime_block_supplied(self, name, runtime_block, :sections)
151
- _all(*merge_args(find_args, runtime_args)).map do |element|
152
- section_class.new(self, element)
153
- end
154
- end
155
- end
156
- end
157
-
158
- def iframe(name, klass, *args)
159
- raise_if_build_time_block_supplied(self, name, block_given?, :elements)
160
- element_find_args = deduce_iframe_element_find_args(args)
161
- scope_find_args = deduce_iframe_scope_find_args(args)
162
- build(:iframe, name, *element_find_args) do
163
- define_method(name) do |&block|
164
- raise MissingBlockError unless block
165
-
166
- within_frame(*scope_find_args) { block.call(klass.new) }
167
- end
168
- end
169
- end
170
-
171
- # Return a list of all mapped items on a SitePrism class instance (Page or Section)
172
- # If legacy is set to true (Default) -> @return [Array]
173
- # If legacy is set to false (New behaviour) -> @return [Hash]
174
- def mapped_items(legacy: false)
175
- return legacy_mapped_items if legacy
176
-
177
- @mapped_items ||= { element: [], elements: [], section: [], sections: [], iframe: [] }
178
- end
179
-
180
- private
181
-
182
- def build(type, name, *find_args)
183
- raise InvalidDSLNameError if ENV.fetch('SITEPRISM_DSL_VALIDATION_ENABLED', nil) && invalid?(name)
184
-
185
- if find_args.empty?
186
- create_error_method(name)
187
- else
188
- map_item(type, name)
189
- yield
190
- end
191
- add_helper_methods(name, type, *find_args)
192
- end
193
-
194
- def add_helper_methods(name, _type, *find_args)
195
- create_existence_checker(name, *find_args)
196
- create_nonexistence_checker(name, *find_args)
197
- SitePrism::RSpecMatchers.new(name)._create_rspec_existence_matchers if defined?(RSpec)
198
- create_visibility_waiter(name, *find_args)
199
- create_invisibility_waiter(name, *find_args)
200
- end
201
-
202
- def create_helper_method(proposed_method_name, *find_args)
203
- return create_error_method(proposed_method_name) if find_args.empty?
204
-
205
- yield
206
- end
207
-
208
- def create_existence_checker(element_name, *find_args)
209
- method_name = "has_#{element_name}?"
210
- create_helper_method(method_name, *find_args) do
211
- define_method(method_name) do |*runtime_args|
212
- args = merge_args(find_args, runtime_args)
213
- element_exists?(*args)
214
- end
215
- end
216
- end
217
-
218
- def create_nonexistence_checker(element_name, *find_args)
219
- method_name = "has_no_#{element_name}?"
220
- create_helper_method(method_name, *find_args) do
221
- define_method(method_name) do |*runtime_args|
222
- args = merge_args(find_args, runtime_args)
223
- element_does_not_exist?(*args)
224
- end
225
- end
226
- end
227
-
228
- def create_visibility_waiter(element_name, *find_args)
229
- method_name = "wait_until_#{element_name}_visible"
230
- create_helper_method(method_name, *find_args) do
231
- define_method(method_name) do |*runtime_args|
232
- args = merge_args(find_args, runtime_args, visible: true)
233
- return true if element_exists?(*args)
234
-
235
- raise SitePrism::ElementVisibilityTimeoutError
236
- end
237
- end
238
- end
239
-
240
- def create_invisibility_waiter(element_name, *find_args)
241
- method_name = "wait_until_#{element_name}_invisible"
242
- create_helper_method(method_name, *find_args) do
243
- define_method(method_name) do |*runtime_args|
244
- args = merge_args(find_args, runtime_args, visible: true)
245
- return true if element_does_not_exist?(*args)
246
-
247
- raise SitePrism::ElementInvisibilityTimeoutError
248
- end
249
- end
250
- end
251
-
252
- def create_error_method(name)
253
- SitePrism::Deprecator.deprecate(
254
- 'DSL definition with no find_args',
255
- 'DSL definition with at least 1 find_arg'
256
- )
257
- SitePrism.logger.error("#{name} has come from an item with no locators.")
258
- define_method(name) { raise SitePrism::InvalidElementError }
259
- end
260
-
261
- def raise_if_build_time_block_supplied(parent_object, name, has_block, type)
262
- return unless has_block
263
-
264
- SitePrism.logger.debug("Type passed in: #{type}")
265
- SitePrism.logger.error("#{name} has been defined as a '#{type}' item in #{parent_object}. It does not accept build-time blocks.")
266
- raise SitePrism::UnsupportedBlockError
267
- end
268
-
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
277
- end
278
-
279
- def map_item(type, name)
280
- mapped_items(legacy: true) << { type => name }
281
- mapped_items[type] << name.to_sym
282
- end
283
-
284
- def deduce_iframe_scope_find_args(args)
285
- warn_on_invalid_selector_input(args)
286
- case args[0]
287
- when Integer then [args[0]]
288
- when String then [:css, args[0]]
289
- else args
290
- end
291
- end
292
-
293
- def deduce_iframe_element_find_args(args)
294
- warn_on_invalid_selector_input(args)
295
- case args[0]
296
- when Integer then "iframe:nth-of-type(#{args[0] + 1})"
297
- when String then [:css, args[0]]
298
- else args
299
- end
300
- end
301
-
302
- def warn_on_invalid_selector_input(args)
303
- return unless looks_like_xpath?(args[0])
304
-
305
- SitePrism.logger.warn('The arguments passed in look like xpath. Check your locators.')
306
- SitePrism.logger.debug("Default locator strategy: #{Capybara.default_selector}")
307
- end
308
-
309
- def looks_like_xpath?(arg)
310
- arg.is_a?(String) && arg.start_with?('/', './')
311
- end
312
-
313
- def extract_section_options(args, &block)
314
- if args.first.is_a?(Class)
315
- klass = args.shift
316
- section_class = klass if klass <= SitePrism::Section
317
- end
318
-
319
- section_class = deduce_section_class(section_class, &block)
320
- arguments = deduce_search_arguments(section_class, args)
321
- [section_class, arguments]
322
- end
323
-
324
- def deduce_section_class(base_class, &block)
325
- klass = base_class
326
- klass = Class.new(klass || SitePrism::Section, &block) if block
327
- return klass if klass
328
-
329
- raise ArgumentError, 'You should provide descendant of SitePrism::Section class or/and a block as the second argument.'
330
- end
331
-
332
- def deduce_search_arguments(section_class, args)
333
- extract_search_arguments(args) ||
334
- extract_search_arguments(section_class.default_search_arguments) ||
335
- invalidate_search_arguments!
336
- end
337
-
338
- def extract_search_arguments(args)
339
- args if args && !args.empty?
340
- end
341
-
342
- def invalidate_search_arguments!
343
- SitePrism.logger.error('Could not deduce search_arguments')
344
- raise(ArgumentError, 'search arguments are needed in `section` definition or alternatively use `set_default_search_arguments`')
345
- end
346
- end
347
34
  end
348
35
  end
@@ -13,7 +13,7 @@ module SitePrism
13
13
  # for how the definition of "every item" is derived.
14
14
  #
15
15
  # Example
16
- # @my_page.class.mapped_items
16
+ # `@my_page.class.mapped_items`
17
17
  # {
18
18
  # element => [:button_one, :button_two],
19
19
  # elements => [:button_collection_one, :button_collection_two],
@@ -21,7 +21,7 @@ module SitePrism
21
21
  # sections => [:search_result],
22
22
  # iframe => []
23
23
  # }
24
- # @my_page.all_there?
24
+ # `@my_page.all_there?`
25
25
  # => true - If the items above are all present
26
26
  #
27
27
  # Note that #elements_to_check will check the hash of mapped_items
@@ -48,6 +48,9 @@ module SitePrism
48
48
  # Generic Attribute validation family of errors inherit from this error
49
49
  class AttributeValidationError < SitePrismError; end
50
50
 
51
- # DSL items are not permitted to start with certain prefixes
51
+ # DSL items are not permitted to be named in certain ways
52
52
  class InvalidDSLNameError < AttributeValidationError; end
53
+
54
+ # The version of the target gem is unsupported, so using that feature is not possible
55
+ class UnsupportedGemVersionError < SitePrismError; end
53
56
  end
@@ -13,10 +13,8 @@ module SitePrism
13
13
  base.extend(ClassMethods)
14
14
  end
15
15
 
16
- # In certain circumstances, we cache that the page has already
17
- # been confirmed to be loaded so that actions which
18
- # call `loaded?` a second time do not need to perform
19
- # the load_validation queries against the page a second time.
16
+ # In certain circumstances, we cache that the page or section has already been "loaded" so that actions which
17
+ # call `loaded?` a second time do not need to perform the load_validation queries against the page a second time.
20
18
  attr_accessor :loaded, :load_error
21
19
 
22
20
  # Executes the given block after the page is loaded.
@@ -27,8 +25,7 @@ module SitePrism
27
25
  # inside another when_loaded block.
28
26
  previously_loaded = loaded
29
27
 
30
- # Within the block, check (and cache) loaded?, to see whether the
31
- # page has indeed loaded according to the rules defined by the user.
28
+ # Within the block, check (and cache) loaded?, to see whether the page has indeed loaded according to the rules defined by the user.
32
29
  self.loaded = loaded?
33
30
 
34
31
  # If the page hasn't loaded. Then crash and return the error message.
@@ -68,13 +65,12 @@ module SitePrism
68
65
  end
69
66
 
70
67
  # [SitePrism::Loadable::ClassMethods]
71
- # This exposes all of the DSL definitions users will use when generating "loadables"
68
+ # This exposes all of the DSL definitions users will use when generating "Loadables"
72
69
  #
73
- # A "Loadable" is a definition whereby the page object once loaded must pass a boolean check
74
- # These loadables are typically provided using the method `load_validation`
70
+ # A "Loadable" is a definition whereby the page/section object once loaded must pass a boolean check
71
+ # These Loadables are typically provided using the method `load_validation`
75
72
  module ClassMethods
76
- # The list of load_validations.
77
- # They will be executed in the order they are defined.
73
+ # The list of load_validations. They are executed in the order they are defined.
78
74
  #
79
75
  # @return [Array]
80
76
  def load_validations
@@ -85,21 +81,15 @@ module SitePrism
85
81
  end
86
82
  end
87
83
 
88
- # Appends a load validation block to the page class.
84
+ # Appends a load validation block to the page/section class.
89
85
  #
90
- # When `loaded?` is called, these blocks are instance_eval'd
91
- # against the current page instance.
92
- # This allows users to wait for specific events to occur on
93
- # the page or certain elements to be loaded before performing
94
- # any actions on the page.
86
+ # When `loaded?` is called, these blocks are instance_eval'd against the current page instance. This allows users to wait for
87
+ # specific events to occur on the page or certain elements to be loaded before performing any actions on the page.
95
88
  #
96
- # @param block [&block] A block which returns true if the page
97
- # loaded successfully, or false if it did not.
98
- # This block can contain up to 2 elements in an array
99
- # The first is the physical validation test to be truthily evaluated.
89
+ # @param block [&block] A block which returns true if the page loaded successfully, or false if it did not.
90
+ # This block can contain up to 2 elements in an array -> The first is the physical validation test to be truthily evaluated.
100
91
  #
101
- # If this does not pass, then the 2nd item (if defined), is output
102
- # as an error message to the +FailedLoadValidationError+ that is thrown
92
+ # If this does not pass, then the 2nd item (if defined), is output as an error message on the +FailedLoadValidationError+
103
93
  #
104
94
  # @return [Proc]
105
95
  def load_validation(&block)
@@ -10,7 +10,7 @@ module SitePrism
10
10
  def create(output = $stdout)
11
11
  logger = ::Logger.new(output)
12
12
  logger.progname = 'SitePrism'
13
- logger.level = :UNKNOWN
13
+ logger.level = :WARN
14
14
  logger.formatter = proc do |severity, time, progname, msg|
15
15
  "#{time.strftime('%F %T')} - #{severity} - #{progname} - #{msg}\n"
16
16
  end
@@ -36,24 +36,12 @@ module SitePrism
36
36
  # The specific url matcher that is used to validate the page is loaded.
37
37
  # When one hasn't been previously set, use the url that was set as a direct Regexp exact matcher
38
38
  #
39
- # @return [Regexp]
39
+ # @return [Regexp || String]
40
40
  def url_matcher
41
41
  @url_matcher ||= url
42
42
  end
43
43
  end
44
44
 
45
- # Where a Capybara HTML fragment has been directly injected into `#load` as a block return this loaded fragment
46
- # Where a page has been directly navigated to through traditional means (i.e. Selenium), return an instance of the
47
- # current Capybara session (With all applicable methods)
48
- #
49
- # @return [Capybara::Node::Simple || Capybara::Session]
50
- def page
51
- @_page ||= begin
52
- SitePrism::Deprecator.deprecate('Calling #page on a SitePrism::Page instance')
53
- to_capybara_node
54
- end
55
- end
56
-
57
45
  # This scopes our calls inside Page correctly to the `Capybara::Session`
58
46
  #
59
47
  # @return [Capybara::Node::Simple || Capybara::Session]
@@ -182,8 +170,9 @@ module SitePrism
182
170
  end
183
171
 
184
172
  def load_html_string(string)
173
+ SitePrism::Deprecator.deprecate('Using an input fragment (Loading partials using html strings).')
185
174
  @page = Capybara.string(string)
186
- yield self if block_given?
175
+ yield to_capybara_node if block_given?
187
176
  end
188
177
 
189
178
  def load_html_website(html, &block)
@@ -195,7 +184,7 @@ module SitePrism
195
184
  if with_validations
196
185
  when_loaded(&block)
197
186
  elsif block
198
- yield self
187
+ yield to_capybara_node
199
188
  end
200
189
  end
201
190
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
- VERSION = '4.0.3'
4
+ VERSION = '5.0'
5
5
  end
data/lib/site_prism.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'site_prism/error'
4
3
  require 'site_prism/all_there'
5
4
 
6
5
  require 'addressable/template'
@@ -8,10 +7,10 @@ require 'capybara/dsl'
8
7
  require 'forwardable'
9
8
 
10
9
  require 'site_prism/addressable_url_matcher'
11
- require 'site_prism/dsl'
12
- require 'site_prism/dsl_validator'
13
10
  require 'site_prism/deprecator'
11
+ require 'site_prism/dsl'
14
12
  require 'site_prism/element_checker'
13
+ require 'site_prism/error'
15
14
  require 'site_prism/loadable'
16
15
  require 'site_prism/logger'
17
16
  require 'site_prism/page'
@@ -23,6 +22,11 @@ require 'site_prism/waiter'
23
22
  # [SitePrism]
24
23
  module SitePrism
25
24
  class << self
25
+ # SitePrism will enforce strict validation on all generated DSL items i.e. `element`
26
+ # The validations are found inside the SitePrism::DSL::Validator module
27
+ # NB: To ensure no unwanted validation issues, this must be disabled BEFORE any page / section code is autoloaded
28
+ attr_accessor :dsl_validation_disabled
29
+
26
30
  def configure
27
31
  yield self
28
32
  end