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,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