simple-navigation 3.11.0 → 3.12.0

Sign up to get free protection for your applications and to get access to all the features.
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