page_magic 1.0.0.alpha21 → 1.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 +4 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +9 -7
- data/README.md +181 -78
- data/VERSION +1 -1
- data/lib/page_magic/class_methods.rb +8 -7
- data/lib/page_magic/driver.rb +7 -7
- data/lib/page_magic/drivers.rb +6 -6
- data/lib/page_magic/element/locators.rb +24 -0
- data/lib/page_magic/element/query.rb +1 -0
- data/lib/page_magic/element/selector.rb +11 -9
- data/lib/page_magic/element.rb +47 -85
- data/lib/page_magic/element_context.rb +25 -5
- data/lib/page_magic/element_definition_builder.rb +39 -0
- data/lib/page_magic/elements.rb +24 -27
- data/lib/page_magic/exceptions.rb +11 -8
- data/lib/page_magic/instance_methods.rb +23 -21
- data/lib/page_magic/session.rb +43 -44
- data/lib/page_magic/session_methods.rb +28 -0
- data/lib/page_magic/wait_methods.rb +18 -0
- data/lib/page_magic/watcher.rb +41 -0
- data/lib/page_magic/watchers.rb +43 -0
- data/lib/page_magic.rb +13 -9
- data/spec/element_spec.rb +58 -160
- data/spec/page_magic/class_methods_spec.rb +7 -6
- data/spec/page_magic/driver_spec.rb +14 -13
- data/spec/page_magic/drivers_spec.rb +7 -6
- data/spec/page_magic/element/locators_spec.rb +33 -0
- data/spec/page_magic/element/query_spec.rb +44 -19
- data/spec/page_magic/element/selector_spec.rb +45 -3
- data/spec/page_magic/element_context_spec.rb +41 -11
- data/spec/page_magic/element_definition_builder_spec.rb +76 -0
- data/spec/page_magic/elements_spec.rb +94 -141
- data/spec/page_magic/instance_methods_spec.rb +15 -10
- data/spec/page_magic/session_methods_spec.rb +36 -0
- data/spec/page_magic/session_spec.rb +78 -79
- data/spec/page_magic/wait_methods_spec.rb +41 -0
- data/spec/page_magic/watchers_spec.rb +74 -0
- data/spec/page_magic_spec.rb +9 -9
- data/spec/spec_helper.rb +1 -0
- data/spec/support/shared_contexts/nested_elements_html_context.rb +16 -0
- data/spec/support/shared_contexts/{webapp_context.rb → webapp_fixture_context.rb} +0 -0
- data/spec/support/shared_examples.rb +25 -0
- data/spec/watcher_spec.rb +49 -0
- metadata +23 -11
- data/lib/page_magic/element/method_observer.rb +0 -20
- data/spec/member_methods_spec.rb +0 -2
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'page_magic/watcher'
|
|
2
|
+
|
|
3
|
+
module PageMagic
|
|
4
|
+
# module Watchers - contains methods for adding watchers and checking them
|
|
5
|
+
module Watchers
|
|
6
|
+
ELEMENT_MISSING_MSG = 'Unable to defined watcher: Element or method with the name %s can not be found'
|
|
7
|
+
|
|
8
|
+
# @param [Symbol] name - the name of the watcher
|
|
9
|
+
# @return [Boolean] true if a change is detected
|
|
10
|
+
def changed?(name)
|
|
11
|
+
watched_element = watcher(name)
|
|
12
|
+
watched_element.last != watched_element.check(self).last
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# register a new watcher
|
|
16
|
+
# @param [Object] name of the watcher/element
|
|
17
|
+
# @param [Symbol] method - the method on the watched element to check
|
|
18
|
+
# @yieldreturn [Object] the value that should be checked
|
|
19
|
+
# @example
|
|
20
|
+
# watch(:price, :text)
|
|
21
|
+
# @example
|
|
22
|
+
# watch(:something) do
|
|
23
|
+
# # more complicated code to get value
|
|
24
|
+
# end
|
|
25
|
+
def watch(name, method = nil, &block)
|
|
26
|
+
fail ElementMissingException, (ELEMENT_MISSING_MSG % name) unless block || respond_to?(name)
|
|
27
|
+
watched_element = block ? Watcher.new(name, &block) : Watcher.new(name, method)
|
|
28
|
+
watchers << watched_element.check(self)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# retrieve a watcher given its name
|
|
32
|
+
# @param [Symbol] name the name of the watcher
|
|
33
|
+
# @return [Watcher] watcher with the given name
|
|
34
|
+
def watcher(name)
|
|
35
|
+
watchers.find { |watcher| watcher.name == name }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Array] registered watchers
|
|
39
|
+
def watchers
|
|
40
|
+
@watchers ||= []
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/page_magic.rb
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}")
|
|
2
2
|
require 'capybara'
|
|
3
3
|
require 'page_magic/exceptions'
|
|
4
|
+
require 'page_magic/wait_methods'
|
|
5
|
+
require 'page_magic/watchers'
|
|
4
6
|
require 'page_magic/session'
|
|
5
|
-
require 'page_magic/
|
|
7
|
+
require 'page_magic/session_methods'
|
|
6
8
|
require 'page_magic/elements'
|
|
7
|
-
require 'page_magic/class_methods'
|
|
8
9
|
require 'page_magic/element_context'
|
|
9
10
|
require 'page_magic/element'
|
|
11
|
+
require 'page_magic/class_methods'
|
|
12
|
+
require 'page_magic/instance_methods'
|
|
10
13
|
require 'page_magic/drivers'
|
|
11
14
|
|
|
12
15
|
# module PageMagic - PageMagic is an api for modelling pages in a website.
|
|
13
16
|
module PageMagic
|
|
14
17
|
class << self
|
|
18
|
+
# @return [Drivers] registered drivers
|
|
15
19
|
def drivers
|
|
16
20
|
@drivers ||= Drivers.new.tap(&:load)
|
|
17
21
|
end
|
|
18
22
|
|
|
23
|
+
def included(clazz)
|
|
24
|
+
clazz.class_eval do
|
|
25
|
+
include(InstanceMethods)
|
|
26
|
+
extend(Elements, ClassMethods)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
19
30
|
# Visit this page based on the class level registered url
|
|
20
31
|
# @param [Object] application rack application (optional)
|
|
21
32
|
# @param [Symbol] browser name of browser
|
|
@@ -32,12 +43,5 @@ module PageMagic
|
|
|
32
43
|
|
|
33
44
|
Session.new(Capybara::Session.new(browser, application), url)
|
|
34
45
|
end
|
|
35
|
-
|
|
36
|
-
def included(clazz)
|
|
37
|
-
clazz.class_eval do
|
|
38
|
-
include(InstanceMethods)
|
|
39
|
-
extend(Elements, ClassMethods)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
46
|
end
|
|
43
47
|
end
|
data/spec/element_spec.rb
CHANGED
|
@@ -14,6 +14,17 @@ module PageMagic
|
|
|
14
14
|
|
|
15
15
|
let(:page) { session.current_page }
|
|
16
16
|
|
|
17
|
+
# let!(:browser) { double('browser') }
|
|
18
|
+
|
|
19
|
+
subject do
|
|
20
|
+
described_class.new(:page_element, page)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it_behaves_like 'session accessor'
|
|
24
|
+
it_behaves_like 'element watcher'
|
|
25
|
+
it_behaves_like 'waiter'
|
|
26
|
+
it_behaves_like 'element locator'
|
|
27
|
+
|
|
17
28
|
describe 'inheriting' do
|
|
18
29
|
it 'lets you create custom elements' do
|
|
19
30
|
custom_element = Class.new(described_class) do
|
|
@@ -32,185 +43,58 @@ module PageMagic
|
|
|
32
43
|
end
|
|
33
44
|
end
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
describe '#respond_to?' do
|
|
41
|
-
subject do
|
|
42
|
-
described_class.new(:name,
|
|
43
|
-
Object.new,
|
|
44
|
-
type: :element,
|
|
45
|
-
prefetched_browser_element: double(element_method: '')) do
|
|
46
|
-
element :sub_element, css: '.sub-element'
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
it 'checks for methods on self' do
|
|
50
|
-
expect(subject.respond_to?(:session)).to eq(true)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
it 'checks against registered elements' do
|
|
54
|
-
expect(subject.respond_to?(:sub_element)).to eq(true)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
it 'checks for the method of the browser_element' do
|
|
58
|
-
expect(subject.respond_to?(:element_method)).to eq(true)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
describe '#browser_element' do
|
|
63
|
-
let!(:browser) { double('browser') }
|
|
64
|
-
|
|
65
|
-
context 'options supplied to selector' do
|
|
66
|
-
it 'passes them on to the cappybara finder method' do
|
|
67
|
-
options = { count: 1 }
|
|
68
|
-
xpath_selector = '//div/input'
|
|
69
|
-
expect(page.session.raw_session).to receive(:find).with(:xpath, xpath_selector, options)
|
|
70
|
-
described_class.new(:my_input,
|
|
71
|
-
page,
|
|
72
|
-
type: :text_field,
|
|
73
|
-
selector: { xpath: xpath_selector }.merge(options)).browser_element
|
|
46
|
+
describe 'EVENT_TYPES' do
|
|
47
|
+
context 'methods created' do
|
|
48
|
+
it 'creates methods for each of the event types' do
|
|
49
|
+
missing = described_class::EVENT_TYPES.find_all { |event| !subject.respond_to?(event) }
|
|
50
|
+
expect(missing).to be_empty
|
|
74
51
|
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it 'should find by xpath' do
|
|
78
|
-
element = described_class.new(:my_input,
|
|
79
|
-
page,
|
|
80
|
-
type: :text_field,
|
|
81
|
-
selector: { xpath: '//div/label/input' }).browser_element
|
|
82
|
-
expect(element.value).to eq('filled in')
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it 'should locate an element using its id' do
|
|
86
|
-
element = described_class.new(:my_input,
|
|
87
|
-
page,
|
|
88
|
-
type: :text_field,
|
|
89
|
-
selector: { id: 'field_id' }).browser_element
|
|
90
|
-
expect(element.value).to eq('filled in')
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it 'should locate an element using its name' do
|
|
94
|
-
element = described_class.new(:my_input,
|
|
95
|
-
page,
|
|
96
|
-
type: :text_field,
|
|
97
|
-
selector: { name: 'field_name' }).browser_element
|
|
98
|
-
expect(element.value).to eq('filled in')
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
it 'should locate an element using its label' do
|
|
102
|
-
element = described_class.new(:my_input,
|
|
103
|
-
page,
|
|
104
|
-
type: :text_field,
|
|
105
|
-
selector: { label: 'enter text' }).browser_element
|
|
106
|
-
expect(element[:id]).to eq('field_id')
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
it 'should locate an element using css' do
|
|
110
|
-
element = described_class.new(:my_input,
|
|
111
|
-
page,
|
|
112
|
-
type: :text_field,
|
|
113
|
-
selector: { css: "input[name='field_name']" }).browser_element
|
|
114
|
-
expect(element[:id]).to eq('field_id')
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
it 'should return a prefetched value' do
|
|
118
|
-
element = described_class.new(:help, page, type: :link, prefetched_browser_element: :prefetched_object)
|
|
119
|
-
expect(element.browser_element).to eq(:prefetched_object)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
it 'should raise errors for unsupported criteria' do
|
|
123
|
-
element = described_class.new(:my_link,
|
|
124
|
-
page,
|
|
125
|
-
type: :link,
|
|
126
|
-
selector: { unsupported: '' })
|
|
127
|
-
|
|
128
|
-
expect { element.browser_element }.to raise_error(PageMagic::UnsupportedCriteriaException)
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
context 'text selector' do
|
|
132
|
-
it 'should locate a link' do
|
|
133
|
-
element = described_class.new(:my_link,
|
|
134
|
-
page,
|
|
135
|
-
type: :link,
|
|
136
|
-
selector: { text: 'link in a form' }).browser_element
|
|
137
|
-
expect(element[:id]).to eq('form_link')
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
it 'should locate a button' do
|
|
141
|
-
element = described_class.new(:my_button, page, type: :button, selector: { text: 'a button' }).browser_element
|
|
142
|
-
expect(element[:id]).to eq('form_button')
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
52
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
element :thing, text: 'text'
|
|
53
|
+
context 'method called' do
|
|
54
|
+
let(:browser_element) { instance_double(Capybara::Node::Element) }
|
|
55
|
+
subject do
|
|
56
|
+
described_class.new(browser_element, page)
|
|
152
57
|
end
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
context 'method defined' do
|
|
160
|
-
subject do
|
|
161
|
-
described_class.new(:my_link, :page, type: :link, selector: { text: 'my link' }) do
|
|
162
|
-
def custom_method
|
|
163
|
-
end
|
|
58
|
+
it 'calls the browser_element passing on all args' do
|
|
59
|
+
expect(browser_element).to receive(:select).with(:args)
|
|
60
|
+
subject.select :args
|
|
164
61
|
end
|
|
165
62
|
end
|
|
166
|
-
|
|
167
|
-
it 'returns true' do
|
|
168
|
-
expect(subject.section?).to eq(true)
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
context 'neither method or elements defined' do
|
|
173
|
-
subject do
|
|
174
|
-
described_class.new(:my_link, :page, type: :link, selector: { text: 'my link' })
|
|
175
|
-
end
|
|
176
|
-
it 'returns false' do
|
|
177
|
-
expect(subject.section?).to eq(false)
|
|
178
|
-
end
|
|
179
63
|
end
|
|
180
64
|
end
|
|
181
65
|
|
|
182
|
-
describe '
|
|
183
|
-
it '
|
|
184
|
-
|
|
66
|
+
describe '#initialize' do
|
|
67
|
+
it 'sets the parent element' do
|
|
68
|
+
instance = described_class.new(page, :parent_page_element)
|
|
69
|
+
expect(instance.parent_page_element).to eq(:parent_page_element)
|
|
185
70
|
end
|
|
186
71
|
end
|
|
187
72
|
|
|
188
73
|
describe 'hooks' do
|
|
189
74
|
subject do
|
|
190
|
-
|
|
75
|
+
Class.new(described_class) do
|
|
191
76
|
before_events do
|
|
192
77
|
call_in_before_hook
|
|
193
78
|
end
|
|
194
|
-
end
|
|
79
|
+
end.new(double('button', click: true), page)
|
|
195
80
|
end
|
|
196
81
|
context 'method called in before hook' do
|
|
197
82
|
it 'calls methods on the page element' do
|
|
198
|
-
expect(page.browser).to receive(:find).and_return(double('button', click: true))
|
|
199
83
|
expect(subject).to receive(:call_in_before_hook)
|
|
200
84
|
subject.click
|
|
201
85
|
end
|
|
202
86
|
end
|
|
203
87
|
|
|
204
|
-
context 'method called in
|
|
88
|
+
context 'method called in after hook' do
|
|
205
89
|
subject do
|
|
206
|
-
|
|
90
|
+
Class.new(described_class) do
|
|
207
91
|
after_events do
|
|
208
92
|
call_in_after_hook
|
|
209
93
|
end
|
|
210
|
-
end
|
|
94
|
+
end.new(double('button', click: true), page)
|
|
211
95
|
end
|
|
96
|
+
|
|
212
97
|
it 'calls methods on the page element' do
|
|
213
|
-
expect(page.browser).to receive(:find).and_return(double('button', click: true))
|
|
214
98
|
expect(subject).to receive(:call_in_after_hook)
|
|
215
99
|
subject.click
|
|
216
100
|
end
|
|
@@ -230,22 +114,36 @@ module PageMagic
|
|
|
230
114
|
expect(page.form_by_css).to be_visible
|
|
231
115
|
end
|
|
232
116
|
|
|
233
|
-
context 'method not on capybara browser element' do
|
|
234
|
-
it 'uses the parent page element' do
|
|
235
|
-
page_class.class_eval do
|
|
236
|
-
def parent_method
|
|
237
|
-
:called
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
expect(page.form_by_css.parent_method).to eq(:called)
|
|
241
|
-
end
|
|
242
|
-
end
|
|
243
|
-
|
|
244
117
|
context 'no element definition and not a capybara method' do
|
|
245
118
|
it 'throws and exception' do
|
|
246
119
|
expect { page.form_by_css.bobbins }.to raise_exception NoMethodError
|
|
247
120
|
end
|
|
248
121
|
end
|
|
249
122
|
end
|
|
123
|
+
|
|
124
|
+
describe '#respond_to?' do
|
|
125
|
+
subject do
|
|
126
|
+
Class.new(described_class) do
|
|
127
|
+
element :sub_element, css: '.sub-element'
|
|
128
|
+
end.new(double(element_method: ''), :parent_page_element)
|
|
129
|
+
end
|
|
130
|
+
it 'checks for methods on self' do
|
|
131
|
+
expect(subject.respond_to?(:session)).to eq(true)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'checks against registered elements' do
|
|
135
|
+
expect(subject.respond_to?(:sub_element)).to eq(true)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'checks for the method of the browser_element' do
|
|
139
|
+
expect(subject.respond_to?(:element_method)).to eq(true)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
describe '#session' do
|
|
144
|
+
it 'should have a handle to the session' do
|
|
145
|
+
expect(subject.session).to eq(page.session)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
250
148
|
end
|
|
251
149
|
end
|
|
@@ -6,12 +6,6 @@ module PageMagic
|
|
|
6
6
|
clazz.include(InstanceMethods)
|
|
7
7
|
end
|
|
8
8
|
end
|
|
9
|
-
describe '#url' do
|
|
10
|
-
it 'get/sets a value' do
|
|
11
|
-
subject.url(:url)
|
|
12
|
-
expect(subject.url).to eq(:url)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
9
|
|
|
16
10
|
describe 'on_load' do
|
|
17
11
|
context 'block not set' do
|
|
@@ -29,6 +23,13 @@ module PageMagic
|
|
|
29
23
|
end
|
|
30
24
|
end
|
|
31
25
|
|
|
26
|
+
describe '#url' do
|
|
27
|
+
it 'get/sets a value' do
|
|
28
|
+
subject.url(:url)
|
|
29
|
+
expect(subject.url).to eq(:url)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
32
33
|
describe '#visit' do
|
|
33
34
|
include_context :webapp_fixture
|
|
34
35
|
it 'passes all options to create an active session on the registered url' do
|
|
@@ -6,19 +6,6 @@ module PageMagic
|
|
|
6
6
|
described_class.new :custom_browser
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
describe '#supports?' do
|
|
10
|
-
context 'browser is in supported browsers' do
|
|
11
|
-
it 'returns true' do
|
|
12
|
-
expect(subject.support?(:custom_browser)).to eq(true)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
context 'browser is not in supported browsers' do
|
|
17
|
-
it 'returns false' do
|
|
18
|
-
expect(subject.support?(:unsupported_browser)).to eq(false)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
9
|
describe '#build' do
|
|
23
10
|
it 'returns the result of the block passed to the driver class constructor' do
|
|
24
11
|
subject = described_class.new(:custom_browser)do
|
|
@@ -37,5 +24,19 @@ module PageMagic
|
|
|
37
24
|
subject.build(:rack_app, options: :options, browser: :browser)
|
|
38
25
|
end
|
|
39
26
|
end
|
|
27
|
+
|
|
28
|
+
describe '#supports?' do
|
|
29
|
+
context 'browser is in supported browsers' do
|
|
30
|
+
it 'returns true' do
|
|
31
|
+
expect(subject.support?(:custom_browser)).to eq(true)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'browser is not in supported browsers' do
|
|
36
|
+
it 'returns false' do
|
|
37
|
+
expect(subject.support?(:unsupported_browser)).to eq(false)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
40
41
|
end
|
|
41
42
|
end
|
|
@@ -3,12 +3,6 @@ module PageMagic
|
|
|
3
3
|
describe Drivers do
|
|
4
4
|
subject { described_class.new }
|
|
5
5
|
let(:expected_driver) { Driver.new(:browser_driver) }
|
|
6
|
-
describe '#register' do
|
|
7
|
-
it 'stores the driver' do
|
|
8
|
-
subject.register expected_driver
|
|
9
|
-
expect(subject.all).to eq([expected_driver])
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
6
|
|
|
13
7
|
describe '#find' do
|
|
14
8
|
it 'returns the registered driver' do
|
|
@@ -34,5 +28,12 @@ module PageMagic
|
|
|
34
28
|
expect(subject.find(:custom_browser)).to be(::CustomDriver)
|
|
35
29
|
end
|
|
36
30
|
end
|
|
31
|
+
|
|
32
|
+
describe '#register' do
|
|
33
|
+
it 'stores the driver' do
|
|
34
|
+
subject.register expected_driver
|
|
35
|
+
expect(subject.all).to eq([expected_driver])
|
|
36
|
+
end
|
|
37
|
+
end
|
|
37
38
|
end
|
|
38
39
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module PageMagic
|
|
2
|
+
class Element
|
|
3
|
+
describe Locators do
|
|
4
|
+
subject(:element_clazz) do
|
|
5
|
+
Class.new do
|
|
6
|
+
extend(Elements)
|
|
7
|
+
include(Locators)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
subject { element_clazz.new }
|
|
11
|
+
|
|
12
|
+
describe '#element_by_name' do
|
|
13
|
+
it 'returns the required element' do
|
|
14
|
+
selector = { id: 'child' }
|
|
15
|
+
element_clazz.element :child1, selector
|
|
16
|
+
element_clazz.element :child2, id: 'child 2'
|
|
17
|
+
|
|
18
|
+
expected_builder = ElementDefinitionBuilder.new(definition_class: Element, type: :element, selector: selector)
|
|
19
|
+
|
|
20
|
+
expect(subject.element_by_name(:child1)).to eq(expected_builder)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context 'element not found' do
|
|
24
|
+
it 'raises an error' do
|
|
25
|
+
expected_message = (described_class::ELEMENT_NOT_DEFINED_MSG % :child)
|
|
26
|
+
command = proc { subject.element_by_name(:child) }
|
|
27
|
+
expect(&command).to raise_exception ElementMissingException, expected_message
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
module PageMagic
|
|
2
2
|
class Element
|
|
3
3
|
describe Query do
|
|
4
|
+
it 'has a predefined query for each element type' do
|
|
5
|
+
missing = PageMagic::Elements::TYPES.find_all do |type|
|
|
6
|
+
!described_class.constants.include?(type.upcase.to_sym)
|
|
7
|
+
end
|
|
8
|
+
expect(missing).to be_empty
|
|
9
|
+
end
|
|
10
|
+
|
|
4
11
|
describe '.find' do
|
|
5
12
|
it 'finds the constant with the given name' do
|
|
6
13
|
expect(Query.find(:button)).to be(described_class::BUTTON)
|
|
@@ -42,35 +49,53 @@ module PageMagic
|
|
|
42
49
|
end
|
|
43
50
|
|
|
44
51
|
class Query
|
|
45
|
-
describe
|
|
46
|
-
it 'has
|
|
47
|
-
|
|
48
|
-
!Query.constants.include?(type.upcase.to_sym)
|
|
49
|
-
end
|
|
50
|
-
expect(missing).to be_empty
|
|
52
|
+
describe BUTTON do
|
|
53
|
+
it 'has an element type' do
|
|
54
|
+
expect(described_class.type).to eq(:button)
|
|
51
55
|
end
|
|
56
|
+
end
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
end
|
|
57
|
-
it 'uses the same query for all form field types' do
|
|
58
|
-
expect(TEXT_FIELD).to eq(CHECKBOX).and eq(SELECT_LIST).and eq(RADIOS).and eq(TEXTAREA)
|
|
59
|
-
end
|
|
58
|
+
describe ELEMENT do
|
|
59
|
+
it ' does not has an element type' do
|
|
60
|
+
expect(described_class.type).to be_nil
|
|
60
61
|
end
|
|
62
|
+
end
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
describe LINK do
|
|
65
|
+
it 'has an element type' do
|
|
66
|
+
expect(described_class.type).to eq(:link)
|
|
64
67
|
end
|
|
68
|
+
end
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
70
|
+
describe TEXT_FIELD do
|
|
71
|
+
it 'has an element type' do
|
|
72
|
+
expect(described_class.type).to eq(:field)
|
|
68
73
|
end
|
|
69
74
|
|
|
70
|
-
it '
|
|
71
|
-
expect(
|
|
75
|
+
it 'the same as all form field types' do
|
|
76
|
+
expect(described_class).to eq(CHECKBOX).and eq(SELECT_LIST).and eq(RADIOS).and eq(TEXTAREA)
|
|
72
77
|
end
|
|
73
78
|
end
|
|
74
79
|
end
|
|
80
|
+
|
|
81
|
+
context 'integration' do
|
|
82
|
+
include_context :webapp_fixture
|
|
83
|
+
let(:capybara_session) { Capybara::Session.new(:rack_test, rack_app).tap { |s| s.visit('/elements') } }
|
|
84
|
+
it 'finds fields' do
|
|
85
|
+
expect(capybara_session.all(*Query.find(:text_field).build(name: 'field_name')).size).to eq(1)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'finds buttons' do
|
|
89
|
+
expect(capybara_session.all(*Query.find(:button).build(text: 'a button')).size).to eq(1)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'finds links' do
|
|
93
|
+
expect(capybara_session.all(*Query.find(:link).build(text: 'a link')).size).to eq(1)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'finds elements' do
|
|
97
|
+
expect(capybara_session.all(*Query.find(:element).build(name: 'field_name')).size).to eq(1)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
75
100
|
end
|
|
76
101
|
end
|
|
@@ -18,6 +18,16 @@ module PageMagic
|
|
|
18
18
|
expect(subject.build(:field, :locator)).to eq([:locator])
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
context 'exact is set to true' do
|
|
22
|
+
subject do
|
|
23
|
+
described_class.new(exact: true)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'includes the requirement for the match to be exact' do
|
|
27
|
+
expect(subject.build(:field, :locator)).to include(exact: true)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
21
31
|
context 'supports_type flag set to true in constructor' do
|
|
22
32
|
subject do
|
|
23
33
|
described_class.new(supports_type: true)
|
|
@@ -48,12 +58,19 @@ module PageMagic
|
|
|
48
58
|
end
|
|
49
59
|
end
|
|
50
60
|
end
|
|
61
|
+
|
|
62
|
+
describe '#initialize' do
|
|
63
|
+
it 'sets exact to false by default' do
|
|
64
|
+
expect(subject.exact).to eq(false)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
51
67
|
end
|
|
52
68
|
|
|
53
69
|
class Selector
|
|
54
|
-
shared_examples 'named selector' do
|
|
70
|
+
shared_examples 'named selector' do |options|
|
|
55
71
|
it 'adds name to the result' do
|
|
56
|
-
|
|
72
|
+
expected = [described_class.name, :locator, options].compact
|
|
73
|
+
expect(described_class.build(:element_type, :locator)).to eq(expected)
|
|
57
74
|
end
|
|
58
75
|
end
|
|
59
76
|
|
|
@@ -96,7 +113,7 @@ module PageMagic
|
|
|
96
113
|
end
|
|
97
114
|
|
|
98
115
|
describe LABEL do
|
|
99
|
-
it_behaves_like 'named selector', :
|
|
116
|
+
it_behaves_like 'named selector', exact: true
|
|
100
117
|
it_behaves_like 'non element type selector'
|
|
101
118
|
end
|
|
102
119
|
|
|
@@ -105,5 +122,30 @@ module PageMagic
|
|
|
105
122
|
it_behaves_like 'element type selector'
|
|
106
123
|
end
|
|
107
124
|
end
|
|
125
|
+
|
|
126
|
+
context 'integration' do
|
|
127
|
+
include_context :webapp_fixture
|
|
128
|
+
let(:capybara_session) { Capybara::Session.new(:rack_test, rack_app).tap { |s| s.visit('/elements') } }
|
|
129
|
+
|
|
130
|
+
it 'finds elements by name' do
|
|
131
|
+
expect(capybara_session.all(*Query.find(:text_field).build(name: 'field_name')).size).to eq(1)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'finds elements by xpath' do
|
|
135
|
+
expect(capybara_session.all(*Query.find(:element).build(xpath: '//div/input')).size).to eq(1)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'finds elements by id' do
|
|
139
|
+
expect(capybara_session.all(*Query.find(:text_field).build(id: 'field_id')).size).to eq(1)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'finds elements by label' do
|
|
143
|
+
expect(capybara_session.all(*Query.find(:text_field).build(label: 'enter text')).size).to eq(1)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it 'finds elements by text' do
|
|
147
|
+
expect(capybara_session.all(*Query.find(:link).build(text: 'a link')).size).to eq(1)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
108
150
|
end
|
|
109
151
|
end
|