simple-navigation 3.14.0 → 4.0.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.
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,270 +0,0 @@
1
- require 'spec_helper'
2
- require 'simple_navigation/rails_controller_methods'
3
-
4
- class TestController
5
- include SimpleNavigation::ControllerMethods
6
-
7
- def self.helper_method(*args)
8
- @helper_methods = args
9
- end
10
-
11
- def self.before_filter(*args)
12
- @before_filters = args
13
- end
14
- end
15
-
16
- module SimpleNavigation
17
- describe 'Explicit navigation in rails' do
18
- it 'enhances ActionController after loading the extensions' do
19
- methods = ActionController::Base.instance_methods.map(&:to_s)
20
- expect(methods).to include 'current_navigation'
21
- end
22
- end
23
-
24
- describe ControllerMethods do
25
- let(:controller) { TestController.new }
26
-
27
- before { SimpleNavigation::Configuration.stub(:load) }
28
-
29
- describe 'when the module is included' do
30
- it 'extends the ClassMethods module' do
31
- expect(controller.class).to respond_to(:navigation)
32
- end
33
-
34
- it "includes the InstanceMethods module" do
35
- expect(controller).to respond_to(:current_navigation)
36
- end
37
- end
38
- end
39
-
40
- module ControllerMethods
41
- describe ClassMethods do
42
- let(:controller) { TestController.new }
43
-
44
- describe '#navigation' do
45
- context 'when the navigation method is not called' do
46
- it "doesn't have any instance method called 'sn_set_navigation'" do
47
- has_method = controller.respond_to?(:sn_set_navigation, true)
48
- expect(has_method).to be_false
49
- end
50
- end
51
-
52
- context 'when the navigation method is called' do
53
- before do
54
- controller.class_eval { navigation(:primary, :secondary) }
55
- end
56
-
57
- it 'creates an instance method called "sn_set_navigation"' do
58
- has_method = controller.respond_to?(:sn_set_navigation, true)
59
- expect(has_method).to be_true
60
- end
61
-
62
- it 'does not create a public method' do
63
- methods = controller.public_methods.map(&:to_s)
64
- expect(methods).not_to include 'sn_set_navigation'
65
- end
66
-
67
- it 'creates a protected method' do
68
- methods = controller.protected_methods.map(&:to_s)
69
- expect(methods).to include 'sn_set_navigation'
70
- end
71
-
72
- it 'creates a method that calls current_navigation with the specified keys' do
73
- expect(controller).to receive(:current_navigation)
74
- .with(:primary, :secondary)
75
- controller.send(:sn_set_navigation)
76
- end
77
- end
78
- end
79
- end
80
-
81
- describe InstanceMethods do
82
- let(:controller) { TestController.new }
83
-
84
- describe '#current_navigation' do
85
- shared_examples 'setting the correct sn_current_navigation_args' do |args|
86
- it 'sets the sn_current_navigation_args as specified' do
87
- controller.current_navigation(*args)
88
- args = controller.instance_variable_get(:@sn_current_navigation_args)
89
- expect(args).to eq args
90
- end
91
- end
92
-
93
- it_behaves_like 'setting the correct sn_current_navigation_args', [:first]
94
- it_behaves_like 'setting the correct sn_current_navigation_args', [:first, :second]
95
- end
96
- end
97
- end
98
-
99
- describe 'SimpleNavigation module additions' do
100
- let(:adapter) { double(:adapter, controller: controller) }
101
- let(:controller) { double(:controller) }
102
- let(:simple_navigation) { SimpleNavigation }
103
-
104
- before { simple_navigation.stub(adapter: adapter) }
105
-
106
- describe '.handle_explicit_navigation' do
107
- def args(*args)
108
- keys = args.compact.empty? ? nil : args
109
- simple_navigation.stub(explicit_navigation_args: keys)
110
- end
111
-
112
- context 'when there is an explicit navigation set' do
113
- context 'and it is a list of navigations' do
114
- before { args :first, :second, :third }
115
-
116
- it 'sets the correct instance var in the controller' do
117
- expect(controller).to receive(:instance_variable_set)
118
- .with(:@sn_current_navigation_3, :third)
119
- simple_navigation.handle_explicit_navigation
120
- end
121
- end
122
-
123
- context 'and it is a single navigation' do
124
- context 'and the specified key is a valid navigation item' do
125
- let(:primary) { double(:primary, level_for_item: 2) }
126
-
127
- before do
128
- simple_navigation.stub(primary_navigation: primary)
129
- args :key
130
- end
131
-
132
- it 'sets the correct instance var in the controller' do
133
- expect(controller).to receive(:instance_variable_set)
134
- .with(:@sn_current_navigation_2, :key)
135
- simple_navigation.handle_explicit_navigation
136
- end
137
- end
138
-
139
- context 'and the specified key is an invalid navigation item' do
140
- let(:primary) { double(:primary, level_for_item: nil) }
141
-
142
- before do
143
- subject.stub(primary_navigation: primary)
144
- args :key
145
- end
146
-
147
- it 'raises an exception' do
148
- expect{ subject.handle_explicit_navigation }.to raise_error
149
- end
150
- end
151
- end
152
-
153
- context 'and the argument is a one-level hash' do
154
- before { args level_2: :key }
155
-
156
- it 'sets the correct instance var in the controller' do
157
- expect(controller).to receive(:instance_variable_set)
158
- .with(:@sn_current_navigation_2, :key)
159
- simple_navigation.handle_explicit_navigation
160
- end
161
- end
162
-
163
- context 'when the argument is a multiple levels hash' do
164
- before { args level_2: :key, level_1: :bla }
165
-
166
- it 'sets the correct instance var in the controller' do
167
- expect(controller).to receive(:instance_variable_set)
168
- .with(:@sn_current_navigation_2, :key)
169
- simple_navigation.handle_explicit_navigation
170
- end
171
- end
172
- end
173
-
174
- context 'when no explicit navigation is set' do
175
- before { args nil }
176
-
177
- it "doesn't set the current_navigation instance var in the controller" do
178
- expect(controller).not_to receive(:instance_variable_set)
179
- simple_navigation.handle_explicit_navigation
180
- end
181
- end
182
- end
183
-
184
- describe '#current_navigation_for' do
185
- it 'accesses the correct instance var in the controller' do
186
- expect(controller).to receive(:instance_variable_get)
187
- .with(:@sn_current_navigation_1)
188
- simple_navigation.current_navigation_for(1)
189
- end
190
- end
191
- end
192
-
193
- describe Item do
194
- let(:item) { Item.new(item_container, :my_key, 'name', 'url', {}) }
195
- let(:item_container) { double(:item_container, level: 1) }
196
- let(:simple_navigation) { SimpleNavigation }
197
-
198
- before do
199
- item_container.stub(:dom_attributes=)
200
- simple_navigation.stub(current_navigation_for: navigation_key)
201
- end
202
-
203
- describe '#selected_by_config?' do
204
- context 'when the navigation explicitly set' do
205
- context 'when current matches the key' do
206
- let(:navigation_key) { :my_key }
207
-
208
- it 'selects the item' do
209
- expect(item).to be_selected_by_config
210
- end
211
- end
212
-
213
- context "when current doesn't match the key" do
214
- let(:navigation_key) { :other_key }
215
-
216
- it "doesn't select the item" do
217
- expect(item).not_to be_selected_by_config
218
- end
219
- end
220
- end
221
-
222
- context 'when the navigation is not explicitly set' do
223
- let(:navigation_key) { nil }
224
-
225
- it "doesn't select the item" do
226
- expect(item).not_to be_selected_by_config
227
- end
228
- end
229
- end
230
- end
231
-
232
- describe ItemContainer do
233
- describe '#selected_item' do
234
- let(:item_container) { SimpleNavigation::ItemContainer.new }
235
- let(:item_1) { double(:item, selected?: false) }
236
- let(:item_2) { double(:item, selected?: false) }
237
-
238
- before do
239
- SimpleNavigation.stub(:current_navigation_for)
240
- item_container.instance_variable_set(:@items, [item_1, item_2])
241
- end
242
-
243
- context 'when a navigation is explicitely set' do
244
- before { item_container.stub(:[] => item_1) }
245
-
246
- it 'returns the explicitely selected item' do
247
- expect(item_container.selected_item).to be item_1
248
- end
249
- end
250
-
251
- context 'when no navigation is explicitely set' do
252
- before { item_container.stub(:[] => nil) }
253
-
254
- context 'and no item is selected' do
255
- it 'returns nil' do
256
- expect(item_container.selected_item).to be_nil
257
- end
258
- end
259
-
260
- context 'and one item is selected' do
261
- before { item_1.stub(selected?: true) }
262
-
263
- it 'returns the selected item' do
264
- expect(item_container.selected_item).to be item_1
265
- end
266
- end
267
- end
268
- end
269
- end
270
- end
@@ -1,300 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe SimpleNavigation do
4
- before { subject.config_file_path = 'path_to_config' }
5
-
6
- describe 'config_file_name' do
7
- context 'when the navigation_context is :default' do
8
- it 'returns the name of the default config file' do
9
- expect(subject.config_file_name).to eq 'navigation.rb'
10
- end
11
- end
12
-
13
- context 'when the navigation_context is NOT :default' do
14
- it 'returns the name of the config file matching the specified context' do
15
- file_name = subject.config_file_name(:my_other_context)
16
- expect(file_name).to eq 'my_other_context_navigation.rb'
17
- end
18
-
19
- it 'converts camelcase-contexts to underscore' do
20
- file_name = subject.config_file_name(:WhyWouldYouDoThis)
21
- expect(file_name).to eq 'why_would_you_do_this_navigation.rb'
22
- end
23
- end
24
- end
25
-
26
- describe 'config_file_path=' do
27
- before { subject.config_file_paths = ['existing_path'] }
28
-
29
- it 'overrides the config_file_paths' do
30
- subject.config_file_path = 'new_path'
31
- expect(subject.config_file_paths).to eq ['new_path']
32
- end
33
- end
34
-
35
- describe 'config_file' do
36
- context 'when no config_file_paths are set' do
37
- before { subject.config_file_paths = [] }
38
-
39
- it 'returns nil' do
40
- expect(subject.config_file).to be_nil
41
- end
42
- end
43
-
44
- context 'when one config_file_path is set' do
45
- before { subject.config_file_paths = ['my_config_file_path'] }
46
-
47
- context 'and the requested config file exists' do
48
- before { File.stub(exist?: true) }
49
-
50
- it 'returns the path to the config_file' do
51
- expect(subject.config_file).to eq 'my_config_file_path/navigation.rb'
52
- end
53
- end
54
-
55
- context 'and the requested config file does not exist' do
56
- before { File.stub(exist?: false) }
57
-
58
- it 'returns nil' do
59
- expect(subject.config_file).to be_nil
60
- end
61
- end
62
- end
63
-
64
- context 'when multiple config_file_paths are set' do
65
- before { subject.config_file_paths = ['first_path', 'second_path'] }
66
-
67
- context 'and the requested config file exists' do
68
- before { File.stub(exist?: true) }
69
-
70
- it 'returns the path to the first matching config_file' do
71
- expect(subject.config_file).to eq 'first_path/navigation.rb'
72
- end
73
- end
74
-
75
- context 'and the requested config file does not exist' do
76
- before { File.stub(exist?: false) }
77
-
78
- it 'returns nil' do
79
- expect(subject.config_file).to be_nil
80
- end
81
- end
82
- end
83
- end
84
-
85
- describe '.config_file?' do
86
- context 'when config_file is present' do
87
- before { subject.stub(config_file: 'file') }
88
-
89
- it 'returns true' do
90
- expect(subject.config_file?).to be_true
91
- end
92
- end
93
-
94
- context 'when config_file is not present' do
95
- before { subject.stub(config_file: nil) }
96
-
97
- it 'returns false' do
98
- expect(subject.config_file?).to be_false
99
- end
100
- end
101
- end
102
-
103
- describe '.default_config_file_path' do
104
- before { subject.stub(root: 'root') }
105
-
106
- it 'returns the config file path according to :root setting' do
107
- expect(subject.default_config_file_path).to eq 'root/config'
108
- end
109
- end
110
-
111
- describe 'Regarding renderers' do
112
- it 'registers the builtin renderers by default' do
113
- expect(subject.registered_renderers).not_to be_empty
114
- end
115
-
116
- describe '.register_renderer' do
117
- let(:renderer) { double(:renderer) }
118
-
119
- it 'adds the specified renderer to the list of renderers' do
120
- subject.register_renderer(my_renderer: renderer)
121
- expect(subject.registered_renderers[:my_renderer]).to be renderer
122
- end
123
- end
124
- end
125
-
126
- describe '.set_env' do
127
- before do
128
- subject.config_file_paths = []
129
- subject.stub(default_config_file_path: 'default_path')
130
- subject.set_env('root', 'my_env')
131
- end
132
-
133
- it 'sets the root' do
134
- expect(subject.root).to eq 'root'
135
- end
136
-
137
- it 'sets the environment' do
138
- expect(subject.environment).to eq 'my_env'
139
- end
140
-
141
- it 'adds the default-config path to the list of config_file_paths' do
142
- expect(subject.config_file_paths).to eq ['default_path']
143
- end
144
- end
145
-
146
- describe '.load_config' do
147
- context 'when config_file_path is set' do
148
- before { subject.stub(config_file: 'path_to_config_file') }
149
-
150
- context 'and config_file exists' do
151
- before do
152
- subject.stub(config_file?: true)
153
- IO.stub(read: 'file_content')
154
- end
155
-
156
- it "doesn't raise any error" do
157
- expect{ subject.load_config }.not_to raise_error
158
- end
159
-
160
- it 'reads the specified config file from disc' do
161
- expect(IO).to receive(:read).with('path_to_config_file')
162
- subject.load_config
163
- end
164
-
165
- it 'stores the read content in the module (default context)' do
166
- expect(subject).to receive(:config_file).with(:default)
167
- subject.load_config
168
- expect(subject.config_files[:default]).to eq 'file_content'
169
- end
170
-
171
- it 'stores the content in the module (non default context)' do
172
- expect(subject).to receive(:config_file).with(:my_context)
173
- subject.load_config(:my_context)
174
- expect(subject.config_files[:my_context]).to eq 'file_content'
175
- end
176
- end
177
-
178
- context 'and config_file does not exist' do
179
- before { subject.stub(config_file?: false) }
180
-
181
- it 'raises an exception' do
182
- expect{ subject.load_config }.to raise_error
183
- end
184
- end
185
- end
186
-
187
- context 'when config_file_path is not set' do
188
- before { subject.config_file_path = nil }
189
-
190
- it 'raises an exception' do
191
- expect{ subject.load_config }.to raise_error
192
- end
193
- end
194
-
195
- describe 'Regarding caching of the config-files' do
196
- before do
197
- subject.config_file_path = 'path_to_config'
198
- IO.stub(:read).and_return('file_content')
199
- File.stub(exist?: true)
200
- end
201
-
202
- after { subject.config_files = {} }
203
-
204
- shared_examples 'loading config file' do |env, count|
205
- context "when environment is '#{env}'" do
206
- before { subject.stub(environment: env) }
207
-
208
- it "loads the config file #{count}" do
209
- expect(IO).to receive(:read).exactly(count)
210
- 2.times { subject.load_config }
211
- end
212
- end
213
- end
214
-
215
- it_behaves_like 'loading config file', nil, :twice
216
- it_behaves_like 'loading config file', 'production', :once
217
- it_behaves_like 'loading config file', 'development', :twice
218
- it_behaves_like 'loading config file', 'test', :twice
219
- end
220
- end
221
-
222
- describe '.config' do
223
- it 'returns the Configuration singleton instance' do
224
- expect(subject.config).to be SimpleNavigation::Configuration.instance
225
- end
226
- end
227
-
228
- describe '.active_item_container_for' do
229
- let(:primary) { double(:primary) }
230
-
231
- before { subject.config.stub(primary_navigation: primary) }
232
-
233
- context 'when level is :all' do
234
- it 'returns the primary_navigation' do
235
- nav = subject.active_item_container_for(:all)
236
- expect(nav).to be primary
237
- end
238
- end
239
-
240
- context 'when level is :leaves' do
241
- it 'returns the currently active leaf-container' do
242
- expect(primary).to receive(:active_leaf_container)
243
- subject.active_item_container_for(:leaves)
244
- end
245
- end
246
-
247
- context 'when level is a Range' do
248
- it 'takes the min of the range to lookup the active container' do
249
- expect(primary).to receive(:active_item_container_for).with(2)
250
- subject.active_item_container_for(2..3)
251
- end
252
- end
253
-
254
- context 'when level is an Integer' do
255
- it 'considers the Integer to lookup the active container' do
256
- expect(primary).to receive(:active_item_container_for).with(1)
257
- subject.active_item_container_for(1)
258
- end
259
- end
260
-
261
- context 'when level is something else' do
262
- it 'raises an exception' do
263
- expect{
264
- subject.active_item_container_for('something else')
265
- }.to raise_error
266
- end
267
- end
268
- end
269
-
270
- describe '.load_adapter' do
271
- shared_examples 'loading the right adapter' do |framework, adapter|
272
- context "when the context is #{framework}" do
273
- before do
274
- subject.stub(framework: framework)
275
- subject.load_adapter
276
- end
277
-
278
- it "returns the #{framework} adapter" do
279
- adapter_class = SimpleNavigation::Adapters.const_get(adapter)
280
- expect(subject.adapter_class).to be adapter_class
281
- end
282
- end
283
- end
284
-
285
- it_behaves_like 'loading the right adapter', :rails, :Rails
286
- it_behaves_like 'loading the right adapter', :padrino, :Padrino
287
- it_behaves_like 'loading the right adapter', :sinatra, :Sinatra
288
- end
289
-
290
- describe '.init_adapter_from' do
291
- let(:adapter) { double(:adapter) }
292
- let(:adapter_class) { double(:adapter_class, new: adapter) }
293
-
294
- it 'sets the adapter to a new instance of adapter_class' do
295
- subject.adapter_class = adapter_class
296
- subject.init_adapter_from(:default)
297
- expect(subject.adapter).to be adapter
298
- end
299
- end
300
- end