page_magic 1.2.7 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +135 -144
- data/Makefile +17 -0
- data/README.md +48 -4
- data/Rakefile +12 -2
- data/VERSION +1 -1
- data/circle.yml +4 -2
- data/lib/active_support/core_ext/object/to_query.rb +84 -0
- data/lib/page_magic.rb +22 -20
- 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 -68
- 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 +17 -13
- 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 +200 -0
- data/spec/page_magic/elements_spec.rb +90 -127
- 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 +31 -30
- 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
@@ -1,36 +1,40 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
RSpec.describe PageMagic::SessionMethods do
|
5
|
+
subject(:session_methods) do
|
6
|
+
OpenStruct.new(session: session).tap do |o|
|
7
|
+
o.extend(described_class)
|
9
8
|
end
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:session) do
|
12
|
+
rack_app = instance_double(Proc, call: [200, {}, ['<html><head><title>page1</title></head></html>']])
|
13
|
+
PageMagic.session(application: rack_app, url: '/page1')
|
14
|
+
end
|
10
15
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
+
describe '#execute_script' do
|
17
|
+
it 'returns the output of Session#execute_script' do
|
18
|
+
allow(session.raw_session).to receive(:execute_script).with(:script).and_return(:result)
|
19
|
+
expect(session_methods.execute_script(:script)).to eq(:result)
|
16
20
|
end
|
21
|
+
end
|
17
22
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
23
|
+
describe '#page' do
|
24
|
+
it 'returns the current page of the session' do
|
25
|
+
expect(session_methods.page).to eq(session.current_page)
|
22
26
|
end
|
27
|
+
end
|
23
28
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
29
|
+
describe '#path' do
|
30
|
+
it 'returns the path of the session' do
|
31
|
+
expect(session_methods.path).to eq(session.current_path)
|
28
32
|
end
|
33
|
+
end
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
35
|
+
describe '#url' do
|
36
|
+
it 'returns the url of the session' do
|
37
|
+
expect(session_methods.url).to eq(session.current_url)
|
34
38
|
end
|
35
39
|
end
|
36
40
|
end
|
@@ -1,254 +1,164 @@
|
|
1
|
-
#
|
2
|
-
module PageMagic
|
3
|
-
describe Session do
|
4
|
-
let(:page) do
|
5
|
-
Class.new do
|
6
|
-
include PageMagic
|
7
|
-
url 'http://url.com'
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
subject { described_class.new(browser) }
|
1
|
+
# frozen_string_literal: true
|
12
2
|
|
13
|
-
|
14
|
-
|
3
|
+
RSpec.describe PageMagic::Session do
|
4
|
+
subject(:session) { described_class.new(browser, 'http://base.url') }
|
15
5
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
6
|
+
let(:page) do
|
7
|
+
Class.new do
|
8
|
+
include PageMagic
|
9
|
+
end
|
10
|
+
end
|
23
11
|
|
24
|
-
|
25
|
-
|
26
|
-
|
12
|
+
let(:browser) do
|
13
|
+
rack_application = Class.new do
|
14
|
+
def self.call(_env)
|
15
|
+
[200, {}, ['ok']]
|
27
16
|
end
|
17
|
+
end
|
28
18
|
|
29
|
-
|
30
|
-
|
31
|
-
allow(browser).to receive(:current_url).and_return(page.url)
|
32
|
-
expect(subject.current_page).to be_an_instance_of(page)
|
33
|
-
end
|
34
|
-
end
|
19
|
+
Capybara::Session.new(:rack_test, rack_application)
|
20
|
+
end
|
35
21
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
22
|
+
describe '#current_page' do
|
23
|
+
let(:another_page_class) do
|
24
|
+
Class.new do
|
25
|
+
include PageMagic
|
41
26
|
end
|
42
27
|
end
|
43
28
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
29
|
+
it 'returns the current page' do
|
30
|
+
session.visit(page, url: 'http://base.url')
|
31
|
+
expect(session.current_page).to be_an_instance_of(page)
|
48
32
|
end
|
49
33
|
|
50
|
-
|
51
|
-
it
|
52
|
-
|
34
|
+
context 'when the page url has changed' do
|
35
|
+
it 'returns the mapped page object' do
|
36
|
+
session.define_page_mappings '/another_page1' => another_page_class
|
37
|
+
browser.visit('/another_page1')
|
38
|
+
expect(session.current_page).to be_an_instance_of(another_page_class)
|
53
39
|
end
|
54
40
|
end
|
41
|
+
end
|
55
42
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
43
|
+
describe '#current_path' do
|
44
|
+
it "returns the browser's current path" do
|
45
|
+
browser.visit('/url')
|
46
|
+
expect(session.current_path).to eq(browser.current_path)
|
47
|
+
end
|
48
|
+
end
|
63
49
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
expect(subject.transitions.key(:page)).to be(expected_matcher)
|
69
|
-
end
|
70
|
-
end
|
50
|
+
describe '#current_url' do
|
51
|
+
it "returns the browser's current url" do
|
52
|
+
browser.visit('/url')
|
53
|
+
expect(session.current_url).to eq(session.current_url)
|
71
54
|
end
|
55
|
+
end
|
72
56
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
57
|
+
describe '#define_page_mappings' do
|
58
|
+
context 'when the mapping includes a literal' do
|
59
|
+
it 'creates a matcher to contain the specification' do
|
60
|
+
session.define_page_mappings path: :page
|
61
|
+
expect(session.transitions.to_h).to include(PageMagic::Mapping.new(:path) => :page)
|
77
62
|
end
|
63
|
+
end
|
78
64
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
65
|
+
context 'when the mapping is a matcher' do
|
66
|
+
it 'leaves it intact' do
|
67
|
+
expected_matcher = PageMagic::Mapping.new(:page)
|
68
|
+
session.define_page_mappings expected_matcher => :page
|
69
|
+
expect(session.transitions.key(:page)).to be(expected_matcher)
|
85
70
|
end
|
86
71
|
end
|
72
|
+
end
|
87
73
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
74
|
+
describe '#execute_script' do
|
75
|
+
it 'calls the execute script method on the capybara session' do
|
76
|
+
allow(browser).to receive(:execute_script).with(:script).and_return(:result)
|
77
|
+
expect(session.execute_script(:script)).to be(:result)
|
78
|
+
end
|
92
79
|
|
93
|
-
|
94
|
-
|
95
|
-
subject.define_page_mappings '/page' => :mapped_page_using_string
|
96
|
-
expect(subject.instance_eval { find_mapped_page('/page') }).to be(:mapped_page_using_string)
|
97
|
-
end
|
80
|
+
context 'when the Capybara session does not support #execute_script' do
|
81
|
+
let(:browser) { Capybara::Driver::Base.new }
|
98
82
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
expect(subject.instance_eval { find_mapped_page('/page') }).to eq(:mapped_page_using_string)
|
103
|
-
end
|
104
|
-
end
|
83
|
+
it 'raises an error' do
|
84
|
+
expected_message = described_class::UNSUPPORTED_OPERATION_MSG
|
85
|
+
expect { session.execute_script(:script) }.to raise_error(PageMagic::NotSupportedException, expected_message)
|
105
86
|
end
|
87
|
+
end
|
88
|
+
end
|
106
89
|
|
107
|
-
|
108
|
-
|
109
|
-
|
90
|
+
describe '#method_missing' do
|
91
|
+
before do
|
92
|
+
page.class_eval do
|
93
|
+
def my_method
|
94
|
+
:called
|
110
95
|
end
|
111
96
|
end
|
112
97
|
end
|
113
98
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
it 'returns matching page mappings' do
|
120
|
-
subject.define_page_mappings '/page' => :mapped_page_using_string
|
121
|
-
expect(subject.instance_eval { matches('/page') }).to eq([:mapped_page_using_string])
|
122
|
-
end
|
99
|
+
it 'delegates to current page' do
|
100
|
+
session = described_class.new(browser).visit(page, url: 'http://base.url')
|
101
|
+
expect(session.my_method).to be(:called)
|
102
|
+
end
|
103
|
+
end
|
123
104
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
expect(subject.instance_eval { matches('/page') }).to eq(expected_result)
|
129
|
-
end
|
130
|
-
end
|
105
|
+
describe '#respond_to?' do
|
106
|
+
it 'checks self' do
|
107
|
+
session = described_class.new(browser)
|
108
|
+
expect(session.respond_to?(:current_url)).to eq(true)
|
131
109
|
end
|
132
110
|
|
133
|
-
|
134
|
-
|
111
|
+
context 'when method is not on self' do
|
112
|
+
before do
|
135
113
|
page.class_eval do
|
136
114
|
def my_method
|
137
115
|
:called
|
138
116
|
end
|
139
117
|
end
|
140
|
-
|
141
|
-
session = PageMagic::Session.new(browser).visit(page, url: url)
|
142
|
-
expect(session.my_method).to be(:called)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
context '#respond_to?' do
|
147
|
-
subject do
|
148
|
-
PageMagic::Session.new(browser).tap do |s|
|
149
|
-
allow(s).to receive(:current_page).and_return(page.new)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
it 'checks self' do
|
153
|
-
expect(subject.respond_to?(:current_url)).to eq(true)
|
154
118
|
end
|
155
119
|
|
156
120
|
it 'checks the current page' do
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
161
|
-
expect(subject.respond_to?(:my_method)).to eq(true)
|
121
|
+
session = described_class.new(browser)
|
122
|
+
session.visit(page, url: '/')
|
123
|
+
expect(session.respond_to?(:my_method)).to eq(true)
|
162
124
|
end
|
163
125
|
end
|
126
|
+
end
|
164
127
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
before do
|
172
|
-
base_url << '/'
|
173
|
-
end
|
174
|
-
|
175
|
-
context 'path has / at the beginning' do
|
176
|
-
it 'produces compound url' do
|
177
|
-
expect(subject.send(:url, base_url, path)).to eq(expected_url)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
context 'path does not have / at the beginning' do
|
182
|
-
it 'produces compound url' do
|
183
|
-
expect(subject.send(:url, base_url, "/#{path}")).to eq(expected_url)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
context 'current_url does not have a / on the end' do
|
189
|
-
context 'path has / at the beginning' do
|
190
|
-
it 'produces compound url' do
|
191
|
-
expect(subject.send(:url, base_url, "/#{path}")).to eq(expected_url)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
context 'path does not have / at the beginning' do
|
196
|
-
it 'produces compound url' do
|
197
|
-
expect(subject.send(:url, base_url, path)).to eq(expected_url)
|
198
|
-
end
|
199
|
-
end
|
128
|
+
describe '#visit' do
|
129
|
+
context 'when a page is supplied' do
|
130
|
+
it 'sets the current page' do
|
131
|
+
session.define_page_mappings '/page' => page
|
132
|
+
session.visit(page)
|
133
|
+
expect(session.current_page).to be_a(page)
|
200
134
|
end
|
201
|
-
end
|
202
135
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
136
|
+
it 'uses the base url and the path in the page mappings' do
|
137
|
+
session = described_class.new(browser, 'http://base.url')
|
138
|
+
session.define_page_mappings '/page' => page
|
139
|
+
session.visit(page)
|
140
|
+
expect(session.current_url).to eq('http://base.url/page')
|
207
141
|
end
|
208
142
|
|
209
|
-
|
210
|
-
|
211
|
-
session.define_page_mappings '/page' => page
|
143
|
+
it 'raises an error when page no page mappings are found' do
|
144
|
+
expect do
|
212
145
|
session.visit(page)
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
it 'uses the base url and the path in the page mappings' do
|
217
|
-
session.define_page_mappings '/page' => page
|
218
|
-
expect(browser).to receive(:visit).with("#{url}/page")
|
219
|
-
session.visit(page)
|
220
|
-
end
|
221
|
-
|
222
|
-
context 'no mappings found' do
|
223
|
-
it 'raises an error' do
|
224
|
-
expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::URL_MISSING_MSG
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
context 'mapping is a regular expression' do
|
229
|
-
it 'raises an error' do
|
230
|
-
session.define_page_mappings(/mapping/ => page)
|
231
|
-
expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::REGEXP_MAPPING_MSG
|
232
|
-
end
|
233
|
-
end
|
146
|
+
end.to raise_exception PageMagic::InvalidURLException, described_class::URL_MISSING_MSG
|
147
|
+
end
|
234
148
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
session.define_page_mappings('/page' => page)
|
241
|
-
session.visit(page)
|
242
|
-
expect(on_load_hook_called).to eq(true)
|
243
|
-
end
|
149
|
+
it 'calls the onload hook' do
|
150
|
+
on_load_hook_called = false
|
151
|
+
page.on_load { on_load_hook_called = true }
|
152
|
+
session.visit(page, url: 'http://base.url')
|
153
|
+
expect(on_load_hook_called).to eq(true)
|
244
154
|
end
|
155
|
+
end
|
245
156
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
end
|
157
|
+
context 'when `url` is supplied' do
|
158
|
+
it 'visits that url' do
|
159
|
+
expected_url = 'http://base.url/page'
|
160
|
+
session.visit(url: expected_url)
|
161
|
+
expect(browser.current_url).to eq(expected_url)
|
252
162
|
end
|
253
163
|
end
|
254
164
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe PageMagic::Transitions do
|
4
|
+
describe '#mapped_page' do
|
5
|
+
context 'when a match is match found' do
|
6
|
+
it 'returns the page class' do
|
7
|
+
mappings = described_class.new('/page' => :mapped_page_using_string)
|
8
|
+
expect(mappings.mapped_page('/page')).to be(:mapped_page_using_string)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when more than one match is found' do
|
13
|
+
it 'returns the most specific match' do
|
14
|
+
mappings = described_class.new(%r{/page} => :mapped_page_using_regex, '/page' => :mapped_page_using_string)
|
15
|
+
expect(mappings.mapped_page('/page')).to eq(:mapped_page_using_string)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when a mapping is not found' do
|
20
|
+
it 'returns nil' do
|
21
|
+
mappings = described_class.new({})
|
22
|
+
expect(mappings.mapped_page('/unmapped_page')).to be(nil)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#url_for' do
|
28
|
+
it 'returns the url for the mapped page' do
|
29
|
+
page = Object.new
|
30
|
+
mappings = described_class.new('/mapping' => page)
|
31
|
+
expect(mappings.url_for(page, base_url: 'http://base.url')).to eq('http://base.url/mapping')
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when page mapping is a regular expression' do
|
35
|
+
it 'raises an error' do
|
36
|
+
page = Object.new
|
37
|
+
mappings = described_class.new(/mapping/ => page)
|
38
|
+
expect { mappings.url_for(page, base_url: 'http://base.url') }
|
39
|
+
.to raise_exception PageMagic::InvalidURLException, described_class::REGEXP_MAPPING_MSG
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|