simple-navigation 4.4.1 → 4.5.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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +84 -0
  3. data/.rspec +1 -2
  4. data/.rubocop.yml +49 -0
  5. data/.rubocop_todo.yml +38 -0
  6. data/Appraisals +55 -0
  7. data/CHANGELOG.md +7 -0
  8. data/Gemfile +21 -0
  9. data/Guardfile +4 -2
  10. data/README.md +11 -23
  11. data/Rakefile +2 -27
  12. data/bin/_guard-core +16 -0
  13. data/bin/appraisal +16 -0
  14. data/bin/guard +16 -0
  15. data/bin/rake +16 -0
  16. data/bin/rspec +16 -0
  17. data/bin/rubocop +16 -0
  18. data/gemfiles/rails_6.1.gemfile +35 -0
  19. data/gemfiles/rails_7.0.gemfile +23 -0
  20. data/gemfiles/rails_7.1.gemfile +23 -0
  21. data/gemfiles/rails_7.2.gemfile +23 -0
  22. data/gemfiles/rails_8.0.gemfile +23 -0
  23. data/gemfiles/rails_8.1.gemfile +23 -0
  24. data/generators/navigation_config/navigation_config_generator.rb +2 -0
  25. data/generators/navigation_config/templates/config/navigation.rb +30 -26
  26. data/lib/generators/navigation_config/navigation_config_generator.rb +2 -0
  27. data/lib/simple-navigation.rb +3 -1
  28. data/lib/simple_navigation/adapters/base.rb +2 -0
  29. data/lib/simple_navigation/adapters/nanoc.rb +8 -3
  30. data/lib/simple_navigation/adapters/padrino.rb +3 -1
  31. data/lib/simple_navigation/adapters/rails.rb +12 -14
  32. data/lib/simple_navigation/adapters/sinatra.rb +4 -6
  33. data/lib/simple_navigation/config_file.rb +1 -1
  34. data/lib/simple_navigation/config_file_finder.rb +3 -3
  35. data/lib/simple_navigation/configuration.rb +5 -5
  36. data/lib/simple_navigation/helpers.rb +9 -11
  37. data/lib/simple_navigation/item.rb +26 -20
  38. data/lib/simple_navigation/item_adapter.rb +16 -5
  39. data/lib/simple_navigation/item_container.rb +13 -7
  40. data/lib/simple_navigation/items_provider.rb +6 -4
  41. data/lib/simple_navigation/railtie.rb +3 -1
  42. data/lib/simple_navigation/renderer/base.rb +5 -5
  43. data/lib/simple_navigation/renderer/breadcrumbs.rb +4 -3
  44. data/lib/simple_navigation/renderer/json.rb +1 -1
  45. data/lib/simple_navigation/renderer/links.rb +2 -0
  46. data/lib/simple_navigation/renderer/list.rb +5 -5
  47. data/lib/simple_navigation/renderer/text.rb +3 -1
  48. data/lib/simple_navigation/version.rb +3 -1
  49. data/lib/simple_navigation.rb +32 -24
  50. data/simple-navigation.gemspec +16 -27
  51. data/spec/fake_app/config/navigation.rb +4 -2
  52. data/spec/fake_app/rails_app.rb +5 -3
  53. data/spec/integration/rendering_navigation_spec.rb +7 -5
  54. data/spec/simple_navigation/adapters/nanoc_spec.rb +97 -0
  55. data/spec/simple_navigation/adapters/padrino_spec.rb +41 -22
  56. data/spec/simple_navigation/adapters/rails_spec.rb +199 -206
  57. data/spec/simple_navigation/adapters/sinatra_spec.rb +21 -5
  58. data/spec/simple_navigation/config_file_finder_spec.rb +32 -28
  59. data/spec/simple_navigation/config_file_spec.rb +14 -14
  60. data/spec/simple_navigation/configuration_spec.rb +128 -121
  61. data/spec/simple_navigation/helpers_spec.rb +282 -284
  62. data/spec/simple_navigation/item_adapter_spec.rb +109 -122
  63. data/spec/simple_navigation/item_container_spec.rb +407 -408
  64. data/spec/simple_navigation/item_spec.rb +333 -301
  65. data/spec/simple_navigation/items_provider_spec.rb +30 -27
  66. data/spec/simple_navigation/renderer/base_spec.rb +166 -168
  67. data/spec/simple_navigation/renderer/breadcrumbs_spec.rb +81 -83
  68. data/spec/simple_navigation/renderer/json_spec.rb +49 -56
  69. data/spec/simple_navigation/renderer/links_spec.rb +81 -83
  70. data/spec/simple_navigation/renderer/list_spec.rb +111 -91
  71. data/spec/simple_navigation/renderer/text_spec.rb +37 -39
  72. data/spec/simple_navigation_spec.rb +54 -47
  73. data/spec/spec_helper.rb +146 -53
  74. metadata +25 -164
  75. data/.travis.yml +0 -23
  76. data/gemfiles/rails-3-2-stable.gemfile +0 -11
  77. data/gemfiles/rails-4-1-stable.gemfile +0 -7
  78. data/gemfiles/rails-4-2-stable.gemfile +0 -7
  79. data/gemfiles/rails-5-2-stable.gemfile +0 -7
  80. data/gemfiles/rails-6-0-stable.gemfile +0 -9
  81. data/gemfiles/rails-6-1-stable.gemfile +0 -9
  82. data/init.rb +0 -1
  83. data/install.rb +0 -5
  84. data/lib/simple_navigation/adapters.rb +0 -10
  85. data/lib/simple_navigation/renderer.rb +0 -12
  86. data/spec/initializers/coveralls.rb +0 -3
  87. data/spec/initializers/have_css_matcher.rb +0 -19
  88. data/spec/initializers/memfs.rb +0 -7
  89. data/spec/initializers/rails.rb +0 -4
  90. data/spec/initializers/rspec.rb +0 -7
  91. data/uninstall.rb +0 -1
@@ -1,599 +1,598 @@
1
- module SimpleNavigation
2
- describe ItemContainer do
3
- subject(:item_container) { ItemContainer.new }
4
-
5
- shared_examples 'adding the item to the list' do
6
- it 'adds the item to the list' do
7
- allow(Item).to receive_messages(new: item)
8
- item_container.item(*args)
9
- expect(item_container.items).to include(item)
10
- end
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe SimpleNavigation::ItemContainer do
4
+ subject(:item_container) { described_class.new }
5
+
6
+ shared_examples 'adding the item to the list' do
7
+ it 'adds the item to the list' do
8
+ allow(SimpleNavigation::Item).to receive_messages(new: item)
9
+ item_container.item(*args)
10
+ expect(item_container.items).to include(item)
11
11
  end
12
+ end
12
13
 
13
- shared_examples 'not adding the item to the list' do
14
- it "doesn't add the item to the list" do
15
- allow(Item).to receive_messages(new: item)
16
- item_container.item(*args)
17
- expect(item_container.items).not_to include(item)
18
- end
14
+ shared_examples 'not adding the item to the list' do
15
+ it "doesn't add the item to the list" do
16
+ allow(SimpleNavigation::Item).to receive_messages(new: item)
17
+ item_container.item(*args)
18
+ expect(item_container.items).not_to include(item)
19
19
  end
20
+ end
20
21
 
21
- describe '#initialize' do
22
- it 'sets an empty items array' do
23
- expect(item_container.items).to be_empty
24
- end
22
+ describe '#initialize' do
23
+ it 'sets an empty items array' do
24
+ expect(item_container.items).to be_empty
25
25
  end
26
+ end
26
27
 
27
- describe '#dom_attributes' do
28
- let(:dom_attributes) {{ id: 'test_id', class: 'test_class' }}
28
+ describe '#dom_attributes' do
29
+ let(:dom_attributes) { { id: 'test_id', class: 'test_class' } }
29
30
 
30
- before { item_container.dom_attributes = dom_attributes }
31
+ before { item_container.dom_attributes = dom_attributes }
31
32
 
32
- it "returns the container's dom_attributes" do
33
- expect(item_container.dom_attributes).to eq dom_attributes
34
- end
33
+ it "returns the container's dom_attributes" do
34
+ expect(item_container.dom_attributes).to eq dom_attributes
35
+ end
35
36
 
36
- context 'when the dom_attributes do not contain any id or class' do
37
- let(:dom_attributes) {{ test: 'test' }}
37
+ context 'when the dom_attributes do not contain any id or class' do
38
+ let(:dom_attributes) { { test: 'test' } }
38
39
 
39
- context "and the container hasn't any dom_id" do
40
- it "returns the contaier's dom_attributes without any id" do
41
- expect(item_container.dom_attributes).not_to include(:id)
42
- end
40
+ context "when the container hasn't any dom_id" do
41
+ it "returns the contaier's dom_attributes without any id" do
42
+ expect(item_container.dom_attributes).not_to include(:id)
43
43
  end
44
+ end
44
45
 
45
- context 'and the container has a dom_id' do
46
- before { item_container.dom_id = 'test_id' }
46
+ context 'when the container has a dom_id' do
47
+ before { item_container.dom_id = 'test_id' }
47
48
 
48
- it "returns the contaier's dom_attributes including the #dom_id" do
49
- expect(item_container.dom_attributes).to include(id: 'test_id')
50
- end
49
+ it "returns the contaier's dom_attributes including the #dom_id" do
50
+ expect(item_container.dom_attributes).to include(id: 'test_id')
51
51
  end
52
+ end
52
53
 
53
- context "and the container hasn't any dom_class" do
54
- it "returns the contaier's dom_attributes without any class" do
55
- expect(item_container.dom_attributes).not_to include(:class)
56
- end
54
+ context "when the container hasn't any dom_class" do
55
+ it "returns the contaier's dom_attributes without any class" do
56
+ expect(item_container.dom_attributes).not_to include(:class)
57
57
  end
58
+ end
58
59
 
59
- context 'and the container has a dom_class' do
60
- before { item_container.dom_class = 'test_class' }
60
+ context 'when the container has a dom_class' do
61
+ before { item_container.dom_class = 'test_class' }
61
62
 
62
- it "returns the contaier's dom_attributes including the #dom_class" do
63
- expect(item_container.dom_attributes).to include(class: 'test_class')
64
- end
63
+ it "returns the contaier's dom_attributes including the #dom_class" do
64
+ expect(item_container.dom_attributes).to include(class: 'test_class')
65
65
  end
66
66
  end
67
67
  end
68
+ end
68
69
 
69
- describe '#items=' do
70
- let(:item) {{ key: :my_key, name: 'test', url: '/' }}
71
- let(:items) { [item] }
72
- let(:item_adapter) { double(:item_adapter).as_null_object }
73
- let(:real_item) { double(:real_item) }
74
-
75
- before do
76
- allow(ItemAdapter).to receive_messages(new: item_adapter)
77
- allow(item_adapter).to receive(:to_simple_navigation_item)
78
- .with(item_container)
79
- .and_return(real_item)
80
- end
70
+ describe '#items=' do
71
+ let(:item) { { key: :my_key, name: 'test', url: '/' } }
72
+ let(:items) { [item] }
73
+ let(:item_adapter) { double(:item_adapter).as_null_object }
74
+ let(:real_item) { double(:real_item) }
75
+
76
+ before do
77
+ allow(SimpleNavigation::ItemAdapter).to receive_messages(new: item_adapter)
78
+ allow(item_adapter).to receive(:to_simple_navigation_item)
79
+ .with(item_container)
80
+ .and_return(real_item)
81
+ end
81
82
 
82
- context 'when the item should be added' do
83
- before { allow(item_container).to receive_messages(should_add_item?: true) }
83
+ context 'when the item should be added' do
84
+ before { allow(item_container).to receive_messages(should_add_item?: true) }
84
85
 
85
- it 'converts it to an Item and adds it to the items collection' do
86
- item_container.items = items
87
- expect(item_container.items).to include(real_item)
88
- end
86
+ it 'converts it to an Item and adds it to the items collection' do
87
+ item_container.items = items
88
+ expect(item_container.items).to include(real_item)
89
89
  end
90
+ end
90
91
 
91
- context 'when the item should not be added' do
92
- before { allow(item_container).to receive_messages(should_add_item?: false) }
92
+ context 'when the item should not be added' do
93
+ before { allow(item_container).to receive_messages(should_add_item?: false) }
93
94
 
94
- it "doesn't add it to the items collection" do
95
- item_container.items = items
96
- expect(item_container.items).not_to include(real_item)
97
- end
95
+ it "doesn't add it to the items collection" do
96
+ item_container.items = items
97
+ expect(item_container.items).not_to include(real_item)
98
98
  end
99
99
  end
100
+ end
100
101
 
101
- describe '#selected?' do
102
- let(:item_1) { double(:item, selected?: false) }
103
- let(:item_2) { double(:item, selected?: false) }
102
+ describe '#selected?' do
103
+ let(:first_item) { double(:item, selected?: false) }
104
+ let(:second_item) { double(:item, selected?: false) }
104
105
 
105
- before do
106
- item_container.instance_variable_set(:@items, [item_1, item_2])
107
- end
106
+ before do
107
+ item_container.instance_variable_set(:@items, [first_item, second_item])
108
+ end
108
109
 
109
- context 'when no item is selected' do
110
- it 'returns nil' do
111
- expect(item_container).not_to be_selected
112
- end
110
+ context 'when no item is selected' do
111
+ it 'returns nil' do
112
+ expect(item_container).not_to be_selected
113
113
  end
114
+ end
114
115
 
115
- context 'when an item is selected' do
116
- it 'returns true' do
117
- allow(item_1).to receive_messages(selected?: true)
118
- expect(item_container).to be_selected
119
- end
116
+ context 'when an item is selected' do
117
+ it 'returns true' do
118
+ allow(first_item).to receive_messages(selected?: true)
119
+ expect(item_container).to be_selected
120
120
  end
121
121
  end
122
+ end
122
123
 
123
- describe '#selected_item' do
124
- let(:item_1) { double(:item, selected?: false) }
125
- let(:item_2) { double(:item, selected?: false) }
124
+ describe '#selected_item' do
125
+ let(:first_item) { double(:item, selected?: false) }
126
+ let(:second_item) { double(:item, selected?: false) }
126
127
 
127
- before(:each) do
128
- allow(SimpleNavigation).to receive_messages(current_navigation_for: :nav)
129
- allow(item_container).to receive_messages(:[] => nil)
130
- item_container.instance_variable_set(:@items, [item_1, item_2])
131
- end
128
+ before do
129
+ allow(SimpleNavigation).to receive_messages(current_navigation_for: :nav)
130
+ allow(item_container).to receive_messages(:[] => nil)
131
+ item_container.instance_variable_set(:@items, [first_item, second_item])
132
+ end
132
133
 
133
- context "when navigation isn't explicitely set" do
134
- context 'and no item is selected' do
135
- it 'returns nil' do
136
- expect(item_container.selected_item).to be_nil
137
- end
134
+ context "when navigation isn't explicitely set" do
135
+ context 'when no item is selected' do
136
+ it 'returns nil' do
137
+ expect(item_container.selected_item).to be_nil
138
138
  end
139
+ end
139
140
 
140
- context 'and an item selected' do
141
- before { allow(item_1).to receive_messages(selected?: true) }
141
+ context 'when an item is selected' do
142
+ before { allow(first_item).to receive_messages(selected?: true) }
142
143
 
143
- it 'returns the selected item' do
144
- expect(item_container.selected_item).to be item_1
145
- end
144
+ it 'returns the selected item' do
145
+ expect(item_container.selected_item).to be first_item
146
146
  end
147
147
  end
148
148
  end
149
+ end
149
150
 
150
- describe '#active_item_container_for' do
151
- context "when the desired level is the same as the container's" do
152
- it 'returns the container itself' do
153
- expect(item_container.active_item_container_for(1)).to be item_container
154
- end
151
+ describe '#active_item_container_for' do
152
+ context "when the desired level is the same as the container's" do
153
+ it 'returns the container itself' do
154
+ expect(item_container.active_item_container_for(1)).to be item_container
155
155
  end
156
+ end
156
157
 
157
- context "when the desired level is different than the container's" do
158
- context 'and no subnavigation is selected' do
159
- before { allow(item_container).to receive_messages(selected_sub_navigation?: false) }
160
-
161
- it 'returns nil' do
162
- expect(item_container.active_item_container_for(2)).to be_nil
163
- end
164
- end
165
-
166
- context 'and a subnavigation is selected' do
167
- let(:sub_navigation) { double(:sub_navigation) }
168
- let(:selected_item) { double(:selected_item) }
169
-
170
- before do
171
- allow(item_container).to \
172
- receive_messages(selected_sub_navigation?: true, selected_item: selected_item)
173
- allow(selected_item).to receive_messages(sub_navigation: sub_navigation)
174
- end
158
+ context "when the desired level is different than the container's" do
159
+ context 'when no subnavigation is selected' do
160
+ before { allow(item_container).to receive_messages(selected_sub_navigation?: false) }
175
161
 
176
- it 'calls recursively on the sub_navigation' do
177
- expect(sub_navigation).to receive(:active_item_container_for)
178
- .with(2)
179
- item_container.active_item_container_for(2)
180
- end
162
+ it 'returns nil' do
163
+ expect(item_container.active_item_container_for(2)).to be_nil
181
164
  end
182
165
  end
183
- end
184
166
 
185
- describe '#active_leaf_container' do
186
- context 'when the current container has a selected subnavigation' do
167
+ context 'when a subnavigation is selected' do
187
168
  let(:sub_navigation) { double(:sub_navigation) }
188
169
  let(:selected_item) { double(:selected_item) }
189
170
 
190
171
  before do
191
- allow(item_container).to receive_messages(selected_sub_navigation?: true,
192
- selected_item: selected_item)
172
+ allow(item_container).to \
173
+ receive_messages(selected_sub_navigation?: true, selected_item: selected_item)
193
174
  allow(selected_item).to receive_messages(sub_navigation: sub_navigation)
194
175
  end
195
176
 
196
177
  it 'calls recursively on the sub_navigation' do
197
- expect(sub_navigation).to receive(:active_leaf_container)
198
- item_container.active_leaf_container
178
+ expect(sub_navigation).to receive(:active_item_container_for)
179
+ .with(2)
180
+ item_container.active_item_container_for(2)
199
181
  end
200
182
  end
183
+ end
184
+ end
201
185
 
202
- context 'when the current container is the leaf already' do
203
- before { allow(item_container).to receive_messages(selected_sub_navigation?: false) }
186
+ describe '#active_leaf_container' do
187
+ context 'when the current container has a selected subnavigation' do
188
+ let(:sub_navigation) { double(:sub_navigation) }
189
+ let(:selected_item) { double(:selected_item) }
204
190
 
205
- it 'returns itsself' do
206
- expect(item_container.active_leaf_container).to be item_container
207
- end
191
+ before do
192
+ allow(item_container).to receive_messages(selected_sub_navigation?: true,
193
+ selected_item: selected_item)
194
+ allow(selected_item).to receive_messages(sub_navigation: sub_navigation)
195
+ end
196
+
197
+ it 'calls recursively on the sub_navigation' do
198
+ expect(sub_navigation).to receive(:active_leaf_container)
199
+ item_container.active_leaf_container
208
200
  end
209
201
  end
210
202
 
211
- describe '#item' do
212
- let(:options) { Hash.new }
213
- let(:item) { double(:item) }
203
+ context 'when the current container is the leaf already' do
204
+ before { allow(item_container).to receive_messages(selected_sub_navigation?: false) }
214
205
 
215
- context 'when a block is given' do
216
- let(:block) { proc{} }
217
- let(:sub_container) { double(:sub_container) }
206
+ it 'returns itsself' do
207
+ expect(item_container.active_leaf_container).to be item_container
208
+ end
209
+ end
210
+ end
218
211
 
219
- it 'yields a new ItemContainer' do
220
- allow_any_instance_of(Item).to \
221
- receive_messages(sub_navigation: sub_container)
212
+ describe '#item' do
213
+ let(:options) { {} }
214
+ let(:item) { double(:item) }
222
215
 
223
- expect{ |blk|
224
- item_container.item('key', 'name', 'url', options, &blk)
225
- }.to yield_with_args(sub_container)
226
- end
216
+ context 'when a block is given' do
217
+ let(:block) { proc {} }
218
+ let(:sub_container) { double(:sub_container) }
227
219
 
228
- it "creates a new Item with the given params and block" do
229
- allow(Item).to receive(:new)
230
- .with(item_container, 'key', 'name', 'url', options, &block)
231
- .and_return(item)
232
- item_container.item('key', 'name', 'url', options, &block)
233
- expect(item_container.items).to include(item)
234
- end
220
+ it 'yields a new ItemContainer' do
221
+ allow_any_instance_of(SimpleNavigation::Item).to receive_messages(sub_navigation: sub_container) # rubocop:disable RSpec/AnyInstance
235
222
 
236
- it 'adds the created item to the list of items' do
237
- item_container.item('key', 'name', 'url', options) {}
238
- expect(item_container.items).not_to include(item)
239
- end
223
+ expect do |blk|
224
+ item_container.item('key', 'name', 'url', options, &blk)
225
+ end.to yield_with_args(sub_container)
240
226
  end
241
227
 
242
- context 'when no block is given' do
243
- it 'creates a new Item with the given params and no sub navigation' do
244
- allow(Item).to receive(:new)
245
- .with(item_container, 'key', 'name', 'url', options)
246
- .and_return(item)
247
- item_container.item('key', 'name', 'url', options)
248
- expect(item_container.items).to include(item)
249
- end
228
+ it 'creates a new Item with the given params and block' do
229
+ allow(SimpleNavigation::Item).to receive(:new)
230
+ .with(item_container, 'key', 'name', 'url', options, &block)
231
+ .and_return(item)
232
+ item_container.item('key', 'name', 'url', options, &block)
233
+ expect(item_container.items).to include(item)
234
+ end
235
+
236
+ it 'adds the created item to the list of items' do
237
+ item_container.item('key', 'name', 'url', options) {} # rubocop:disable Lint/EmptyBlock
238
+ expect(item_container.items).not_to include(item)
239
+ end
240
+ end
241
+
242
+ context 'when no block is given' do
243
+ it 'creates a new Item with the given params and no sub navigation' do
244
+ allow(SimpleNavigation::Item).to receive(:new)
245
+ .with(item_container, 'key', 'name', 'url', options)
246
+ .and_return(item)
247
+ item_container.item('key', 'name', 'url', options)
248
+ expect(item_container.items).to include(item)
249
+ end
250
+
251
+ it 'adds the created item to the list of items' do
252
+ allow(SimpleNavigation::Item).to receive_messages(new: item)
253
+ item_container.item('key', 'name', 'url', options) {} # rubocop:disable Lint/EmptyBlock
254
+ expect(item_container.items).to include(item)
255
+ end
256
+ end
250
257
 
251
- it 'adds the created item to the list of items' do
252
- allow(Item).to receive_messages(new: item)
253
- item_container.item('key', 'name', 'url', options) {}
254
- expect(item_container.items).to include(item)
258
+ describe 'Optional url and optional options' do
259
+ context 'when item specifed without url or options' do
260
+ it_behaves_like 'adding the item to the list' do
261
+ let(:args) { %w[key name] }
255
262
  end
256
263
  end
257
264
 
258
- describe 'Optional url and optional options' do
259
- context 'when item specifed without url or options' do
260
- it_behaves_like 'adding the item to the list' do
261
- let(:args) { ['key', 'name'] }
262
- end
265
+ context 'when item is specified with only a url' do
266
+ it_behaves_like 'adding the item to the list' do
267
+ let(:args) { %w[key name url] }
263
268
  end
269
+ end
264
270
 
265
- context 'when item is specified with only a url' do
271
+ context 'when item is specified with only options' do
272
+ context 'when options do not contain any condition' do
266
273
  it_behaves_like 'adding the item to the list' do
267
- let(:args) { ['key', 'name', 'url'] }
274
+ let(:args) { ['key', 'name', { option: true }] }
268
275
  end
269
276
  end
270
277
 
271
- context 'when item is specified with only options' do
272
- context 'and options do not contain any condition' do
273
- it_behaves_like 'adding the item to the list' do
274
- let(:args) { ['key', 'name', { option: true }] }
275
- end
276
- end
277
-
278
- context 'and options contains a negative condition' do
279
- it_behaves_like 'not adding the item to the list' do
280
- let(:args) { ['key', 'name', nil, { if: ->{ false }, option: true }] }
281
- end
278
+ context 'when options contains a negative condition' do
279
+ it_behaves_like 'not adding the item to the list' do
280
+ let(:args) { ['key', 'name', nil, { if: -> { false }, option: true }] }
282
281
  end
282
+ end
283
283
 
284
- context 'and options contains a positive condition' do
285
- it_behaves_like 'adding the item to the list' do
286
- let(:args) { ['key', 'name', nil, { if: ->{ true }, option: true }] }
287
- end
284
+ context 'when options contains a positive condition' do
285
+ it_behaves_like 'adding the item to the list' do
286
+ let(:args) { ['key', 'name', nil, { if: -> { true }, option: true }] }
288
287
  end
289
288
  end
289
+ end
290
290
 
291
- context 'when item is specified with a url and options' do
292
- context 'and options do not contain any condition' do
293
- it_behaves_like 'adding the item to the list' do
294
- let(:args) { ['key', 'name', 'url', { option: true }] }
295
- end
291
+ context 'when item is specified with a url and options' do
292
+ context 'when options do not contain any condition' do
293
+ it_behaves_like 'adding the item to the list' do
294
+ let(:args) { ['key', 'name', 'url', { option: true }] }
296
295
  end
296
+ end
297
297
 
298
- context 'and options contains a negative condition' do
299
- it_behaves_like 'not adding the item to the list' do
300
- let(:args) { ['key', 'name', 'url', { if: ->{ false }, option: true }] }
301
- end
298
+ context 'when options contains a negative condition' do
299
+ it_behaves_like 'not adding the item to the list' do
300
+ let(:args) { ['key', 'name', 'url', { if: -> { false }, option: true }] }
302
301
  end
302
+ end
303
303
 
304
- context 'and options contains a positive condition' do
305
- it_behaves_like 'adding the item to the list' do
306
- let(:args) { ['key', 'name', 'url', { if: ->{ true }, option: true }] }
307
- end
304
+ context 'when options contains a positive condition' do
305
+ it_behaves_like 'adding the item to the list' do
306
+ let(:args) { ['key', 'name', 'url', { if: -> { true }, option: true }] }
308
307
  end
309
308
  end
309
+ end
310
310
 
311
- context 'when a frozen options hash is given' do
312
- let(:options) do
313
- { html: { id: 'test' } }.freeze
314
- end
311
+ context 'when a frozen options hash is given' do
312
+ let(:options) do
313
+ { html: { id: 'test' } }.freeze
314
+ end
315
315
 
316
- it 'does not raise an exception' do
317
- expect{
318
- item_container.item('key', 'name', 'url', options)
319
- }.not_to raise_error
320
- end
316
+ it 'does not raise an exception' do
317
+ expect do
318
+ item_container.item('key', 'name', 'url', options)
319
+ end.not_to raise_error
321
320
  end
321
+ end
322
322
 
323
- describe "container options" do
324
- before do
325
- allow(item_container).to receive_messages(should_add_item?: add_item)
326
- item_container.item :key, 'name', 'url', options
327
- end
323
+ describe 'container options' do
324
+ before do
325
+ allow(item_container).to receive_messages(should_add_item?: add_item)
326
+ item_container.item :key, 'name', 'url', options
327
+ end
328
328
 
329
- context 'when the container :id option is specified' do
330
- let(:options) {{ container: { id: 'c_id' } }}
329
+ context 'when the container :id option is specified' do
330
+ let(:options) { { container: { id: 'c_id' } } }
331
331
 
332
- context 'and the item should be added' do
333
- let(:add_item) { true }
332
+ context 'when the item should be added' do
333
+ let(:add_item) { true }
334
334
 
335
- it 'changes its dom_id' do
336
- expect(item_container.dom_id).to eq 'c_id'
337
- end
335
+ it 'changes its dom_id' do
336
+ expect(item_container.dom_id).to eq 'c_id'
338
337
  end
338
+ end
339
339
 
340
- context "and the item shouldn't be added" do
341
- let(:add_item) { false }
340
+ context "when the item shouldn't be added" do
341
+ let(:add_item) { false }
342
342
 
343
- it "doesn't change its dom_id" do
344
- expect(item_container.dom_id).to be_nil
345
- end
343
+ it "doesn't change its dom_id" do
344
+ expect(item_container.dom_id).to be_nil
346
345
  end
347
346
  end
347
+ end
348
348
 
349
- context 'when the container :class option is specified' do
350
- let(:options) {{ container: { class: 'c_class' } }}
349
+ context 'when the container :class option is specified' do
350
+ let(:options) { { container: { class: 'c_class' } } }
351
351
 
352
- context 'and the item should be added' do
353
- let(:add_item) { true }
352
+ context 'when the item should be added' do
353
+ let(:add_item) { true }
354
354
 
355
- it 'changes its dom_class' do
356
- expect(item_container.dom_class).to eq 'c_class'
357
- end
355
+ it 'changes its dom_class' do
356
+ expect(item_container.dom_class).to eq 'c_class'
358
357
  end
358
+ end
359
359
 
360
- context "and the item shouldn't be added" do
361
- let(:add_item) { false }
360
+ context "when the item shouldn't be added" do
361
+ let(:add_item) { false }
362
362
 
363
- it "doesn't change its dom_class" do
364
- expect(item_container.dom_class).to be_nil
365
- end
363
+ it "doesn't change its dom_class" do
364
+ expect(item_container.dom_class).to be_nil
366
365
  end
367
366
  end
367
+ end
368
368
 
369
- context 'when the container :attributes option is specified' do
370
- let(:options) {{ container: { attributes: { option: true } } }}
369
+ context 'when the container :attributes option is specified' do
370
+ let(:options) { { container: { attributes: { option: true } } } }
371
371
 
372
- context 'and the item should be added' do
373
- let(:add_item) { true }
372
+ context 'when the item should be added' do
373
+ let(:add_item) { true }
374
374
 
375
- it 'changes its dom_attributes' do
376
- expect(item_container.dom_attributes).to eq(option: true)
377
- end
375
+ it 'changes its dom_attributes' do
376
+ expect(item_container.dom_attributes).to eq(option: true)
378
377
  end
378
+ end
379
379
 
380
- context "and the item shouldn't be added" do
381
- let(:add_item) { false }
380
+ context "when the item shouldn't be added" do
381
+ let(:add_item) { false }
382
382
 
383
- it "doesn't change its dom_attributes" do
384
- expect(item_container.dom_attributes).to eq({})
385
- end
383
+ it "doesn't change its dom_attributes" do
384
+ expect(item_container.dom_attributes).to eq({})
386
385
  end
387
386
  end
387
+ end
388
388
 
389
- context 'when the container :selected_class option is specified' do
390
- let(:options) {{ container: { selected_class: 'sel_class' } }}
389
+ context 'when the container :selected_class option is specified' do
390
+ let(:options) { { container: { selected_class: 'sel_class' } } }
391
391
 
392
- context 'and the item should be added' do
393
- let(:add_item) { true }
392
+ context 'when the item should be added' do
393
+ let(:add_item) { true }
394
394
 
395
- it 'changes its selected_class' do
396
- expect(item_container.selected_class).to eq 'sel_class'
397
- end
395
+ it 'changes its selected_class' do
396
+ expect(item_container.selected_class).to eq 'sel_class'
398
397
  end
398
+ end
399
399
 
400
- context "and the item shouldn't be added" do
401
- let(:add_item) { false }
400
+ context "when the item shouldn't be added" do
401
+ let(:add_item) { false }
402
402
 
403
- it "doesn't change its selected_class" do
404
- expect(item_container.selected_class).to be_nil
405
- end
403
+ it "doesn't change its selected_class" do
404
+ expect(item_container.selected_class).to be_nil
406
405
  end
407
406
  end
408
407
  end
409
408
  end
409
+ end
410
410
 
411
- describe 'Conditions' do
412
- context 'when an :if option is given' do
413
- let(:options) {{ if: proc{condition} }}
414
- let(:condition) { nil }
411
+ describe 'Conditions' do
412
+ context 'when an :if option is given' do
413
+ let(:options) { { if: proc { condition } } }
414
+ let(:condition) { nil }
415
415
 
416
- context 'and it evals to true' do
417
- let(:condition) { true }
416
+ context 'when it evals to true' do
417
+ let(:condition) { true }
418
418
 
419
- it 'creates a new Item' do
420
- expect(Item).to receive(:new)
421
- item_container.item('key', 'name', 'url', options)
422
- end
419
+ it 'creates a new Item' do
420
+ expect(SimpleNavigation::Item).to receive(:new)
421
+ item_container.item('key', 'name', 'url', options)
423
422
  end
423
+ end
424
424
 
425
- context 'and it evals to false' do
426
- let(:condition) { false }
425
+ context 'when it evals to false' do
426
+ let(:condition) { false }
427
427
 
428
- it "doesn't create a new Item" do
429
- expect(Item).not_to receive(:new)
430
- item_container.item('key', 'name', 'url', options)
431
- end
428
+ it "doesn't create a new Item" do
429
+ expect(SimpleNavigation::Item).not_to receive(:new)
430
+ item_container.item('key', 'name', 'url', options)
432
431
  end
432
+ end
433
433
 
434
- context 'and it is not a proc or a method' do
435
- it 'raises an error' do
436
- expect{
437
- item_container.item('key', 'name', 'url', { if: 'text' })
438
- }.to raise_error(ArgumentError, ':if or :unless must be procs or lambdas')
439
- end
434
+ context 'when it is not a proc or a method' do
435
+ it 'raises an error' do
436
+ expect do
437
+ item_container.item('key', 'name', 'url', { if: 'text' })
438
+ end.to raise_error(ArgumentError, ':if or :unless must be procs or lambdas')
440
439
  end
441
440
  end
441
+ end
442
442
 
443
- context 'when an :unless option is given' do
444
- let(:options) {{ unless: proc{condition} }}
445
- let(:condition) { nil }
443
+ context 'when an :unless option is given' do
444
+ let(:options) { { unless: proc { condition } } }
445
+ let(:condition) { nil }
446
446
 
447
- context 'and it evals to false' do
448
- let(:condition) { false }
447
+ context 'when it evals to false' do
448
+ let(:condition) { false }
449
449
 
450
- it 'creates a new Navigation-Item' do
451
- expect(Item).to receive(:new)
452
- item_container.item('key', 'name', 'url', options)
453
- end
450
+ it 'creates a new Navigation-Item' do
451
+ expect(SimpleNavigation::Item).to receive(:new)
452
+ item_container.item('key', 'name', 'url', options)
454
453
  end
454
+ end
455
455
 
456
- context 'and it evals to true' do
457
- let(:condition) { true }
456
+ context 'when it evals to true' do
457
+ let(:condition) { true }
458
458
 
459
- it "doesn't create a new Navigation-Item" do
460
- expect(Item).not_to receive(:new)
461
- item_container.item('key', 'name', 'url', options)
462
- end
459
+ it "doesn't create a new Navigation-Item" do
460
+ expect(SimpleNavigation::Item).not_to receive(:new)
461
+ item_container.item('key', 'name', 'url', options)
463
462
  end
464
463
  end
465
464
  end
466
465
  end
466
+ end
467
467
 
468
- describe '#[]' do
469
- before do
470
- item_container.item(:first, 'first', 'bla')
471
- item_container.item(:second, 'second', 'bla')
472
- item_container.item(:third, 'third', 'bla')
473
- end
468
+ describe '#[]' do
469
+ before do
470
+ item_container.item(:first, 'first', 'bla')
471
+ item_container.item(:second, 'second', 'bla')
472
+ item_container.item(:third, 'third', 'bla')
473
+ end
474
474
 
475
- it 'returns the item with the specified navi_key' do
476
- expect(item_container[:second].name).to eq 'second'
477
- end
475
+ it 'returns the item with the specified navi_key' do
476
+ expect(item_container[:second].name).to eq 'second'
477
+ end
478
478
 
479
- context 'when no item exists for the specified navi_key' do
480
- it 'returns nil' do
481
- expect(item_container[:invalid]).to be_nil
482
- end
479
+ context 'when no item exists for the specified navi_key' do
480
+ it 'returns nil' do
481
+ expect(item_container[:invalid]).to be_nil
483
482
  end
484
483
  end
484
+ end
485
485
 
486
- describe '#render' do
487
- # TODO
488
- let(:renderer_instance) { double(:renderer).as_null_object }
489
- let(:renderer_class) { double(:renderer_class, new: renderer_instance) }
490
-
491
- context 'when renderer is specified as an option' do
492
- context 'and is specified as a class' do
493
- it 'instantiates the passed renderer_class with the options' do
494
- expect(renderer_class).to receive(:new)
495
- .with(renderer: renderer_class)
496
- item_container.render(renderer: renderer_class)
497
- end
486
+ describe '#render' do
487
+ # TODO
488
+ let(:renderer_instance) { double(:renderer).as_null_object }
489
+ let(:renderer_class) { double(:renderer_class, new: renderer_instance) }
498
490
 
499
- it 'calls render on the renderer and passes self' do
500
- expect(renderer_instance).to receive(:render).with(item_container)
501
- item_container.render(renderer: renderer_class)
502
- end
491
+ context 'when renderer is specified as an option' do
492
+ context 'when it is specified as a class' do
493
+ it 'instantiates the passed renderer_class with the options' do
494
+ expect(renderer_class).to receive(:new)
495
+ .with({ renderer: renderer_class })
496
+ item_container.render(renderer: renderer_class)
503
497
  end
504
498
 
505
- context 'and is specified as a symbol' do
506
- before do
507
- SimpleNavigation.registered_renderers = {
508
- my_renderer: renderer_class
509
- }
510
- end
511
-
512
- it "instantiates the passed renderer_class with the options" do
513
- expect(renderer_class).to receive(:new).with(renderer: :my_renderer)
514
- item_container.render(renderer: :my_renderer)
515
- end
516
-
517
- it 'calls render on the renderer and passes self' do
518
- expect(renderer_instance).to receive(:render).with(item_container)
519
- item_container.render(renderer: :my_renderer)
520
- end
499
+ it 'calls render on the renderer and passes self' do
500
+ expect(renderer_instance).to receive(:render).with(item_container)
501
+ item_container.render(renderer: renderer_class)
521
502
  end
522
503
  end
523
504
 
524
- context 'when no renderer is specified' do
525
- let(:options) { Hash.new }
526
-
527
- before { allow(item_container).to receive_messages(renderer: renderer_class) }
505
+ context 'when it is specified as a symbol' do
506
+ before do
507
+ SimpleNavigation.registered_renderers = {
508
+ my_renderer: renderer_class
509
+ }
510
+ end
528
511
 
529
- it "instantiates the container's renderer with the options" do
530
- expect(renderer_class).to receive(:new).with(options)
531
- item_container.render(options)
512
+ it 'instantiates the passed renderer_class with the options' do
513
+ expect(renderer_class).to receive(:new).with({ renderer: :my_renderer })
514
+ item_container.render(renderer: :my_renderer)
532
515
  end
533
516
 
534
517
  it 'calls render on the renderer and passes self' do
535
518
  expect(renderer_instance).to receive(:render).with(item_container)
536
- item_container.render(options)
519
+ item_container.render(renderer: :my_renderer)
537
520
  end
538
521
  end
539
522
  end
540
523
 
541
- describe '#renderer' do
542
- context 'when no renderer is set explicitly' do
543
- it 'returns globally-configured renderer' do
544
- expect(item_container.renderer).to be Configuration.instance.renderer
545
- end
546
- end
524
+ context 'when no renderer is specified' do
525
+ let(:options) { {} }
547
526
 
548
- context 'when a renderer is set explicitly' do
549
- let(:renderer) { double(:renderer) }
527
+ before { allow(item_container).to receive_messages(renderer: renderer_class) }
550
528
 
551
- before { item_container.renderer = renderer }
529
+ it "instantiates the container's renderer with the options" do
530
+ expect(renderer_class).to receive(:new).with(options)
531
+ item_container.render(options)
532
+ end
552
533
 
553
- it 'returns the specified renderer' do
554
- expect(item_container.renderer).to be renderer
555
- end
534
+ it 'calls render on the renderer and passes self' do
535
+ expect(renderer_instance).to receive(:render).with(item_container)
536
+ item_container.render(options)
556
537
  end
557
538
  end
539
+ end
558
540
 
559
- describe '#level_for_item' do
560
- before(:each) do
561
- item_container.item(:p1, 'p1', 'p1')
562
- item_container.item(:p2, 'p2', 'p2') do |p2|
563
- p2.item(:s1, 's1', 's1')
564
- p2.item(:s2, 's2', 's2') do |s2|
565
- s2.item(:ss1, 'ss1', 'ss1')
566
- s2.item(:ss2, 'ss2', 'ss2')
567
- end
568
- p2.item(:s3, 's3', 's3')
569
- end
570
- item_container.item(:p3, 'p3', 'p3')
541
+ describe '#renderer' do
542
+ context 'when no renderer is set explicitly' do
543
+ it 'returns globally-configured renderer' do
544
+ expect(item_container.renderer).to be SimpleNavigation::Configuration.instance.renderer
571
545
  end
546
+ end
572
547
 
573
- shared_examples 'returning the level of an item' do |item, level|
574
- specify{ expect(item_container.level_for_item(item)).to eq level }
575
- end
548
+ context 'when a renderer is set explicitly' do
549
+ let(:renderer) { double(:renderer) }
576
550
 
577
- it_behaves_like 'returning the level of an item', :p1, 1
578
- it_behaves_like 'returning the level of an item', :p3, 1
579
- it_behaves_like 'returning the level of an item', :s1, 2
580
- it_behaves_like 'returning the level of an item', :ss1, 3
581
- it_behaves_like 'returning the level of an item', :x, nil
551
+ before { item_container.renderer = renderer }
552
+
553
+ it 'returns the specified renderer' do
554
+ expect(item_container.renderer).to be renderer
555
+ end
582
556
  end
557
+ end
583
558
 
584
- describe '#empty?' do
585
- context 'when there are no items' do
586
- it 'returns true' do
587
- item_container.instance_variable_set(:@items, [])
588
- expect(item_container).to be_empty
559
+ describe '#level_for_item' do
560
+ before do
561
+ item_container.item(:p1, 'p1', 'p1')
562
+ item_container.item(:p2, 'p2', 'p2') do |p2|
563
+ p2.item(:s1, 's1', 's1')
564
+ p2.item(:s2, 's2', 's2') do |s2|
565
+ s2.item(:ss1, 'ss1', 'ss1')
566
+ s2.item(:ss2, 'ss2', 'ss2')
589
567
  end
568
+ p2.item(:s3, 's3', 's3')
590
569
  end
570
+ item_container.item(:p3, 'p3', 'p3')
571
+ end
591
572
 
592
- context 'when there are some items' do
593
- it 'returns false' do
594
- item_container.instance_variable_set(:@items, [double(:item)])
595
- expect(item_container).not_to be_empty
596
- end
573
+ shared_examples 'returning the level of an item' do |item, level|
574
+ specify { expect(item_container.level_for_item(item)).to eq level }
575
+ end
576
+
577
+ it_behaves_like 'returning the level of an item', :p1, 1
578
+ it_behaves_like 'returning the level of an item', :p3, 1
579
+ it_behaves_like 'returning the level of an item', :s1, 2
580
+ it_behaves_like 'returning the level of an item', :ss1, 3
581
+ it_behaves_like 'returning the level of an item', :x, nil
582
+ end
583
+
584
+ describe '#empty?' do
585
+ context 'when there are no items' do
586
+ it 'returns true' do
587
+ item_container.instance_variable_set(:@items, [])
588
+ expect(item_container).to be_empty
589
+ end
590
+ end
591
+
592
+ context 'when there are some items' do
593
+ it 'returns false' do
594
+ item_container.instance_variable_set(:@items, [double(:item)])
595
+ expect(item_container).not_to be_empty
597
596
  end
598
597
  end
599
598
  end