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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +84 -0
- data/.rspec +1 -2
- data/.rubocop.yml +49 -0
- data/.rubocop_todo.yml +38 -0
- data/Appraisals +55 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +21 -0
- data/Guardfile +4 -2
- data/README.md +11 -23
- data/Rakefile +2 -27
- data/bin/_guard-core +16 -0
- data/bin/appraisal +16 -0
- data/bin/guard +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/bin/rubocop +16 -0
- data/gemfiles/rails_6.1.gemfile +35 -0
- data/gemfiles/rails_7.0.gemfile +23 -0
- data/gemfiles/rails_7.1.gemfile +23 -0
- data/gemfiles/rails_7.2.gemfile +23 -0
- data/gemfiles/rails_8.0.gemfile +23 -0
- data/gemfiles/rails_8.1.gemfile +23 -0
- data/generators/navigation_config/navigation_config_generator.rb +2 -0
- data/generators/navigation_config/templates/config/navigation.rb +30 -26
- data/lib/generators/navigation_config/navigation_config_generator.rb +2 -0
- data/lib/simple-navigation.rb +3 -1
- data/lib/simple_navigation/adapters/base.rb +2 -0
- data/lib/simple_navigation/adapters/nanoc.rb +8 -3
- data/lib/simple_navigation/adapters/padrino.rb +3 -1
- data/lib/simple_navigation/adapters/rails.rb +12 -14
- data/lib/simple_navigation/adapters/sinatra.rb +4 -6
- data/lib/simple_navigation/config_file.rb +1 -1
- data/lib/simple_navigation/config_file_finder.rb +3 -3
- data/lib/simple_navigation/configuration.rb +5 -5
- data/lib/simple_navigation/helpers.rb +9 -11
- data/lib/simple_navigation/item.rb +26 -20
- data/lib/simple_navigation/item_adapter.rb +16 -5
- data/lib/simple_navigation/item_container.rb +13 -7
- data/lib/simple_navigation/items_provider.rb +6 -4
- data/lib/simple_navigation/railtie.rb +3 -1
- data/lib/simple_navigation/renderer/base.rb +5 -5
- data/lib/simple_navigation/renderer/breadcrumbs.rb +4 -3
- data/lib/simple_navigation/renderer/json.rb +1 -1
- data/lib/simple_navigation/renderer/links.rb +2 -0
- data/lib/simple_navigation/renderer/list.rb +5 -5
- data/lib/simple_navigation/renderer/text.rb +3 -1
- data/lib/simple_navigation/version.rb +3 -1
- data/lib/simple_navigation.rb +32 -24
- data/simple-navigation.gemspec +16 -27
- data/spec/fake_app/config/navigation.rb +4 -2
- data/spec/fake_app/rails_app.rb +5 -3
- data/spec/integration/rendering_navigation_spec.rb +7 -5
- data/spec/simple_navigation/adapters/nanoc_spec.rb +97 -0
- data/spec/simple_navigation/adapters/padrino_spec.rb +41 -22
- data/spec/simple_navigation/adapters/rails_spec.rb +199 -206
- data/spec/simple_navigation/adapters/sinatra_spec.rb +21 -5
- data/spec/simple_navigation/config_file_finder_spec.rb +32 -28
- data/spec/simple_navigation/config_file_spec.rb +14 -14
- data/spec/simple_navigation/configuration_spec.rb +128 -121
- data/spec/simple_navigation/helpers_spec.rb +282 -284
- data/spec/simple_navigation/item_adapter_spec.rb +109 -122
- data/spec/simple_navigation/item_container_spec.rb +407 -408
- data/spec/simple_navigation/item_spec.rb +333 -301
- data/spec/simple_navigation/items_provider_spec.rb +30 -27
- data/spec/simple_navigation/renderer/base_spec.rb +166 -168
- data/spec/simple_navigation/renderer/breadcrumbs_spec.rb +81 -83
- data/spec/simple_navigation/renderer/json_spec.rb +49 -56
- data/spec/simple_navigation/renderer/links_spec.rb +81 -83
- data/spec/simple_navigation/renderer/list_spec.rb +111 -91
- data/spec/simple_navigation/renderer/text_spec.rb +37 -39
- data/spec/simple_navigation_spec.rb +54 -47
- data/spec/spec_helper.rb +146 -53
- metadata +25 -164
- data/.travis.yml +0 -23
- data/gemfiles/rails-3-2-stable.gemfile +0 -11
- data/gemfiles/rails-4-1-stable.gemfile +0 -7
- data/gemfiles/rails-4-2-stable.gemfile +0 -7
- data/gemfiles/rails-5-2-stable.gemfile +0 -7
- data/gemfiles/rails-6-0-stable.gemfile +0 -9
- data/gemfiles/rails-6-1-stable.gemfile +0 -9
- data/init.rb +0 -1
- data/install.rb +0 -5
- data/lib/simple_navigation/adapters.rb +0 -10
- data/lib/simple_navigation/renderer.rb +0 -12
- data/spec/initializers/coveralls.rb +0 -3
- data/spec/initializers/have_css_matcher.rb +0 -19
- data/spec/initializers/memfs.rb +0 -7
- data/spec/initializers/rails.rb +0 -4
- data/spec/initializers/rspec.rb +0 -7
- data/uninstall.rb +0 -1
|
@@ -1,115 +1,113 @@
|
|
|
1
|
-
|
|
2
|
-
module Renderer
|
|
3
|
-
describe Breadcrumbs do
|
|
4
|
-
let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
|
|
1
|
+
# frozen_string_literal: true
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let(:output) { renderer.render(navigation) }
|
|
9
|
-
let(:renderer) { Breadcrumbs.new(options) }
|
|
3
|
+
RSpec.describe SimpleNavigation::Renderer::Breadcrumbs do
|
|
4
|
+
let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
|
|
10
5
|
|
|
11
|
-
|
|
6
|
+
let(:item) { nil }
|
|
7
|
+
let(:options) { { level: :all } }
|
|
8
|
+
let(:output) { renderer.render(navigation) }
|
|
9
|
+
let(:renderer) { described_class.new(options) }
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
it "renders a 'div' tag for the navigation" do
|
|
15
|
-
expect(output).to have_css('div')
|
|
16
|
-
end
|
|
11
|
+
before { select_an_item(navigation[item]) if item }
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
describe '#render' do
|
|
14
|
+
it "renders a 'div' tag for the navigation" do
|
|
15
|
+
expect(output).to have_css('div')
|
|
16
|
+
end
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
it "sets the right html id on the rendered 'div' tag" do
|
|
19
|
+
expect(output).to have_css('div#nav_id')
|
|
20
|
+
end
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
end
|
|
30
|
-
end
|
|
22
|
+
it "sets the right html classes on the rendered 'div' tag" do
|
|
23
|
+
expect(output).to have_css('div.nav_class')
|
|
24
|
+
end
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
context 'when no item is selected' do
|
|
27
|
+
it "doesn't render any 'a' tag in the 'div' tag" do
|
|
28
|
+
expect(output).to have_no_css('div a')
|
|
29
|
+
end
|
|
30
|
+
end
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
end
|
|
32
|
+
context 'when an item is selected' do
|
|
33
|
+
let(:item) { :invoices }
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
it "renders the selected 'a' tag" do
|
|
36
|
+
expect(output).to have_css('div a')
|
|
37
|
+
end
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
it "remders the 'a' tag without any html id" do
|
|
40
|
+
expect(output).to have_no_css('div a[id]')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "renders the 'a' tag without any html class" do
|
|
44
|
+
expect(output).to have_no_css('div a[class]')
|
|
45
|
+
end
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
context 'when the :allow_classes_and_ids option is true' do
|
|
48
|
+
let(:options) { { level: :all, allow_classes_and_ids: true } }
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
it "renders the 'a' tag with the selected class" do
|
|
51
|
+
expect(output).to have_css('div a.selected')
|
|
52
|
+
end
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
context "when the item hasn't any id explicitly set" do
|
|
55
|
+
it "renders the 'a' tag without any html id" do
|
|
56
|
+
expect(output).to have_no_css('div a[id]')
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
context 'when the item has an explicitly set id' do
|
|
61
|
+
let(:item) { :users }
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
end
|
|
66
|
-
end
|
|
63
|
+
it "renders the 'a' tag with an html id" do
|
|
64
|
+
expect(output).to have_css('div a#breadcrumb_users_link_id')
|
|
67
65
|
end
|
|
68
66
|
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
context 'when the :prefix option is set' do
|
|
71
|
+
let(:options) { { prefix: 'You are here: ' } }
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
context 'when there are no items to render' do
|
|
74
|
+
let(:item) { nil }
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
it "doesn't render the prefix before the breadcrumbs" do
|
|
77
|
+
expect(output).not_to match(/^<div.+>You are here: /)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
context 'when there are items to render' do
|
|
82
|
+
let(:item) { :invoices }
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
end
|
|
87
|
-
end
|
|
84
|
+
it 'renders the prefix before the breadcrumbs' do
|
|
85
|
+
expect(output).to match(/^<div.+>You are here: /)
|
|
88
86
|
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
context 'when a sub navigation item is selected' do
|
|
91
|
+
before do
|
|
92
|
+
allow(navigation[:invoices]).to receive_messages(selected?: true)
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
allow(navigation[:invoices].sub_navigation[:unpaid]).to \
|
|
95
|
+
receive_messages(selected?: true, selected_by_condition?: true)
|
|
96
|
+
end
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
it 'renders all items as links' do
|
|
99
|
+
expect(output).to have_css('div a', 2)
|
|
100
|
+
end
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
context 'when the :static_leaf option is true' do
|
|
103
|
+
let(:options) { { level: :all, static_leaf: true } }
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
it 'renders the items as links' do
|
|
106
|
+
expect(output).to have_css('div a')
|
|
107
|
+
end
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
end
|
|
112
|
-
end
|
|
109
|
+
it 'renders the last item as simple text' do
|
|
110
|
+
expect(output).to have_css('div span')
|
|
113
111
|
end
|
|
114
112
|
end
|
|
115
113
|
end
|
|
@@ -1,73 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
module Renderer
|
|
3
|
-
describe Json do
|
|
4
|
-
describe '#render' do
|
|
5
|
-
let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
|
|
1
|
+
# frozen_string_literal: true
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
let(:parsed_output) { JSON.parse(output) }
|
|
11
|
-
let(:renderer) { Json.new(options) }
|
|
3
|
+
RSpec.describe SimpleNavigation::Renderer::Json do
|
|
4
|
+
describe '#render' do
|
|
5
|
+
let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
|
|
12
6
|
|
|
13
|
-
|
|
7
|
+
let(:item) { :invoices }
|
|
8
|
+
let(:options) { { level: :all } }
|
|
9
|
+
let(:output) { renderer.render(navigation) }
|
|
10
|
+
let(:parsed_output) { JSON.parse(output) }
|
|
11
|
+
let(:renderer) { described_class.new(options) }
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
before { select_an_item(navigation[item]) if item }
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
context 'when an item is selected' do
|
|
16
|
+
it 'renders the selected page' do
|
|
17
|
+
invoices_item = parsed_output.find { |item| item['name'] == 'Invoices' }
|
|
18
|
+
expect(invoices_item).to include('selected' => true)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
context 'when the :as_hash option is true' do
|
|
23
|
+
let(:options) { { level: :all, as_hash: true } }
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
it 'returns every item as a hash' do # rubocop:disable RSpec/MultipleExpectations
|
|
26
|
+
expect(output).to be_an Array
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
end
|
|
32
|
-
end
|
|
28
|
+
expect(output).to all(be_an Hash)
|
|
29
|
+
end
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
it 'renders the selected page' do
|
|
32
|
+
invoices_item = output.find { |item| item[:name] == 'Invoices' }
|
|
33
|
+
expect(invoices_item).to include(selected: true)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
end
|
|
46
|
-
end
|
|
37
|
+
context 'with options' do
|
|
38
|
+
it 'renders options for each item' do
|
|
39
|
+
expect(parsed_output).to all(have_key('options'))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
context 'when a sub navigation item is selected' do
|
|
44
|
+
let(:invoices_item) do
|
|
45
|
+
parsed_output.find { |item| item['name'] == 'Invoices' }
|
|
46
|
+
end
|
|
47
|
+
let(:unpaid_item) do
|
|
48
|
+
invoices_item['items'].find { |item| item['name'] == 'Unpaid' }
|
|
49
|
+
end
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
before do
|
|
52
|
+
allow(navigation[:invoices]).to receive_messages(selected?: true)
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
allow(navigation[:invoices].sub_navigation[:unpaid]).to \
|
|
55
|
+
receive_messages(selected?: true, selected_by_condition?: true)
|
|
56
|
+
end
|
|
62
57
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
it 'marks all the parent items as selected' do
|
|
59
|
+
expect(invoices_item).to include('selected' => true)
|
|
60
|
+
end
|
|
66
61
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
end
|
|
62
|
+
it 'marks the item as selected' do
|
|
63
|
+
expect(unpaid_item).to include('selected' => true)
|
|
71
64
|
end
|
|
72
65
|
end
|
|
73
66
|
end
|
|
@@ -1,86 +1,84 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
end
|
|
83
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe SimpleNavigation::Renderer::Links do
|
|
4
|
+
describe '#render' do
|
|
5
|
+
let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
|
|
6
|
+
|
|
7
|
+
let(:item) { nil }
|
|
8
|
+
let(:options) { { level: :all } }
|
|
9
|
+
let(:output) { renderer.render(navigation) }
|
|
10
|
+
let(:renderer) { described_class.new(options) }
|
|
11
|
+
|
|
12
|
+
before { select_an_item(navigation[item]) if item }
|
|
13
|
+
|
|
14
|
+
it "renders a 'div' tag for the navigation" do
|
|
15
|
+
expect(output).to have_css('div')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "sets the right html id on the rendered 'div' tag" do
|
|
19
|
+
expect(output).to have_css('div#nav_id')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "sets the right html classes on the rendered 'div' tag" do
|
|
23
|
+
expect(output).to have_css('div.nav_class')
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "renders an 'a' tag for each item" do
|
|
27
|
+
expect(output).to have_css('a', 3)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "renders the 'a' tags with the corresponding item's :html_options" do
|
|
31
|
+
expect(output).to have_css('a[style="float:right"]')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context 'when an item has a specified id' do
|
|
35
|
+
it "renders the 'a' tags with the specified id" do
|
|
36
|
+
expect(output).to have_css('a#users_id')
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'when an item has no specified id' do
|
|
41
|
+
it "uses a default id by stringifying the item's key" do
|
|
42
|
+
expect(output).to have_css('a#invoices')
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'when no item is selected' do
|
|
47
|
+
it "renders items without the 'selected' class" do
|
|
48
|
+
expect(output).to have_no_css('a.selected')
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context 'when an item is selected' do
|
|
53
|
+
let(:item) { :invoices }
|
|
54
|
+
|
|
55
|
+
it "renders the selected item with the 'selected' class" do
|
|
56
|
+
expect(output).to have_css('a#invoices.selected')
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'when the :join_with option is set' do
|
|
61
|
+
let(:options) { { level: :all, join_with: ' | ' } }
|
|
62
|
+
|
|
63
|
+
it 'separates the items with the specified separator' do
|
|
64
|
+
expect(output.scan(' | ').size).to eq 3
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context 'when a sub navigation item is selected' do
|
|
69
|
+
before do
|
|
70
|
+
allow(navigation[:invoices]).to receive_messages(selected?: true)
|
|
71
|
+
|
|
72
|
+
allow(navigation[:invoices].sub_navigation[:unpaid]).to \
|
|
73
|
+
receive_messages(selected?: true, selected_by_condition?: true)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'renders the main parent as selected' do
|
|
77
|
+
expect(output).to have_css('a#invoices.selected')
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "doesn't render the nested item's link" do
|
|
81
|
+
expect(output).to have_no_css('a#unpaid')
|
|
84
82
|
end
|
|
85
83
|
end
|
|
86
84
|
end
|