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
@@ -1,78 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
describe
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
expect(&execution).to_not raise_exception
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'selector defined on the definition_class' do
|
20
|
-
it 'uses the selector on the class' do
|
21
|
-
definition_class = Class.new(Element) do
|
22
|
-
selector css: 'selector'
|
23
|
-
end
|
24
|
-
|
25
|
-
builder = described_class.new(definition_class: definition_class,
|
26
|
-
type: :element,
|
27
|
-
selector: nil)
|
28
|
-
|
29
|
-
expect(builder.selector).to eq(css: 'selector')
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'selector nil' do
|
34
|
-
it 'raises an error' do
|
35
|
-
execution = proc { described_class.new(definition_class: Element, type: :element, selector: nil) }
|
36
|
-
expect(&execution).to raise_exception UndefinedSelectorException, described_class::INVALID_SELECTOR_MSG
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'selector empty' do
|
41
|
-
it 'raises an error' do
|
42
|
-
execution = proc { described_class.new(definition_class: Element, type: :element, selector: {}) }
|
43
|
-
expect(&execution).to raise_exception UndefinedSelectorException, described_class::INVALID_SELECTOR_MSG
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'selector defined on definition_class' do
|
49
|
-
it 'uses the supplied selector' do
|
50
|
-
definition_class = Class.new(Element) do
|
51
|
-
selector css: 'selector'
|
52
|
-
end
|
53
|
-
|
54
|
-
expected_selector = { id: 'id' }
|
55
|
-
builder = described_class.new(definition_class: definition_class,
|
56
|
-
type: :element,
|
57
|
-
selector: expected_selector)
|
58
|
-
|
59
|
-
expect(builder.selector).to eq(expected_selector)
|
60
|
-
end
|
3
|
+
RSpec.describe PageMagic::ElementDefinitionBuilder do
|
4
|
+
describe '#build' do
|
5
|
+
it 'returns an instance of `definition_class`' do
|
6
|
+
options = { count: 1 }
|
7
|
+
builder = described_class.new(
|
8
|
+
definition_class: PageMagic::Element,
|
9
|
+
selector: PageMagic::Element::Selector.find(:xpath).build(:text_field, '//xpath', options: options)
|
10
|
+
)
|
11
|
+
|
12
|
+
allow_any_instance_of(PageMagic::Element::Query::SingleResult).to receive(:execute) do |_query, element, &block|
|
13
|
+
block.call(element)
|
61
14
|
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe 'build_query' do
|
65
|
-
it 'returns a capybara query' do
|
66
|
-
options = { count: 1 }
|
67
|
-
selector = { xpath: '//xpath' }
|
68
|
-
builder = described_class.new(definition_class: Element,
|
69
|
-
type: :text_field,
|
70
|
-
selector: selector,
|
71
|
-
element: Object.new,
|
72
|
-
options: options)
|
73
15
|
|
74
|
-
|
75
|
-
end
|
16
|
+
expect(builder.build(:capybara_object)).to have_attributes(browser_element: :capybara_object)
|
76
17
|
end
|
77
18
|
end
|
78
19
|
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe PageMagic::Element do
|
4
|
+
let(:described_class) do
|
5
|
+
Class.new(PageMagic::Element) # rubocop:disable RSpec/DescribedClass
|
6
|
+
end
|
7
|
+
|
8
|
+
it_behaves_like 'session accessor'
|
9
|
+
it_behaves_like 'element watcher'
|
10
|
+
it_behaves_like 'waiter'
|
11
|
+
it_behaves_like 'element locator'
|
12
|
+
|
13
|
+
describe '.after_events' do
|
14
|
+
context 'when a hook is registered' do
|
15
|
+
it 'returns that hook' do
|
16
|
+
hook = proc {}
|
17
|
+
described_class.after_events(&hook)
|
18
|
+
expect(described_class.after_events).to eq([described_class::DEFAULT_HOOK, hook])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when a hook is not registered' do
|
23
|
+
it 'returns the default hook' do
|
24
|
+
expect(described_class.after_events).to eq([described_class::DEFAULT_HOOK])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.before_events' do
|
30
|
+
context 'when a is hook registered' do
|
31
|
+
it 'returns that hook' do
|
32
|
+
hook = proc {}
|
33
|
+
described_class.before_events(&hook)
|
34
|
+
expect(described_class.before_events).to eq([described_class::DEFAULT_HOOK, hook])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when a hook is not registered' do
|
39
|
+
it 'returns the default hook' do
|
40
|
+
expect(described_class.before_events).to eq([described_class::DEFAULT_HOOK])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '.inherited' do
|
46
|
+
it 'copies before hooks on to the inheritor' do
|
47
|
+
before_hook = proc {}
|
48
|
+
described_class.before_events(&before_hook)
|
49
|
+
sub_class = Class.new(described_class)
|
50
|
+
expect(sub_class.before_events).to include(before_hook)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'copies after hooks on to the inheritor' do
|
54
|
+
after_hook = proc {}
|
55
|
+
described_class.after_events(&after_hook)
|
56
|
+
sub_class = Class.new(described_class)
|
57
|
+
expect(sub_class.after_events).to include(after_hook)
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when subclasses define their own elements' do
|
61
|
+
it 'puts the element definition on the sub class' do
|
62
|
+
custom_element = Class.new(described_class) do
|
63
|
+
text_field :form_field, id: 'field_id'
|
64
|
+
end
|
65
|
+
expect(custom_element.new(:page_element).element_definitions).to include(:form_field)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'does not put the definition on the parent class' do
|
69
|
+
Class.new(described_class) do
|
70
|
+
text_field :form_field, id: 'field_id'
|
71
|
+
end
|
72
|
+
expect(described_class.new(:page_element).element_definitions).not_to include(:form_field)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '.load' do
|
78
|
+
let(:page_source) do
|
79
|
+
<<-HTML
|
80
|
+
<div id='links'>
|
81
|
+
<a class='cta'>link text</a>
|
82
|
+
</div>
|
83
|
+
HTML
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'returns an instance that works against the supplied string' do
|
87
|
+
subject = Class.new(described_class) do
|
88
|
+
element(:links, id: 'links') { link(:cta, css: '.cta') }
|
89
|
+
end
|
90
|
+
expect(subject.load(page_source).links.cta.text).to eq('link text')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '.watch' do
|
95
|
+
it 'adds a before hook' do
|
96
|
+
watch_block = described_class.watch(:object_id).last
|
97
|
+
expect(described_class.before_events).to include(watch_block)
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'the before hook that is added' do
|
101
|
+
it 'contains a watcher' do
|
102
|
+
watch_block = described_class.watch(:object_id).last
|
103
|
+
instance = described_class.new(:element)
|
104
|
+
instance.instance_exec(&watch_block)
|
105
|
+
|
106
|
+
watcher = instance.watchers.first
|
107
|
+
expect(watcher.observed_value).to eq(instance.object_id)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'EVENT_TYPES' do
|
113
|
+
it 'creates methods for each of the event types' do
|
114
|
+
instance = described_class.new(:capybara_element)
|
115
|
+
missing = described_class::EVENT_TYPES.find_all { |event| !instance.respond_to?(event) }
|
116
|
+
expect(missing).to be_empty
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'when one of the methods are called' do
|
120
|
+
it 'calls the browser_element passing on all args' do
|
121
|
+
browser_element = instance_double(Capybara::Node::Actions)
|
122
|
+
allow(browser_element).to receive(:select)
|
123
|
+
described_class.new(browser_element).select :args
|
124
|
+
expect(browser_element).to have_received(:select).with(:args)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when the underlying capybara element does not respond to the method' do
|
129
|
+
it 'raises an error' do
|
130
|
+
expected_message = (described_class::EVENT_NOT_SUPPORTED_MSG % 'click')
|
131
|
+
browser_element = instance_double(Capybara::Node::Element)
|
132
|
+
page_element = described_class.new(browser_element)
|
133
|
+
expect { page_element.click }.to raise_error(PageMagic::NotSupportedException, expected_message)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe 'hooks' do
|
139
|
+
context 'when a method called from within a before_events hook' do
|
140
|
+
let(:page_element_class) do
|
141
|
+
Class.new(described_class) do
|
142
|
+
before_events do
|
143
|
+
call_in_before_events
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'delegates to the `PageMagic::Element`' do
|
149
|
+
capybara_button = instance_double(Capybara::Node::Element, click: true)
|
150
|
+
page_element = page_element_class.new(capybara_button)
|
151
|
+
allow(page_element).to receive(:call_in_before_events)
|
152
|
+
page_element.click
|
153
|
+
expect(page_element).to have_received(:call_in_before_events)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'when a method called from within a after_events hook' do
|
158
|
+
let(:page_element_class) do
|
159
|
+
Class.new(described_class) do
|
160
|
+
after_events do
|
161
|
+
call_in_after_events
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'delegates to the `PageMagic::Element`' do
|
167
|
+
capybara_button = instance_double(Capybara::Node::Element, click: true)
|
168
|
+
page_element = page_element_class.new(capybara_button)
|
169
|
+
allow(page_element).to receive(:call_in_after_events)
|
170
|
+
page_element.click
|
171
|
+
expect(page_element).to have_received(:call_in_after_events)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe '#initialize' do
|
177
|
+
it 'sets the parent element' do
|
178
|
+
described_class.parent_element(:page)
|
179
|
+
instance = described_class.new(:element)
|
180
|
+
expect(instance.parent_element).to eq(:page)
|
181
|
+
end
|
182
|
+
|
183
|
+
describe 'inherited items' do
|
184
|
+
it 'copies the before hooks' do
|
185
|
+
before_hook = proc {}
|
186
|
+
described_class.before_events(&before_hook)
|
187
|
+
|
188
|
+
instance = described_class.new(:element)
|
189
|
+
expect(instance.before_events).to include(before_hook)
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'copies the after hooks' do
|
193
|
+
after_hook = proc {}
|
194
|
+
described_class.after_events(&after_hook)
|
195
|
+
|
196
|
+
instance = described_class.new(:element)
|
197
|
+
expect(instance.after_events).to include(after_hook)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe '#method_missing' do
|
203
|
+
context 'when no sub element definition found' do
|
204
|
+
it 'delegates to the capybara element' do
|
205
|
+
instance = described_class.new(instance_double(Capybara::Node::Element, visible?: true))
|
206
|
+
expect(instance).to be_visible
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'when method not found on the capybara element' do
|
211
|
+
it 'calls method on parent element' do
|
212
|
+
element = Struct.new(:parent_method).new(:called)
|
213
|
+
described_class.parent_element(element)
|
214
|
+
instance = described_class.new(:capybara_element)
|
215
|
+
expect(instance.parent_method).to eq(:called)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'when the method is not found on parent' do
|
220
|
+
it 'throws and exception' do
|
221
|
+
described_class.parent_element(:parent_element)
|
222
|
+
instance = described_class.new(:capybara_element)
|
223
|
+
expect { instance.bobbins }.to raise_exception NoMethodError
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe '#respond_to?' do
|
229
|
+
subject(:instance) do
|
230
|
+
capybara_element = Struct.new(:element_method).new(:called)
|
231
|
+
Class.new(described_class) do
|
232
|
+
element :sub_element, css: '.sub-element'
|
233
|
+
end.new(capybara_element)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'checks for methods on self' do
|
237
|
+
expect(instance).to respond_to(:session)
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'checks against registered elements' do
|
241
|
+
expect(instance).to respond_to(:sub_element)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'checks for the method of the browser_element' do
|
245
|
+
expect(instance).to respond_to(:element_method)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe '#session' do
|
250
|
+
it 'has a handle to the session' do
|
251
|
+
described_class.parent_element(instance_double(PageMagic::InstanceMethods, session: :session))
|
252
|
+
instance = described_class.new(:capybara_element)
|
253
|
+
expect(instance.session).to eq(:session)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe PageMagic::Elements::Config do
|
4
|
+
describe '.build' do
|
5
|
+
it 'sets of the type' do
|
6
|
+
options = described_class.build([], :field)
|
7
|
+
expect(options.type).to eq(:field)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'sets the options' do
|
11
|
+
user_options = { option: 1 }
|
12
|
+
options = described_class.build([{ id: 'child' }, user_options], :field)
|
13
|
+
expect(options.options).to eq(user_options)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'name' do
|
17
|
+
context 'when supplied' do
|
18
|
+
it 'sets it' do
|
19
|
+
options = described_class.build([:name], :field)
|
20
|
+
expect(options.name).to eq(:name)
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when an element class supplied' do
|
24
|
+
it 'uses the supplied name' do
|
25
|
+
element_class = Class.new(PageMagic::Element) do
|
26
|
+
selector({ css: 'class' })
|
27
|
+
def self.name
|
28
|
+
'PageSection'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
options = described_class.build([:supplied_name, element_class], :field)
|
33
|
+
expect(options.name).to eq(:supplied_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when not supplied' do
|
39
|
+
context 'when an element class supplied' do
|
40
|
+
it 'uses the name of the class' do
|
41
|
+
element_class = Class.new(PageMagic::Element) do
|
42
|
+
selector({ css: 'class' })
|
43
|
+
def self.name
|
44
|
+
'PageSection'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
options = described_class.build([element_class], :field)
|
49
|
+
expect(options.name).to eq(:page_section)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'selector' do
|
56
|
+
context 'when selector supplied' do
|
57
|
+
it 'sets the selector' do
|
58
|
+
options = described_class.build([{ id: 'child' }], :field)
|
59
|
+
expect(options.selector).to eq(PageMagic::Element::Selector.find(:id).build(:field, 'child'))
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when page_element class supplied' do
|
63
|
+
it 'uses the selector on the class' do
|
64
|
+
expected_selector = { css: 'class' }
|
65
|
+
element_class = Class.new(PageMagic::Element) do
|
66
|
+
selector({ css: 'class' })
|
67
|
+
def self.name
|
68
|
+
'PageSection'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
options = described_class.build([element_class, expected_selector], :field)
|
72
|
+
|
73
|
+
expect(options.selector).to eq(PageMagic::Element::Selector.find(:css).build(:field, 'class'))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when no selector supplied' do
|
79
|
+
context 'when page_element class supplied' do
|
80
|
+
it 'uses the selector on the class' do
|
81
|
+
element_class = Class.new(PageMagic::Element) do
|
82
|
+
selector({ css: 'class' })
|
83
|
+
|
84
|
+
def self.name
|
85
|
+
'PageSection'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
options = described_class.build([element_class], :field)
|
89
|
+
|
90
|
+
expect(options.selector).to eq(PageMagic::Element::Selector.find(:css).build(:field, 'class'))
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'sets prefetched options' do
|
97
|
+
options = described_class.build(%i[page_section prefetched_element], :field)
|
98
|
+
expect(options.element).to eq(:prefetched_element)
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'complex elements' do
|
102
|
+
let!(:element_class) do
|
103
|
+
Class.new(PageMagic::Element) do
|
104
|
+
def self.name
|
105
|
+
'PageSection'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '.validate!' do
|
113
|
+
let(:options) do
|
114
|
+
{
|
115
|
+
type: :type,
|
116
|
+
selector: { css: 'css' },
|
117
|
+
element: :object,
|
118
|
+
element_class: Class.new(PageMagic::Element)
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
describe 'selector' do
|
123
|
+
context 'when nil' do
|
124
|
+
context 'and prefetched `element` is nil' do
|
125
|
+
it 'raise an error' do
|
126
|
+
subject = described_class.new(options.except(:selector, :element))
|
127
|
+
expect { subject.validate! }.to raise_exception(PageMagic::InvalidConfigurationException,
|
128
|
+
described_class::INVALID_SELECTOR_MSG)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'when `element` is not nil' do
|
133
|
+
it 'does not raise an error' do
|
134
|
+
subject = described_class.new(options.except(:selector))
|
135
|
+
expect { subject.validate! }.not_to raise_exception
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'when is empty hash' do
|
141
|
+
it 'raises an error' do
|
142
|
+
subject = described_class.new(options.update(selector: {}).except(:element))
|
143
|
+
expect { subject.validate! }.to raise_exception(PageMagic::InvalidConfigurationException,
|
144
|
+
described_class::INVALID_SELECTOR_MSG)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'when defined on both class and as parameter' do
|
149
|
+
it 'uses the supplied selector' do
|
150
|
+
element_class = Class.new(PageMagic::Element) do
|
151
|
+
selector css: 'selector'
|
152
|
+
end
|
153
|
+
|
154
|
+
subject = described_class.new(options.update(element_class: element_class))
|
155
|
+
expect { subject.validate! }.not_to raise_exception
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'when type nil' do
|
161
|
+
it 'raise an error' do
|
162
|
+
subject = described_class.new(options.except(:type))
|
163
|
+
expect { subject.validate! }.to raise_exception(PageMagic::InvalidConfigurationException,
|
164
|
+
described_class::TYPE_REQUIRED_MESSAGE)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe '`element_class`' do
|
169
|
+
context 'when nil' do
|
170
|
+
it 'raise and error' do
|
171
|
+
subject = described_class.new(options.except(:element_class))
|
172
|
+
expect { subject.validate! }.to raise_exception(PageMagic::InvalidConfigurationException,
|
173
|
+
described_class::INVALID_ELEMENT_CLASS_MSG)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'not a type of `PageMagic::Element`' do
|
178
|
+
it 'raise and error' do
|
179
|
+
subject = described_class.new(options.update(element_class: Object))
|
180
|
+
expect { subject.validate! }.to raise_exception(PageMagic::InvalidConfigurationException,
|
181
|
+
described_class::INVALID_ELEMENT_CLASS_MSG)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '#selector' do
|
188
|
+
it 'returns a selector' do
|
189
|
+
input_options = {
|
190
|
+
type: :type,
|
191
|
+
selector: { css: 'css' },
|
192
|
+
options: { a: :b },
|
193
|
+
element: :object,
|
194
|
+
element_class: Class.new(PageMagic::Element)
|
195
|
+
}
|
196
|
+
options = described_class.new(input_options)
|
197
|
+
expect(options.selector).to eq(PageMagic::Element::Selector.find(:css).build(:type, 'css', options: { a: :b }))
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|