loaf 0.5.0 → 0.6.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -3
  3. data/.rspec +1 -0
  4. data/.travis.yml +30 -12
  5. data/Appraisals +27 -9
  6. data/CHANGELOG.md +59 -11
  7. data/Gemfile +11 -11
  8. data/Gemfile.lock +182 -0
  9. data/README.md +120 -56
  10. data/assets/loaf_logo.png +0 -0
  11. data/bin/appraisal +16 -0
  12. data/bin/rake +16 -0
  13. data/gemfiles/rails3.2.gemfile +15 -13
  14. data/gemfiles/rails4.0.gemfile +13 -12
  15. data/gemfiles/rails4.1.gemfile +14 -13
  16. data/gemfiles/rails4.2.gemfile +14 -13
  17. data/gemfiles/rails5.0.gemfile +22 -0
  18. data/gemfiles/rails5.1.gemfile +22 -0
  19. data/lib/loaf.rb +2 -22
  20. data/lib/loaf/breadcrumb.rb +30 -0
  21. data/lib/loaf/configuration.rb +7 -8
  22. data/lib/loaf/controller_extensions.rb +13 -28
  23. data/lib/loaf/crumb.rb +5 -4
  24. data/lib/loaf/crumb_formatter.rb +3 -1
  25. data/lib/loaf/errors.rb +1 -3
  26. data/lib/loaf/options_validator.rb +2 -2
  27. data/lib/loaf/railtie.rb +19 -13
  28. data/lib/loaf/translation.rb +1 -1
  29. data/lib/loaf/version.rb +1 -3
  30. data/lib/loaf/view_extensions.rb +69 -18
  31. data/loaf.gemspec +20 -13
  32. data/spec/integration/{crumbs_routing_spec.rb → breadcrumb_trail_spec.rb} +19 -12
  33. data/spec/rails_app/app/controllers/application_controller.rb +2 -0
  34. data/spec/rails_app/app/controllers/posts_controller.rb +1 -4
  35. data/spec/rails_app/app/views/layouts/_breadcrumbs.html.erb +7 -5
  36. data/spec/rails_app/app/views/layouts/application.html.erb +0 -2
  37. data/spec/rails_app/config/environments/test.rb +1 -1
  38. data/spec/rails_app/config/secrets.yml +22 -0
  39. data/spec/spec_helper.rb +3 -3
  40. data/spec/support/dummy_controller.rb +9 -0
  41. data/spec/support/dummy_view.rb +42 -2
  42. data/spec/unit/configuration_spec.rb +35 -0
  43. data/spec/unit/controller_extensions_spec.rb +5 -14
  44. data/spec/unit/generators/install_generator_spec.rb +2 -1
  45. data/spec/unit/view_extensions/breadcrumb_trail_spec.rb +232 -0
  46. metadata +65 -31
  47. data/.ruby-version +0 -1
  48. data/init.rb +0 -3
  49. data/lib/loaf/builder.rb +0 -38
  50. data/spec/rails_app/.gitignore +0 -5
  51. data/spec/rails_app/lib/assets/.gitkeep +0 -0
  52. data/spec/rails_app/lib/tasks/.gitkeep +0 -0
  53. data/spec/rails_app/script/rails +0 -6
  54. 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 |s|
7
- s.name = 'loaf'
8
- s.version = Loaf::VERSION.dup
9
- s.authors = ['Piotr Murach']
10
- s.email = [""]
11
- s.homepage = 'https://github.com/peter-murach/loaf'
12
- s.summary = %q{Loaf manages and displays breadcrumb trails in your Rails application.}
13
- s.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.}
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
- s.files = `git ls-files`.split("\n")
16
- s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
17
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
- s.require_paths = ["lib"]
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
- s.add_dependency 'rails', '>= 3.1'
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
- require 'spec_helper'
4
-
5
- RSpec.describe "crumbs routing" do
3
+ RSpec.describe "breadcrumbs trail" do
6
4
  include ActionView::TestCase::Behavior
7
5
 
8
- it "doens't show empty breadcrumbs" do
6
+ it "shows root breadcrumb" do
9
7
  visit root_path
10
- expect(page).to_not have_content("breadcrumbs")
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
- expect(page.html).to include('<a href="/posts">All Posts</a>')
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
- within '#breadcrumbs' do
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(posts_path)
45
+ expect(page.current_path).to eq(new_post_path)
41
46
  within '#breadcrumbs' do
42
- expect(page).to have_content('New Post')
43
- expect(page).to have_selector('.selected')
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
- within '#breadcrumbs' do
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,3 +1,5 @@
1
1
  class ApplicationController < ActionController::Base
2
2
  protect_from_forgery
3
+
4
+ breadcrumb 'Home', :root_path, only: :index
3
5
  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 breadcrumbs? %>
1
+ <% if breadcrumb_trail.any? %>
2
2
  <ul id='breadcrumbs'>
3
- <% breadcrumbs do |name, url, styles| %>
4
- <li class="<%= styles %>">
5
- <%= link_to name, url %>
6
- <span><%= styles == 'selected' ? '' : '::' %></span>
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>
@@ -2,8 +2,6 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>RailsApp</title>
5
- <%= stylesheet_link_tag "application" %>
6
- <%= javascript_include_tag "application" %>
7
5
  <%= csrf_meta_tags %>
8
6
  </head>
9
7
  <body>
@@ -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.serve_static_assets = true
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 RUBY_VERSION > '1.9' and (ENV['COVERAGE'] || ENV['TRAVIS'])
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'
@@ -0,0 +1,9 @@
1
+ class DummyController < ActionController::Base
2
+ def self.before_filter(options, &block)
3
+ yield self.new
4
+ end
5
+ class << self
6
+ alias before_action before_filter
7
+ end
8
+ include Loaf::ControllerExtensions
9
+ end
@@ -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
- def url_for(*); end
6
- def current_page?(*); end
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 before_filter' do
25
- allow(DummyController).to receive(:before_filter)
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(:before_filter)
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 'spec_helper'
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