page_magic 2.0.0.alpha1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -2
  3. data/.zsh_config +5 -5
  4. data/Dockerfile +2 -1
  5. data/Gemfile +2 -1
  6. data/Gemfile.lock +9 -5
  7. data/Makefile +7 -3
  8. data/README.md +16 -4
  9. data/VERSION +1 -1
  10. data/lib/active_support/core_ext/object/to_query.rb +6 -6
  11. data/lib/page_magic.rb +15 -16
  12. data/lib/page_magic/class_methods.rb +1 -1
  13. data/lib/page_magic/comparator.rb +37 -0
  14. data/lib/page_magic/comparator/fuzzy.rb +23 -0
  15. data/lib/page_magic/comparator/literal.rb +22 -0
  16. data/lib/page_magic/comparator/null.rb +26 -0
  17. data/lib/page_magic/comparator/parameter_map.rb +52 -0
  18. data/lib/page_magic/drivers.rb +2 -2
  19. data/lib/page_magic/element.rb +19 -8
  20. data/lib/page_magic/element/locators.rb +4 -4
  21. data/lib/page_magic/element/not_found.rb +38 -0
  22. data/lib/page_magic/element/query.rb +19 -27
  23. data/lib/page_magic/element/query/multiple_results.rb +21 -0
  24. data/lib/page_magic/element/query/prefetched_result.rb +26 -0
  25. data/lib/page_magic/element/query/single_result.rb +20 -0
  26. data/lib/page_magic/element/selector.rb +38 -16
  27. data/lib/page_magic/element/selector/methods.rb +18 -0
  28. data/lib/page_magic/element/selector/model.rb +21 -0
  29. data/lib/page_magic/element_context.rb +5 -21
  30. data/lib/page_magic/element_definition_builder.rb +17 -24
  31. data/lib/page_magic/elements.rb +62 -102
  32. data/lib/page_magic/elements/config.rb +103 -0
  33. data/lib/page_magic/elements/inheritance_hooks.rb +15 -0
  34. data/lib/page_magic/elements/types.rb +25 -0
  35. data/lib/page_magic/exceptions.rb +3 -0
  36. data/lib/page_magic/instance_methods.rb +2 -2
  37. data/lib/page_magic/mapping.rb +79 -0
  38. data/lib/page_magic/session.rb +10 -32
  39. data/lib/page_magic/session_methods.rb +1 -1
  40. data/lib/page_magic/transitions.rb +49 -0
  41. data/lib/page_magic/utils/string.rb +4 -0
  42. data/lib/page_magic/utils/url.rb +20 -0
  43. data/lib/page_magic/watcher.rb +10 -17
  44. data/lib/page_magic/watchers.rb +28 -15
  45. data/spec/page_magic/class_methods_spec.rb +64 -37
  46. data/spec/page_magic/comparator/fuzzy_spec.rb +44 -0
  47. data/spec/page_magic/comparator/literal_spec.rb +41 -0
  48. data/spec/page_magic/comparator/null_spec.rb +35 -0
  49. data/spec/page_magic/comparator/parameter_map_spec.rb +75 -0
  50. data/spec/page_magic/driver_spec.rb +25 -29
  51. data/spec/page_magic/drivers/poltergeist_spec.rb +4 -7
  52. data/spec/page_magic/drivers/rack_test_spec.rb +4 -9
  53. data/spec/page_magic/drivers/selenium_spec.rb +9 -12
  54. data/spec/page_magic/drivers_spec.rb +36 -29
  55. data/spec/page_magic/element/locators_spec.rb +26 -25
  56. data/spec/page_magic/element/not_found_spec.rb +24 -0
  57. data/spec/page_magic/element/query/multiple_results_spec.rb +14 -0
  58. data/spec/page_magic/element/query/single_result_spec.rb +21 -0
  59. data/spec/page_magic/element/query_spec.rb +26 -47
  60. data/spec/page_magic/element/selector_spec.rb +118 -110
  61. data/spec/page_magic/element_context_spec.rb +46 -88
  62. data/spec/page_magic/element_definition_builder_spec.rb +12 -71
  63. data/spec/page_magic/element_spec.rb +256 -0
  64. data/spec/page_magic/elements/config_spec.rb +200 -0
  65. data/spec/page_magic/elements_spec.rb +87 -138
  66. data/spec/page_magic/instance_methods_spec.rb +63 -63
  67. data/spec/page_magic/mapping_spec.rb +181 -0
  68. data/spec/page_magic/session_methods_spec.rb +27 -25
  69. data/spec/page_magic/session_spec.rb +109 -198
  70. data/spec/page_magic/transitions_spec.rb +43 -0
  71. data/spec/page_magic/utils/string_spec.rb +20 -27
  72. data/spec/page_magic/utils/url_spec.rb +9 -0
  73. data/spec/page_magic/wait_methods_spec.rb +14 -22
  74. data/spec/page_magic/watcher_spec.rb +22 -0
  75. data/spec/page_magic/watchers_spec.rb +56 -62
  76. data/spec/page_magic_spec.rb +27 -24
  77. data/spec/spec_helper.rb +7 -3
  78. data/spec/support/shared_examples.rb +15 -17
  79. metadata +48 -15
  80. data/lib/page_magic/element/query_builder.rb +0 -61
  81. data/lib/page_magic/element/selector_methods.rb +0 -16
  82. data/lib/page_magic/matcher.rb +0 -130
  83. data/spec/element_spec.rb +0 -251
  84. data/spec/page_magic/element/query_builder_spec.rb +0 -110
  85. data/spec/page_magic/matcher_spec.rb +0 -338
  86. data/spec/support/shared_contexts/files_context.rb +0 -9
  87. data/spec/support/shared_contexts/nested_elements_html_context.rb +0 -18
  88. data/spec/support/shared_contexts/rack_application_context.rb +0 -11
  89. data/spec/support/shared_contexts/webapp_fixture_context.rb +0 -41
  90. data/spec/watcher_spec.rb +0 -64
@@ -1,110 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PageMagic
4
- class Element
5
- describe QueryBuilder do
6
- it 'has a predefined query for each element type' do
7
- missing = PageMagic::Elements::TYPES.dup.delete_if { |type| type.to_s.end_with?('s') }.find_all do |type|
8
- described_class.constants.include?(type)
9
- end
10
- expect(missing).to be_empty
11
- end
12
-
13
- describe '.find' do
14
- it 'finds the constant with the given name' do
15
- expect(described_class.find(:button)).to be(described_class::BUTTON)
16
- end
17
-
18
- context 'constant not found' do
19
- it 'returns a default' do
20
- expect(described_class.find(:billy)).to be(described_class::ELEMENT)
21
- end
22
- end
23
- end
24
-
25
- describe '#build' do
26
- let(:selector) { Selector.new }
27
- before do
28
- expect(Selector).to receive(:find).with(:css).and_return(selector)
29
- end
30
- let(:locator) { { css: '.css' } }
31
-
32
- it 'builds a query using the correct selector' do
33
- expected = Query.new(locator.values)
34
- expect(subject.build(locator)).to eq(expected)
35
- end
36
-
37
- it 'adds options to the result' do
38
- expected = Query.new(locator.values.concat([:options]))
39
- expect(subject.build(locator, :options)).to eq(expected)
40
- end
41
-
42
- context 'selector support element type' do
43
- subject do
44
- described_class.new(:field)
45
- end
46
-
47
- it 'passes element type through to the selector' do
48
- expect(selector).to receive(:build).with(:field, '.css').and_call_original
49
- subject.build(locator)
50
- end
51
- end
52
- end
53
- end
54
-
55
- class QueryBuilder
56
- describe BUTTON do
57
- it 'has an element type' do
58
- expect(described_class.type).to eq(:button)
59
- end
60
- end
61
-
62
- describe ELEMENT do
63
- it ' does not has an element type' do
64
- expect(described_class.type).to be_nil
65
- end
66
- end
67
-
68
- describe LINK do
69
- it 'has an element type' do
70
- expect(described_class.type).to eq(:link)
71
- end
72
- end
73
-
74
- describe TEXT_FIELD do
75
- it 'has an element type' do
76
- expect(described_class.type).to eq(:field)
77
- end
78
-
79
- it 'the same as all form field types' do
80
- expect(described_class).to eq(CHECKBOX).and eq(SELECT_LIST).and eq(RADIO).and eq(TEXTAREA).and eq(FILE_FIELD).and eq(FILLABLE_FIELD).and eq(RADIO_BUTTON)
81
- end
82
- end
83
- end
84
-
85
- context 'integration' do
86
- include_context :webapp_fixture
87
- let(:capybara_session) { Capybara::Session.new(:rack_test, rack_app).tap { |s| s.visit('/elements') } }
88
-
89
- it 'finds fields' do
90
- query = QueryBuilder.find(:text_field).build({ name: 'field_name' })
91
- expect(query.execute(capybara_session).tag_name).to eq('input')
92
- end
93
-
94
- it 'finds buttons' do
95
- query = QueryBuilder.find(:button).build({ text: 'a button' })
96
- expect(query.execute(capybara_session).tag_name).to eq('button')
97
- end
98
-
99
- it 'finds links' do
100
- query = QueryBuilder.find(:link).build({ text: 'a link' })
101
- expect(query.execute(capybara_session).tag_name).to eq('a')
102
- end
103
-
104
- it 'finds elements' do
105
- query = QueryBuilder.find(:element).build({ name: 'field_name' })
106
- expect(query.execute(capybara_session).tag_name).to eq('input')
107
- end
108
- end
109
- end
110
- end
@@ -1,338 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # rubocop:disable Metrics/ModuleLength
4
- module PageMagic
5
- describe Matcher do
6
- describe '#initialize' do
7
- context 'no componentes specified' do
8
- it 'raises an exeception' do
9
- expect { described_class.new }.to raise_exception(MatcherInvalidException)
10
- end
11
- end
12
- end
13
- describe '#can_compute_uri?' do
14
- context 'regex in path' do
15
- it 'returns false' do
16
- expect(described_class.new(//).can_compute_uri?).to eq(false)
17
- end
18
- end
19
-
20
- context 'regex in parameters' do
21
- it 'returns false' do
22
- expect(described_class.new(parameters: { param: // }).can_compute_uri?).to eq(false)
23
- end
24
- end
25
-
26
- context 'regexp in fragment' do
27
- it 'returns false' do
28
- expect(described_class.new(fragment: //).can_compute_uri?).to eq(false)
29
- end
30
- end
31
-
32
- context 'regexp not present' do
33
- it 'returns true' do
34
- expect(described_class.new('/').can_compute_uri?).to eq(true)
35
- end
36
- end
37
- end
38
-
39
- describe 'compare' do
40
- subject { described_class.new('/') }
41
- context 'param 1 not nil' do
42
- context 'param 2 not nil' do
43
- context 'literal to fuzzy' do
44
- it 'returns -1' do
45
- expect(subject.instance_eval { compare('/', //) }).to eq(-1)
46
- end
47
- end
48
-
49
- context 'literal to literal' do
50
- it 'returns 0' do
51
- expect(subject.instance_eval { compare('/', '/') }).to eq(0)
52
- end
53
- end
54
-
55
- context 'fuzzy to fuzzy' do
56
- it 'returns 0' do
57
- expect(subject.instance_eval { compare(//, //) }).to eq(0)
58
- end
59
- end
60
-
61
- context 'fuzzy to literal' do
62
- it 'returns 1' do
63
- expect(subject.instance_eval { compare(//, '/') }).to eq(1)
64
- end
65
- end
66
- end
67
-
68
- context 'param2 is nil' do
69
- it 'returns -1' do
70
- expect(subject.instance_eval { compare('/', nil) }).to eq(-1)
71
- end
72
- end
73
- end
74
-
75
- context 'param1 is nil' do
76
- context 'param2 not nil' do
77
- it 'returns 1' do
78
- expect(subject.instance_eval { compare(nil, '/') }).to eq(1)
79
- end
80
- end
81
-
82
- context 'param2 nil' do
83
- it 'returns 0' do
84
- expect(subject.instance_eval { compare(nil, nil) }).to eq(0)
85
- end
86
- end
87
- end
88
- end
89
-
90
- describe 'compute_uri' do
91
- context 'path present' do
92
- it 'returns a uri' do
93
- expect(described_class.new('/').compute_uri).to eq('/')
94
- end
95
- end
96
-
97
- context 'params present' do
98
- context '1 param' do
99
- it 'returns a uri' do
100
- expect(described_class.new(parameters: { a: 1 }).compute_uri).to eq('?a=1')
101
- end
102
- end
103
-
104
- context 'more than 1 param' do
105
- it 'returns a uri' do
106
- expect(described_class.new(parameters: { a: 1, b: 2 }).compute_uri).to eq('?a=1&b=2')
107
- end
108
- end
109
- end
110
-
111
- context 'fragment present' do
112
- it 'returns a uri' do
113
- expect(described_class.new(fragment: 'fragment').compute_uri).to eq('#fragment')
114
- end
115
- end
116
- end
117
-
118
- describe '#matches?' do
119
- let(:matching_url) { 'http://www.example.com/path?foo=bar#fragment' }
120
- let(:incompatible_url) { 'http://www.example.com/mismatch?miss=match#mismatch' }
121
- context 'path requirement exists' do
122
- context 'path is literal' do
123
- subject do
124
- described_class.new('/path')
125
- end
126
- it 'returns true for an exact match' do
127
- expect(subject.match?(matching_url)).to eq(true)
128
- end
129
-
130
- it 'returns false when not an exact match' do
131
- expect(subject.match?(incompatible_url)).to eq(false)
132
- end
133
- end
134
-
135
- context 'path is regexp' do
136
- subject do
137
- described_class.new(/\d/)
138
- end
139
- it 'returns true for a match on the regexp' do
140
- expect(subject.match?('3')).to eq(true)
141
- end
142
-
143
- it 'returns false when regexp is not a match' do
144
- expect(subject.match?('/mismatch')).to eq(false)
145
- end
146
- end
147
- end
148
-
149
- context 'query string requirement exists' do
150
- context 'parameter requirement is a literal' do
151
- subject do
152
- described_class.new(parameters: { foo: 'bar' })
153
- end
154
-
155
- it 'returns true for a match' do
156
- expect(subject.match?(matching_url)).to eq(true)
157
- end
158
-
159
- it 'returns false when regexp is not a match' do
160
- expect(subject.match?(incompatible_url)).to eq(false)
161
- end
162
- end
163
-
164
- context 'parameter requirement is a regexp' do
165
- subject do
166
- described_class.new(parameters: { foo: /bar/ })
167
- end
168
-
169
- it 'returns true for a match on the regexp' do
170
- expect(subject.match?(matching_url)).to eq(true)
171
- end
172
-
173
- it 'returns false when regexp is not a match' do
174
- expect(subject.match?(incompatible_url)).to eq(false)
175
- end
176
- end
177
- end
178
-
179
- context 'fragment requirement exists' do
180
- context 'fragment requirement is a literal' do
181
- subject do
182
- described_class.new(fragment: 'fragment')
183
- end
184
-
185
- it 'returns true for a match' do
186
- expect(subject.match?(matching_url)).to eq(true)
187
- end
188
-
189
- it 'returns false when regexp is not a match' do
190
- expect(subject.match?(incompatible_url)).to eq(false)
191
- end
192
- end
193
-
194
- context 'fragment requirement is a regexp' do
195
- subject do
196
- described_class.new(fragment: /fragment/)
197
- end
198
-
199
- it 'returns true for a match on the regexp' do
200
- expect(subject.match?(matching_url)).to eq(true)
201
- end
202
-
203
- it 'returns false when regexp is not a match' do
204
- expect(subject.match?(incompatible_url)).to eq(false)
205
- end
206
- end
207
- end
208
- end
209
-
210
- describe '<=>' do
211
- let(:literal_path_matcher) { '/' }
212
- let(:fuzzy_path_matcher) { // }
213
- let(:literal_parameter_matchers) { { param: 'value' } }
214
- let(:fuzzy_parameter_matchers) { { param: // } }
215
-
216
- let(:literal_fragment_matcher) { 'fragment' }
217
- let(:fuzzy_fragment_matcher) { // }
218
-
219
- context 'path' do
220
- context 'path is of same class as path on other' do
221
- subject(:a) { described_class.new('/a') }
222
- subject(:b) { described_class.new('/b') }
223
- it 'returns self and other as equivalent' do
224
- expect(a <=> b).to eq(0)
225
- end
226
- end
227
-
228
- context 'path on other is fuzzy' do
229
- subject(:a) { described_class.new(literal_path_matcher) }
230
- subject(:b) { described_class.new(fuzzy_path_matcher) }
231
- it 'returns other as lesser' do
232
- expect(a <=> b).to eq(-1)
233
- end
234
- end
235
- end
236
-
237
- context 'parameters' do
238
- context 'parameters on self and other contain literal values' do
239
- subject(:a) do
240
- described_class.new(literal_path_matcher,
241
- parameters: literal_parameter_matchers)
242
- end
243
- subject(:b) do
244
- described_class.new(literal_path_matcher,
245
- parameters: literal_parameter_matchers)
246
- end
247
- it 'returns self and other as equivalent' do
248
- expect(a <=> b).to eq(0)
249
- end
250
- end
251
-
252
- context 'parameters on self literal values and other has fuzzy values' do
253
- subject(:a) do
254
- described_class.new(literal_path_matcher,
255
- parameters: literal_parameter_matchers)
256
- end
257
- subject(:b) do
258
- described_class.new(literal_path_matcher,
259
- parameters: fuzzy_parameter_matchers)
260
- end
261
- it 'returns other as lesser' do
262
- expect(a <=> b).to eq(-1)
263
- end
264
- end
265
- context 'parameters on self fuzzy values and other has literal values' do
266
- subject(:a) do
267
- described_class.new(literal_path_matcher,
268
- parameters: fuzzy_parameter_matchers)
269
- end
270
-
271
- subject(:b) do
272
- described_class.new(literal_path_matcher,
273
- parameters: literal_parameter_matchers)
274
- end
275
-
276
- it 'returns other as greater' do
277
- expect(a <=> b).to eq(1)
278
- end
279
- end
280
- end
281
-
282
- context 'fragment' do
283
- context 'fragment is of same class as path on other' do
284
- subject(:a) do
285
- described_class.new(literal_path_matcher,
286
- parameters: literal_parameter_matchers,
287
- fragment: literal_fragment_matcher)
288
- end
289
-
290
- subject(:b) do
291
- described_class.new(literal_path_matcher,
292
- parameters: literal_parameter_matchers,
293
- fragment: literal_fragment_matcher)
294
- end
295
-
296
- it 'returns self and other as equivalent' do
297
- expect(a <=> b).to eq(0)
298
- end
299
- end
300
-
301
- context 'fragment is literal on self and fuzzy on other' do
302
- subject(:a) do
303
- described_class.new(literal_path_matcher,
304
- parameters: literal_parameter_matchers,
305
- fragment: literal_fragment_matcher)
306
- end
307
-
308
- subject(:b) do
309
- described_class.new(literal_path_matcher,
310
- parameters: literal_parameter_matchers,
311
- fragment: fuzzy_fragment_matcher)
312
- end
313
-
314
- it 'returns other as lesser' do
315
- expect(a <=> b).to eq(-1)
316
- end
317
- end
318
-
319
- context 'fragment is fuzzy on self and literal on other' do
320
- subject(:a) do
321
- described_class.new(literal_path_matcher,
322
- parameters: literal_parameter_matchers,
323
- fragment: fuzzy_fragment_matcher)
324
- end
325
-
326
- subject(:b) do
327
- described_class.new(literal_path_matcher,
328
- parameters: literal_parameter_matchers,
329
- fragment: literal_fragment_matcher)
330
- end
331
- it 'returns other as lesser' do
332
- expect(a <=> b).to eq(1)
333
- end
334
- end
335
- end
336
- end
337
- end
338
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- shared_context :files do
4
- require 'tmpdir'
5
-
6
- def scratch_dir
7
- @dir ||= Dir.mktmpdir
8
- end
9
- end