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
data/spec/element_spec.rb
DELETED
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
# rubocop:disable Metrics/ModuleLength
|
|
2
|
-
module PageMagic
|
|
3
|
-
describe Element do
|
|
4
|
-
include_context :webapp_fixture
|
|
5
|
-
|
|
6
|
-
let(:page_class) do
|
|
7
|
-
Class.new do
|
|
8
|
-
include PageMagic
|
|
9
|
-
url '/elements'
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
let(:session) { page_class.visit(application: rack_app) }
|
|
14
|
-
|
|
15
|
-
let(:page) { session.current_page }
|
|
16
|
-
|
|
17
|
-
let(:described_class) do
|
|
18
|
-
Class.new(Element).tap { |clazz| clazz.parent_element(page) }
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
subject do
|
|
22
|
-
described_class.new(:page_element)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it_behaves_like 'session accessor'
|
|
26
|
-
it_behaves_like 'element watcher'
|
|
27
|
-
it_behaves_like 'waiter'
|
|
28
|
-
it_behaves_like 'element locator'
|
|
29
|
-
|
|
30
|
-
describe '.after_events' do
|
|
31
|
-
subject do
|
|
32
|
-
Class.new(described_class)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
context 'hook set' do
|
|
36
|
-
it 'returns that hook' do
|
|
37
|
-
hook = proc {}
|
|
38
|
-
subject.after_events(&hook)
|
|
39
|
-
expect(subject.after_events).to eq([described_class::DEFAULT_HOOK, hook])
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
context 'hook not registered' do
|
|
43
|
-
it 'returns the default hook' do
|
|
44
|
-
expect(subject.after_events).to eq([described_class::DEFAULT_HOOK])
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
describe '.before_events' do
|
|
50
|
-
subject do
|
|
51
|
-
Class.new(described_class)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
context 'hook set' do
|
|
55
|
-
it 'returns that hook' do
|
|
56
|
-
hook = proc {}
|
|
57
|
-
subject.before_events(&hook)
|
|
58
|
-
expect(subject.before_events).to eq([described_class::DEFAULT_HOOK, hook])
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
context 'hook not registered' do
|
|
62
|
-
it 'returns the default hook' do
|
|
63
|
-
expect(subject.before_events).to eq([described_class::DEFAULT_HOOK])
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
describe '.inherited' do
|
|
69
|
-
it 'copies before hooks' do
|
|
70
|
-
before_hook = proc {}
|
|
71
|
-
described_class.before_events(&before_hook)
|
|
72
|
-
sub_class = Class.new(described_class)
|
|
73
|
-
expect(sub_class.before_events).to include(before_hook)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it 'copies after hooks' do
|
|
77
|
-
after_hook = proc {}
|
|
78
|
-
described_class.after_events(&after_hook)
|
|
79
|
-
sub_class = Class.new(described_class)
|
|
80
|
-
expect(sub_class.after_events).to include(after_hook)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
it 'lets sub classes defined their own elements' do
|
|
84
|
-
custom_element = Class.new(described_class) do
|
|
85
|
-
text_field :form_field, id: 'field_id'
|
|
86
|
-
|
|
87
|
-
def self.name
|
|
88
|
-
'Form'
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
page_class.class_eval do
|
|
93
|
-
element custom_element, css: '.form'
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
expect(page.form.form_field).to be_visible
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
describe '.watch' do
|
|
101
|
-
let(:described_class) { Class.new(Element) }
|
|
102
|
-
it 'adds a before hook with the watcher in it' do
|
|
103
|
-
described_class.watch(:object_id)
|
|
104
|
-
instance = described_class.new(:element)
|
|
105
|
-
|
|
106
|
-
watcher_block = instance.before_events.last
|
|
107
|
-
instance.instance_exec(&watcher_block)
|
|
108
|
-
expect(instance.watchers.first.last).to eq(instance.object_id)
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
describe 'EVENT_TYPES' do
|
|
113
|
-
context 'methods created' do
|
|
114
|
-
it 'creates methods for each of the event types' do
|
|
115
|
-
missing = described_class::EVENT_TYPES.find_all { |event| !subject.respond_to?(event) }
|
|
116
|
-
expect(missing).to be_empty
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
context 'method called' do
|
|
120
|
-
let(:browser_element) { instance_double(Capybara::Node::Element) }
|
|
121
|
-
subject do
|
|
122
|
-
described_class.new(browser_element)
|
|
123
|
-
end
|
|
124
|
-
it 'calls the browser_element passing on all args' do
|
|
125
|
-
expect(browser_element).to receive(:select).with(:args)
|
|
126
|
-
subject.select :args
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
context 'Capybara element does not respond to the method' do
|
|
131
|
-
it 'raises an error' do
|
|
132
|
-
expected_message = (described_class::EVENT_NOT_SUPPORTED_MSG % 'click')
|
|
133
|
-
expect { subject.click }.to raise_error(NotSupportedException, expected_message)
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
describe 'hooks' do
|
|
140
|
-
subject do
|
|
141
|
-
Class.new(described_class) do
|
|
142
|
-
before_events do
|
|
143
|
-
call_in_before_events
|
|
144
|
-
end
|
|
145
|
-
end.new(double('button', click: true))
|
|
146
|
-
end
|
|
147
|
-
context 'method called in before_events' do
|
|
148
|
-
it 'calls methods on the page element' do
|
|
149
|
-
expect(subject).to receive(:call_in_before_events)
|
|
150
|
-
subject.click
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
context 'method called in after_events' do
|
|
155
|
-
subject do
|
|
156
|
-
Class.new(described_class) do
|
|
157
|
-
after_events do
|
|
158
|
-
call_in_after_events
|
|
159
|
-
end
|
|
160
|
-
end.new(double('button', click: true))
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
it 'calls methods on the page element' do
|
|
164
|
-
expect(subject).to receive(:call_in_after_events)
|
|
165
|
-
subject.click
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
describe '#initialize' do
|
|
171
|
-
it 'sets the parent element' do
|
|
172
|
-
instance = described_class.new(:element)
|
|
173
|
-
expect(instance.parent_element).to eq(page)
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
context 'inherited items' do
|
|
177
|
-
let(:described_class) do
|
|
178
|
-
Class.new(Element)
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
it 'copies the event hooks from the class' do
|
|
182
|
-
before_hook = proc {}
|
|
183
|
-
after_hook = proc {}
|
|
184
|
-
described_class.before_events(&before_hook)
|
|
185
|
-
described_class.after_events(&after_hook)
|
|
186
|
-
|
|
187
|
-
instance = described_class.new(:element)
|
|
188
|
-
|
|
189
|
-
expect(instance.before_events).to include(before_hook)
|
|
190
|
-
expect(instance.after_events).to include(after_hook)
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
describe '#method_missing' do
|
|
196
|
-
before do
|
|
197
|
-
page_class.class_eval do
|
|
198
|
-
element :form_by_css, css: '.form' do
|
|
199
|
-
def parent_method
|
|
200
|
-
:parent_method_called
|
|
201
|
-
end
|
|
202
|
-
link(:link_in_form, text: 'link in a form')
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
it 'can delegate to capybara' do
|
|
208
|
-
expect(page.form_by_css).to be_visible
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
context 'no element definition and not a capybara method' do
|
|
212
|
-
it 'calls method on parent element' do
|
|
213
|
-
expect(page.form_by_css.link_in_form.parent_method).to eq(:parent_method_called)
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
context 'method not found on parent' do
|
|
217
|
-
it 'throws and exception' do
|
|
218
|
-
expect { page.form_by_css.link_in_a_form.bobbins }.to raise_exception ElementMissingException
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
describe '#respond_to?' do
|
|
225
|
-
subject do
|
|
226
|
-
Class.new(described_class) do
|
|
227
|
-
element :sub_element, css: '.sub-element'
|
|
228
|
-
end.new(double(element_method: ''))
|
|
229
|
-
end
|
|
230
|
-
it 'checks for methods on self' do
|
|
231
|
-
expect(subject.respond_to?(:session)).to eq(true)
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
it 'checks against registered elements' do
|
|
235
|
-
expect(subject.respond_to?(:sub_element)).to eq(true)
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
it 'checks for the method of the browser_element' do
|
|
239
|
-
expect(subject.respond_to?(:element_method)).to eq(true)
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
describe '#session' do
|
|
244
|
-
it 'should have a handle to the session' do
|
|
245
|
-
expect(subject.session).to eq(page.session)
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
end
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
module PageMagic
|
|
2
|
-
class Element
|
|
3
|
-
describe QueryBuilder do
|
|
4
|
-
it 'has a predefined query for each element type' do
|
|
5
|
-
missing = PageMagic::Elements::TYPES.dup.delete_if { |type| type.to_s.end_with?('s') }.find_all do |type|
|
|
6
|
-
described_class.constants.include?(type)
|
|
7
|
-
end
|
|
8
|
-
expect(missing).to be_empty
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
describe '.find' do
|
|
12
|
-
it 'finds the constant with the given name' do
|
|
13
|
-
expect(described_class.find(:button)).to be(described_class::BUTTON)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
context 'constant not found' do
|
|
17
|
-
it 'returns a default' do
|
|
18
|
-
expect(described_class.find(:billy)).to be(described_class::ELEMENT)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
describe '#build' do
|
|
24
|
-
let(:selector) { Selector.new }
|
|
25
|
-
before do
|
|
26
|
-
expect(Selector).to receive(:find).with(:css).and_return(selector)
|
|
27
|
-
end
|
|
28
|
-
let(:locator) { { css: '.css' } }
|
|
29
|
-
|
|
30
|
-
it 'builds a query using the correct selector' do
|
|
31
|
-
expected = Query.new(locator.values)
|
|
32
|
-
expect(subject.build(locator)).to eq(expected)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it 'adds options to the result' do
|
|
36
|
-
expected = Query.new(locator.values.concat([:options]))
|
|
37
|
-
expect(subject.build(locator, :options)).to eq(expected)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
context 'selector support element type' do
|
|
41
|
-
subject do
|
|
42
|
-
described_class.new(:field)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it 'passes element type through to the selector' do
|
|
46
|
-
expect(selector).to receive(:build).with(:field, '.css').and_call_original
|
|
47
|
-
subject.build(locator)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
class QueryBuilder
|
|
54
|
-
describe BUTTON do
|
|
55
|
-
it 'has an element type' do
|
|
56
|
-
expect(described_class.type).to eq(:button)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
describe ELEMENT do
|
|
61
|
-
it ' does not has an element type' do
|
|
62
|
-
expect(described_class.type).to be_nil
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
describe LINK do
|
|
67
|
-
it 'has an element type' do
|
|
68
|
-
expect(described_class.type).to eq(:link)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
describe TEXT_FIELD do
|
|
73
|
-
it 'has an element type' do
|
|
74
|
-
expect(described_class.type).to eq(:field)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it 'the same as all form field types' do
|
|
78
|
-
expect(described_class).to eq(CHECKBOX).and eq(SELECT_LIST).and eq(RADIO).and eq(TEXTAREA)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
context 'integration' do
|
|
84
|
-
include_context :webapp_fixture
|
|
85
|
-
let(:capybara_session) { Capybara::Session.new(:rack_test, rack_app).tap { |s| s.visit('/elements') } }
|
|
86
|
-
|
|
87
|
-
it 'finds fields' do
|
|
88
|
-
query = QueryBuilder.find(:text_field).build(name: 'field_name')
|
|
89
|
-
expect(query.execute(capybara_session).tag_name).to eq('input')
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
it 'finds buttons' do
|
|
93
|
-
query = QueryBuilder.find(:button).build(text: 'a button')
|
|
94
|
-
expect(query.execute(capybara_session).tag_name).to eq('button')
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
it 'finds links' do
|
|
98
|
-
query = QueryBuilder.find(:link).build(text: 'a link')
|
|
99
|
-
expect(query.execute(capybara_session).tag_name).to eq('a')
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
it 'finds elements' do
|
|
103
|
-
query = QueryBuilder.find(:element).build(name: 'field_name')
|
|
104
|
-
expect(query.execute(capybara_session).tag_name).to eq('input')
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
# rubocop:disable Metrics/ModuleLength
|
|
2
|
-
module PageMagic
|
|
3
|
-
describe Matcher do
|
|
4
|
-
describe '#initialize' do
|
|
5
|
-
context 'no componentes specified' do
|
|
6
|
-
it 'raises an exeception' do
|
|
7
|
-
expect { described_class.new }.to raise_exception(MatcherInvalidException)
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
describe '#can_compute_uri?' do
|
|
12
|
-
context 'regex in path' do
|
|
13
|
-
it 'returns false' do
|
|
14
|
-
expect(described_class.new(//).can_compute_uri?).to eq(false)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
context 'regex in parameters' do
|
|
19
|
-
it 'returns false' do
|
|
20
|
-
expect(described_class.new(parameters: { param: // }).can_compute_uri?).to eq(false)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
context 'regexp in fragment' do
|
|
25
|
-
it 'returns false' do
|
|
26
|
-
expect(described_class.new(fragment: //).can_compute_uri?).to eq(false)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
context 'regexp not present' do
|
|
31
|
-
it 'returns true' do
|
|
32
|
-
expect(described_class.new('/').can_compute_uri?).to eq(true)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
describe 'compare' do
|
|
38
|
-
subject { described_class.new('/') }
|
|
39
|
-
context 'param 1 not nil' do
|
|
40
|
-
context 'param 2 not nil' do
|
|
41
|
-
context 'literal to fuzzy' do
|
|
42
|
-
it 'returns -1' do
|
|
43
|
-
expect(subject.instance_eval { compare('/', //) }).to eq(-1)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
context 'literal to literal' do
|
|
48
|
-
it 'returns 0' do
|
|
49
|
-
expect(subject.instance_eval { compare('/', '/') }).to eq(0)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
context 'fuzzy to fuzzy' do
|
|
54
|
-
it 'returns 0' do
|
|
55
|
-
expect(subject.instance_eval { compare(//, //) }).to eq(0)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
context 'fuzzy to literal' do
|
|
60
|
-
it 'returns 1' do
|
|
61
|
-
expect(subject.instance_eval { compare(//, '/') }).to eq(1)
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
context 'param2 is nil' do
|
|
67
|
-
it 'returns -1' do
|
|
68
|
-
expect(subject.instance_eval { compare('/', nil) }).to eq(-1)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
context 'param1 is nil' do
|
|
74
|
-
context 'param2 not nil' do
|
|
75
|
-
it 'returns 1' do
|
|
76
|
-
expect(subject.instance_eval { compare(nil, '/') }).to eq(1)
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
context 'param2 nil' do
|
|
81
|
-
it 'returns 0' do
|
|
82
|
-
expect(subject.instance_eval { compare(nil, nil) }).to eq(0)
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
describe 'compute_uri' do
|
|
89
|
-
context 'path present' do
|
|
90
|
-
it 'returns a uri' do
|
|
91
|
-
expect(described_class.new('/').compute_uri).to eq('/')
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
context 'params present' do
|
|
96
|
-
context '1 param' do
|
|
97
|
-
it 'returns a uri' do
|
|
98
|
-
expect(described_class.new(parameters: { a: 1 }).compute_uri).to eq('?a=1')
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
context 'more than 1 param' do
|
|
103
|
-
it 'returns a uri' do
|
|
104
|
-
expect(described_class.new(parameters: { a: 1, b: 2 }).compute_uri).to eq('?a=1&b=2')
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
context 'fragment present' do
|
|
110
|
-
it 'returns a uri' do
|
|
111
|
-
expect(described_class.new(fragment: 'fragment').compute_uri).to eq('#fragment')
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
describe '#matches?' do
|
|
117
|
-
let(:matching_url) { 'http://www.example.com/path?foo=bar#fragment' }
|
|
118
|
-
let(:incompatible_url) { 'http://www.example.com/mismatch?miss=match#mismatch' }
|
|
119
|
-
context 'path requirement exists' do
|
|
120
|
-
context 'path is literal' do
|
|
121
|
-
subject do
|
|
122
|
-
described_class.new('/path')
|
|
123
|
-
end
|
|
124
|
-
it 'returns true for an exact match' do
|
|
125
|
-
expect(subject.match?(matching_url)).to eq(true)
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
it 'returns false when not an exact match' do
|
|
129
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
context 'path is regexp' do
|
|
134
|
-
subject do
|
|
135
|
-
described_class.new(/\d/)
|
|
136
|
-
end
|
|
137
|
-
it 'returns true for a match on the regexp' do
|
|
138
|
-
expect(subject.match?('3')).to eq(true)
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
it 'returns false when regexp is not a match' do
|
|
142
|
-
expect(subject.match?('/mismatch')).to eq(false)
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
context 'query string requirement exists' do
|
|
148
|
-
context 'parameter requirement is a literal' do
|
|
149
|
-
subject do
|
|
150
|
-
described_class.new(parameters: { foo: 'bar' })
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
it 'returns true for a match' do
|
|
154
|
-
expect(subject.match?(matching_url)).to eq(true)
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
it 'returns false when regexp is not a match' do
|
|
158
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
context 'parameter requirement is a regexp' do
|
|
163
|
-
subject do
|
|
164
|
-
described_class.new(parameters: { foo: /b[a]r/ })
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
it 'returns true for a match on the regexp' do
|
|
168
|
-
expect(subject.match?(matching_url)).to eq(true)
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
it 'returns false when regexp is not a match' do
|
|
172
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
context 'fragment requirement exists' do
|
|
178
|
-
context 'fragment requirement is a literal' do
|
|
179
|
-
subject do
|
|
180
|
-
described_class.new(fragment: 'fragment')
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
it 'returns true for a match' do
|
|
184
|
-
expect(subject.match?(matching_url)).to eq(true)
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
it 'returns false when regexp is not a match' do
|
|
188
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
context 'fragment requirement is a regexp' do
|
|
193
|
-
subject do
|
|
194
|
-
described_class.new(fragment: /fragment/)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
it 'returns true for a match on the regexp' do
|
|
198
|
-
expect(subject.match?(matching_url)).to eq(true)
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
it 'returns false when regexp is not a match' do
|
|
202
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
describe '<=>' do
|
|
209
|
-
let(:literal_path_matcher) { '/' }
|
|
210
|
-
let(:fuzzy_path_matcher) { // }
|
|
211
|
-
let(:literal_parameter_matchers) { { param: 'value' } }
|
|
212
|
-
let(:fuzzy_parameter_matchers) { { param: // } }
|
|
213
|
-
|
|
214
|
-
let(:literal_fragment_matcher) { 'fragment' }
|
|
215
|
-
let(:fuzzy_fragment_matcher) { // }
|
|
216
|
-
|
|
217
|
-
context 'path' do
|
|
218
|
-
context 'path is of same class as path on other' do
|
|
219
|
-
subject(:a) { described_class.new('/a') }
|
|
220
|
-
subject(:b) { described_class.new('/b') }
|
|
221
|
-
it 'returns self and other as equivalent' do
|
|
222
|
-
expect(a <=> b).to eq(0)
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
context 'path on other is fuzzy' do
|
|
227
|
-
subject(:a) { described_class.new(literal_path_matcher) }
|
|
228
|
-
subject(:b) { described_class.new(fuzzy_path_matcher) }
|
|
229
|
-
it 'returns other as lesser' do
|
|
230
|
-
expect(a <=> b).to eq(-1)
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
context 'parameters' do
|
|
236
|
-
context 'parameters on self and other contain literal values' do
|
|
237
|
-
subject(:a) do
|
|
238
|
-
described_class.new(literal_path_matcher,
|
|
239
|
-
parameters: literal_parameter_matchers)
|
|
240
|
-
end
|
|
241
|
-
subject(:b) do
|
|
242
|
-
described_class.new(literal_path_matcher,
|
|
243
|
-
parameters: literal_parameter_matchers)
|
|
244
|
-
end
|
|
245
|
-
it 'returns self and other as equivalent' do
|
|
246
|
-
expect(a <=> b).to eq(0)
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
context 'parameters on self literal values and other has fuzzy values' do
|
|
251
|
-
subject(:a) do
|
|
252
|
-
described_class.new(literal_path_matcher,
|
|
253
|
-
parameters: literal_parameter_matchers)
|
|
254
|
-
end
|
|
255
|
-
subject(:b) do
|
|
256
|
-
described_class.new(literal_path_matcher,
|
|
257
|
-
parameters: fuzzy_parameter_matchers)
|
|
258
|
-
end
|
|
259
|
-
it 'returns other as lesser' do
|
|
260
|
-
expect(a <=> b).to eq(-1)
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
context 'parameters on self fuzzy values and other has literal values' do
|
|
264
|
-
subject(:a) do
|
|
265
|
-
described_class.new(literal_path_matcher,
|
|
266
|
-
parameters: fuzzy_parameter_matchers)
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
subject(:b) do
|
|
270
|
-
described_class.new(literal_path_matcher,
|
|
271
|
-
parameters: literal_parameter_matchers)
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
it 'returns other as greater' do
|
|
275
|
-
expect(a <=> b).to eq(1)
|
|
276
|
-
end
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
context 'fragment' do
|
|
281
|
-
context 'fragment is of same class as path on other' do
|
|
282
|
-
subject(:a) do
|
|
283
|
-
described_class.new(literal_path_matcher,
|
|
284
|
-
parameters: literal_parameter_matchers,
|
|
285
|
-
fragment: literal_fragment_matcher)
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
subject(:b) do
|
|
289
|
-
described_class.new(literal_path_matcher,
|
|
290
|
-
parameters: literal_parameter_matchers,
|
|
291
|
-
fragment: literal_fragment_matcher)
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
it 'returns self and other as equivalent' do
|
|
295
|
-
expect(a <=> b).to eq(0)
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
context 'fragment is literal on self and fuzzy on other' do
|
|
300
|
-
subject(:a) do
|
|
301
|
-
described_class.new(literal_path_matcher,
|
|
302
|
-
parameters: literal_parameter_matchers,
|
|
303
|
-
fragment: literal_fragment_matcher)
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
subject(:b) do
|
|
307
|
-
described_class.new(literal_path_matcher,
|
|
308
|
-
parameters: literal_parameter_matchers,
|
|
309
|
-
fragment: fuzzy_fragment_matcher)
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
it 'returns other as lesser' do
|
|
313
|
-
expect(a <=> b).to eq(-1)
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
context 'fragment is fuzzy on self and literal on other' do
|
|
318
|
-
subject(:a) do
|
|
319
|
-
described_class.new(literal_path_matcher,
|
|
320
|
-
parameters: literal_parameter_matchers,
|
|
321
|
-
fragment: fuzzy_fragment_matcher)
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
subject(:b) do
|
|
325
|
-
described_class.new(literal_path_matcher,
|
|
326
|
-
parameters: literal_parameter_matchers,
|
|
327
|
-
fragment: literal_fragment_matcher)
|
|
328
|
-
end
|
|
329
|
-
it 'returns other as lesser' do
|
|
330
|
-
expect(a <=> b).to eq(1)
|
|
331
|
-
end
|
|
332
|
-
end
|
|
333
|
-
end
|
|
334
|
-
end
|
|
335
|
-
end
|
|
336
|
-
end
|