loaf 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -3
- data/.rspec +1 -0
- data/.travis.yml +30 -12
- data/Appraisals +27 -9
- data/CHANGELOG.md +59 -11
- data/Gemfile +11 -11
- data/Gemfile.lock +182 -0
- data/README.md +120 -56
- data/assets/loaf_logo.png +0 -0
- data/bin/appraisal +16 -0
- data/bin/rake +16 -0
- data/gemfiles/rails3.2.gemfile +15 -13
- data/gemfiles/rails4.0.gemfile +13 -12
- data/gemfiles/rails4.1.gemfile +14 -13
- data/gemfiles/rails4.2.gemfile +14 -13
- data/gemfiles/rails5.0.gemfile +22 -0
- data/gemfiles/rails5.1.gemfile +22 -0
- data/lib/loaf.rb +2 -22
- data/lib/loaf/breadcrumb.rb +30 -0
- data/lib/loaf/configuration.rb +7 -8
- data/lib/loaf/controller_extensions.rb +13 -28
- data/lib/loaf/crumb.rb +5 -4
- data/lib/loaf/crumb_formatter.rb +3 -1
- data/lib/loaf/errors.rb +1 -3
- data/lib/loaf/options_validator.rb +2 -2
- data/lib/loaf/railtie.rb +19 -13
- data/lib/loaf/translation.rb +1 -1
- data/lib/loaf/version.rb +1 -3
- data/lib/loaf/view_extensions.rb +69 -18
- data/loaf.gemspec +20 -13
- data/spec/integration/{crumbs_routing_spec.rb → breadcrumb_trail_spec.rb} +19 -12
- data/spec/rails_app/app/controllers/application_controller.rb +2 -0
- data/spec/rails_app/app/controllers/posts_controller.rb +1 -4
- data/spec/rails_app/app/views/layouts/_breadcrumbs.html.erb +7 -5
- data/spec/rails_app/app/views/layouts/application.html.erb +0 -2
- data/spec/rails_app/config/environments/test.rb +1 -1
- data/spec/rails_app/config/secrets.yml +22 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/support/dummy_controller.rb +9 -0
- data/spec/support/dummy_view.rb +42 -2
- data/spec/unit/configuration_spec.rb +35 -0
- data/spec/unit/controller_extensions_spec.rb +5 -14
- data/spec/unit/generators/install_generator_spec.rb +2 -1
- data/spec/unit/view_extensions/breadcrumb_trail_spec.rb +232 -0
- metadata +65 -31
- data/.ruby-version +0 -1
- data/init.rb +0 -3
- data/lib/loaf/builder.rb +0 -38
- data/spec/rails_app/.gitignore +0 -5
- data/spec/rails_app/lib/assets/.gitkeep +0 -0
- data/spec/rails_app/lib/tasks/.gitkeep +0 -0
- data/spec/rails_app/script/rails +0 -6
- data/spec/unit/view_extensions/breadcrumbs_spec.rb +0 -128
data/loaf.gemspec
CHANGED
@@ -3,19 +3,26 @@ lib = File.expand_path('../lib', __FILE__)
|
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
4
|
require 'loaf/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'loaf'
|
8
|
+
spec.version = Loaf::VERSION.dup
|
9
|
+
spec.authors = ['Piotr Murach']
|
10
|
+
spec.email = [""]
|
11
|
+
spec.homepage = 'https://github.com/piotrmurach/loaf'
|
12
|
+
spec.summary = %q{Loaf manages and displays breadcrumb trails in your Rails application.}
|
13
|
+
spec.description = %q{Loaf manages and displays breadcrumb trails in your Rails app. It aims to handle breadcrumb data through easy dsl and expose it through view helpers without any assumptions about markup.}
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
spec.files = `git ls-files`.split("\n")
|
16
|
+
spec.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
17
|
+
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
|
20
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
21
|
+
spec.metadata['source_code_uri'] = 'https://github.com/piotrmurach/loaf'
|
22
|
+
spec.metadata['changelog_uri'] = 'https://github.com/piotrmurach/loaf/blob/master/CHANGELOG.md'
|
23
|
+
|
24
|
+
spec.add_dependency 'rails', '>= 3.2'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
27
|
+
spec.add_development_dependency 'rake'
|
21
28
|
end
|
@@ -1,25 +1,30 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
RSpec.describe "crumbs routing" do
|
3
|
+
RSpec.describe "breadcrumbs trail" do
|
6
4
|
include ActionView::TestCase::Behavior
|
7
5
|
|
8
|
-
it "
|
6
|
+
it "shows root breadcrumb" do
|
9
7
|
visit root_path
|
10
|
-
|
8
|
+
|
9
|
+
within '#breadcrumbs .selected' do
|
10
|
+
expect(page.html).to include('<a href="/">Home</a>')
|
11
|
+
end
|
11
12
|
end
|
12
13
|
|
13
14
|
it "inherits controller breadcrumb and adds index action breadcrumb" do
|
14
15
|
visit posts_path
|
16
|
+
|
15
17
|
within '#breadcrumbs' do
|
16
18
|
expect(page.html).to include('<a href="/">Home</a>')
|
17
|
-
|
19
|
+
within '.selected' do
|
20
|
+
expect(page.html).to include('<a href="/posts">All Posts</a>')
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
21
25
|
it 'filters out controller breadcrumb and adds new action breadcrumb' do
|
22
26
|
visit new_post_path
|
27
|
+
|
23
28
|
within '#breadcrumbs' do
|
24
29
|
expect(page).to_not have_content('Home')
|
25
30
|
expect(page).to have_content('New Post')
|
@@ -28,25 +33,27 @@ RSpec.describe "crumbs routing" do
|
|
28
33
|
|
29
34
|
it "adds breadcrumb in view with path variable" do
|
30
35
|
visit post_path(1)
|
31
|
-
|
36
|
+
|
37
|
+
within '#breadcrumbs .selected' do
|
32
38
|
expect(page.html).to include('<a href="/posts/1">Show Post in view</a>')
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
36
42
|
it 'is current when forced' do
|
37
43
|
visit new_post_path
|
38
|
-
click_button "Create"
|
39
44
|
|
40
|
-
expect(page.current_path).to eq(
|
45
|
+
expect(page.current_path).to eq(new_post_path)
|
41
46
|
within '#breadcrumbs' do
|
42
|
-
expect(page).to
|
43
|
-
expect(page).to
|
47
|
+
expect(page).to have_selector('li.selected', count: 2)
|
48
|
+
expect(page.html).to include('<a href="/posts">All</a>')
|
49
|
+
expect(page.html).to include('<a href="/posts/new">New Post</a>')
|
44
50
|
end
|
45
51
|
end
|
46
52
|
|
47
53
|
it "allows for procs in name and url" do
|
48
54
|
visit post_comments_path(1)
|
49
|
-
|
55
|
+
|
56
|
+
within '#breadcrumbs .selected' do
|
50
57
|
expect(page.html).to include('<a href="/posts/1/comments">Post comments</a>')
|
51
58
|
end
|
52
59
|
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
class Post < Struct.new(:id); end
|
2
2
|
|
3
3
|
class PostsController < ApplicationController
|
4
|
-
|
5
|
-
breadcrumb 'Home', :root_path, only: :index
|
6
|
-
|
7
4
|
def index
|
8
5
|
breadcrumb 'all_posts', posts_path
|
9
6
|
end
|
@@ -13,11 +10,11 @@ class PostsController < ApplicationController
|
|
13
10
|
end
|
14
11
|
|
15
12
|
def new
|
13
|
+
breadcrumb 'All', :posts_path, match: :force
|
16
14
|
breadcrumb 'New Post', new_post_path
|
17
15
|
end
|
18
16
|
|
19
17
|
def create
|
20
|
-
breadcrumb 'New Post', new_post_path, force: true
|
21
18
|
render action: :new
|
22
19
|
end
|
23
20
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
<% if
|
1
|
+
<% if breadcrumb_trail.any? %>
|
2
2
|
<ul id='breadcrumbs'>
|
3
|
-
<%
|
4
|
-
<li class="<%=
|
5
|
-
<%= link_to name, url %>
|
6
|
-
|
3
|
+
<% breadcrumb_trail do |crumb| %>
|
4
|
+
<li class="<%= crumb.current? ? 'selected' : '' %>">
|
5
|
+
<%= link_to crumb.name, crumb.url %>
|
6
|
+
<% unless crumb.current? %>
|
7
|
+
<span>::</span>
|
8
|
+
<% end %>
|
7
9
|
</li>
|
8
10
|
<% end %>
|
9
11
|
</ul>
|
@@ -8,7 +8,7 @@ RailsApp::Application.configure do
|
|
8
8
|
config.cache_classes = true
|
9
9
|
|
10
10
|
# Configure static asset server for tests with Cache-Control for performance
|
11
|
-
config.
|
11
|
+
config.serve_static_files = true
|
12
12
|
config.static_cache_control = "public, max-age=3600"
|
13
13
|
|
14
14
|
# Show full error reports and disable caching
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Your secret key is used for verifying the integrity of signed cookies.
|
4
|
+
# If you change this key, all old signed cookies will become invalid!
|
5
|
+
|
6
|
+
# Make sure the secret is at least 30 characters and all random,
|
7
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
8
|
+
# You can use `rake secret` to generate a secure secret key.
|
9
|
+
|
10
|
+
# Make sure the secrets in this file are kept private
|
11
|
+
# if you're sharing your code publicly.
|
12
|
+
|
13
|
+
development:
|
14
|
+
secret_key_base: c392df63ec28b42b36b92a5b9e8603fa62d7807024d07801ab162ec7a2a165a87d27a4a8535ce09cd2bf4a82afe45e3080fb8cc56613d608e5b18335594782b3
|
15
|
+
|
16
|
+
test:
|
17
|
+
secret_key_base: 4b1fba0d12c53b8b21880fda47b603b3dcca117ccf41fcc70091351b88ede5d4c5c91371f407cd056efd66fa5f306c23add65a89d4304e06a4243289ee97be1d
|
18
|
+
|
19
|
+
# Do not keep production secrets in the repository,
|
20
|
+
# instead read values from the environment.
|
21
|
+
production:
|
22
|
+
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
if
|
3
|
+
if (ENV['COVERAGE'] || ENV['TRAVIS']) && RUBY_VERSION < '2.4.0'
|
4
4
|
require 'simplecov'
|
5
5
|
require 'coveralls'
|
6
6
|
|
7
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
7
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
8
8
|
SimpleCov::Formatter::HTMLFormatter,
|
9
9
|
Coveralls::SimpleCov::Formatter
|
10
|
-
]
|
10
|
+
])
|
11
11
|
|
12
12
|
SimpleCov.start do
|
13
13
|
command_name 'spec'
|
data/spec/support/dummy_view.rb
CHANGED
@@ -1,7 +1,47 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
1
3
|
class DummyView < ActionView::Base
|
4
|
+
module FakeRequest
|
5
|
+
class Request
|
6
|
+
attr_accessor :path, :fullpath, :protocol, :host_with_port
|
7
|
+
def get?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
def request
|
12
|
+
@request ||= Request.new
|
13
|
+
end
|
14
|
+
def params
|
15
|
+
@params ||= {}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
include FakeRequest
|
20
|
+
include ActionView::Helpers::UrlHelper
|
2
21
|
include Loaf::ViewExtensions
|
22
|
+
|
3
23
|
attr_reader :_breadcrumbs
|
4
24
|
|
5
|
-
|
6
|
-
|
25
|
+
routes = ActionDispatch::Routing::RouteSet.new
|
26
|
+
routes.draw do
|
27
|
+
get "/" => "foo#bar", :as => :home
|
28
|
+
get "/posts" => "foo#posts"
|
29
|
+
get "/posts/:title" => "foo#posts"
|
30
|
+
get "/post/:id" => "foo#post", :as => :post
|
31
|
+
get "/post/:title" => "foo#title"
|
32
|
+
get "/post/:id/comments" => "foo#comments"
|
33
|
+
|
34
|
+
namespace :blog do
|
35
|
+
get "/" => "foo#bar"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
include routes.url_helpers
|
40
|
+
|
41
|
+
def set_path(path)
|
42
|
+
request.path = path
|
43
|
+
request.fullpath = path
|
44
|
+
request.protocol = 'http://'
|
45
|
+
request.host_with_port = 'www.example.com'
|
46
|
+
end
|
7
47
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
RSpec.describe Loaf::Configuration do
|
4
|
+
it "allows to set and read attributes" do
|
5
|
+
config = Loaf::Configuration.new
|
6
|
+
|
7
|
+
config.crumb_length = 4
|
8
|
+
|
9
|
+
expect(config.crumb_length).to eq(4)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "accepts attributes at initialization" do
|
13
|
+
options = { crumb_length: 12 }
|
14
|
+
config = Loaf::Configuration.new(options)
|
15
|
+
|
16
|
+
expect(config.crumb_length).to eq(12)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "exports configuration as hash" do
|
20
|
+
config = Loaf::Configuration.new
|
21
|
+
expect(config.to_hash).to eq({
|
22
|
+
capitalize: false,
|
23
|
+
crumb_length: 30,
|
24
|
+
locales_path: '/'
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
it "yields configuration" do
|
29
|
+
conf = double(:conf)
|
30
|
+
allow(Loaf).to receive(:configuration).and_return(conf)
|
31
|
+
expect { |b|
|
32
|
+
Loaf.configure(&b)
|
33
|
+
}.to yield_with_args(conf)
|
34
|
+
end
|
35
|
+
end
|
@@ -1,14 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
class DummyController < ActionController::Base
|
6
|
-
def self.before_filter(options, &block)
|
7
|
-
yield self.new
|
8
|
-
end
|
9
|
-
include Loaf::ControllerExtensions
|
10
|
-
end
|
11
|
-
|
12
3
|
RSpec.describe Loaf::ControllerExtensions do
|
13
4
|
|
14
5
|
context 'when classes extend controller_extensions' do
|
@@ -16,18 +7,18 @@ RSpec.describe Loaf::ControllerExtensions do
|
|
16
7
|
it { expect(DummyController).to respond_to(:breadcrumb) }
|
17
8
|
it { expect(DummyController.new).to respond_to(:add_breadcrumb) }
|
18
9
|
it { expect(DummyController.new).to respond_to(:breadcrumb) }
|
19
|
-
it { expect(DummyController.new).to respond_to(:add_breadcrumbs) }
|
20
10
|
it { expect(DummyController.new).to respond_to(:clear_breadcrumbs) }
|
21
11
|
end
|
22
12
|
|
23
13
|
context 'class methods' do
|
24
|
-
it 'invokes
|
25
|
-
allow(DummyController).to receive(:
|
14
|
+
it 'invokes before_action' do
|
15
|
+
allow(DummyController).to receive(:before_action)
|
16
|
+
allow(DummyController).to receive(:respond_to?).and_return(true)
|
26
17
|
DummyController.breadcrumb('name', 'url_path')
|
27
|
-
expect(DummyController).to have_received(:
|
18
|
+
expect(DummyController).to have_received(:before_action)
|
28
19
|
end
|
29
20
|
|
30
|
-
it 'delegates to instance' do
|
21
|
+
it 'delegates breadcrumb registration to controller instance' do
|
31
22
|
name = 'List objects'
|
32
23
|
url = :object_path
|
33
24
|
options = {force: true}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'fileutils'
|
4
4
|
require 'generators/loaf/install_generator'
|
5
5
|
|
6
6
|
RSpec.describe Loaf::Generators::InstallGenerator, type: :generator do
|
@@ -12,5 +12,6 @@ RSpec.describe Loaf::Generators::InstallGenerator, type: :generator do
|
|
12
12
|
run_generator
|
13
13
|
locale = file("config/locales/loaf.en.yml")
|
14
14
|
expect(locale).to exist
|
15
|
+
FileUtils.rm_rf(File.expand_path("../../../tmp", __FILE__))
|
15
16
|
end
|
16
17
|
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
RSpec.describe Loaf::ViewExtensions, '#breadcrumb_trail' do
|
4
|
+
it "resolves breadcrumb paths" do
|
5
|
+
view = DummyView.new
|
6
|
+
view.breadcrumb('home', :home_path)
|
7
|
+
view.breadcrumb('posts', :posts_path)
|
8
|
+
view.set_path('/posts')
|
9
|
+
|
10
|
+
yielded = []
|
11
|
+
block = -> (crumb) { yielded << crumb.to_a }
|
12
|
+
view.breadcrumb_trail(&block)
|
13
|
+
|
14
|
+
expect(yielded).to eq([
|
15
|
+
['home', '/', false],
|
16
|
+
['posts', '/posts', true]
|
17
|
+
])
|
18
|
+
end
|
19
|
+
|
20
|
+
it "matches current path with :inclusive option as default" do
|
21
|
+
view = DummyView.new
|
22
|
+
view.breadcrumb('home', :home_path)
|
23
|
+
view.breadcrumb('posts', :posts_path)
|
24
|
+
view.set_path('/posts?id=73-title')
|
25
|
+
|
26
|
+
yielded = []
|
27
|
+
block = -> (crumb) { yielded << crumb.to_a }
|
28
|
+
view.breadcrumb_trail(&block)
|
29
|
+
|
30
|
+
expect(yielded).to eq([
|
31
|
+
['home', '/', false],
|
32
|
+
['posts', '/posts', true]
|
33
|
+
])
|
34
|
+
end
|
35
|
+
|
36
|
+
it "matches current path with :inclusive when query params" do
|
37
|
+
view = DummyView.new
|
38
|
+
view.breadcrumb('posts', '/posts', match: :inclusive)
|
39
|
+
view.set_path('/posts?foo=bar')
|
40
|
+
|
41
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', true]])
|
42
|
+
end
|
43
|
+
|
44
|
+
it "matches current path with :inclusive when nested" do
|
45
|
+
view = DummyView.new
|
46
|
+
view.breadcrumb('posts', '/posts', match: :inclusive)
|
47
|
+
view.set_path('/posts/1/comment')
|
48
|
+
|
49
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', true]])
|
50
|
+
end
|
51
|
+
|
52
|
+
it "matches current path with :inclusive when nested" do
|
53
|
+
view = DummyView.new
|
54
|
+
view.breadcrumb('posts', '/posts', match: :inclusive)
|
55
|
+
view.set_path('/posts/1/comment')
|
56
|
+
|
57
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', true]])
|
58
|
+
end
|
59
|
+
|
60
|
+
it "doesn't match with :inclusive when unrelated path" do
|
61
|
+
view = DummyView.new
|
62
|
+
view.breadcrumb('posts', '/posts', match: :inclusive)
|
63
|
+
view.set_path('/post/1')
|
64
|
+
|
65
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', false]])
|
66
|
+
end
|
67
|
+
|
68
|
+
it "matches current path with :inclusive when extra trailing slash" do
|
69
|
+
view = DummyView.new
|
70
|
+
view.breadcrumb('posts', '/posts/', match: :inclusive)
|
71
|
+
view.set_path('/posts')
|
72
|
+
|
73
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts/', true]])
|
74
|
+
end
|
75
|
+
|
76
|
+
it "matches current path with :inclusive when absolute path" do
|
77
|
+
view = DummyView.new
|
78
|
+
view.breadcrumb('posts', 'http://www.example.com/posts/', match: :inclusive)
|
79
|
+
view.set_path('/posts')
|
80
|
+
|
81
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([
|
82
|
+
['posts', 'http://www.example.com/posts/', true]
|
83
|
+
])
|
84
|
+
end
|
85
|
+
|
86
|
+
it "matches current path with :exact when trailing slash" do
|
87
|
+
view = DummyView.new
|
88
|
+
view.breadcrumb('posts', '/posts/', match: :exact)
|
89
|
+
view.set_path('/posts')
|
90
|
+
|
91
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts/', true]])
|
92
|
+
end
|
93
|
+
|
94
|
+
it "fails to match current path with :exact when nested" do
|
95
|
+
view = DummyView.new
|
96
|
+
view.breadcrumb('posts', '/posts', match: :exact)
|
97
|
+
view.set_path('/posts/1/comment')
|
98
|
+
|
99
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', false]])
|
100
|
+
end
|
101
|
+
|
102
|
+
it "fails to match current path with :exact when query params" do
|
103
|
+
view = DummyView.new
|
104
|
+
view.breadcrumb('posts', '/posts', match: :exact)
|
105
|
+
view.set_path('/posts?foo=bar')
|
106
|
+
|
107
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', false]])
|
108
|
+
end
|
109
|
+
|
110
|
+
it "matches current path with :exclusive option when query params" do
|
111
|
+
view = DummyView.new
|
112
|
+
view.breadcrumb('posts', '/posts', match: :exclusive)
|
113
|
+
view.set_path('/posts?foo=bar')
|
114
|
+
|
115
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', true]])
|
116
|
+
end
|
117
|
+
|
118
|
+
it "fails to match current path with :exclusive option when nested" do
|
119
|
+
view = DummyView.new
|
120
|
+
view.breadcrumb('posts', '/posts', match: :exclusive)
|
121
|
+
view.set_path('/posts/1/comment')
|
122
|
+
|
123
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', false]])
|
124
|
+
end
|
125
|
+
|
126
|
+
it "matches current path with regex option when query params" do
|
127
|
+
view = DummyView.new
|
128
|
+
view.breadcrumb('posts', '/posts', match: %r{/po})
|
129
|
+
view.set_path('/posts?foo=bar')
|
130
|
+
|
131
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', true]])
|
132
|
+
end
|
133
|
+
|
134
|
+
it "matches current path with query params option" do
|
135
|
+
view = DummyView.new
|
136
|
+
view.breadcrumb('posts', '/posts', match: {foo: :bar})
|
137
|
+
view.set_path('/posts?foo=bar&baz=boo')
|
138
|
+
|
139
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', true]])
|
140
|
+
end
|
141
|
+
|
142
|
+
it "fails to match current path with query params option" do
|
143
|
+
view = DummyView.new
|
144
|
+
view.breadcrumb('posts', '/posts', match: {foo: :bar})
|
145
|
+
view.set_path('/posts?foo=2&baz=boo')
|
146
|
+
|
147
|
+
expect(view.breadcrumb_trail.map(&:to_a)).to eq([['posts', '/posts', false]])
|
148
|
+
end
|
149
|
+
|
150
|
+
it "failse to recognize the match option" do
|
151
|
+
view = DummyView.new
|
152
|
+
view.breadcrumb('posts', 'http://www.example.com/posts/', match: :boom)
|
153
|
+
view.set_path('/posts')
|
154
|
+
block = -> (*args) { }
|
155
|
+
expect {
|
156
|
+
view.breadcrumb_trail(&block)
|
157
|
+
}.to raise_error(ArgumentError, "Unknown `:boom` match option!")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "forces current path" do
|
161
|
+
view = DummyView.new
|
162
|
+
view.breadcrumb('home', :home_path)
|
163
|
+
view.breadcrumb('posts', :posts_path, match: :force)
|
164
|
+
view.set_path('/')
|
165
|
+
|
166
|
+
yielded = []
|
167
|
+
block = -> (crumb) { yielded << crumb.to_a }
|
168
|
+
view.breadcrumb_trail(&block)
|
169
|
+
|
170
|
+
expect(yielded).to eq([
|
171
|
+
['home', '/', true],
|
172
|
+
['posts', '/posts', true]
|
173
|
+
])
|
174
|
+
end
|
175
|
+
|
176
|
+
it "returns enumerator without block" do
|
177
|
+
view = DummyView.new
|
178
|
+
view.breadcrumb('home', :home_path)
|
179
|
+
view.breadcrumb('posts', :posts_path)
|
180
|
+
view.set_path('/posts')
|
181
|
+
|
182
|
+
result = view.breadcrumb_trail
|
183
|
+
|
184
|
+
expect(result).to be_a(Enumerable)
|
185
|
+
expect(result.take(2).map(&:to_a)).to eq([
|
186
|
+
['home', '/', false],
|
187
|
+
['posts', '/posts', true]
|
188
|
+
])
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'validates passed options' do
|
192
|
+
view = DummyView.new
|
193
|
+
block = -> (name, url, styles) { }
|
194
|
+
expect {
|
195
|
+
view.breadcrumb_trail(unknown: true, &block)
|
196
|
+
}.to raise_error(Loaf::InvalidOptions)
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'uses global configuration for crumb formatting' do
|
200
|
+
allow(Loaf.configuration).to receive(:crumb_length).and_return(10)
|
201
|
+
view = DummyView.new
|
202
|
+
view.breadcrumb('home-sweet-home', :home_path)
|
203
|
+
view.breadcrumb('posts-for-everybody', :posts_path)
|
204
|
+
view.set_path('/posts')
|
205
|
+
|
206
|
+
yielded = []
|
207
|
+
block = -> (crumb) { yielded << crumb.to_a }
|
208
|
+
view.breadcrumb_trail(&block)
|
209
|
+
|
210
|
+
expect(yielded).to eq([
|
211
|
+
['home-sw...', '/', false],
|
212
|
+
['posts-f...', '/posts', true]
|
213
|
+
])
|
214
|
+
end
|
215
|
+
|
216
|
+
it "allows to overwrite global configuration" do
|
217
|
+
allow(Loaf.configuration).to receive(:crumb_length).and_return(10)
|
218
|
+
view = DummyView.new
|
219
|
+
view.breadcrumb('home-sweet-home', :home_path)
|
220
|
+
view.breadcrumb('posts-for-everybody', :posts_path)
|
221
|
+
view.set_path('/posts')
|
222
|
+
|
223
|
+
yielded = []
|
224
|
+
block = -> (crumb) { yielded << crumb.to_a }
|
225
|
+
view.breadcrumb_trail(crumb_length: 15, &block)
|
226
|
+
|
227
|
+
expect(yielded).to eq([
|
228
|
+
['home-sweet-home', '/', false],
|
229
|
+
['posts-for-ev...', '/posts', true]
|
230
|
+
])
|
231
|
+
end
|
232
|
+
end
|