page_magic 1.2.8 → 2.0.2
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 +5 -5
- data/.rubocop.yml +23 -4
- data/.simplecov +5 -3
- data/.zsh_config +6 -0
- data/Dockerfile +11 -0
- data/Gemfile +13 -13
- data/Gemfile.lock +136 -148
- data/Makefile +17 -0
- data/README.md +26 -5
- data/Rakefile +12 -2
- data/VERSION +1 -1
- data/circle.yml +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +84 -0
- data/lib/page_magic.rb +31 -24
- data/lib/page_magic/class_methods.rb +5 -2
- data/lib/page_magic/comparator.rb +37 -0
- data/lib/page_magic/comparator/fuzzy.rb +23 -0
- data/lib/page_magic/comparator/literal.rb +22 -0
- data/lib/page_magic/comparator/null.rb +26 -0
- data/lib/page_magic/comparator/parameter_map.rb +52 -0
- data/lib/page_magic/driver.rb +3 -0
- data/lib/page_magic/drivers.rb +6 -5
- data/lib/page_magic/drivers/poltergeist.rb +2 -0
- data/lib/page_magic/drivers/rack_test.rb +3 -1
- data/lib/page_magic/drivers/selenium.rb +4 -2
- data/lib/page_magic/element.rb +35 -15
- data/lib/page_magic/element/locators.rb +8 -5
- data/lib/page_magic/element/not_found.rb +38 -0
- data/lib/page_magic/element/query.rb +21 -20
- data/lib/page_magic/element/query/multiple_results.rb +21 -0
- data/lib/page_magic/element/query/prefetched_result.rb +26 -0
- data/lib/page_magic/element/query/single_result.rb +20 -0
- data/lib/page_magic/element/selector.rb +41 -16
- data/lib/page_magic/element/selector/methods.rb +18 -0
- data/lib/page_magic/element/selector/model.rb +21 -0
- data/lib/page_magic/element_context.rb +7 -21
- data/lib/page_magic/element_definition_builder.rb +20 -24
- data/lib/page_magic/elements.rb +65 -69
- data/lib/page_magic/elements/config.rb +103 -0
- data/lib/page_magic/elements/inheritance_hooks.rb +15 -0
- data/lib/page_magic/elements/types.rb +25 -0
- data/lib/page_magic/exceptions.rb +6 -1
- data/lib/page_magic/instance_methods.rb +8 -3
- data/lib/page_magic/mapping.rb +79 -0
- data/lib/page_magic/session.rb +15 -35
- data/lib/page_magic/session_methods.rb +3 -1
- data/lib/page_magic/transitions.rb +49 -0
- data/lib/page_magic/utils/string.rb +18 -0
- data/lib/page_magic/utils/url.rb +20 -0
- data/lib/page_magic/wait_methods.rb +3 -0
- data/lib/page_magic/watcher.rb +12 -17
- data/lib/page_magic/watchers.rb +31 -15
- data/page_magic.gemspec +15 -11
- data/spec/lib/active_support/core_ext/object/to_query_test.rb +78 -0
- data/spec/page_magic/class_methods_spec.rb +66 -37
- data/spec/page_magic/comparator/fuzzy_spec.rb +44 -0
- data/spec/page_magic/comparator/literal_spec.rb +41 -0
- data/spec/page_magic/comparator/null_spec.rb +35 -0
- data/spec/page_magic/comparator/parameter_map_spec.rb +75 -0
- data/spec/page_magic/driver_spec.rb +26 -28
- data/spec/page_magic/drivers/poltergeist_spec.rb +6 -7
- data/spec/page_magic/drivers/rack_test_spec.rb +6 -9
- data/spec/page_magic/drivers/selenium_spec.rb +11 -12
- data/spec/page_magic/drivers_spec.rb +38 -29
- data/spec/page_magic/element/locators_spec.rb +28 -25
- data/spec/page_magic/element/not_found_spec.rb +24 -0
- data/spec/page_magic/element/query/multiple_results_spec.rb +14 -0
- data/spec/page_magic/element/query/single_result_spec.rb +21 -0
- data/spec/page_magic/element/query_spec.rb +26 -45
- data/spec/page_magic/element/selector_spec.rb +120 -110
- data/spec/page_magic/element_context_spec.rb +47 -87
- data/spec/page_magic/element_definition_builder_spec.rb +14 -71
- data/spec/page_magic/element_spec.rb +256 -0
- data/spec/page_magic/elements/config_spec.rb +203 -0
- data/spec/page_magic/elements_spec.rb +90 -134
- data/spec/page_magic/instance_methods_spec.rb +65 -63
- data/spec/page_magic/mapping_spec.rb +181 -0
- data/spec/page_magic/session_methods_spec.rb +29 -25
- data/spec/page_magic/session_spec.rb +109 -199
- data/spec/page_magic/transitions_spec.rb +43 -0
- data/spec/page_magic/utils/string_spec.rb +29 -0
- data/spec/page_magic/utils/url_spec.rb +9 -0
- data/spec/page_magic/wait_methods_spec.rb +16 -22
- data/spec/page_magic/watcher_spec.rb +22 -0
- data/spec/page_magic/watchers_spec.rb +58 -62
- data/spec/page_magic_spec.rb +37 -29
- data/spec/spec_helper.rb +9 -2
- data/spec/support/shared_contexts.rb +3 -1
- data/spec/support/shared_examples.rb +17 -17
- metadata +101 -48
- data/lib/page_magic/element/query_builder.rb +0 -48
- data/lib/page_magic/element/selector_methods.rb +0 -13
- data/lib/page_magic/matcher.rb +0 -121
- data/spec/element_spec.rb +0 -249
- data/spec/page_magic/element/query_builder_spec.rb +0 -108
- data/spec/page_magic/matcher_spec.rb +0 -336
- data/spec/support/shared_contexts/files_context.rb +0 -7
- data/spec/support/shared_contexts/nested_elements_html_context.rb +0 -16
- data/spec/support/shared_contexts/rack_application_context.rb +0 -9
- data/spec/support/shared_contexts/webapp_fixture_context.rb +0 -39
- data/spec/watcher_spec.rb +0 -61
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PageMagic
|
|
4
|
+
class Element
|
|
5
|
+
class Selector
|
|
6
|
+
# module SelectorMethods - adds method for getting and setting an element selector
|
|
7
|
+
module Methods
|
|
8
|
+
# Gets/Sets a selector
|
|
9
|
+
# @param [Hash<Symbol,String>] selector method for locating the browser element. E.g. text: 'the text'
|
|
10
|
+
def selector(selector = nil)
|
|
11
|
+
return @selector unless selector
|
|
12
|
+
|
|
13
|
+
@selector = selector
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PageMagic
|
|
4
|
+
class Element
|
|
5
|
+
class Selector
|
|
6
|
+
# class model - represents the parameters for capybara finder methods
|
|
7
|
+
class Model
|
|
8
|
+
attr_reader :args, :options
|
|
9
|
+
|
|
10
|
+
def initialize(args, options = {})
|
|
11
|
+
@args = args
|
|
12
|
+
@options = options
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def ==(other)
|
|
16
|
+
other.args == args && other.options == options
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module PageMagic
|
|
2
4
|
# class ElementContext - resolves which element definition to use when accessing the browser.
|
|
3
5
|
class ElementContext
|
|
@@ -7,9 +9,9 @@ module PageMagic
|
|
|
7
9
|
@page_element = page_element
|
|
8
10
|
end
|
|
9
11
|
|
|
10
|
-
# acts as proxy to element
|
|
11
|
-
# @return [Object] result of
|
|
12
|
-
# @return [Element]
|
|
12
|
+
# acts as proxy to element definitions defined on @page_element
|
|
13
|
+
# @return [Object] result of calling method on page_element
|
|
14
|
+
# @return [Element] page element containing located browser element
|
|
13
15
|
# @return [Array<Element>] array of elements if more that one result was found the browser
|
|
14
16
|
def method_missing(method, *args, &block)
|
|
15
17
|
return page_element.send(method, *args, &block) if page_element.methods.include?(method)
|
|
@@ -18,27 +20,11 @@ module PageMagic
|
|
|
18
20
|
|
|
19
21
|
super unless builder
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
return builder.build(prefecteched_element) if prefecteched_element
|
|
23
|
-
|
|
24
|
-
find(builder)
|
|
23
|
+
builder.build(page_element.browser_element)
|
|
25
24
|
end
|
|
26
25
|
|
|
27
|
-
def
|
|
26
|
+
def respond_to_missing?(*args)
|
|
28
27
|
page_element.respond_to?(*args) || super
|
|
29
28
|
end
|
|
30
|
-
|
|
31
|
-
private
|
|
32
|
-
|
|
33
|
-
def find(builder)
|
|
34
|
-
query = builder.build_query
|
|
35
|
-
result = query.execute(page_element.browser_element)
|
|
36
|
-
|
|
37
|
-
if query.multiple_results?
|
|
38
|
-
result.collect { |e| builder.build(e) }
|
|
39
|
-
else
|
|
40
|
-
builder.build(result)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
29
|
end
|
|
44
30
|
end
|
|
@@ -1,41 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module PageMagic
|
|
2
4
|
# Builder for creating ElementDefinitions
|
|
3
5
|
class ElementDefinitionBuilder
|
|
4
|
-
|
|
5
|
-
attr_reader :definition_class, :options, :selector, :type, :element, :query_builder
|
|
6
|
-
|
|
7
|
-
def initialize(definition_class:, selector:, type:, options: {}, element: nil)
|
|
8
|
-
unless element
|
|
9
|
-
selector ||= definition_class.selector
|
|
10
|
-
raise UndefinedSelectorException, INVALID_SELECTOR_MSG if selector.nil? || selector.empty?
|
|
11
|
-
end
|
|
12
|
-
|
|
6
|
+
def initialize(definition_class:, selector:, query_class: PageMagic::Element::Query::SingleResult, element: nil)
|
|
13
7
|
@definition_class = definition_class
|
|
14
|
-
@selector = selector
|
|
15
|
-
@type = type
|
|
16
|
-
@query_builder = Element::QueryBuilder.find(type)
|
|
17
|
-
|
|
18
|
-
@options = { multiple_results: false }.merge(options)
|
|
19
|
-
@element = element
|
|
20
|
-
end
|
|
21
8
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
@query = if element
|
|
10
|
+
PageMagic::Element::Query::PrefetchedResult.new(element)
|
|
11
|
+
else
|
|
12
|
+
query_class.new(*selector.args, options: selector.options)
|
|
13
|
+
end
|
|
26
14
|
end
|
|
27
15
|
|
|
28
16
|
# Create new instance of the ElementDefinition modeled by this builder
|
|
29
17
|
# @param [Object] browser_element capybara browser element corresponding to the element modelled by this builder
|
|
30
|
-
# @return [Element]
|
|
18
|
+
# @return [Capybara::Node::Element]
|
|
19
|
+
# @return [Array<Capybara::Node::Element>]
|
|
31
20
|
def build(browser_element)
|
|
32
|
-
|
|
21
|
+
query.execute(browser_element) do |result|
|
|
22
|
+
definition_class.new(result)
|
|
23
|
+
end
|
|
33
24
|
end
|
|
34
25
|
|
|
35
26
|
def ==(other)
|
|
36
27
|
return false unless other.is_a?(ElementDefinitionBuilder)
|
|
37
|
-
|
|
38
|
-
this
|
|
28
|
+
|
|
29
|
+
this = [query, definition_class]
|
|
30
|
+
this == [other.send(:query), other.send(:definition_class)]
|
|
39
31
|
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
attr_reader :query, :definition_class
|
|
40
36
|
end
|
|
41
37
|
end
|
data/lib/page_magic/elements.rb
CHANGED
|
@@ -1,126 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'active_support/inflector'
|
|
2
|
-
|
|
4
|
+
require_relative 'element_definition_builder'
|
|
5
|
+
require_relative 'elements/inheritance_hooks'
|
|
6
|
+
require_relative 'elements/config'
|
|
7
|
+
require_relative 'elements/types'
|
|
8
|
+
|
|
3
9
|
module PageMagic
|
|
4
10
|
# module Elements - contains methods that add element definitions to the objects it is mixed in to
|
|
5
11
|
module Elements
|
|
6
|
-
|
|
7
|
-
module InheritanceHooks
|
|
8
|
-
# Copies parent element definitions on to subclass
|
|
9
|
-
# @param [Class] clazz - inheritting class
|
|
10
|
-
def inherited(clazz)
|
|
11
|
-
clazz.element_definitions.merge!(element_definitions)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
INVALID_METHOD_NAME_MSG = 'a method already exists with this method name'.freeze
|
|
16
|
-
|
|
17
|
-
TYPES = [:text_field, :button, :link, :checkbox, :select_list, :radio, :textarea].collect do |type|
|
|
18
|
-
[type, :"#{type}s"]
|
|
19
|
-
end.flatten.freeze
|
|
12
|
+
INVALID_METHOD_NAME_MSG = 'a method already exists with this method name'
|
|
20
13
|
|
|
21
14
|
class << self
|
|
22
15
|
def extended(clazz)
|
|
23
16
|
clazz.extend(InheritanceHooks)
|
|
24
17
|
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def define_element_methods(types)
|
|
22
|
+
types.each { |type| alias_method type, :element }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def define_pluralised_element_methods(types)
|
|
26
|
+
types.each { |type| alias_method type.to_s.pluralize, :elements }
|
|
27
|
+
end
|
|
25
28
|
end
|
|
26
29
|
|
|
27
|
-
# Creates an
|
|
28
|
-
# Element defintions contain specifications for locating them and other sub elements.
|
|
29
|
-
# if a block is specified then it will be executed against the element defintion.
|
|
30
|
+
# Creates an Element definition
|
|
30
31
|
# This method is aliased to each of the names specified in {TYPES TYPES}
|
|
32
|
+
# Element definitions contain specifications for locating them and other sub elements.
|
|
33
|
+
# @yield if a block is specified then it will be executed against the element definition.
|
|
31
34
|
# @example
|
|
32
35
|
# element :widget, id: 'widget' do
|
|
33
36
|
# link :next, text: 'next'
|
|
34
37
|
# end
|
|
35
38
|
# @overload element(name, selector, &block)
|
|
36
39
|
# @param [Symbol] name the name of the element.
|
|
37
|
-
# @param [Hash] selector a key value pair defining the method for locating this element
|
|
40
|
+
# @param [Hash<Symbol,String>] selector a key value pair defining the method for locating this element
|
|
38
41
|
# @option selector [String] :text text contained within the element
|
|
39
42
|
# @option selector [String] :css css selector
|
|
40
43
|
# @option selector [String] :id the id of the element
|
|
41
44
|
# @option selector [String] :name the value of the name attribute belonging to the element
|
|
42
45
|
# @option selector [String] :label value of the label tied to the require field
|
|
46
|
+
# @param optional [Hash<Symbol,String>] capybara_options
|
|
43
47
|
# @overload element(element_class, &block)
|
|
44
48
|
# @param [ElementClass] element_class a custom class of element that inherits {Element}.
|
|
45
49
|
# the name of the element is derived from the class name. the Class name coverted to snakecase.
|
|
46
50
|
# The selector must be defined on the class itself.
|
|
51
|
+
# @param optional [Hash<Symbol,String>] capybara_options
|
|
47
52
|
# @overload element(name, element_class, &block)
|
|
48
53
|
# @param [Symbol] name the name of the element.
|
|
49
54
|
# @param [ElementClass] element_class a custom class of element that inherits {Element}.
|
|
50
55
|
# The selector must be defined on the class itself.
|
|
56
|
+
# @param optional [Hash<Symbol,String>] capybara_options
|
|
51
57
|
# @overload element(name, element_class, selector, &block)
|
|
52
58
|
# @param [Symbol] name the name of the element.
|
|
53
59
|
# @param [ElementClass] element_class a custom class of element that inherits {Element}.
|
|
54
|
-
# @param [Hash]
|
|
55
|
-
def element(*args, &block)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
# @param optional [Hash<Symbol,String>] capybara_options
|
|
61
|
+
def element(*args, **capybara_options, &block)
|
|
62
|
+
define_element(*args,
|
|
63
|
+
type: __callee__,
|
|
64
|
+
query_class: PageMagic::Element::Query::SingleResult,
|
|
65
|
+
**capybara_options,
|
|
66
|
+
&block)
|
|
67
|
+
end
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
# see docs for {Elements#element}
|
|
70
|
+
def elements(*args, **capybara_options, &block)
|
|
71
|
+
define_element(*args,
|
|
72
|
+
type: __callee__.to_s.singularize.to_sym,
|
|
73
|
+
query_class: PageMagic::Element::Query::MultipleResults,
|
|
74
|
+
**capybara_options,
|
|
75
|
+
&block)
|
|
68
76
|
end
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
TYPES
|
|
78
|
+
define_element_methods(TYPES)
|
|
79
|
+
define_pluralised_element_methods(TYPES)
|
|
72
80
|
|
|
73
|
-
# @return [Hash] element definition names mapped to
|
|
74
|
-
#
|
|
81
|
+
# @return [Hash<Symbol,ElementDefinitionBuilder>] element definition names mapped to
|
|
82
|
+
# blocks that can be used to create unique instances of {Element} definitions
|
|
75
83
|
def element_definitions
|
|
76
84
|
@element_definitions ||= {}
|
|
77
85
|
end
|
|
78
86
|
|
|
79
87
|
private
|
|
80
88
|
|
|
81
|
-
def
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
type: type,
|
|
86
|
-
selector: compute_selector(args, section_class),
|
|
87
|
-
options: compute_argument(args, Hash),
|
|
88
|
-
element: args.delete_at(0),
|
|
89
|
-
section_class: section_class }.tap do |hash|
|
|
90
|
-
hash[:options][:multiple_results] = type.to_s.end_with?('s')
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def add_element_definition(name, &block)
|
|
95
|
-
raise InvalidElementNameException, 'duplicate page element defined' if element_definitions[name]
|
|
96
|
-
|
|
97
|
-
methods = respond_to?(:instance_methods) ? instance_methods : methods()
|
|
98
|
-
raise InvalidElementNameException, INVALID_METHOD_NAME_MSG if methods.find { |method| method == name }
|
|
99
|
-
|
|
100
|
-
element_definitions[name] = block
|
|
101
|
-
end
|
|
89
|
+
def define_element(*args, type:, query_class:, **capybara_options, &block)
|
|
90
|
+
block ||= proc {}
|
|
91
|
+
args << capybara_options unless capybara_options.empty?
|
|
92
|
+
config = validate!(args, type)
|
|
102
93
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
94
|
+
element_definitions[config.name] = proc do |parent_element, *e_args|
|
|
95
|
+
config.definition_class = Class.new(config.element_class) do
|
|
96
|
+
parent_element(parent_element)
|
|
97
|
+
class_exec(*e_args, &block)
|
|
98
|
+
end
|
|
107
99
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
selector || section_class.selector if section_class.respond_to?(:selector)
|
|
100
|
+
ElementDefinitionBuilder.new(query_class: query_class, **config.element_options)
|
|
101
|
+
end
|
|
111
102
|
end
|
|
112
103
|
|
|
113
104
|
def method_added(method)
|
|
105
|
+
super
|
|
114
106
|
raise InvalidMethodNameException, 'method name matches element name' if element_definitions[method]
|
|
115
107
|
end
|
|
116
108
|
|
|
117
|
-
def
|
|
118
|
-
|
|
109
|
+
def validate!(args, type)
|
|
110
|
+
config = Config.build(args, type).validate!
|
|
111
|
+
validate_element_name(config.name)
|
|
112
|
+
config
|
|
119
113
|
end
|
|
120
114
|
|
|
121
|
-
def
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
def validate_element_name(name)
|
|
116
|
+
raise InvalidElementNameException, 'duplicate page element defined' if element_definitions[name]
|
|
117
|
+
|
|
118
|
+
methods = respond_to?(:instance_methods) ? instance_methods : methods()
|
|
119
|
+
raise InvalidElementNameException, INVALID_METHOD_NAME_MSG if methods.find { |method| method == name }
|
|
124
120
|
end
|
|
125
121
|
end
|
|
126
122
|
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PageMagic
|
|
4
|
+
module Elements
|
|
5
|
+
CONFIG_STRUCT = Struct.new(:name,
|
|
6
|
+
:definition_class,
|
|
7
|
+
:type,
|
|
8
|
+
:selector,
|
|
9
|
+
:options,
|
|
10
|
+
:element,
|
|
11
|
+
:element_class,
|
|
12
|
+
keyword_init: true)
|
|
13
|
+
|
|
14
|
+
# class Config - use to validate input to {PageMagic::Elements#elment}
|
|
15
|
+
class Config < CONFIG_STRUCT
|
|
16
|
+
INVALID_SELECTOR_MSG = 'Pass a locator/define one on the class'
|
|
17
|
+
INVALID_ELEMENT_CLASS_MSG = 'Element class must be of type `PageMagic::Element`'
|
|
18
|
+
TYPE_REQUIRED_MESSAGE = 'element type required'
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
# Create `Config` used to build instances `PageMagic::Element` see `Page::Elements#element` for details
|
|
22
|
+
# @param [Args<Object>] args arguments passed to `Page::Elements#element`
|
|
23
|
+
# @return [Config]
|
|
24
|
+
def build(args, type)
|
|
25
|
+
element_class = remove_argument(args, Class) || Element
|
|
26
|
+
new(
|
|
27
|
+
name: compute_name(args, element_class),
|
|
28
|
+
type: type_for(type),
|
|
29
|
+
selector: compute_selector(args, element_class),
|
|
30
|
+
options: compute_argument(args, Hash),
|
|
31
|
+
element: args.delete_at(0),
|
|
32
|
+
element_class: element_class
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def compute_name(args, element_class)
|
|
39
|
+
name = remove_argument(args, Symbol)
|
|
40
|
+
name || element_class.name.demodulize.underscore.to_sym unless element_class.is_a?(Element)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def compute_selector(args, element_class)
|
|
44
|
+
selector = remove_argument(args, Hash)
|
|
45
|
+
selector || element_class.selector if element_class.respond_to?(:selector)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def compute_argument(args, clazz)
|
|
49
|
+
remove_argument(args, clazz) || clazz.new
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def remove_argument(args, clazz)
|
|
53
|
+
argument = args.find { |arg| arg.is_a?(clazz) }
|
|
54
|
+
args.delete(argument)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def type_for(type)
|
|
58
|
+
field?(type) ? :field : type
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def field?(type)
|
|
62
|
+
%i[ text_field checkbox select_list radio textarea field file_field fillable_field
|
|
63
|
+
radio_button select].include?(type)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Options for the building of `PageMagic::Element` via `PageMagic::ElementDefinitionBuilder#new`
|
|
68
|
+
# @return [Hash<Symbol,Object>]
|
|
69
|
+
def element_options
|
|
70
|
+
to_h.except(:element_class, :name, :type, :options).update(selector: selector)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Selector built using supplied configuration
|
|
74
|
+
# @return [PageMagic::Element::Selector::Model]
|
|
75
|
+
def selector
|
|
76
|
+
selector = self[:selector] || definition_class.selector
|
|
77
|
+
raise PageMagic::InvalidConfigurationException, INVALID_SELECTOR_MSG unless validate_selector?(selector)
|
|
78
|
+
|
|
79
|
+
Element::Selector.find(selector.keys.first).build(type, selector.values.first, options: options)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Validate supplied configuration
|
|
83
|
+
# @raise [PageMagic::InvalidConfigurationException]
|
|
84
|
+
# @return [PageMagic::Elements::Config]
|
|
85
|
+
def validate!
|
|
86
|
+
raise PageMagic::InvalidConfigurationException, 'element type required' unless type
|
|
87
|
+
raise PageMagic::InvalidConfigurationException, INVALID_ELEMENT_CLASS_MSG unless valid_element_class?
|
|
88
|
+
|
|
89
|
+
self
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def validate_selector?(selector)
|
|
95
|
+
selector.is_a?(Hash) && !selector.empty?
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def valid_element_class?
|
|
99
|
+
element_class && (element_class == PageMagic::Element || element_class < PageMagic::Element)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|