aygabtu 0.2.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.
@@ -0,0 +1,61 @@
1
+ require 'rails_application_helper'
2
+
3
+ require 'aygabtu/rspec'
4
+
5
+ require 'support/aygabtu_sees_routes'
6
+
7
+ describe "anatonomy of an aygabtu example" do
8
+ extend AygabtuSeesRoutes
9
+
10
+ include Aygabtu::RSpec.example_group_module
11
+
12
+ aygabtu_sees_routes do
13
+ get 'bogus/:segment1/:segment2', to: 'bogus#action'
14
+ end
15
+
16
+ context "contains a generated example" do
17
+ action(:action) do
18
+ let(:spy) { double "assertion spy" }
19
+
20
+ before do
21
+ # HERE are the assertions
22
+ #
23
+ # We could depend upon aygabtu internals to make three examples out of this,
24
+ # but probably it is better to keep the excercised code close to "production" code
25
+ # sacrifying test readibility and RSpec idioms a bit.
26
+
27
+ # for dynamic segments, the corresponding method is called
28
+ expect(spy).to receive(:dynamic_segment) { 'foo' }
29
+
30
+ # the aygabtu example uses capybara-rspec in this way:
31
+ expect(spy).to receive(:visit).with('/bogus/fixed/foo')
32
+
33
+ # then, this is how asserting is triggered
34
+ expect(spy).to receive(:aygabtu_assertions)
35
+ end
36
+
37
+ def visit(argument)
38
+ spy.visit(argument)
39
+ end
40
+
41
+ def aygabtu_assertions
42
+ spy.aygabtu_assertions
43
+ end
44
+
45
+ def dynamic_segment
46
+ spy.dynamic_segment
47
+ end
48
+
49
+ visit_with(segment1: 'fixed', segment2: :dynamic_segment)
50
+ end
51
+ end
52
+
53
+ remaining do
54
+ # sanity check.
55
+ it "has covered route and thus created an example" do
56
+ expect(self.class.aygabtu_matching_routes).to be_empty
57
+ end
58
+ end
59
+ end
60
+
61
+
@@ -0,0 +1,140 @@
1
+ require 'rails_application_helper'
2
+
3
+ require 'aygabtu/rspec'
4
+
5
+ require 'support/identifies_routes'
6
+ require 'support/aygabtu_sees_routes'
7
+ require 'support/matcher_shims'
8
+
9
+ #require 'pry-byebug'
10
+
11
+ describe "RouteWrapper" do
12
+ extend AygabtuSeesRoutes
13
+ include IdentifiesRoutes
14
+ include MatcherShims
15
+
16
+ include Aygabtu::RSpec.example_group_module
17
+
18
+ aygabtu_sees_routes do
19
+ get 'bogus', identified_by(:test_identification).merge(to: 'bogus#bogus')
20
+
21
+ get 'bogus', identified_by(:has_implicit_controller).merge(to: 'foo#bogus')
22
+ get 'bogus', identified_by(:has_explicit_controller).merge(controller: :foo, action: :bogus)
23
+ get 'bogus', identified_by(:no_controller).merge(to: redirect('/'))
24
+ namespace "namespace" do
25
+ get 'bogus', identified_by(:namespaced_controller).merge(to: 'foo#bogus')
26
+ end
27
+ get 'bogus', identified_by(:unnamespaced_controller).merge(to: 'foo#bogus')
28
+ namespace 'namespace' do
29
+ get 'bogus', identified_by(:namespaced_no_controller).merge(to: redirect('/'))
30
+ end
31
+
32
+ get 'bogus', identified_by(:has_implicit_action).merge(to: 'bogus#foo')
33
+ get 'bogus', identified_by(:has_explicit_action).merge(controller: :bogus, action: :foo)
34
+ get 'bogus', identified_by(:no_action).merge(to: redirect('/'))
35
+
36
+ get 'name', identified_by(:explicitly_named).merge(to: 'bogus#bogus')
37
+
38
+ get '/:segment/*glob/bogus', identified_by(:has_segments).merge(to: 'bogus#bogus')
39
+ end
40
+
41
+ describe "#controller" do
42
+ context "for a route to a controller" do
43
+ it "has that controller" do
44
+ expect(route_identified_by(:has_implicit_controller).controller).to be == 'foo'
45
+ expect(route_identified_by(:has_explicit_controller).controller).to be == 'foo'
46
+ end
47
+ end
48
+
49
+ context "for a route not to a controller" do
50
+ it "has nil as controller" do
51
+ expect(route_identified_by(:no_controller).controller).to be_nil
52
+ end
53
+ end
54
+
55
+ context "for a route to a namespaced contoller" do
56
+ it "has namespace/controller as controller attribute" do
57
+ expect(route_identified_by(:namespaced_controller).controller).to be == 'namespace/foo'
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "#action" do
63
+ context "for a route to a controller" do
64
+ it "has the declared action" do
65
+ expect(route_identified_by(:has_implicit_action).action).to be == 'foo'
66
+ expect(route_identified_by(:has_explicit_action).action).to be == 'foo'
67
+ end
68
+ end
69
+
70
+ context "for a route not to a controller" do
71
+ it "has nil as action" do
72
+ expect(route_identified_by(:no_action).action).to be_nil
73
+ end
74
+ end
75
+ end
76
+
77
+ describe "#name" do
78
+ it "has the declared name for an explicitly named route" do
79
+ expect(route_identified_by(:explicitly_named).name).to be == 'name'
80
+ end
81
+ end
82
+
83
+ describe "#controller_namespace" do
84
+ it "has the namespace of a namespaced route" do
85
+ expect(route_identified_by(:namespaced_controller).controller_namespace).to be == 'namespace'
86
+ end
87
+
88
+ it "has nil namespace of an unnamespaced route" do
89
+ expect(route_identified_by(:unnamespaced_controller).controller_namespace).to be_nil
90
+ end
91
+
92
+ it "has nil namespace of a namespaced route not routing to a controller" do
93
+ expect(route_identified_by(:namespaced_no_controller).controller_namespace).to be_nil
94
+ end
95
+ end
96
+
97
+ describe "#controller_basename" do
98
+ context "for a route to a controller" do
99
+ it "has that controller basename" do
100
+ expect(route_identified_by(:has_implicit_controller).controller_basename).to be == 'foo'
101
+ expect(route_identified_by(:has_explicit_controller).controller_basename).to be == 'foo'
102
+ end
103
+ end
104
+
105
+ context "for a namespaced route to a controller" do
106
+ it "has that controller basename" do
107
+ expect(route_identified_by(:namespaced_controller).controller_basename).to be == 'foo'
108
+ end
109
+ end
110
+
111
+ it "has nil controller_basename fo route not routing to a controller" do
112
+ expect(route_identified_by(:no_controller).controller_basename).to be_nil
113
+ end
114
+ end
115
+
116
+ describe "#really_required_keys" do
117
+ context "for a route without any segments" do
118
+ it "has no really_required_keys" do
119
+ expect(route_identified_by(:has_implicit_controller).really_required_keys).to be_empty
120
+ end
121
+ end
122
+
123
+ context "for a route with segments" do
124
+ it "has these as really_required_keys" do
125
+ expect(route_identified_by(:has_segments).really_required_keys).to \
126
+ contain_exactly('segment', 'glob')
127
+ end
128
+ end
129
+ end
130
+
131
+ # all routes seen by route_identified_by
132
+ def all_routes
133
+ matching_routes
134
+ end
135
+
136
+ def matching_routes
137
+ # we only test those routes facing aygabtu example groups, when fex. non-get routes have already been filtered out
138
+ self.class.aygabtu_matching_routes
139
+ end
140
+ end
@@ -0,0 +1,384 @@
1
+ require 'rails_application_helper'
2
+
3
+ require 'aygabtu/rspec'
4
+
5
+ require 'support/identifies_routes'
6
+ require 'support/aygabtu_sees_routes'
7
+ require 'support/matcher_shims'
8
+
9
+ describe "aygabtu scopes and their matching routes" do
10
+ # make routes_for_scope a hash shared by all example groups below
11
+ def self.routes_for_scope
12
+ return superclass.routes_for_scope if superclass.respond_to?(:routes_for_scope)
13
+ @routes_for_scope ||= {}
14
+ end
15
+
16
+ context "setup for anything but the remaining scope" do
17
+ # This context contains no examples, but collects matching routes in different
18
+ # contexts that are used by examples later on in this file.
19
+
20
+ extend AygabtuSeesRoutes
21
+ include Aygabtu::RSpec.example_group_module
22
+
23
+ aygabtu_sees_routes do
24
+ get 'bogus', identified_by(:controller_route).merge(to: 'controller_a#bogus')
25
+
26
+ namespace "namespace" do
27
+ get 'bogus', identified_by(:namespaced_controller_route).merge(to: 'controller_a#bogus')
28
+
29
+ get 'bogus', identified_by(:namespaced_and_named).merge(to: 'bogus#bogus', as: 'name')
30
+
31
+ namespace :another_namespace do
32
+ get 'bogus', identified_by(:deeply_namespaced).merge(to: 'controller_a#bogus')
33
+ end
34
+ end
35
+
36
+ get 'bogus', identified_by(:action_route).merge(to: 'bogus#some_action')
37
+ get 'bogus', identified_by(:another_action_route).merge(to: 'bogus#other_action')
38
+
39
+ get ':segment', identified_by(:with_segment).merge(to: 'bogus#bogus')
40
+ get '*glob', identified_by(:with_glob).merge(to: 'bogus#bogus')
41
+
42
+ get ':first_segment/:second_segment', identified_by(:two_segments).merge(to: 'bogus#bogus')
43
+
44
+ get 'implicitly_named', identified_by(:implicitly_named).merge(to: 'bogus#bogus')
45
+ get 'bogus', identified_by(:explicitly_named).merge(to: 'bogus#bogus', as: :explicitly_named)
46
+ end
47
+
48
+ controller(:controller_a) do
49
+ routes_for_scope['controller controller_a'] = aygabtu_matching_routes
50
+ end
51
+
52
+ controller('namespace/controller_a') do
53
+ routes_for_scope['controller namespace/controller_a'] = aygabtu_matching_routes
54
+ end
55
+
56
+ action(:some_action) do
57
+ routes_for_scope['action some_action'] = aygabtu_matching_routes
58
+ end
59
+
60
+ action(:some_action, :other_action) do
61
+ routes_for_scope['action with multiple args'] = aygabtu_matching_routes
62
+ end
63
+
64
+ namespace('namespace') do
65
+ routes_for_scope['namespace namespace'] = aygabtu_matching_routes
66
+
67
+ controller(:controller_a) do
68
+ routes_for_scope['namespace namespace controller controller_a'] = aygabtu_matching_routes
69
+ end
70
+
71
+ namespace(:another_namespace) do
72
+ routes_for_scope['namespace namespace namespace another_namespace'] = aygabtu_matching_routes
73
+ end
74
+ end
75
+
76
+ namespace('namespace/another_namespace') do
77
+ routes_for_scope['namespace namespace/another_namespace'] = aygabtu_matching_routes
78
+ end
79
+
80
+ named(:implicitly_named) do
81
+ routes_for_scope['named implicitly_named'] = aygabtu_matching_routes
82
+ end
83
+
84
+ named(:explicitly_named) do
85
+ routes_for_scope['named explicitly_named'] = aygabtu_matching_routes
86
+ end
87
+
88
+ named(:explicitly_named, :implicitly_named) do
89
+ routes_for_scope['named with multiple args'] = aygabtu_matching_routes
90
+ end
91
+
92
+ requiring(:segment) do
93
+ routes_for_scope['requiring segment'] = aygabtu_matching_routes
94
+ end
95
+
96
+ requiring(:glob) do
97
+ routes_for_scope['requiring glob'] = aygabtu_matching_routes
98
+ end
99
+
100
+ requiring(:first_segment, :second_segment) do
101
+ routes_for_scope['requiring multiple args'] = aygabtu_matching_routes
102
+ end
103
+
104
+ dynamic_routes do
105
+ routes_for_scope['dynamic_routes'] = aygabtu_matching_routes
106
+ end
107
+
108
+ static_routes do
109
+ routes_for_scope['static_routes'] = aygabtu_matching_routes
110
+ end
111
+
112
+ namespace(:namespace).named(:namespace_name) do
113
+ routes_for_scope['namespaced and named'] = aygabtu_matching_routes
114
+ end
115
+ end
116
+
117
+ context "setup for the remaining scope" do
118
+ # This context contains no examples, but collects matching routes in different
119
+ # contexts that are used by examples later on in this file.
120
+
121
+ extend AygabtuSeesRoutes
122
+ include Aygabtu::RSpec.example_group_module
123
+
124
+ aygabtu_sees_routes do
125
+ get 'bogus', identified_by(:visited_initially).merge(to: 'bogus#visited_initially')
126
+ get 'bogus', identified_by(:remaining_initially).merge(to: 'bogus#remaining_initially')
127
+ get 'bogus', identified_by(:remaining_eventually).merge(to: 'bogus#remaining_eventually')
128
+ end
129
+
130
+ # don't generate examples here so we can use visit etc.
131
+ def aygabtu_example_for(*) end
132
+
133
+ action(:visited_initially).visit
134
+
135
+ routes_for_scope['examples for remaining, remaining after initial visit'] =
136
+ aygabtu_matching_routes(remaining)
137
+
138
+ remaining do
139
+ routes_for_scope['examples for remaining, nested in remaining, after initial visit'] =
140
+ aygabtu_matching_routes
141
+
142
+ action(:remaining_initially).visit
143
+
144
+ routes_for_scope['examples for remaining, nested in remaining, after nested visit'] =
145
+ aygabtu_matching_routes
146
+ action(:remaining_initially).visit # this would generate an exception when matching no
147
+ # route. we do not rely on that alone by capturing matching routes immediately above
148
+
149
+ routes_for_scope['examples for remaining, nested in remaining, remaining after final visit'] = aygabtu_matching_routes(remaining)
150
+ remaining do
151
+ routes_for_scope['examples for remaining, nested in remaining, nested after final visit'] = aygabtu_matching_routes
152
+ end
153
+ end
154
+ end
155
+
156
+ include IdentifiesRoutes
157
+ include MatcherShims
158
+
159
+ describe 'matching routes' do
160
+ # use the :scope metadata to define an example group's routes
161
+ def self.routes
162
+ @routes ||= routes_for_scope.delete(metadata.fetch(:scope)) || raise("bad scope key?")
163
+ end
164
+
165
+ # make these routes available to the group's examples
166
+ def routes
167
+ self.class.routes
168
+ end
169
+
170
+ shared_examples_for "namespaced controller scoping" do
171
+ it "does not match unnamespaced controller route" do
172
+ expect(routes).not_to include(be_identified_by(:controller_route))
173
+ end
174
+
175
+ it "matches namespaced controller route" do
176
+ expect(routes).to include(be_identified_by(:namespaced_controller_route))
177
+ end
178
+
179
+ it "does not match controller route namespaced deeper" do
180
+ expect(routes).not_to include(be_identified_by(:deeply_namespaced))
181
+ end
182
+ end
183
+
184
+ describe 'controller scoping' do
185
+ context "scope", scope: 'controller controller_a' do
186
+ it "matches unnamespaced controller route" do
187
+ expect(routes).to include(be_identified_by(:controller_route))
188
+ end
189
+
190
+ it "does not match namespaced controller route" do
191
+ expect(routes).not_to include(be_identified_by(:namespaced_controller_route))
192
+ end
193
+ end
194
+
195
+ context "scope", scope: 'controller namespace/controller_a' do
196
+ include_examples "namespaced controller scoping"
197
+ end
198
+ end
199
+
200
+ describe 'namespace scoping' do
201
+ context "scope", scope: 'namespace namespace' do
202
+ it "matches namespaced route" do
203
+ expect(routes).to contain_exactly(
204
+ be_identified_by(:namespaced_controller_route),
205
+ be_identified_by(:namespaced_and_named),
206
+ be_identified_by(:deeply_namespaced)
207
+ )
208
+ end
209
+ end
210
+
211
+ shared_examples_for "namespace nesting" do
212
+ it "matches deeply namespaced route" do
213
+ expect(routes).to contain_exactly(be_identified_by(:deeply_namespaced))
214
+ end
215
+ end
216
+
217
+ context "scope", scope: 'namespace namespace namespace another_namespace' do
218
+ include_examples "namespace nesting"
219
+ end
220
+
221
+ context "scope", scope: 'namespace namespace/another_namespace' do
222
+ include_examples "namespace nesting"
223
+ end
224
+ end
225
+
226
+ describe 'combined namespace controller scoping' do
227
+ context "scope", scope: 'namespace namespace controller controller_a' do
228
+ include_examples "namespaced controller scoping"
229
+ end
230
+ end
231
+
232
+ describe 'action scoping' do
233
+ context "scope", scope: 'action some_action' do
234
+ it "matches route with given action" do
235
+ expect(routes).to contain_exactly(be_identified_by(:action_route))
236
+ end
237
+ end
238
+
239
+ context "scope", scope: 'action with multiple args' do
240
+ it "matches routes with given actions" do
241
+ expect(routes).to contain_exactly(
242
+ be_identified_by(:action_route),
243
+ be_identified_by(:another_action_route)
244
+ )
245
+ end
246
+ end
247
+ end
248
+
249
+ describe 'named scoping' do
250
+ context "scope", scope: 'named implicitly_named' do
251
+ it "matches implicitly named route" do
252
+ expect(routes).to contain_exactly(be_identified_by(:implicitly_named))
253
+ end
254
+ end
255
+
256
+ context "scope", scope: 'named explicitly_named' do
257
+ it "matches explicitly named route" do
258
+ expect(routes).to contain_exactly(be_identified_by(:explicitly_named))
259
+ end
260
+ end
261
+
262
+ context "scope", scope: 'named with multiple args' do
263
+ it "matches given named routes" do
264
+ expect(routes).to contain_exactly(
265
+ be_identified_by(:explicitly_named),
266
+ be_identified_by(:implicitly_named)
267
+ )
268
+ end
269
+ end
270
+ end
271
+
272
+ describe 'requiring scoping' do
273
+ context "scope", scope: 'requiring segment' do
274
+ it "matches route requiring given segment" do
275
+ expect(routes).to contain_exactly(be_identified_by(:with_segment))
276
+ end
277
+ end
278
+
279
+ context "scope", scope: 'requiring glob' do
280
+ it "matches route requiring given glob" do
281
+ expect(routes).to contain_exactly(be_identified_by(:with_glob))
282
+ end
283
+ end
284
+
285
+ context "scope", scope: 'requiring multiple args' do
286
+ it "matches route requiring given segments" do
287
+ expect(routes).to contain_exactly(be_identified_by(:two_segments))
288
+ end
289
+ end
290
+ end
291
+
292
+ describe "static_routes / dynamic_routes scoping" do
293
+ context "scope", scope: 'dynamic_routes' do
294
+ it "matches route requiring any segment or glob" do
295
+ expect(routes).to contain_exactly(
296
+ be_identified_by(:with_segment),
297
+ be_identified_by(:with_glob),
298
+ be_identified_by(:two_segments)
299
+ )
300
+ end
301
+ end
302
+
303
+ context "scope", scope: 'static_routes' do
304
+ it "matches route not requiring any segment or glob" do
305
+ expect(routes).not_to be_empty
306
+ expect(routes).not_to include(be_identified_by(:with_segment))
307
+ expect(routes).not_to include(be_identified_by(:with_glob))
308
+ end
309
+ end
310
+ end
311
+
312
+ describe "combined scoping" do
313
+ context "scope", scope: 'namespaced and named' do
314
+ it "matches route matching both criteria" do
315
+ expect(routes).to include(be_identified_by(:namespaced_and_named))
316
+ end
317
+ end
318
+ end
319
+
320
+ describe "remaining scoping" do
321
+ shared_examples_for "remaining routes right after initial visit" do
322
+ it "does not match route visited before" do
323
+ expect(routes).not_to include(be_identified_by(:visited_initially))
324
+ end
325
+
326
+ it "matches routes not visited before" do
327
+ expect(routes).to include(
328
+ be_identified_by(:remaining_initially),
329
+ be_identified_by(:remaining_eventually)
330
+ )
331
+ end
332
+ end
333
+
334
+ context "scope", scope: 'examples for remaining, remaining after initial visit' do
335
+ it_behaves_like "remaining routes right after initial visit"
336
+ end
337
+
338
+ context "scope", scope: 'examples for remaining, nested in remaining, after initial visit' do
339
+ it "does not match route visited before" do
340
+ expect(routes).not_to include(be_identified_by(:visited_initially))
341
+ end
342
+
343
+ it "matches routes not visited before" do
344
+ expect(routes).to include(
345
+ be_identified_by(:remaining_initially),
346
+ be_identified_by(:remaining_eventually)
347
+ )
348
+ end
349
+ end
350
+
351
+ context "scope", scope: 'examples for remaining, nested in remaining, after nested visit' do
352
+ it_behaves_like "remaining routes right after initial visit"
353
+ end
354
+
355
+ shared_examples_for "remaining routes after nested visit" do
356
+ it "does not match route visited before" do
357
+ expect(routes).not_to include(be_identified_by(:visited_initially))
358
+ expect(routes).not_to include(be_identified_by(:remaining_initially))
359
+ end
360
+
361
+ it "matches routes not visited before" do
362
+ expect(routes).to include(be_identified_by(:remaining_eventually))
363
+ end
364
+ end
365
+
366
+ context "scope", scope: 'examples for remaining, nested in remaining, remaining after final visit' do
367
+ it_behaves_like "remaining routes after nested visit"
368
+ end
369
+
370
+ context "scope", scope: 'examples for remaining, nested in remaining, nested after final visit' do
371
+ it_behaves_like "remaining routes after nested visit"
372
+ end
373
+ end
374
+ end
375
+
376
+ after(:all) do
377
+ next if self.class.routes_for_scope.empty?
378
+
379
+ $stderr.puts "Sanity check failed: not all saved configurations have been asserted against"
380
+ # RSpec tries hard to take full control and exit the process normally,
381
+ # so we apply a lot of force here.
382
+ Kernel.exit! 1
383
+ end
384
+ end