simple-navigation 3.11.0 → 3.12.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 (46) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +4 -0
  4. data/CHANGELOG +11 -0
  5. data/Gemfile +2 -16
  6. data/Guardfile +5 -0
  7. data/LICENSE +22 -0
  8. data/README.md +40 -0
  9. data/Rakefile +6 -39
  10. data/generators/navigation_config/templates/config/navigation.rb +7 -5
  11. data/init.rb +1 -0
  12. data/install.rb +5 -0
  13. data/lib/simple_navigation/adapters/rails.rb +5 -1
  14. data/lib/simple_navigation/core/configuration.rb +5 -1
  15. data/lib/simple_navigation/core/item.rb +2 -1
  16. data/lib/simple_navigation/core/item_adapter.rb +4 -4
  17. data/lib/simple_navigation/core/item_container.rb +6 -1
  18. data/lib/simple_navigation/rendering/renderer/breadcrumbs.rb +2 -2
  19. data/lib/simple_navigation/rendering/renderer/links.rb +2 -2
  20. data/lib/simple_navigation/rendering/renderer/list.rb +1 -1
  21. data/lib/simple_navigation/version.rb +3 -0
  22. data/lib/simple_navigation.rb +1 -0
  23. data/simple-navigation.gemspec +40 -0
  24. data/spec/initializers/have_css_matcher.rb +13 -0
  25. data/spec/lib/simple_navigation/adapters/padrino_spec.rb +23 -25
  26. data/spec/lib/simple_navigation/adapters/rails_spec.rb +276 -250
  27. data/spec/lib/simple_navigation/adapters/sinatra_spec.rb +64 -53
  28. data/spec/lib/simple_navigation/core/configuration_spec.rb +128 -106
  29. data/spec/lib/simple_navigation/core/item_adapter_spec.rb +144 -168
  30. data/spec/lib/simple_navigation/core/item_container_spec.rb +361 -339
  31. data/spec/lib/simple_navigation/core/item_spec.rb +571 -434
  32. data/spec/lib/simple_navigation/core/items_provider_spec.rb +35 -49
  33. data/spec/lib/simple_navigation/rails_controller_methods_spec.rb +194 -173
  34. data/spec/lib/simple_navigation/rendering/helpers_spec.rb +381 -225
  35. data/spec/lib/simple_navigation/rendering/renderer/base_spec.rb +205 -164
  36. data/spec/lib/simple_navigation/rendering/renderer/breadcrumbs_spec.rb +87 -67
  37. data/spec/lib/simple_navigation/rendering/renderer/json_spec.rb +52 -31
  38. data/spec/lib/simple_navigation/rendering/renderer/links_spec.rb +75 -48
  39. data/spec/lib/simple_navigation/rendering/renderer/list_spec.rb +62 -174
  40. data/spec/lib/simple_navigation/rendering/renderer/text_spec.rb +41 -28
  41. data/spec/lib/simple_navigation_spec.rb +207 -225
  42. data/spec/spec_helper.rb +53 -82
  43. data/uninstall.rb +1 -0
  44. metadata +100 -22
  45. data/README +0 -22
  46. data/VERSION +0 -1
@@ -1,199 +1,240 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe SimpleNavigation::Renderer::Base do
4
- before(:each) do
5
- @options = stub(:options).as_null_object
6
- @adapter = stub(:adapter)
7
- SimpleNavigation.stub!(:adapter => @adapter)
8
- @base_renderer = SimpleNavigation::Renderer::Base.new(@options)
9
- end
10
-
11
- describe 'delegated methods' do
12
- it {@base_renderer.should respond_to(:link_to)}
13
- it {@base_renderer.should respond_to(:content_tag)}
14
- end
3
+ module SimpleNavigation
4
+ module Renderer
5
+ describe Base do
6
+ subject(:base) { Base.new(options) }
15
7
 
16
- describe 'initialize' do
17
- it {@base_renderer.adapter.should == @adapter}
18
- it {@base_renderer.options.should == @options}
19
- end
20
-
21
- describe 'render' do
22
- it "be subclass responsability" do
23
- lambda {@base_renderer.render(:container)}.should raise_error('subclass responsibility')
24
- end
25
- end
26
-
27
- describe 'expand_all?' do
28
- context 'option is set' do
29
- context 'expand_all is true' do
30
- before(:each) do
31
- @base_renderer.stub!(:options => {:expand_all => true})
32
- end
33
- it {@base_renderer.expand_all?.should be_true}
34
- end
35
- context 'expand_all is false' do
36
- before(:each) do
37
- @base_renderer.stub!(:options => {:expand_all => false})
38
- end
39
- it {@base_renderer.expand_all?.should be_false}
40
- end
41
- end
42
- context 'option is not set' do
43
- before(:each) do
44
- @base_renderer.stub!(:options => {})
45
- end
46
- it {@base_renderer.expand_all?.should be_false}
47
- end
48
- end
8
+ let(:adapter) { double(:adapter) }
9
+ let(:options) { Hash.new }
49
10
 
50
- describe 'skip_if_empty?' do
51
- context 'option is set' do
52
- context 'skip_if_empty is true' do
53
- before(:each) do
54
- @base_renderer.stub!(:options => {:skip_if_empty => true})
55
- end
56
- it {@base_renderer.skip_if_empty?.should be_true}
57
- end
58
- context 'skip_if_empty is false' do
59
- before(:each) do
60
- @base_renderer.stub!(:options => {:skip_if_empty => false})
61
- end
62
- it {@base_renderer.skip_if_empty?.should be_false}
63
- end
64
- end
65
- context 'option is not set' do
66
- before(:each) do
67
- @base_renderer.stub!(:options => {})
68
- end
69
- it {@base_renderer.skip_if_empty?.should be_false}
70
- end
71
- end
11
+ before { SimpleNavigation.stub(adapter: adapter) }
72
12
 
73
- describe 'level' do
74
- context 'options[level] is set' do
75
- before(:each) do
76
- @base_renderer.stub!(:options => {:level => 1})
13
+ it 'delegates the :link_to method to adapter' do
14
+ adapter.stub(link_to: 'link_to')
15
+ expect(base.link_to).to eq 'link_to'
77
16
  end
78
- it {@base_renderer.level.should == 1}
79
- end
80
- context 'options[level] is not set' do
81
- before(:each) do
82
- @base_renderer.stub!(:options => {})
83
- end
84
- it {@base_renderer.level.should == :all}
85
- end
86
- end
87
17
 
88
- describe 'consider_sub_navigation?' do
89
- before(:each) do
90
- @item = stub(:item)
91
- end
92
- context 'item has no subnavigation' do
93
- before(:each) do
94
- @item.stub!(:sub_navigation => nil)
18
+ it 'delegates the :content_tag method to adapter' do
19
+ adapter.stub(content_tag: 'content_tag')
20
+ expect(base.content_tag).to eq 'content_tag'
95
21
  end
96
- it {@base_renderer.send(:consider_sub_navigation?, @item).should be_false}
97
- end
98
- context 'item has subnavigation' do
99
- before(:each) do
100
- @sub_navigation = stub(:sub_navigation)
101
- @item.stub!(:sub_navigation => @sub_navigation)
102
- end
103
- context 'level is something unknown' do
104
- before(:each) do
105
- @base_renderer.stub!(:level => 'unknown')
22
+
23
+ describe '#initialize' do
24
+ it "sets the renderer adapter to the SimpleNavigation one" do
25
+ expect(base.adapter).to be adapter
106
26
  end
107
- it {@base_renderer.send(:consider_sub_navigation?, @item).should be_false}
108
27
  end
109
- context 'level is :all' do
110
- before(:each) do
111
- @base_renderer.stub!(:level => :all)
28
+
29
+ describe '#options' do
30
+ it "returns the renderer's options" do
31
+ expect(base.options).to be options
112
32
  end
113
- it {@base_renderer.send(:consider_sub_navigation?, @item).should be_true}
114
33
  end
115
- context 'level is an Integer' do
116
- before(:each) do
117
- @base_renderer.stub!(:level => 2)
34
+
35
+ describe '#render' do
36
+ it "raise an exception to indicate it's a subclass responsibility" do
37
+ expect{ base.render(:container) }.to raise_error
118
38
  end
119
- it {@base_renderer.send(:consider_sub_navigation?, @item).should be_false}
120
39
  end
121
- context 'level is a Range' do
122
- before(:each) do
123
- @base_renderer.stub!(:level => 2..3)
40
+
41
+ describe '#expand_all?' do
42
+ context 'when :options is set' do
43
+ context 'and the :expand_all option is true' do
44
+ let(:options) {{ expand_all: true }}
45
+
46
+ it 'returns true' do
47
+ expect(base.expand_all?).to be_true
48
+ end
49
+ end
50
+
51
+ context 'and the :expand_all option is false' do
52
+ let(:options) {{ expand_all: false }}
53
+
54
+ it 'returns false' do
55
+ expect(base.expand_all?).to be_false
56
+ end
57
+ end
124
58
  end
125
- context 'subnavs level > range.max' do
126
- before(:each) do
127
- @sub_navigation.stub!(:level => 4)
59
+
60
+ context "when :options isn't set" do
61
+ let(:options) { Hash.new }
62
+
63
+ it 'returns false' do
64
+ expect(base.expand_all?).to be_false
128
65
  end
129
- it {@base_renderer.send(:consider_sub_navigation?, @item).should be_false}
130
66
  end
131
- context 'subnavs level = range.max' do
132
- before(:each) do
133
- @sub_navigation.stub!(:level => 3)
67
+ end
68
+
69
+ describe '#skip_if_empty?' do
70
+ context 'when :options is set' do
71
+ context 'and the :skip_if_empty option is true' do
72
+ let(:options) {{ skip_if_empty: true }}
73
+
74
+ it 'returns true' do
75
+ expect(base.skip_if_empty?).to be_true
76
+ end
134
77
  end
135
- it {@base_renderer.send(:consider_sub_navigation?, @item).should be_true}
136
78
 
79
+ context 'and the :skip_if_empty option is false' do
80
+ let(:options) {{ skip_if_empty: false }}
81
+
82
+ it 'returns true' do
83
+ expect(base.skip_if_empty?).to be_false
84
+ end
85
+ end
137
86
  end
138
- context 'subnavs level < range.max' do
139
- before(:each) do
140
- @sub_navigation.stub!(:level => 2)
87
+
88
+ context "when :options isn't set" do
89
+ let(:options) { Hash.new }
90
+
91
+ it 'returns true' do
92
+ expect(base.skip_if_empty?).to be_false
141
93
  end
142
- it {@base_renderer.send(:consider_sub_navigation?, @item).should be_true}
143
94
  end
144
95
  end
145
- end
146
- end
147
96
 
148
- describe 'include_sub_navigation?' do
149
- before(:each) do
150
- @item = stub(:item)
151
- end
152
- context 'consider_sub_navigation? is true' do
153
- before(:each) do
154
- @base_renderer.stub!(:consider_sub_navigation? => true)
155
- end
156
- context 'expand_sub_navigation? is true' do
157
- before(:each) do
158
- @base_renderer.stub!(:expand_sub_navigation? => true)
97
+ describe '#level' do
98
+ context 'and the :level option is set' do
99
+ let(:options) {{ level: 1 }}
100
+
101
+ it 'returns the specified level' do
102
+ expect(base.level).to eq 1
103
+ end
159
104
  end
160
- it {@base_renderer.include_sub_navigation?(@item).should be_true}
161
- end
162
- context 'expand_sub_navigation? is false' do
163
- before(:each) do
164
- @base_renderer.stub!(:expand_sub_navigation? => false)
105
+
106
+ context "and the :level option isn't set" do
107
+ let(:options) { Hash.new }
108
+
109
+ it 'returns :all' do
110
+ expect(base.level).to eq :all
111
+ end
165
112
  end
166
- it {@base_renderer.include_sub_navigation?(@item).should be_false}
167
113
  end
168
- end
169
- context 'consider_sub_navigation is false' do
170
- before(:each) do
171
- @base_renderer.stub!(:consider_sub_navigation? => false)
172
- end
173
- context 'expand_sub_navigation? is true' do
174
- before(:each) do
175
- @base_renderer.stub!(:expand_sub_navigation? => true)
114
+
115
+ describe '#consider_sub_navigation?' do
116
+ let(:item) { double(:item) }
117
+
118
+ before { item.stub(sub_navigation: sub_navigation) }
119
+
120
+ context 'when the item has no sub navigation' do
121
+ let(:sub_navigation) { nil }
122
+
123
+ it 'returns false' do
124
+ expect(base.send(:consider_sub_navigation?, item)).to be_false
125
+ end
126
+ end
127
+
128
+ context 'when the item has sub navigation' do
129
+ let(:sub_navigation) { double(:sub_navigation) }
130
+
131
+ context 'and the renderer has an unknown level' do
132
+ before { base.stub(level: 'unknown') }
133
+
134
+ it 'returns false' do
135
+ expect(base.send(:consider_sub_navigation?, item)).to be_false
136
+ end
137
+ end
138
+
139
+ context 'and the renderer has a level set to :all' do
140
+ before { base.stub(level: :all) }
141
+
142
+ it 'returns false' do
143
+ expect(base.send(:consider_sub_navigation?, item)).to be_true
144
+ end
145
+ end
146
+
147
+ context "when the renderer's level is a number" do
148
+ before { base.stub(level: 2) }
149
+
150
+ it 'returns false' do
151
+ expect(base.send(:consider_sub_navigation?, item)).to be_false
152
+ end
153
+ end
154
+
155
+ context "when the renderer's level is a Range" do
156
+ before { base.stub(level: 2..3) }
157
+
158
+ context "and sub navigation's level is greater than range.max" do
159
+ before { sub_navigation.stub(level: 4) }
160
+
161
+ it 'returns false' do
162
+ expect(base.send(:consider_sub_navigation?, item)).to be_false
163
+ end
164
+ end
165
+
166
+ context "and sub navigation's level is equal to range.max" do
167
+ before { sub_navigation.stub(level: 3) }
168
+
169
+ it 'returns true' do
170
+ expect(base.send(:consider_sub_navigation?, item)).to be_true
171
+ end
172
+ end
173
+
174
+ context "and sub navigation's level is equal to range.min" do
175
+ before { sub_navigation.stub(level: 2) }
176
+
177
+ it 'returns true' do
178
+ expect(base.send(:consider_sub_navigation?, item)).to be_true
179
+ end
180
+ end
181
+ end
176
182
  end
177
- it {@base_renderer.include_sub_navigation?(@item).should be_false}
178
183
  end
179
- context 'expand_sub_navigation? is false' do
180
- before(:each) do
181
- @base_renderer.stub!(:expand_sub_navigation? => false)
184
+
185
+ describe '#include_sub_navigation?' do
186
+ let(:item) { double(:item) }
187
+
188
+ context 'when consider_sub_navigation? is true' do
189
+ before { base.stub(consider_sub_navigation?: true) }
190
+
191
+ context 'and expand_sub_navigation? is true' do
192
+ before { base.stub(expand_sub_navigation?: true) }
193
+
194
+ it 'returns true' do
195
+ expect(base.include_sub_navigation?(item)).to be_true
196
+ end
197
+ end
198
+
199
+ context 'and expand_sub_navigation? is false' do
200
+ before { base.stub(expand_sub_navigation?: false) }
201
+
202
+ it 'returns false' do
203
+ expect(base.include_sub_navigation?(item)).to be_false
204
+ end
205
+ end
206
+ end
207
+
208
+ context 'consider_sub_navigation? is false' do
209
+ before { base.stub(consider_sub_navigation?: false) }
210
+
211
+ context 'and expand_sub_navigation? is true' do
212
+ before { base.stub(expand_sub_navigation?: true) }
213
+
214
+ it 'returns false' do
215
+ expect(base.include_sub_navigation?(item)).to be_false
216
+ end
217
+ end
218
+
219
+ context 'and expand_sub_navigation? is false' do
220
+ before { base.stub(expand_sub_navigation?: false) }
221
+
222
+ it 'returns false' do
223
+ expect(base.include_sub_navigation?(item)).to be_false
224
+ end
225
+ end
182
226
  end
183
- it {@base_renderer.include_sub_navigation?(@item).should be_false}
184
227
  end
185
- end
186
- end
187
228
 
188
- describe 'render_sub_navigation_for' do
189
- before(:each) do
190
- @sub_navigation = stub(:sub_navigation)
191
- @item = stub(:item, :sub_navigation => @sub_navigation)
192
- end
193
- it "should call render on the sub_navigation (passing the options)" do
194
- @sub_navigation.should_receive(:render).with(@options)
195
- @base_renderer.render_sub_navigation_for(@item)
229
+ describe '#render_sub_navigation_for' do
230
+ let(:item) { double(:item, sub_navigation: sub_navigation) }
231
+ let(:sub_navigation) { double(:sub_navigation) }
232
+
233
+ it 'renders the sub navigation passing it the options' do
234
+ expect(sub_navigation).to receive(:render).with(options)
235
+ base.render_sub_navigation_for(item)
236
+ end
237
+ end
196
238
  end
197
239
  end
198
-
199
240
  end
@@ -1,99 +1,119 @@
1
1
  require 'spec_helper'
2
- require 'html/document'# unless defined? HTML::Document
3
2
 
4
- describe SimpleNavigation::Renderer::Breadcrumbs do
3
+ module SimpleNavigation
4
+ module Renderer
5
+ describe Breadcrumbs do
6
+ let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
5
7
 
6
- describe 'render' do
8
+ let(:item) { nil }
9
+ let(:options) {{ level: :all }}
10
+ let(:output) { HTML::Document.new(raw_output).root }
11
+ let(:raw_output) { renderer.render(navigation) }
12
+ let(:renderer) { setup_renderer(Breadcrumbs, options) }
7
13
 
8
- def render(current_nav=nil, options={:level => :all})
9
- primary_navigation = primary_container
10
- select_item(current_nav) if current_nav
11
- setup_renderer_for SimpleNavigation::Renderer::Breadcrumbs, :rails, options
12
- HTML::Document.new(@renderer.render(primary_navigation)).root
13
- end
14
-
15
- context 'regarding result' do
14
+ before { select_an_item(navigation[item]) if item }
16
15
 
17
- it "should render a div-tag around the items" do
18
- HTML::Selector.new('div').select(render).should have(1).entries
16
+ describe '#render' do
17
+ it "renders a 'div' tag for the navigation" do
18
+ expect(output).to have_css('div')
19
19
  end
20
- it "the rendered div-tag should have the specified dom_id" do
21
- HTML::Selector.new('div#nav_dom_id').select(render).should have(1).entries
20
+
21
+ it "sets the right html id on the rendered 'div' tag" do
22
+ expect(output).to have_css('div#nav_id')
22
23
  end
23
- it "the rendered div-tag should have the specified class" do
24
- HTML::Selector.new('div.nav_dom_class').select(render).should have(1).entries
24
+
25
+ it "sets the right html classes on the rendered 'div' tag" do
26
+ expect(output).to have_css('div.nav_class')
25
27
  end
26
28
 
27
- context 'without current_navigation set' do
28
- it "should not render any a-tag in the div-tag" do
29
- HTML::Selector.new('div a').select(render).should have(0).entries
29
+ context 'when no item is selected' do
30
+ it "doesn't render any 'a' tag in the 'div' tag" do
31
+ expect(output).not_to have_css('div a')
30
32
  end
31
33
  end
32
34
 
33
- context 'with current_navigation set' do
34
- before(:each) do
35
- @selection = HTML::Selector.new('div a').select(render(:invoices))
36
- end
37
- it "should render the selected a tags" do
38
- @selection.should have(1).entries
39
- end
35
+ context 'when an item is selected' do
36
+ let(:item) { :invoices }
40
37
 
41
- it "should not render class or id" do
42
- @selection.each do |tag|
43
- raise unless tag.name == "a"
44
- tag["id"].should be_nil
45
- tag["class"].should be_nil
38
+ it "renders the selected 'a' tag" do
39
+ expect(output).to have_css('div a')
40
+ end
41
+
42
+ it "remders the 'a' tag without any html id" do
43
+ expect(output).not_to have_css('div a[id]')
46
44
  end
47
- end
48
45
 
49
- context 'with allow_classes_and_ids option' do
50
- before(:each) do
51
- @selection = HTML::Selector.new('div a').select(render(:users, :level => :all, :allow_classes_and_ids => true))
46
+ it "renders the 'a' tag without any html class" do
47
+ expect(output).not_to have_css('div a[class]')
52
48
  end
53
- it "should render class and id" do
54
- @selection.each do |tag|
55
- raise unless tag.name == "a"
56
- tag["id"].should_not be_nil
57
- tag["class"].should_not be_nil
49
+
50
+ context 'and the :allow_classes_and_ids option is true' do
51
+ let(:options) {{ level: :all, allow_classes_and_ids: true }}
52
+
53
+ it "renders the 'a' tag with the selected class" do
54
+ expect(output).to have_css('div a.selected')
55
+ end
56
+
57
+ context "and the item hasn't any id explicitly set" do
58
+ it "renders the 'a' tag without any html id" do
59
+ expect(output).not_to have_css('div a[id]')
60
+ end
61
+ end
62
+
63
+ context 'and the item has an explicitly set id' do
64
+ let(:item) { :users }
65
+
66
+ it "renders the 'a' tag with an html id" do
67
+ expect(output).to have_css('div a#breadcrumb_users_link_id')
68
+ end
58
69
  end
59
70
  end
60
71
  end
61
72
 
62
- context 'with prefix option' do
63
- it 'should render prefix before breadcrumbs' do
64
- selection = HTML::Selector.new('div').select(render(:subnav1, :level => :all, :prefix => 'You are here: '))
65
- raise unless selection.count == 1
66
- tag = selection.first
67
- tag.to_s.should =~ /^\<div.+\>You are here\: /
73
+ context 'and the :prefix option is set' do
74
+ let(:options) {{ prefix: 'You are here: ' }}
75
+
76
+ context 'and there are no items to render' do
77
+ let(:item) { nil }
78
+
79
+ it "doesn't render the prefix before the breadcrumbs" do
80
+ expect(raw_output).not_to match(/^<div.+>You are here: /)
81
+ end
68
82
  end
69
83
 
70
- it 'should not render prefix if there is no available breadcrumb' do
71
- allow_message_expectations_on_nil
72
- selection = HTML::Selector.new('div').select(render('', :prefix => 'You are here: '))
73
- tag = selection.first
74
- tag.to_s.should =~ /^\<div.+\>\<\/div\>/
84
+ context 'and there are items to render' do
85
+ let(:item) { :invoices }
86
+
87
+ it 'renders the prefix before the breadcrumbs' do
88
+ expect(raw_output).to match(/^<div.+>You are here: /)
89
+ end
75
90
  end
76
91
  end
77
92
 
78
- context 'with static_leaf option' do
79
- before(:each) do
80
- @selection = HTML::Selector.new('div *').select(render(:subnav1, :level => :all, :static_leaf => true))
81
- end
82
- it "should render link for non-leaes" do
83
- @selection[0..-2].each do |tag|
84
- tag.name.should == 'a'
85
- end
93
+ context 'when a sub navigation item is selected' do
94
+ before do
95
+ navigation[:invoices].stub(selected?: true)
96
+
97
+ navigation[:invoices]
98
+ .sub_navigation[:unpaid]
99
+ .stub(selected?: true, selected_by_condition?: true)
86
100
  end
87
- it "should not render link for leaf" do
88
- @selection.last.name.should == 'span'
101
+
102
+ it 'renders all items as links' do
103
+ expect(output).to have_css('div a', 2)
89
104
  end
90
- end
91
- end
92
105
 
106
+ context 'when the :static_leaf option is true' do
107
+ let(:options) {{ level: :all, static_leaf: true }}
93
108
 
94
- context 'nested sub_navigation' do
95
- it "should add an a tag for each selected item" do
96
- HTML::Selector.new('div a').select(render(:subnav1)).should have(2).entries
109
+ it 'renders the items as links' do
110
+ expect(output).to have_css('div a')
111
+ end
112
+
113
+ it 'renders the last item as simple text' do
114
+ expect(output).to have_css('div span')
115
+ end
116
+ end
97
117
  end
98
118
  end
99
119
  end