page_magic 2.0.0.alpha1 → 2.0.0
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/.rubocop.yml +5 -2
- data/.zsh_config +5 -5
- data/Dockerfile +2 -1
- data/Gemfile +2 -1
- data/Gemfile.lock +9 -5
- data/Makefile +7 -3
- data/README.md +16 -4
- data/VERSION +1 -1
- data/lib/active_support/core_ext/object/to_query.rb +6 -6
- data/lib/page_magic.rb +15 -16
- data/lib/page_magic/class_methods.rb +1 -1
- 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/drivers.rb +2 -2
- data/lib/page_magic/element.rb +19 -8
- data/lib/page_magic/element/locators.rb +4 -4
- data/lib/page_magic/element/not_found.rb +38 -0
- data/lib/page_magic/element/query.rb +19 -27
- 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 +38 -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 +5 -21
- data/lib/page_magic/element_definition_builder.rb +17 -24
- data/lib/page_magic/elements.rb +62 -102
- 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 +3 -0
- data/lib/page_magic/instance_methods.rb +2 -2
- data/lib/page_magic/mapping.rb +79 -0
- data/lib/page_magic/session.rb +10 -32
- data/lib/page_magic/session_methods.rb +1 -1
- data/lib/page_magic/transitions.rb +49 -0
- data/lib/page_magic/utils/string.rb +4 -0
- data/lib/page_magic/utils/url.rb +20 -0
- data/lib/page_magic/watcher.rb +10 -17
- data/lib/page_magic/watchers.rb +28 -15
- data/spec/page_magic/class_methods_spec.rb +64 -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 +25 -29
- data/spec/page_magic/drivers/poltergeist_spec.rb +4 -7
- data/spec/page_magic/drivers/rack_test_spec.rb +4 -9
- data/spec/page_magic/drivers/selenium_spec.rb +9 -12
- data/spec/page_magic/drivers_spec.rb +36 -29
- data/spec/page_magic/element/locators_spec.rb +26 -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 -47
- data/spec/page_magic/element/selector_spec.rb +118 -110
- data/spec/page_magic/element_context_spec.rb +46 -88
- data/spec/page_magic/element_definition_builder_spec.rb +12 -71
- data/spec/page_magic/element_spec.rb +256 -0
- data/spec/page_magic/elements/config_spec.rb +200 -0
- data/spec/page_magic/elements_spec.rb +87 -138
- data/spec/page_magic/instance_methods_spec.rb +63 -63
- data/spec/page_magic/mapping_spec.rb +181 -0
- data/spec/page_magic/session_methods_spec.rb +27 -25
- data/spec/page_magic/session_spec.rb +109 -198
- data/spec/page_magic/transitions_spec.rb +43 -0
- data/spec/page_magic/utils/string_spec.rb +20 -27
- data/spec/page_magic/utils/url_spec.rb +9 -0
- data/spec/page_magic/wait_methods_spec.rb +14 -22
- data/spec/page_magic/watcher_spec.rb +22 -0
- data/spec/page_magic/watchers_spec.rb +56 -62
- data/spec/page_magic_spec.rb +27 -24
- data/spec/spec_helper.rb +7 -3
- data/spec/support/shared_examples.rb +15 -17
- metadata +48 -15
- data/lib/page_magic/element/query_builder.rb +0 -61
- data/lib/page_magic/element/selector_methods.rb +0 -16
- data/lib/page_magic/matcher.rb +0 -130
- data/spec/element_spec.rb +0 -251
- data/spec/page_magic/element/query_builder_spec.rb +0 -110
- data/spec/page_magic/matcher_spec.rb +0 -338
- data/spec/support/shared_contexts/files_context.rb +0 -9
- data/spec/support/shared_contexts/nested_elements_html_context.rb +0 -18
- data/spec/support/shared_contexts/rack_application_context.rb +0 -11
- data/spec/support/shared_contexts/webapp_fixture_context.rb +0 -41
- data/spec/watcher_spec.rb +0 -64
data/lib/page_magic/elements.rb
CHANGED
@@ -1,162 +1,122 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'active_support/inflector'
|
4
|
-
|
4
|
+
require_relative 'element_definition_builder'
|
5
|
+
require_relative 'elements/inheritance_hooks'
|
6
|
+
require_relative 'elements/config'
|
7
|
+
require_relative 'elements/types'
|
8
|
+
|
5
9
|
module PageMagic
|
6
10
|
# module Elements - contains methods that add element definitions to the objects it is mixed in to
|
7
11
|
module Elements
|
8
|
-
# hooks for objects that inherit classes that include the Elements module
|
9
|
-
module InheritanceHooks
|
10
|
-
# Copies parent element definitions on to subclass
|
11
|
-
# @param [Class] clazz - inheritting class
|
12
|
-
def inherited(clazz)
|
13
|
-
clazz.element_definitions.merge!(element_definitions)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
12
|
INVALID_METHOD_NAME_MSG = 'a method already exists with this method name'
|
18
13
|
|
19
|
-
# css
|
20
|
-
# datalist_input
|
21
|
-
# datalist_option
|
22
|
-
# field
|
23
|
-
# fieldset
|
24
|
-
# file_field
|
25
|
-
# fillable_field
|
26
|
-
# frame
|
27
|
-
# link_or_button
|
28
|
-
# option
|
29
|
-
# radio_button
|
30
|
-
# select
|
31
|
-
# table
|
32
|
-
# table_row
|
33
|
-
# xpath
|
34
|
-
#
|
35
|
-
|
36
|
-
TYPES = %i[field
|
37
|
-
fieldset
|
38
|
-
file_field
|
39
|
-
fillable_field
|
40
|
-
frame
|
41
|
-
link_or_button
|
42
|
-
option
|
43
|
-
radio_button
|
44
|
-
select
|
45
|
-
table
|
46
|
-
table_row
|
47
|
-
text_field
|
48
|
-
button
|
49
|
-
link
|
50
|
-
checkbox
|
51
|
-
select_list
|
52
|
-
radio
|
53
|
-
textarea
|
54
|
-
label].collect{ |type| [type, :"#{type}s"]}.flatten.freeze
|
55
|
-
|
56
14
|
class << self
|
57
15
|
def extended(clazz)
|
58
16
|
clazz.extend(InheritanceHooks)
|
59
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
|
60
28
|
end
|
61
29
|
|
62
|
-
# Creates an
|
63
|
-
# Element defintions contain specifications for locating them and other sub elements.
|
64
|
-
# if a block is specified then it will be executed against the element defintion.
|
30
|
+
# Creates an Element definition
|
65
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.
|
66
34
|
# @example
|
67
35
|
# element :widget, id: 'widget' do
|
68
36
|
# link :next, text: 'next'
|
69
37
|
# end
|
70
38
|
# @overload element(name, selector, &block)
|
71
39
|
# @param [Symbol] name the name of the element.
|
72
|
-
# @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
|
73
41
|
# @option selector [String] :text text contained within the element
|
74
42
|
# @option selector [String] :css css selector
|
75
43
|
# @option selector [String] :id the id of the element
|
76
44
|
# @option selector [String] :name the value of the name attribute belonging to the element
|
77
45
|
# @option selector [String] :label value of the label tied to the require field
|
46
|
+
# @param optional [Hash<Symbol,String>] capybara_options
|
78
47
|
# @overload element(element_class, &block)
|
79
48
|
# @param [ElementClass] element_class a custom class of element that inherits {Element}.
|
80
49
|
# the name of the element is derived from the class name. the Class name coverted to snakecase.
|
81
50
|
# The selector must be defined on the class itself.
|
51
|
+
# @param optional [Hash<Symbol,String>] capybara_options
|
82
52
|
# @overload element(name, element_class, &block)
|
83
53
|
# @param [Symbol] name the name of the element.
|
84
54
|
# @param [ElementClass] element_class a custom class of element that inherits {Element}.
|
85
55
|
# The selector must be defined on the class itself.
|
56
|
+
# @param optional [Hash<Symbol,String>] capybara_options
|
86
57
|
# @overload element(name, element_class, selector, &block)
|
87
58
|
# @param [Symbol] name the name of the element.
|
88
59
|
# @param [ElementClass] element_class a custom class of element that inherits {Element}.
|
89
|
-
# @param [Hash]
|
90
|
-
def element(*args, &block)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
definition_class = Class.new(section_class) do
|
98
|
-
parent_element(parent_element)
|
99
|
-
class_exec(*e_args, &block)
|
100
|
-
end
|
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
|
101
68
|
|
102
|
-
|
103
|
-
|
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)
|
104
76
|
end
|
105
77
|
|
106
|
-
|
107
|
-
TYPES
|
78
|
+
define_element_methods(TYPES)
|
79
|
+
define_pluralised_element_methods(TYPES)
|
108
80
|
|
109
|
-
# @return [Hash] element definition names mapped to
|
110
|
-
#
|
81
|
+
# @return [Hash<Symbol,ElementDefinitionBuilder>] element definition names mapped to
|
82
|
+
# blocks that can be used to create unique instances of {Element} definitions
|
111
83
|
def element_definitions
|
112
84
|
@element_definitions ||= {}
|
113
85
|
end
|
114
86
|
|
115
87
|
private
|
116
88
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
type: type,
|
122
|
-
selector: compute_selector(args, section_class),
|
123
|
-
options: compute_argument(args, Hash),
|
124
|
-
element: args.delete_at(0),
|
125
|
-
section_class: section_class }.tap do |hash|
|
126
|
-
hash[:options][:multiple_results] = type.to_s.end_with?('s')
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def add_element_definition(name, &block)
|
131
|
-
raise InvalidElementNameException, 'duplicate page element defined' if element_definitions[name]
|
132
|
-
|
133
|
-
methods = respond_to?(:instance_methods) ? instance_methods : methods()
|
134
|
-
raise InvalidElementNameException, INVALID_METHOD_NAME_MSG if methods.find { |method| method == name }
|
135
|
-
|
136
|
-
element_definitions[name] = block
|
137
|
-
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)
|
138
93
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
143
99
|
|
144
|
-
|
145
|
-
|
146
|
-
selector || section_class.selector if section_class.respond_to?(:selector)
|
100
|
+
ElementDefinitionBuilder.new(query_class: query_class, **config.element_options)
|
101
|
+
end
|
147
102
|
end
|
148
103
|
|
149
104
|
def method_added(method)
|
105
|
+
super
|
150
106
|
raise InvalidMethodNameException, 'method name matches element name' if element_definitions[method]
|
151
107
|
end
|
152
108
|
|
153
|
-
def
|
154
|
-
|
109
|
+
def validate!(args, type)
|
110
|
+
config = Config.build(args, type).validate!
|
111
|
+
validate_element_name(config.name)
|
112
|
+
config
|
155
113
|
end
|
156
114
|
|
157
|
-
def
|
158
|
-
|
159
|
-
|
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 }
|
160
120
|
end
|
161
121
|
end
|
162
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]
|
77
|
+
Element::Selector.find(selector.keys.first).build(type, selector.values.first, options: options)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Validate supplied configuration
|
81
|
+
# @raise [PageMagic::InvalidConfigurationException]
|
82
|
+
# @return [PageMagic::Elements::Config]
|
83
|
+
def validate!
|
84
|
+
raise PageMagic::InvalidConfigurationException, INVALID_SELECTOR_MSG unless element || valid_selector?
|
85
|
+
raise PageMagic::InvalidConfigurationException, 'element type required' unless type
|
86
|
+
raise PageMagic::InvalidConfigurationException, INVALID_ELEMENT_CLASS_MSG unless valid_element_class?
|
87
|
+
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def valid_selector?
|
94
|
+
selector = self[: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
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PageMagic
|
4
|
+
module Elements
|
5
|
+
# hooks for objects that inherit classes that include the Elements module
|
6
|
+
module InheritanceHooks
|
7
|
+
# Copies parent element definitions on to subclass
|
8
|
+
# @param [Class] clazz - inheriting class
|
9
|
+
def inherited(clazz)
|
10
|
+
super
|
11
|
+
clazz.element_definitions.merge!(element_definitions)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PageMagic
|
4
|
+
module Elements
|
5
|
+
TYPES = %i[field
|
6
|
+
fieldset
|
7
|
+
file_field
|
8
|
+
fillable_field
|
9
|
+
frame
|
10
|
+
link_or_button
|
11
|
+
option
|
12
|
+
radio_button
|
13
|
+
select
|
14
|
+
table
|
15
|
+
table_row
|
16
|
+
text_field
|
17
|
+
button
|
18
|
+
link
|
19
|
+
checkbox
|
20
|
+
select_list
|
21
|
+
radio
|
22
|
+
textarea
|
23
|
+
label].freeze
|
24
|
+
end
|
25
|
+
end
|
@@ -19,7 +19,7 @@ module PageMagic
|
|
19
19
|
@browser_element = browser
|
20
20
|
end
|
21
21
|
|
22
|
-
# @return [Array] class level defined element definitions
|
22
|
+
# @return [Array<ElementDefinitionBuilder>] class level defined element definitions
|
23
23
|
def element_definitions
|
24
24
|
self.class.element_definitions
|
25
25
|
end
|
@@ -37,7 +37,7 @@ module PageMagic
|
|
37
37
|
element_context.send(method, *args)
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
40
|
+
def respond_to_missing?(*args)
|
41
41
|
contains_element?(args.first) || super
|
42
42
|
end
|
43
43
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../active_support/core_ext/object/to_query'
|
4
|
+
require_relative 'comparator'
|
5
|
+
|
6
|
+
|
7
|
+
module PageMagic
|
8
|
+
# models mapping used to relate pages to uris
|
9
|
+
class Mapping
|
10
|
+
attr_reader :path, :parameters, :fragment
|
11
|
+
|
12
|
+
# @param [Object] path String or Regular expression to match with
|
13
|
+
# @param [Hash] parameters mapping of parameter name to literal or regex to match with
|
14
|
+
# @param [Object] fragment String or Regular expression to match with
|
15
|
+
# @raise [MatcherInvalidException] if at least one component is not specified
|
16
|
+
def initialize(path = nil, parameters: {}, fragment: nil)
|
17
|
+
raise MatcherInvalidException unless path || parameters || fragment
|
18
|
+
|
19
|
+
@path = Comparator.for(path)
|
20
|
+
@parameters = Comparator.for(parameters)
|
21
|
+
@fragment = Comparator.for(fragment)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Boolean] true if no component contains a Regexp
|
25
|
+
def can_compute_uri?
|
26
|
+
!fragment.fuzzy? && !path.fuzzy? && !parameters.fuzzy?
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [String] uri represented by this mapping
|
30
|
+
def compute_uri
|
31
|
+
path.to_s.dup.tap do |uri|
|
32
|
+
uri << "?#{parameters.comparator.to_query}" unless parameters.empty?
|
33
|
+
uri << "##{fragment}" if fragment.present?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Fixnum] hash for instance
|
38
|
+
def hash
|
39
|
+
[path, parameters, fragment].hash
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [String] uri
|
43
|
+
# @return [Boolean] returns true if the uri is matched against this matcher
|
44
|
+
def match?(uri)
|
45
|
+
uri = URI(uri)
|
46
|
+
path.match?(uri.path) && parameters.match?(parameters_hash(uri.query)) && fragment.match?(uri.fragment)
|
47
|
+
end
|
48
|
+
|
49
|
+
# compare this matcher against another
|
50
|
+
# @param [Mapping] other
|
51
|
+
# @return [Fixnum] -1 = smaller, 0 = equal to, 1 = greater than
|
52
|
+
def <=>(other)
|
53
|
+
path_comparison = path <=> other.path
|
54
|
+
return path_comparison unless path_comparison.zero?
|
55
|
+
|
56
|
+
parameter_comparison = parameters <=> other.parameters
|
57
|
+
return parameter_comparison unless parameter_comparison.zero?
|
58
|
+
|
59
|
+
fragment <=> other.fragment
|
60
|
+
end
|
61
|
+
|
62
|
+
# check equality
|
63
|
+
# @param [Mapping] other
|
64
|
+
# @return [Boolean]
|
65
|
+
def ==(other)
|
66
|
+
return false unless other.is_a?(Mapping)
|
67
|
+
|
68
|
+
path == other.path && parameters == other.parameters && fragment == other.fragment
|
69
|
+
end
|
70
|
+
|
71
|
+
alias eql? ==
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def parameters_hash(string)
|
76
|
+
CGI.parse(string.to_s.downcase).collect { |key, value| [key.downcase, value.first] }.to_h
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|