site_prism 4.0.3 → 5.0.beta
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.
- checksums.yaml +4 -4
- data/lib/site_prism/dsl/builder.rb +157 -0
- data/lib/site_prism/dsl/locators.rb +68 -0
- data/lib/site_prism/dsl/methods.rb +135 -0
- data/lib/site_prism/dsl/validator.rb +93 -0
- data/lib/site_prism/dsl.rb +14 -327
- data/lib/site_prism/error.rb +1 -1
- data/lib/site_prism/page.rb +2 -14
- data/lib/site_prism/version.rb +1 -1
- data/lib/site_prism.rb +2 -3
- metadata +53 -38
- data/lib/site_prism/dsl_validator.rb +0 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 919e215261486aca371a708b7b06826e54941a29cf1580ebca68e2dea4cfbc0a
|
4
|
+
data.tar.gz: ecd938940c5546287ffbbf182aece2d6aacf96b454738f33a73b114c09803f19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebb6eb3adbe1cb9663160d4347a5c3189c333937b4cb49649bf998a397cd634be4d4b557d5dc6ad5e5415d7eee8f297a8b05e8b894d19fe98cb3a9ff7a602657
|
7
|
+
data.tar.gz: e63ee2fd016759f69c943de5ea7e477151c1333af5c25aef8a10834426db5e14fa1790accf5069726c405ae9ec33dd2a96d9877ad75cfb558b85b284e4e1875d
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SitePrism
|
4
|
+
module DSL
|
5
|
+
# [SitePrism::DSL::Builder]
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
# The Building logic - Initially coming from `.build`
|
10
|
+
# This will take a request to build from a DSL invocation such as `element` and generate a series of
|
11
|
+
# helper methods and waiters. It will also generate the correct classes for `SitePrism::Section` objects
|
12
|
+
#
|
13
|
+
# Whilst doing all of this, it will also build up a "map" of objects in memory which can be used for
|
14
|
+
# future interrogation. There are 2 ways of this being stored currently (Default as a hash, Legacy as an array)
|
15
|
+
#
|
16
|
+
module Builder
|
17
|
+
# Return a list of all mapped items on a SitePrism class instance (Page or Section)
|
18
|
+
# If legacy is set to false (Default) -> @return [Hash]
|
19
|
+
# If legacy is set to true (Old behaviour) -> @return [Array]
|
20
|
+
def mapped_items(legacy: false)
|
21
|
+
return legacy_mapped_items if legacy
|
22
|
+
|
23
|
+
@mapped_items ||= { element: [], elements: [], section: [], sections: [], iframe: [] }
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def build(type, name, *find_args)
|
29
|
+
raise InvalidDSLNameError if ENV.fetch('SITEPRISM_DSL_VALIDATION_ENABLED', 'true') == 'true' && invalid?(name)
|
30
|
+
|
31
|
+
if find_args.empty?
|
32
|
+
create_error_method(name)
|
33
|
+
else
|
34
|
+
map_item(type, name)
|
35
|
+
yield
|
36
|
+
end
|
37
|
+
add_helper_methods(name, type, *find_args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_error_method(name)
|
41
|
+
SitePrism::Deprecator.deprecate(
|
42
|
+
'DSL definition with no find_args',
|
43
|
+
'DSL definition with at least 1 find_arg'
|
44
|
+
)
|
45
|
+
SitePrism.logger.error("#{name} has come from an item with no locators.")
|
46
|
+
define_method(name) { raise SitePrism::InvalidElementError }
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_helper_methods(name, _type, *find_args)
|
50
|
+
create_existence_checker(name, *find_args)
|
51
|
+
create_nonexistence_checker(name, *find_args)
|
52
|
+
SitePrism::RSpecMatchers.new(name)._create_rspec_existence_matchers if defined?(RSpec)
|
53
|
+
create_visibility_waiter(name, *find_args)
|
54
|
+
create_invisibility_waiter(name, *find_args)
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_existence_checker(element_name, *find_args)
|
58
|
+
method_name = "has_#{element_name}?"
|
59
|
+
create_helper_method(method_name, *find_args) do
|
60
|
+
define_method(method_name) do |*runtime_args|
|
61
|
+
args = merge_args(find_args, runtime_args)
|
62
|
+
element_exists?(*args)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_nonexistence_checker(element_name, *find_args)
|
68
|
+
method_name = "has_no_#{element_name}?"
|
69
|
+
create_helper_method(method_name, *find_args) do
|
70
|
+
define_method(method_name) do |*runtime_args|
|
71
|
+
args = merge_args(find_args, runtime_args)
|
72
|
+
element_does_not_exist?(*args)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def create_visibility_waiter(element_name, *find_args)
|
78
|
+
method_name = "wait_until_#{element_name}_visible"
|
79
|
+
create_helper_method(method_name, *find_args) do
|
80
|
+
define_method(method_name) do |*runtime_args|
|
81
|
+
args = merge_args(find_args, runtime_args, visible: true)
|
82
|
+
return true if element_exists?(*args)
|
83
|
+
|
84
|
+
raise SitePrism::ElementVisibilityTimeoutError
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_invisibility_waiter(element_name, *find_args)
|
90
|
+
method_name = "wait_until_#{element_name}_invisible"
|
91
|
+
create_helper_method(method_name, *find_args) do
|
92
|
+
define_method(method_name) do |*runtime_args|
|
93
|
+
args = merge_args(find_args, runtime_args, visible: true)
|
94
|
+
return true if element_does_not_exist?(*args)
|
95
|
+
|
96
|
+
raise SitePrism::ElementInvisibilityTimeoutError
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def create_helper_method(proposed_method_name, *find_args)
|
102
|
+
return create_error_method(proposed_method_name) if find_args.empty?
|
103
|
+
|
104
|
+
yield
|
105
|
+
end
|
106
|
+
|
107
|
+
def legacy_mapped_items
|
108
|
+
@legacy_mapped_items ||= begin
|
109
|
+
SitePrism::Deprecator.deprecate(
|
110
|
+
'.mapped_items structure (internally), on a class',
|
111
|
+
'the new .mapped_items structure'
|
112
|
+
)
|
113
|
+
[]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def map_item(type, name)
|
118
|
+
mapped_items(legacy: true) << { type => name }
|
119
|
+
mapped_items[type] << name.to_sym
|
120
|
+
end
|
121
|
+
|
122
|
+
def extract_section_options(args, &block)
|
123
|
+
if args.first.is_a?(Class)
|
124
|
+
klass = args.shift
|
125
|
+
section_class = klass if klass <= SitePrism::Section
|
126
|
+
end
|
127
|
+
|
128
|
+
section_class = deduce_section_class(section_class, &block)
|
129
|
+
arguments = deduce_search_arguments(section_class, args)
|
130
|
+
[section_class, arguments]
|
131
|
+
end
|
132
|
+
|
133
|
+
def deduce_section_class(base_class, &block)
|
134
|
+
klass = base_class
|
135
|
+
klass = Class.new(klass || SitePrism::Section, &block) if block
|
136
|
+
return klass if klass
|
137
|
+
|
138
|
+
raise ArgumentError, 'You should provide descendant of SitePrism::Section class or/and a block as the second argument.'
|
139
|
+
end
|
140
|
+
|
141
|
+
def deduce_search_arguments(section_class, args)
|
142
|
+
extract_search_arguments(args) ||
|
143
|
+
extract_search_arguments(section_class.default_search_arguments) ||
|
144
|
+
invalidate_search_arguments!
|
145
|
+
end
|
146
|
+
|
147
|
+
def extract_search_arguments(args)
|
148
|
+
args if args && !args.empty?
|
149
|
+
end
|
150
|
+
|
151
|
+
def invalidate_search_arguments!
|
152
|
+
SitePrism.logger.error('Could not deduce search_arguments')
|
153
|
+
raise(ArgumentError, 'search arguments are needed in `section` definition or alternatively use `set_default_search_arguments`')
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SitePrism
|
4
|
+
module DSL
|
5
|
+
# [SitePrism::DSL::Locators]
|
6
|
+
#
|
7
|
+
# The locator logic for scoping all items - for use in locators, boolean tests and waiters
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
#
|
11
|
+
module Locators
|
12
|
+
private
|
13
|
+
|
14
|
+
def _find(*find_args)
|
15
|
+
kwargs = find_args.pop
|
16
|
+
to_capybara_node.find(*find_args, **kwargs)
|
17
|
+
end
|
18
|
+
|
19
|
+
def _all(*find_args)
|
20
|
+
kwargs = find_args.pop
|
21
|
+
to_capybara_node.all(*find_args, **kwargs)
|
22
|
+
end
|
23
|
+
|
24
|
+
def element_exists?(*find_args)
|
25
|
+
kwargs = find_args.pop
|
26
|
+
to_capybara_node.has_selector?(*find_args, **kwargs)
|
27
|
+
end
|
28
|
+
|
29
|
+
def element_does_not_exist?(*find_args)
|
30
|
+
kwargs = find_args.pop
|
31
|
+
to_capybara_node.has_no_selector?(*find_args, **kwargs)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Sanitize method called before calling any SitePrism DSL method or
|
35
|
+
# meta-programmed method. This ensures that the Capybara query is correct.
|
36
|
+
#
|
37
|
+
# Accepts any combination of arguments sent at DSL definition or runtime
|
38
|
+
# and combines them in such a way that Capybara can operate with them.
|
39
|
+
def merge_args(find_args, runtime_args, visibility_args = {})
|
40
|
+
find_args = find_args.dup
|
41
|
+
runtime_args = runtime_args.dup
|
42
|
+
options = visibility_args.dup
|
43
|
+
SitePrism.logger.debug("Initial args: #{find_args}, #{runtime_args}.")
|
44
|
+
|
45
|
+
recombine_args(find_args, runtime_args, options)
|
46
|
+
|
47
|
+
return [*find_args, *runtime_args, {}] if options.empty?
|
48
|
+
|
49
|
+
[*find_args, *runtime_args, options]
|
50
|
+
end
|
51
|
+
|
52
|
+
# Options re-combiner. This takes the original inputs and combines
|
53
|
+
# them such that there is only one hash passed as a final argument
|
54
|
+
# to Capybara.
|
55
|
+
#
|
56
|
+
# If the hash is empty, then the hash is omitted from the payload sent
|
57
|
+
# to Capybara, and the find / runtime arguments are sent alone.
|
58
|
+
#
|
59
|
+
# NB: If the +wait+ key is present in the options hash, even as false or 0, It will
|
60
|
+
# be set as the user-supplied value (So user error can be the cause for issues).
|
61
|
+
def recombine_args(find_args, runtime_args, options)
|
62
|
+
options.merge!(find_args.pop) if find_args.last.is_a? Hash
|
63
|
+
options.merge!(runtime_args.pop) if runtime_args.last.is_a? Hash
|
64
|
+
options[:wait] = Capybara.default_max_wait_time unless options.key?(:wait)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SitePrism
|
4
|
+
module DSL
|
5
|
+
# [SitePrism::DSL::Methods]
|
6
|
+
#
|
7
|
+
# The meta-programmed methods for using SitePrism during runtime. This public DSL contains all the methods
|
8
|
+
# you will use on `SitePrism::Page` or `SitePrism::Section` classes
|
9
|
+
#
|
10
|
+
module Methods
|
11
|
+
attr_reader :expected_items
|
12
|
+
|
13
|
+
# Sets the `expected_items` iVar on a class. This property is used in conjunction with
|
14
|
+
# `all_there?` to provide a way of granularising the check made to only interrogate a sub-set
|
15
|
+
# of DSL defined items
|
16
|
+
def expected_elements(*elements)
|
17
|
+
@expected_items = elements
|
18
|
+
end
|
19
|
+
|
20
|
+
# Creates an instance of a SitePrism Element - This will create several methods designed to
|
21
|
+
# Locate the element -> @return [Capybara::Node::Element]
|
22
|
+
# Check the elements presence or non-presence -> @return [Boolean]
|
23
|
+
# Wait for the elements to be present or not -> @return [TrueClass, SitePrism::Error]
|
24
|
+
# Validate certain properties about the element
|
25
|
+
def element(name, *find_args)
|
26
|
+
raise_if_build_time_block_supplied(self, name, block_given?, :element)
|
27
|
+
build(:element, name, *find_args) do
|
28
|
+
define_method(name) do |*runtime_args, &runtime_block|
|
29
|
+
raise_if_runtime_block_supplied(self, name, runtime_block, :element)
|
30
|
+
_find(*merge_args(find_args, runtime_args))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Creates a enumerable instance of a SitePrism Element - This will create several methods designed to
|
36
|
+
# Locate the enumerable element -> @return [Capybara::Result]
|
37
|
+
# Check the elements presence or non-presence -> @return [Boolean]
|
38
|
+
# Wait for the elements to be present or not -> @return [TrueClass, SitePrism::Error]
|
39
|
+
# Validate certain properties about the elements
|
40
|
+
def elements(name, *find_args)
|
41
|
+
raise_if_build_time_block_supplied(self, name, block_given?, :elements)
|
42
|
+
build(:elements, name, *find_args) do
|
43
|
+
define_method(name) do |*runtime_args, &runtime_block|
|
44
|
+
raise_if_runtime_block_supplied(self, name, runtime_block, :elements)
|
45
|
+
_all(*merge_args(find_args, runtime_args))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Creates an instance of a SitePrism Section - This will create several methods designed to
|
51
|
+
# Locate the section -> @return [SitePrism::Section]
|
52
|
+
# Check the section presence or non-presence -> @return [Boolean]
|
53
|
+
# Wait for the section to be present or not -> @return [TrueClass, SitePrism::Error]
|
54
|
+
# Validate certain properties about the section
|
55
|
+
def section(name, *args, &block)
|
56
|
+
section_class, find_args = extract_section_options(args, &block)
|
57
|
+
build(:section, name, *find_args) do
|
58
|
+
define_method(name) do |*runtime_args, &runtime_block|
|
59
|
+
section_element = _find(*merge_args(find_args, runtime_args))
|
60
|
+
section_class.new(self, section_element, &runtime_block)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Creates an enumerable instance of a SitePrism Section - This will create several methods designed to
|
66
|
+
# Locate the sections -> @return [Array]
|
67
|
+
# Check the sections presence or non-presence -> @return [Boolean]
|
68
|
+
# Wait for the sections to be present or not -> @return [TrueClass, SitePrism::Error]
|
69
|
+
# Validate certain properties about the section
|
70
|
+
def sections(name, *args, &block)
|
71
|
+
section_class, find_args = extract_section_options(args, &block)
|
72
|
+
build(:sections, name, *find_args) do
|
73
|
+
define_method(name) do |*runtime_args, &runtime_block|
|
74
|
+
raise_if_runtime_block_supplied(self, name, runtime_block, :sections)
|
75
|
+
_all(*merge_args(find_args, runtime_args)).map do |element|
|
76
|
+
section_class.new(self, element)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def iframe(name, klass, *args)
|
83
|
+
raise_if_build_time_block_supplied(self, name, block_given?, :elements)
|
84
|
+
element_find_args = deduce_iframe_element_find_args(args)
|
85
|
+
scope_find_args = deduce_iframe_scope_find_args(args)
|
86
|
+
build(:iframe, name, *element_find_args) do
|
87
|
+
define_method(name) do |&block|
|
88
|
+
raise MissingBlockError unless block
|
89
|
+
|
90
|
+
within_frame(*scope_find_args) { block.call(klass.new) }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def raise_if_build_time_block_supplied(parent_object, name, has_block, type)
|
98
|
+
return unless has_block
|
99
|
+
|
100
|
+
SitePrism.logger.debug("Type passed in: #{type}")
|
101
|
+
SitePrism.logger.error("#{name} has been defined as a '#{type}' item in #{parent_object}. It does not accept build-time blocks.")
|
102
|
+
raise SitePrism::UnsupportedBlockError
|
103
|
+
end
|
104
|
+
|
105
|
+
def deduce_iframe_element_find_args(args)
|
106
|
+
warn_on_invalid_selector_input(args)
|
107
|
+
case args[0]
|
108
|
+
when Integer then "iframe:nth-of-type(#{args[0] + 1})"
|
109
|
+
when String then [:css, args[0]]
|
110
|
+
else args
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def deduce_iframe_scope_find_args(args)
|
115
|
+
warn_on_invalid_selector_input(args)
|
116
|
+
case args[0]
|
117
|
+
when Integer then [args[0]]
|
118
|
+
when String then [:css, args[0]]
|
119
|
+
else args
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def warn_on_invalid_selector_input(args)
|
124
|
+
return unless looks_like_xpath?(args[0])
|
125
|
+
|
126
|
+
SitePrism.logger.warn('The arguments passed in look like xpath. Check your locators.')
|
127
|
+
SitePrism.logger.debug("Default locator strategy: #{Capybara.default_selector}")
|
128
|
+
end
|
129
|
+
|
130
|
+
def looks_like_xpath?(arg)
|
131
|
+
arg.is_a?(String) && arg.start_with?('/', './')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SitePrism
|
4
|
+
module DSL
|
5
|
+
# [SitePrism::DSL::Validators]
|
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
|
+
def invalid?(name)
|
14
|
+
prefix_invalid?(name) ||
|
15
|
+
suffix_invalid?(name) ||
|
16
|
+
characters_invalid?(name) ||
|
17
|
+
blacklisted?(name)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def prefix_invalid?(name)
|
23
|
+
return unless prefix_blacklist.any? { |prefix| name.start_with?(prefix) }
|
24
|
+
|
25
|
+
log_failure(name, 'prefix')
|
26
|
+
end
|
27
|
+
|
28
|
+
def suffix_invalid?(name)
|
29
|
+
return unless suffix_blacklist.any? { |prefix| name.end_with?(prefix) }
|
30
|
+
|
31
|
+
log_failure(name, 'suffix')
|
32
|
+
end
|
33
|
+
|
34
|
+
def characters_invalid?(name)
|
35
|
+
return if name.match?(regex_permission)
|
36
|
+
|
37
|
+
log_failure(name, 'character(s)')
|
38
|
+
end
|
39
|
+
|
40
|
+
def blacklisted?(name)
|
41
|
+
return unless blacklisted_names.include?(name)
|
42
|
+
|
43
|
+
log_failure(name, 'name (blacklisted entry)')
|
44
|
+
end
|
45
|
+
|
46
|
+
def regex_permission
|
47
|
+
/^[a-z]\w+$/
|
48
|
+
end
|
49
|
+
|
50
|
+
def prefix_blacklist
|
51
|
+
%w[
|
52
|
+
no_
|
53
|
+
_
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
def suffix_blacklist
|
58
|
+
%w[
|
59
|
+
_
|
60
|
+
?
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
def blacklisted_names
|
65
|
+
%w[
|
66
|
+
attributes
|
67
|
+
html
|
68
|
+
no
|
69
|
+
title
|
70
|
+
element
|
71
|
+
elements
|
72
|
+
section
|
73
|
+
sections
|
74
|
+
iframe
|
75
|
+
]
|
76
|
+
end
|
77
|
+
|
78
|
+
def log_failure(name, type)
|
79
|
+
SitePrism.logger.error("DSL item: #{name} has an invalid #{type}")
|
80
|
+
SitePrism.logger.debug(debug_error(type))
|
81
|
+
end
|
82
|
+
|
83
|
+
def debug_error(type)
|
84
|
+
case type
|
85
|
+
when 'prefix'; then "Invalid Prefixes: #{prefix_blacklist.join(', ')}."
|
86
|
+
when 'suffix'; then "Invalid Suffixes: #{suffix_blacklist.join(', ')}"
|
87
|
+
when 'character(s)'; then "Invalid DSL Names: #{blacklisted_names.join(', ')}"
|
88
|
+
else "DSL Charset REGEX: #{regex_permission.inspect}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/site_prism/dsl.rb
CHANGED
@@ -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
|
7
|
-
#
|
8
|
-
#
|
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
|
14
|
-
klass.extend
|
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
|
data/lib/site_prism/error.rb
CHANGED
@@ -48,6 +48,6 @@ 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
|
51
|
+
# DSL items are not permitted to be named in certain ways
|
52
52
|
class InvalidDSLNameError < AttributeValidationError; end
|
53
53
|
end
|
data/lib/site_prism/page.rb
CHANGED
@@ -42,18 +42,6 @@ module SitePrism
|
|
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]
|
@@ -183,7 +171,7 @@ module SitePrism
|
|
183
171
|
|
184
172
|
def load_html_string(string)
|
185
173
|
@page = Capybara.string(string)
|
186
|
-
yield
|
174
|
+
yield to_capybara_node if block_given?
|
187
175
|
end
|
188
176
|
|
189
177
|
def load_html_website(html, &block)
|
@@ -195,7 +183,7 @@ module SitePrism
|
|
195
183
|
if with_validations
|
196
184
|
when_loaded(&block)
|
197
185
|
elsif block
|
198
|
-
yield
|
186
|
+
yield to_capybara_node
|
199
187
|
end
|
200
188
|
end
|
201
189
|
end
|
data/lib/site_prism/version.rb
CHANGED
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'
|
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:
|
4
|
+
version: 5.0.beta
|
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: 2023-
|
12
|
+
date: 2023-10-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: addressable
|
@@ -18,6 +18,9 @@ dependencies:
|
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '2.8'
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.8.1
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -25,54 +28,77 @@ dependencies:
|
|
25
28
|
- - "~>"
|
26
29
|
- !ruby/object:Gem::Version
|
27
30
|
version: '2.8'
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.8.1
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: capybara
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
31
37
|
requirements:
|
32
38
|
- - "~>"
|
33
39
|
- !ruby/object:Gem::Version
|
34
|
-
version: '3.
|
40
|
+
version: '3.31'
|
35
41
|
type: :runtime
|
36
42
|
prerelease: false
|
37
43
|
version_requirements: !ruby/object:Gem::Requirement
|
38
44
|
requirements:
|
39
45
|
- - "~>"
|
40
46
|
- !ruby/object:Gem::Version
|
41
|
-
version: '3.
|
47
|
+
version: '3.31'
|
42
48
|
- !ruby/object:Gem::Dependency
|
43
49
|
name: site_prism-all_there
|
44
50
|
requirement: !ruby/object:Gem::Requirement
|
45
51
|
requirements:
|
46
|
-
- - "
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2'
|
55
|
+
- - "<"
|
47
56
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
57
|
+
version: '4'
|
49
58
|
type: :runtime
|
50
59
|
prerelease: false
|
51
60
|
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '2'
|
65
|
+
- - "<"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '4'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: automation_helpers
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
52
71
|
requirements:
|
53
72
|
- - "~>"
|
54
73
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
74
|
+
version: '4.0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '4.0'
|
56
82
|
- !ruby/object:Gem::Dependency
|
57
83
|
name: cucumber
|
58
84
|
requirement: !ruby/object:Gem::Requirement
|
59
85
|
requirements:
|
60
86
|
- - ">"
|
61
87
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
88
|
+
version: '7'
|
63
89
|
- - "<"
|
64
90
|
- !ruby/object:Gem::Version
|
65
|
-
version: '
|
91
|
+
version: '10'
|
66
92
|
type: :development
|
67
93
|
prerelease: false
|
68
94
|
version_requirements: !ruby/object:Gem::Requirement
|
69
95
|
requirements:
|
70
96
|
- - ">"
|
71
97
|
- !ruby/object:Gem::Version
|
72
|
-
version: '
|
98
|
+
version: '7'
|
73
99
|
- - "<"
|
74
100
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
101
|
+
version: '10'
|
76
102
|
- !ruby/object:Gem::Dependency
|
77
103
|
name: rspec
|
78
104
|
requirement: !ruby/object:Gem::Requirement
|
@@ -93,56 +119,56 @@ dependencies:
|
|
93
119
|
requirements:
|
94
120
|
- - "~>"
|
95
121
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.
|
122
|
+
version: 1.53.0
|
97
123
|
type: :development
|
98
124
|
prerelease: false
|
99
125
|
version_requirements: !ruby/object:Gem::Requirement
|
100
126
|
requirements:
|
101
127
|
- - "~>"
|
102
128
|
- !ruby/object:Gem::Version
|
103
|
-
version: 1.
|
129
|
+
version: 1.53.0
|
104
130
|
- !ruby/object:Gem::Dependency
|
105
131
|
name: rubocop-performance
|
106
132
|
requirement: !ruby/object:Gem::Requirement
|
107
133
|
requirements:
|
108
134
|
- - "~>"
|
109
135
|
- !ruby/object:Gem::Version
|
110
|
-
version: 1.
|
136
|
+
version: 1.19.0
|
111
137
|
type: :development
|
112
138
|
prerelease: false
|
113
139
|
version_requirements: !ruby/object:Gem::Requirement
|
114
140
|
requirements:
|
115
141
|
- - "~>"
|
116
142
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.
|
143
|
+
version: 1.19.0
|
118
144
|
- !ruby/object:Gem::Dependency
|
119
145
|
name: rubocop-rspec
|
120
146
|
requirement: !ruby/object:Gem::Requirement
|
121
147
|
requirements:
|
122
148
|
- - "~>"
|
123
149
|
- !ruby/object:Gem::Version
|
124
|
-
version: 2.
|
150
|
+
version: 2.23.2
|
125
151
|
type: :development
|
126
152
|
prerelease: false
|
127
153
|
version_requirements: !ruby/object:Gem::Requirement
|
128
154
|
requirements:
|
129
155
|
- - "~>"
|
130
156
|
- !ruby/object:Gem::Version
|
131
|
-
version: 2.
|
157
|
+
version: 2.23.2
|
132
158
|
- !ruby/object:Gem::Dependency
|
133
159
|
name: selenium-webdriver
|
134
160
|
requirement: !ruby/object:Gem::Requirement
|
135
161
|
requirements:
|
136
162
|
- - "~>"
|
137
163
|
- !ruby/object:Gem::Version
|
138
|
-
version: '4.
|
164
|
+
version: '4.7'
|
139
165
|
type: :development
|
140
166
|
prerelease: false
|
141
167
|
version_requirements: !ruby/object:Gem::Requirement
|
142
168
|
requirements:
|
143
169
|
- - "~>"
|
144
170
|
- !ruby/object:Gem::Version
|
145
|
-
version: '4.
|
171
|
+
version: '4.7'
|
146
172
|
- !ruby/object:Gem::Dependency
|
147
173
|
name: simplecov
|
148
174
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,20 +183,6 @@ dependencies:
|
|
157
183
|
- - "~>"
|
158
184
|
- !ruby/object:Gem::Version
|
159
185
|
version: '0.21'
|
160
|
-
- !ruby/object:Gem::Dependency
|
161
|
-
name: webdrivers
|
162
|
-
requirement: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - "~>"
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: '5.0'
|
167
|
-
type: :development
|
168
|
-
prerelease: false
|
169
|
-
version_requirements: !ruby/object:Gem::Requirement
|
170
|
-
requirements:
|
171
|
-
- - "~>"
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: '5.0'
|
174
186
|
description: SitePrism gives you a simple, clean and semantic DSL for describing your
|
175
187
|
site. SitePrism implements the Page Object Model pattern on top of Capybara.
|
176
188
|
email:
|
@@ -186,7 +198,10 @@ files:
|
|
186
198
|
- lib/site_prism/addressable_url_matcher.rb
|
187
199
|
- lib/site_prism/deprecator.rb
|
188
200
|
- lib/site_prism/dsl.rb
|
189
|
-
- lib/site_prism/
|
201
|
+
- lib/site_prism/dsl/builder.rb
|
202
|
+
- lib/site_prism/dsl/locators.rb
|
203
|
+
- lib/site_prism/dsl/methods.rb
|
204
|
+
- lib/site_prism/dsl/validator.rb
|
190
205
|
- lib/site_prism/element_checker.rb
|
191
206
|
- lib/site_prism/error.rb
|
192
207
|
- lib/site_prism/loadable.rb
|
@@ -212,14 +227,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
212
227
|
requirements:
|
213
228
|
- - ">="
|
214
229
|
- !ruby/object:Gem::Version
|
215
|
-
version: '2.
|
230
|
+
version: '2.7'
|
216
231
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
217
232
|
requirements:
|
218
|
-
- - "
|
233
|
+
- - ">"
|
219
234
|
- !ruby/object:Gem::Version
|
220
|
-
version:
|
235
|
+
version: 1.3.1
|
221
236
|
requirements: []
|
222
|
-
rubygems_version: 3.
|
237
|
+
rubygems_version: 3.2.3
|
223
238
|
signing_key:
|
224
239
|
specification_version: 4
|
225
240
|
summary: A Page Object Model DSL for Capybara
|
@@ -1,75 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SitePrism
|
4
|
-
# [SitePrism::DSLValidator]
|
5
|
-
#
|
6
|
-
# This is the new validator module which will check all DSL items against a whitelist
|
7
|
-
# for any entries which are prohibited
|
8
|
-
module DSLValidator
|
9
|
-
def invalid?(name)
|
10
|
-
prefix_invalid?(name) ||
|
11
|
-
suffix_invalid?(name) ||
|
12
|
-
characters_invalid?(name) ||
|
13
|
-
blacklisted?(name)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def prefix_invalid?(name)
|
19
|
-
prefix_blacklist.any? { |prefix| name.start_with?(prefix) }.tap { |result| log_failure(name, 'prefix') unless result }
|
20
|
-
end
|
21
|
-
|
22
|
-
def suffix_invalid?(name)
|
23
|
-
suffix_blacklist.any? { |prefix| name.end_with?(prefix) }.tap { |result| log_failure(name, 'suffix') unless result }
|
24
|
-
end
|
25
|
-
|
26
|
-
def characters_invalid?(name)
|
27
|
-
!name.match?(regex_permission).tap { |result| log_failure(name, 'character(s)') unless result }
|
28
|
-
end
|
29
|
-
|
30
|
-
def blacklisted?(name)
|
31
|
-
blacklisted_names.include?(name).tap { |result| log_failure(name, 'name (blacklisted entry)') unless result }
|
32
|
-
end
|
33
|
-
|
34
|
-
def regex_permission
|
35
|
-
/^[a-z]\w+$/
|
36
|
-
end
|
37
|
-
|
38
|
-
def prefix_blacklist
|
39
|
-
%w[
|
40
|
-
no_
|
41
|
-
_
|
42
|
-
]
|
43
|
-
end
|
44
|
-
|
45
|
-
def suffix_blacklist
|
46
|
-
%w[
|
47
|
-
_
|
48
|
-
?
|
49
|
-
]
|
50
|
-
end
|
51
|
-
|
52
|
-
def blacklisted_names
|
53
|
-
%w[
|
54
|
-
attributes
|
55
|
-
html
|
56
|
-
no
|
57
|
-
title
|
58
|
-
]
|
59
|
-
end
|
60
|
-
|
61
|
-
def log_failure(name, type)
|
62
|
-
SitePrism.logger.error("DSL item: #{name} has an invalid #{type}")
|
63
|
-
SitePrism.logger.debug(debug_error(type))
|
64
|
-
end
|
65
|
-
|
66
|
-
def debug_error(type)
|
67
|
-
case type
|
68
|
-
when 'prefix'; then "Invalid Prefixes: #{prefix_blacklist.join(', ')}."
|
69
|
-
when 'suffix'; then "Invalid Suffixes: #{suffix_blacklist.join(', ')}"
|
70
|
-
when 'character(s)'; then "Invalid DSL Names: #{blacklisted_names.join(', ')}"
|
71
|
-
else "DSL Charset REGEX: #{regex_permission.inspect}"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|