aygabtu 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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