simple-navigation 3.14.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +10 -2
  5. data/CHANGELOG.md +400 -0
  6. data/Guardfile +4 -2
  7. data/README.md +1 -1
  8. data/gemfiles/.bundle/config +2 -0
  9. data/gemfiles/rails-3-2-stable.gemfile +10 -0
  10. data/gemfiles/rails-4-1-stable.gemfile +6 -0
  11. data/gemfiles/rails-4-2-stable.gemfile +7 -0
  12. data/generators/navigation_config/navigation_config_generator.rb +0 -1
  13. data/generators/navigation_config/templates/config/navigation.rb +18 -15
  14. data/lib/simple_navigation.rb +25 -42
  15. data/lib/simple_navigation/adapters/rails.rb +1 -24
  16. data/lib/simple_navigation/adapters/sinatra.rb +2 -11
  17. data/lib/simple_navigation/config_file.rb +36 -0
  18. data/lib/simple_navigation/config_file_finder.rb +42 -0
  19. data/lib/simple_navigation/{core/configuration.rb → configuration.rb} +7 -1
  20. data/lib/simple_navigation/{rendering/helpers.rb → helpers.rb} +0 -4
  21. data/lib/simple_navigation/{core/item.rb → item.rb} +76 -85
  22. data/lib/simple_navigation/{core/item_adapter.rb → item_adapter.rb} +3 -17
  23. data/lib/simple_navigation/{core/item_container.rb → item_container.rb} +23 -14
  24. data/lib/simple_navigation/{core/items_provider.rb → items_provider.rb} +0 -0
  25. data/lib/simple_navigation/railtie.rb +7 -0
  26. data/lib/simple_navigation/renderer.rb +12 -0
  27. data/lib/simple_navigation/{rendering/renderer → renderer}/base.rb +1 -1
  28. data/lib/simple_navigation/{rendering/renderer → renderer}/breadcrumbs.rb +0 -0
  29. data/lib/simple_navigation/{rendering/renderer → renderer}/json.rb +2 -0
  30. data/lib/simple_navigation/{rendering/renderer → renderer}/links.rb +0 -0
  31. data/lib/simple_navigation/{rendering/renderer → renderer}/list.rb +0 -0
  32. data/lib/simple_navigation/{rendering/renderer → renderer}/text.rb +0 -0
  33. data/lib/simple_navigation/version.rb +1 -1
  34. data/simple-navigation.gemspec +5 -4
  35. data/spec/fake_app/config/navigation.rb +6 -0
  36. data/spec/fake_app/rails_app.rb +35 -0
  37. data/spec/initializers/coveralls.rb +3 -0
  38. data/spec/initializers/have_css_matcher.rb +8 -3
  39. data/spec/initializers/memfs.rb +7 -0
  40. data/spec/initializers/rails.rb +4 -0
  41. data/spec/initializers/rspec.rb +7 -0
  42. data/spec/integration/rendering_navigation_spec.rb +12 -0
  43. data/spec/{lib/simple_navigation → simple_navigation}/adapters/padrino_spec.rb +0 -2
  44. data/spec/{lib/simple_navigation → simple_navigation}/adapters/rails_spec.rb +36 -93
  45. data/spec/{lib/simple_navigation → simple_navigation}/adapters/sinatra_spec.rb +4 -6
  46. data/spec/simple_navigation/config_file_finder_spec.rb +50 -0
  47. data/spec/simple_navigation/config_file_spec.rb +25 -0
  48. data/spec/{lib/simple_navigation/core → simple_navigation}/configuration_spec.rb +29 -19
  49. data/spec/{lib/simple_navigation/rendering → simple_navigation}/helpers_spec.rb +10 -13
  50. data/spec/{lib/simple_navigation/core → simple_navigation}/item_adapter_spec.rb +14 -11
  51. data/spec/{lib/simple_navigation/core → simple_navigation}/item_container_spec.rb +130 -42
  52. data/spec/simple_navigation/item_spec.rb +467 -0
  53. data/spec/{lib/simple_navigation/core → simple_navigation}/items_provider_spec.rb +1 -3
  54. data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/base_spec.rb +34 -36
  55. data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/breadcrumbs_spec.rb +4 -7
  56. data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/json_spec.rb +5 -11
  57. data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/links_spec.rb +5 -8
  58. data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/list_spec.rb +4 -7
  59. data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/text_spec.rb +4 -7
  60. data/spec/simple_navigation_spec.rb +190 -0
  61. data/spec/spec_helper.rb +29 -35
  62. metadata +103 -68
  63. data/CHANGELOG +0 -292
  64. data/lib/simple_navigation/core.rb +0 -5
  65. data/lib/simple_navigation/rails_controller_methods.rb +0 -164
  66. data/lib/simple_navigation/rendering.rb +0 -12
  67. data/rails/init.rb +0 -1
  68. data/spec/lib/simple_navigation/core/item_spec.rb +0 -703
  69. data/spec/lib/simple_navigation/rails_controller_methods_spec.rb +0 -270
  70. data/spec/lib/simple_navigation_spec.rb +0 -300
@@ -1,5 +0,0 @@
1
- require 'simple_navigation/core/configuration'
2
- require 'simple_navigation/core/item_adapter'
3
- require 'simple_navigation/core/item'
4
- require 'simple_navigation/core/item_container'
5
- require 'simple_navigation/core/items_provider'
@@ -1,164 +0,0 @@
1
- module SimpleNavigation
2
- def self.explicit_navigation_args
3
- adapter.controller.instance_variable_get(:'@sn_current_navigation_args')
4
- end
5
-
6
- # Reads the current navigation for the specified level from the controller.
7
- # Returns nil if there is no current navigation set for level.
8
- def self.current_navigation_for(level)
9
- adapter.controller.instance_variable_get(:"@sn_current_navigation_#{level}")
10
- end
11
-
12
- # If any navigation has been explicitely set in the controller this method
13
- # evaluates the specified args set in the controller and sets the correct
14
- # instance variable in the controller.
15
- def self.handle_explicit_navigation
16
- return unless explicit_navigation_args
17
- level, navigation = parse_explicit_navigation_args
18
- navigation_level = :"@sn_current_navigation_#{level}"
19
- adapter.controller.instance_variable_set(navigation_level, navigation)
20
- end
21
-
22
- def self.parse_explicit_navigation_args
23
- args = if explicit_navigation_args.empty?
24
- [{}]
25
- else
26
- explicit_navigation_args
27
- end
28
- indexed_args = args_indexed_by_level(args)
29
- deepest = deepest_level_and_item(indexed_args)
30
-
31
- if deepest.first.zero?
32
- fail ArgumentError, 'Invalid level specified or item key not found'
33
- end
34
-
35
- deepest
36
- end
37
-
38
- private
39
-
40
- def self.deepest_level_and_item(navigation_args)
41
- navigation_args.map { |k, v| [k.to_s[/level_(\d)/, 1].to_i, v] }
42
- .max
43
- end
44
-
45
- def self.args_indexed_by_level(navigation_args)
46
- if navigation_args.first.is_a?(Hash)
47
- navigation_args.first
48
- elsif navigation_args.size == 1
49
- level = primary_navigation.level_for_item(navigation_args.first)
50
- level ? { :"level_#{level}" => navigation_args.first } : {}
51
- else
52
- navigation_args.each_with_index
53
- .with_object({}) do |(arg, i), h|
54
- h[:"level_#{i + 1}"] = arg
55
- end
56
- end
57
- end
58
-
59
- # Adds methods for explicitely setting the current 'active' navigation to
60
- # the controllers.
61
- # Since version 2.0.0 the simple_navigation plugin determines the active
62
- # navigation based on the current url by default (auto highlighting),
63
- # so explicitely defining the active navigation in the controllers is only
64
- # needed for edge cases where automatic highlighting does not work.
65
- #
66
- # On the controller class level, use the <tt>navigation</tt> method to set the
67
- # active navigation for all actions in the controller.
68
- # Let's assume that we have a primary navigation item :account which in turn
69
- # has a sub navigation item :settings.
70
- #
71
- # ==== Examples
72
- # class AccountController << ActionController
73
- # navigation :account
74
- # ...
75
- # end
76
- #
77
- # class AccountSettingsController << ActionController
78
- # navigation :settings
79
- # ...
80
- # end
81
- #
82
- # The first example sets the current primary navigation to :account for all
83
- # actions. No active sub_navigation.
84
- # The second example sets the current sub navigation to :settings and since
85
- # it is a child of :account the current primary navigation is set to :account.
86
- #
87
- # On the controller instance level, use the <tt>current_navigation</tt> method
88
- # to define the active navigation for a specific action.
89
- # The navigation item that is set in <tt>current_navigation</tt> overrides the
90
- # one defined on the controller class level (see <tt>navigation</tt> method).
91
- # Thus if you have an :account primary item with a :special
92
- # sub navigation item:
93
- #
94
- # ==== Example
95
- # class AccountController << ActionController
96
- # navigation :account
97
- #
98
- # def your_special_action
99
- # ...
100
- # current_navigation :special
101
- # end
102
- # end
103
- #
104
- # The code above still sets the active primary navigation to :account for all
105
- # actions, but sets the sub_navigation to :account -> :special for
106
- # 'your_special_action'.
107
- #
108
- # Note 1: As you can see above you just have to set the navigation item of
109
- # your 'deepest' navigation level as active and all its parents are
110
- # marked as active, too.
111
- #
112
- # Note 2: The specified symbols must match the keys for your navigation
113
- # items in your config/navigation.rb file.
114
- module ControllerMethods
115
- def self.included(base) #:nodoc:
116
- base.class_eval do
117
- extend ClassMethods
118
- include InstanceMethods
119
- end
120
- end
121
-
122
- module ClassMethods
123
- # Sets the active navigation for all actions in this controller.
124
- #
125
- # The specified symbol must match the keys for your navigation items
126
- # in your config/navigation.rb file.
127
- def navigation(*args)
128
- class_eval do
129
- define_method :sn_set_navigation do
130
- current_navigation(*args)
131
- end
132
- protected :sn_set_navigation
133
- before_filter :sn_set_navigation
134
- end
135
- end
136
- end
137
-
138
- module InstanceMethods
139
- # Sets the active navigation. Call this method in any action to override
140
- # the controller-wide active navigation specified by navigation.
141
- #
142
- # The specified symbol must match the keys for your navigation items in
143
- # your config/navigation.rb file.
144
- def current_navigation(*args)
145
- @sn_current_navigation_args = args
146
- end
147
- end
148
- end
149
-
150
- class Item
151
- def selected_by_config?
152
- key == SimpleNavigation.current_navigation_for(container.level)
153
- end
154
- end
155
-
156
- class ItemContainer
157
- def selected_item
158
- self[SimpleNavigation.current_navigation_for(level)] ||
159
- items.find(&:selected?)
160
- end
161
- end
162
- end
163
-
164
- ActionController::Base.send(:include, SimpleNavigation::ControllerMethods)
@@ -1,12 +0,0 @@
1
- require 'simple_navigation/rendering/helpers'
2
- require 'simple_navigation/rendering/renderer/base'
3
-
4
- module SimpleNavigation
5
- module Renderer
6
- autoload :List, 'simple_navigation/rendering/renderer/list'
7
- autoload :Links, 'simple_navigation/rendering/renderer/links'
8
- autoload :Breadcrumbs, 'simple_navigation/rendering/renderer/breadcrumbs'
9
- autoload :Text, 'simple_navigation/rendering/renderer/text'
10
- autoload :Json, 'simple_navigation/rendering/renderer/json'
11
- end
12
- end
data/rails/init.rb DELETED
@@ -1 +0,0 @@
1
- SimpleNavigation.register
@@ -1,703 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module SimpleNavigation
4
- describe Item do
5
- let!(:item_container) { ItemContainer.new }
6
-
7
- let(:adapter) { double(:adapter) }
8
- let(:item_args) { [item_container, :my_key, 'name', url, options, items] }
9
- let(:item) { Item.new(*item_args) }
10
- let(:items) { nil }
11
- let(:options) { Hash.new }
12
- let(:url) { 'url' }
13
-
14
- before { SimpleNavigation.stub(adapter: adapter) }
15
-
16
- describe '#initialize' do
17
- context 'when there is a sub_navigation' do
18
- let(:subnav_container) { double(:subnav_container).as_null_object }
19
-
20
- before { ItemContainer.stub(new: subnav_container) }
21
-
22
- context 'when a block is given' do
23
- it 'creates a new ItemContainer with a level+1' do
24
- expect(ItemContainer).to receive(:new).with(2)
25
- Item.new(*item_args) {}
26
- end
27
-
28
- it 'calls the block' do
29
- expect{ |blk|
30
- Item.new(*item_args, &blk)
31
- }.to yield_with_args(subnav_container)
32
- end
33
- end
34
-
35
- context 'when no block is given' do
36
- context 'and items are given' do
37
- let(:items) { double(:items) }
38
-
39
- it 'creates a new ItemContainer with a level+1' do
40
- expect(ItemContainer).to receive(:new).with(2)
41
- Item.new(*item_args)
42
- end
43
-
44
- it "sets the items on the subnav_container" do
45
- expect(subnav_container).to receive(:items=).with(items)
46
- Item.new(*item_args)
47
- end
48
- end
49
-
50
- context 'and no items are given' do
51
- it "doesn't create a new ItemContainer" do
52
- expect(ItemContainer).not_to receive(:new)
53
- Item.new(*item_args)
54
- end
55
- end
56
- end
57
- end
58
-
59
- context 'when a :method option is given' do
60
- let(:options) {{ method: :delete }}
61
-
62
- it "sets the item's method" do
63
- expect(item.method).to eq :delete
64
- end
65
-
66
- it 'sets the html options without the method' do
67
- meth = item.instance_variable_get(:@html_options).key?(:method)
68
- expect(meth).to be_false
69
- end
70
- end
71
-
72
- context 'when no :method option is given' do
73
- it "sets the item's method to nil" do
74
- expect(item.method).to be_nil
75
- end
76
- end
77
-
78
- context 'setting class and id on the container' do
79
- let!(:create) { item }
80
-
81
- let(:options) {{
82
- container_class: 'container_class',
83
- container_id: 'container_id',
84
- container_attributes: { 'ng-show' => 'false' }
85
- }}
86
-
87
- it "fills in the container's dom_attributes" do
88
- expect(item_container.dom_attributes).to eq({
89
- id: 'container_id',
90
- class: 'container_class',
91
- 'ng-show' => 'false'
92
- })
93
- end
94
- end
95
-
96
- context 'when a :highlights_on option is given' do
97
- it "sets the item's highlights_on to nil" do
98
- expect(item.highlights_on).to be_nil
99
- end
100
- end
101
-
102
- context 'when no :highlights_on option is given' do
103
- let(:highlights_on) { double(:highlights_on) }
104
- let(:options) {{ highlights_on: highlights_on }}
105
-
106
- it "sets the item's highlights_on" do
107
- expect(item.highlights_on).to eq highlights_on
108
- end
109
-
110
- it 'sets the html options without the method' do
111
- html_options = item.instance_variable_get(:@html_options)
112
- expect(html_options).not_to have_key(:highlights_on)
113
- end
114
- end
115
-
116
- context 'when a url is given' do
117
- context 'and it is a string' do
118
- it "sets the item's url accordingly" do
119
- expect(item.url).to eq 'url'
120
- end
121
- end
122
-
123
- context 'and it is a proc' do
124
- let(:url) { proc{ "my_" + "url" } }
125
-
126
- it "sets the item's url accordingly" do
127
- expect(item.url).to eq 'my_url'
128
- end
129
- end
130
-
131
- context 'and it is nil' do
132
- let(:url) { nil }
133
-
134
- it "sets the item's url accordingly" do
135
- expect(item.url).to be_nil
136
- end
137
- end
138
- end
139
-
140
- describe 'Optional url and optional options' do
141
- context 'when no parameter is specified' do
142
- let(:item_args) { [item_container, :my_key, 'name'] }
143
-
144
- it "sets the item's url to nil" do
145
- expect(item.url).to be_nil
146
- end
147
-
148
- it "sets the item's html_options to an empty hash" do
149
- expect(item.instance_variable_get(:@html_options)).to eq({})
150
- end
151
- end
152
-
153
- context 'when only a url is given' do
154
- let(:item_args) { [item_container, :my_key, 'name', 'url'] }
155
-
156
- it "set the item's url accordingly" do
157
- expect(item.url).to eq 'url'
158
- end
159
-
160
- it "sets the item's html_options to an empty hash" do
161
- expect(item.instance_variable_get(:@html_options)).to eq({})
162
- end
163
- end
164
-
165
- context 'when only options are given' do
166
- let(:item_args) { [item_container, :my_key, 'name', { option: true }] }
167
-
168
- it "sets the item's url to nil" do
169
- expect(item.url).to be_nil
170
- end
171
-
172
- it "sets the item's html_options accordingly" do
173
- html_options = item.instance_variable_get(:@html_options)
174
- expect(html_options).to eq({ option: true })
175
- end
176
- end
177
-
178
- context 'when url and options are given' do
179
- let(:options) {{ option: true }}
180
-
181
- it "set the item's url accordingly" do
182
- expect(item.url).to eq 'url'
183
- end
184
-
185
- it "sets the item's html_options accordingly" do
186
- html_options = item.instance_variable_get(:@html_options)
187
- expect(html_options).to eq({ option: true })
188
- end
189
- end
190
- end
191
- end
192
-
193
- describe '#name' do
194
- before do
195
- SimpleNavigation.config.stub(
196
- name_generator: proc{ |name| "<span>#{name}</span>" })
197
- end
198
-
199
- context 'when no option is given' do
200
- context 'and the name_generator uses only the name' do
201
- it 'uses the default name_generator' do
202
- expect(item.name).to eq '<span>name</span>'
203
- end
204
- end
205
-
206
- context 'and the name_generator uses only the item itself' do
207
- before do
208
- SimpleNavigation.config.stub(
209
- name_generator: proc{ |name, item| "<span>#{item.key}</span>" })
210
- end
211
-
212
- it 'uses the default name_generator' do
213
- expect(item.name).to eq '<span>my_key</span>'
214
- end
215
- end
216
- end
217
-
218
- context 'when the :apply_generator is false' do
219
- it "returns the item's name" do
220
- expect(item.name(apply_generator: false)).to eq 'name'
221
- end
222
- end
223
- end
224
-
225
- describe '#selected?' do
226
- context 'when the item is explicitly selected' do
227
- before { item.stub(selected_by_config?: true) }
228
-
229
- it 'is selected' do
230
- expect(item).to be_selected
231
- end
232
-
233
- # FIXME: testing the implementation not the behavior here
234
- it "doesn't check for selection by sub navigation" do
235
- expect(item).not_to receive(:selected_by_subnav?)
236
- item.selected?
237
- end
238
-
239
- # FIXME: testing the implementation not the behavior here
240
- it "doesn't check for selection by highlighting condition" do
241
- expect(item).not_to receive(:selected_by_condition?)
242
- item.selected?
243
- end
244
- end
245
-
246
- context "when the item isn't explicitly selected" do
247
- before { item.stub(selected_by_config?: false) }
248
-
249
- context 'and it is selected by sub navigation' do
250
- before { item.stub(selected_by_subnav?: true) }
251
-
252
- it 'is selected' do
253
- expect(item).to be_selected
254
- end
255
- end
256
-
257
- context "and it isn't selected by sub navigation" do
258
- before { item.stub(selected_by_subnav?: false) }
259
-
260
- context 'and it is selected by a highlighting condition' do
261
- before { item.stub(selected_by_condition?: true) }
262
-
263
- it 'is selected' do
264
- expect(item).to be_selected
265
- end
266
- end
267
-
268
- context "and it isn't selected by any highlighting condition" do
269
- before { item.stub(selected_by_condition?: false) }
270
-
271
- it "isn't selected" do
272
- expect(item).not_to be_selected
273
- end
274
- end
275
- end
276
- end
277
- end
278
-
279
- describe '#selected_class' do
280
- context 'when the item is selected' do
281
- before { item.stub(selected?: true) }
282
-
283
- it 'returns the default selected_class' do
284
- expect(item.selected_class).to eq 'selected'
285
- end
286
-
287
- context 'and selected_class is defined in the context' do
288
- before { item_container.stub(selected_class: 'defined') }
289
-
290
- it "returns the context's selected_class" do
291
- expect(item.selected_class).to eq 'defined'
292
- end
293
- end
294
- end
295
-
296
- context 'when the item is not selected' do
297
- before { item.stub(selected?: false) }
298
-
299
- it 'returns nil' do
300
- expect(item.selected_class).to be_nil
301
- end
302
- end
303
- end
304
-
305
- describe ':html_options argument' do
306
- let(:selected_classes) { 'selected simple-navigation-active-leaf' }
307
-
308
- context 'when the :class option is given' do
309
- let(:options) {{ class: 'my_class' }}
310
-
311
- context 'and the item is selected' do
312
- before { item.stub(selected?: true, selected_by_condition?: true) }
313
-
314
- it "adds the specified class to the item's html classes" do
315
- expect(item.html_options[:class]).to include('my_class')
316
- end
317
-
318
- it "doesn't replace the default html classes of a selected item" do
319
- expect(item.html_options[:class]).to include(selected_classes)
320
- end
321
- end
322
-
323
- context "and the item isn't selected" do
324
- before { item.stub(selected?: false, selected_by_condition?: false) }
325
-
326
- it "sets the specified class as the item's html classes" do
327
- expect(item.html_options[:class]).to include('my_class')
328
- end
329
- end
330
- end
331
-
332
- context "when the :class option isn't given" do
333
- context 'and the item is selected' do
334
- before { item.stub(selected?: true, selected_by_condition?: true) }
335
-
336
- it "sets the default html classes of a selected item" do
337
- expect(item.html_options[:class]).to include(selected_classes)
338
- end
339
- end
340
-
341
- context "and the item isn't selected" do
342
- before { item.stub(selected?: false, selected_by_condition?: false) }
343
-
344
- it "doesn't set any html class on the item" do
345
- expect(item.html_options[:class]).to be_blank
346
- end
347
- end
348
- end
349
-
350
- shared_examples 'generating id' do |id|
351
- it "sets the item's html id to the specified id" do
352
- expect(item.html_options[:id]).to eq id
353
- end
354
- end
355
-
356
- describe 'when the :id option is given' do
357
- let(:options) {{ id: 'my_id' }}
358
-
359
- before do
360
- item.stub(selected?: false,
361
- selected_by_condition?: false,
362
- autogenerate_item_ids?: generate_ids)
363
- end
364
-
365
- context 'and :autogenerate_item_ids is true' do
366
- let(:generate_ids) { true }
367
-
368
- it_behaves_like 'generating id', 'my_id'
369
- end
370
-
371
- context 'and :autogenerate_item_ids is false' do
372
- let(:generate_ids) { false }
373
-
374
- it_behaves_like 'generating id', 'my_id'
375
- end
376
- end
377
-
378
- context "when the :id option isn't given" do
379
- before do
380
- item.stub(selected?: false,
381
- selected_by_condition?: false,
382
- autogenerate_item_ids?: generate_ids)
383
- end
384
-
385
- context 'and :autogenerate_item_ids is true' do
386
- let(:generate_ids) { true }
387
-
388
- it_behaves_like 'generating id', 'my_key'
389
- end
390
-
391
- context 'and :autogenerate_item_ids is false' do
392
- let(:generate_ids) { false }
393
-
394
- it "doesn't set any html id on the item" do
395
- expect(item.html_options[:id]).to be_blank
396
- end
397
- end
398
- end
399
- end
400
-
401
- describe '#selected_by_subnav?' do
402
- before { item.stub(sub_navigation: sub_navigation) }
403
-
404
- context 'the item has a sub_navigation' do
405
- let(:sub_navigation) { double(:sub_navigation) }
406
-
407
- context 'and an item of the sub_navigation is selected' do
408
- before do
409
- sub_navigation.stub(selected?: true, selected_by_condition?: true)
410
- end
411
-
412
- it 'returns true' do
413
- expect(item).to be_selected_by_subnav
414
- end
415
- end
416
-
417
- context 'and no item of the sub_navigation is selected' do
418
- before do
419
- sub_navigation.stub(selected?: false, selected_by_condition?: true)
420
- end
421
-
422
- it 'returns false' do
423
- expect(item).not_to be_selected_by_subnav
424
- end
425
- end
426
- end
427
-
428
- context "when the item doesn't have any sub_navigation" do
429
- let(:sub_navigation) { nil }
430
-
431
- it 'returns false' do
432
- expect(item).not_to be_selected_by_subnav
433
- end
434
- end
435
- end
436
-
437
- describe '#selected_by_condition?' do
438
- let(:current_url) { '' }
439
-
440
- before { adapter.stub(request_uri: current_url) }
441
-
442
- context 'when the :highlights_on option is set' do
443
- before { item.stub(highlights_on: /^\/matching/) }
444
-
445
- context 'and :highlights_on is a regexp' do
446
- context 'and it matches the current url' do
447
- let(:current_url) { '/matching_url' }
448
-
449
- it 'returns true' do
450
- expect(item).to be_selected_by_condition
451
- end
452
- end
453
-
454
- context "and it doesn't match current url" do
455
- let(:current_url) { '/other_url' }
456
-
457
- it 'returns false' do
458
- expect(item).not_to be_selected_by_condition
459
- end
460
- end
461
- end
462
-
463
- context 'and :highlights_on is a lambda' do
464
- context 'and it is truthy' do
465
- before { item.stub(highlights_on: ->{ true }) }
466
-
467
- it 'returns true' do
468
- expect(item).to be_selected_by_condition
469
- end
470
- end
471
-
472
- context 'falsey lambda results in no selection' do
473
- before { item.stub(highlights_on: ->{ false }) }
474
-
475
- it 'returns false' do
476
- expect(item).not_to be_selected_by_condition
477
- end
478
- end
479
- end
480
-
481
- context 'and :highlights_on is :subpath' do
482
- before { item.stub(url: '/path', highlights_on: :subpath) }
483
-
484
- context "and the current url is a sub path of the item's url" do
485
- let(:current_url) { '/path/sub-path' }
486
-
487
- it 'returns true' do
488
- expect(item).to be_selected_by_condition
489
- end
490
- end
491
-
492
- context "and the current url starts with item's url" do
493
- let(:current_url) { '/path_group/id' }
494
-
495
- it 'returns false' do
496
- expect(item).not_to be_selected_by_condition
497
- end
498
- end
499
-
500
- context "and the current url is totally different from the item's url" do
501
- let(:current_url) { '/other_path/id' }
502
-
503
- it 'returns false' do
504
- expect(item).not_to be_selected_by_condition
505
- end
506
- end
507
- end
508
-
509
- context 'when :highlights_on something else' do
510
- before { item.stub(highlights_on: 'nothing') }
511
-
512
- it 'raises an exception' do
513
- expect{ item.send(:selected_by_condition?) }.to raise_error
514
- end
515
- end
516
- end
517
-
518
- context 'when :auto_highlight is true' do
519
- before { item.stub(auto_highlight?: true) }
520
-
521
- context 'and root path matches' do
522
- before { item.stub(root_path_match?: true) }
523
-
524
- it 'returns true' do
525
- expect(item).to be_selected_by_condition
526
- end
527
- end
528
-
529
- context "and root path doesn't match" do
530
- before { item.stub(root_path_match?: false) }
531
-
532
- context "and the current url matches the item's url" do
533
- let(:url) { 'url#anchor' }
534
-
535
- before { adapter.stub(current_page?: true) }
536
-
537
- it 'returns true' do
538
- expect(item).to be_selected_by_condition
539
- end
540
-
541
- # FIXME: testing the implementation not the behavior here
542
- it "removes anchors before testing the item's url" do
543
- expect(adapter).to receive(:current_page?).with('url')
544
- item.send(:selected_by_condition?)
545
- end
546
-
547
- context 'when url is nil' do
548
- let(:url) { nil }
549
-
550
- it "doesn't check the url" do
551
- expect(adapter).not_to receive(:current_page?)
552
- item.send(:selected_by_condition?)
553
- end
554
- end
555
- end
556
-
557
- context "and the current url doesn't match the item's url" do
558
- before { adapter.stub(current_page?: false) }
559
-
560
- it 'returns false' do
561
- expect(item).not_to be_selected_by_condition
562
- end
563
- end
564
- end
565
- end
566
-
567
- context 'when :auto_highlight is false' do
568
- before { item.stub(auto_highlight?: false) }
569
-
570
- it 'returns false' do
571
- expect(item).not_to be_selected_by_condition
572
- end
573
- end
574
- end
575
-
576
- describe '#root_path_match?' do
577
- context "when current url is /" do
578
- before { adapter.stub(request_path: '/') }
579
-
580
- context "and the item's url is /" do
581
- let(:url) { '/' }
582
-
583
- it 'returns true' do
584
- expect(item.send(:root_path_match?)).to be_true
585
- end
586
- end
587
-
588
- context "and the item's url isn't /" do
589
- let(:url) { '/other' }
590
-
591
- it 'returns false' do
592
- expect(item.send(:root_path_match?)).to be_false
593
- end
594
- end
595
- end
596
-
597
- context "when current url isn't /" do
598
- before { adapter.stub(request_path: '/other') }
599
-
600
- context "and the item's url is /" do
601
- let(:url) { '/' }
602
-
603
- it 'returns false' do
604
- expect(item.send(:root_path_match?)).to be_false
605
- end
606
- end
607
-
608
- context "and the item's url is nil" do
609
- let(:url) { nil }
610
-
611
- it 'returns false' do
612
- expect(item.send(:root_path_match?)).to be_false
613
- end
614
- end
615
- end
616
-
617
- context "when current url doesn't match the item's url" do
618
- let(:url) { '/path' }
619
-
620
- before { adapter.stub(request_path: '/other') }
621
-
622
- it 'returns false' do
623
- expect(item.send(:root_path_match?)).to be_false
624
- end
625
- end
626
-
627
- context "when current url doesn't match the item's url" do
628
- let(:url) { nil }
629
-
630
- before { adapter.stub(request_path: '/other') }
631
-
632
- it 'returns false' do
633
- expect(item.send(:root_path_match?)).to be_false
634
- end
635
- end
636
- end
637
-
638
- describe '#auto_highlight?' do
639
- let(:global) { double(:config) }
640
-
641
- before { SimpleNavigation.stub(config: global) }
642
-
643
- context 'when :auto_highlight is globally true' do
644
- before { global.stub(auto_highlight: true) }
645
-
646
- context "and container's :auto_highlight is true" do
647
- before { item_container.stub(auto_highlight: true) }
648
-
649
- it 'returns true' do
650
- expect(item.send(:auto_highlight?)).to be_true
651
- end
652
- end
653
-
654
- context "and container's :auto_highlight is false" do
655
- before { item_container.stub(auto_highlight: false) }
656
-
657
- it 'returns false' do
658
- expect(item.send(:auto_highlight?)).to be_false
659
- end
660
- end
661
- end
662
-
663
- context 'when :auto_highlight is globally false' do
664
- before { global.stub(auto_highlight: false) }
665
-
666
- context 'when :auto_highlight is globally true' do
667
- before { item_container.stub(auto_highlight: true) }
668
-
669
- it 'returns false' do
670
- expect(item.send(:auto_highlight?)).to be_false
671
- end
672
- end
673
-
674
- context "and container's :auto_highlight is false" do
675
- before { item_container.stub(auto_highlight: false) }
676
-
677
- it 'returns false' do
678
- expect(item.send(:auto_highlight?)).to be_false
679
- end
680
- end
681
- end
682
- end
683
-
684
- describe '#autogenerated_item_id' do
685
- context 'when no generator is configured' do
686
- let(:id_generator) { double(:id_generator) }
687
-
688
- before { SimpleNavigation.config.stub(id_generator: id_generator) }
689
-
690
- it 'calls the globally configured id generator' do
691
- expect(id_generator).to receive(:call).with(:my_key)
692
- item.send(:autogenerated_item_id)
693
- end
694
- end
695
-
696
- context 'when no generator is configured' do
697
- it 'uses the default generator' do
698
- expect(item.send(:autogenerated_item_id)).to eq 'my_key'
699
- end
700
- end
701
- end
702
- end
703
- end