breadcrumby 0.1.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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +12 -0
  3. data/LICENSE +21 -0
  4. data/README.md +221 -0
  5. data/lib/breadcrumby.rb +11 -0
  6. data/lib/breadcrumby/engine.rb +15 -0
  7. data/lib/breadcrumby/helpers/view_helper.rb +9 -0
  8. data/lib/breadcrumby/models/extension.rb +74 -0
  9. data/lib/breadcrumby/models/home.rb +23 -0
  10. data/lib/breadcrumby/models/viewer.rb +154 -0
  11. data/lib/breadcrumby/version.rb +5 -0
  12. data/spec/factories/course.rb +9 -0
  13. data/spec/factories/grade.rb +10 -0
  14. data/spec/factories/level.rb +9 -0
  15. data/spec/factories/school.rb +7 -0
  16. data/spec/factories/unit.rb +9 -0
  17. data/spec/lib/breadcrumby/helpers/breadcrumby_spec.rb +22 -0
  18. data/spec/lib/breadcrumby/models/extension/breadcrumby_options_spec.rb +89 -0
  19. data/spec/lib/breadcrumby/models/extension/breadcrumby_spec.rb +126 -0
  20. data/spec/lib/breadcrumby/models/home/name_spec.rb +25 -0
  21. data/spec/lib/breadcrumby/models/home/show_path_spec.rb +25 -0
  22. data/spec/lib/breadcrumby/models/viewer/breadcrumb_spec.rb +55 -0
  23. data/spec/lib/breadcrumby/models/viewer/breadcrumbs_spec.rb +25 -0
  24. data/spec/lib/breadcrumby/models/viewer/current_object_spec.rb +68 -0
  25. data/spec/lib/breadcrumby/models/viewer/i18n_action_name_spec.rb +28 -0
  26. data/spec/lib/breadcrumby/models/viewer/i18n_name_spec.rb +53 -0
  27. data/spec/lib/breadcrumby/models/viewer/item_options_spec.rb +17 -0
  28. data/spec/lib/breadcrumby/models/viewer/item_spec.rb +30 -0
  29. data/spec/lib/breadcrumby/models/viewer/link_action_spec.rb +23 -0
  30. data/spec/lib/breadcrumby/models/viewer/link_options_spec.rb +49 -0
  31. data/spec/lib/breadcrumby/models/viewer/link_spec.rb +40 -0
  32. data/spec/lib/breadcrumby/models/viewer/link_tag_name_options_spec.rb +13 -0
  33. data/spec/lib/breadcrumby/models/viewer/link_tag_name_spec.rb +35 -0
  34. data/spec/lib/breadcrumby/models/viewer/list_options_spec.rb +17 -0
  35. data/spec/lib/breadcrumby/models/viewer/meta_spec.rb +14 -0
  36. data/spec/lib/breadcrumby/models/viewer/object_extra_spec.rb +80 -0
  37. data/spec/lib/breadcrumby/models/viewer/scope_spec.rb +35 -0
  38. data/spec/rails_helper.rb +11 -0
  39. data/spec/support/common.rb +22 -0
  40. data/spec/support/database_cleaner.rb +21 -0
  41. data/spec/support/db/migrate/course.rb +11 -0
  42. data/spec/support/db/migrate/grade.rb +12 -0
  43. data/spec/support/db/migrate/level.rb +11 -0
  44. data/spec/support/db/migrate/school.rb +9 -0
  45. data/spec/support/db/migrate/unit.rb +11 -0
  46. data/spec/support/factory_girl.rb +9 -0
  47. data/spec/support/html_matchers.rb +7 -0
  48. data/spec/support/migrate.rb +9 -0
  49. data/spec/support/models/course.rb +5 -0
  50. data/spec/support/models/grade.rb +6 -0
  51. data/spec/support/models/level.rb +5 -0
  52. data/spec/support/models/school.rb +15 -0
  53. data/spec/support/models/unit.rb +13 -0
  54. data/spec/support/shoulda.rb +10 -0
  55. metadata +321 -0
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.i18n_action_name' do
6
+ subject { described_class.new object, options, view }
7
+
8
+ let!(:object) { build :school }
9
+ let!(:options) { {} }
10
+ let!(:view) { double }
11
+ let!(:action) { :edit }
12
+
13
+ before do
14
+ allow(I18n).to receive(:t).with(:edit) { 'edit' }
15
+
16
+ allow(I18n).to receive(:t).with(
17
+ 'actions.edit.name', scope: [:breadcrumby], default: 'edit'
18
+ ) { 'root || edit' }
19
+
20
+ allow(I18n).to receive(:t).with(
21
+ 'actions.edit.name', scope: [:breadcrumby, 'school'], default: 'root || edit'
22
+ ) { 'translation' }
23
+ end
24
+
25
+ it 'returns a name for object fetched from i18n with root fallback' do
26
+ expect(subject.i18n_action_name(object, action)).to eq 'translation'
27
+ end
28
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.i18n_name' do
6
+ subject { described_class.new object, options, view }
7
+
8
+ let!(:object) { build :school }
9
+ let!(:options) { {} }
10
+ let!(:view) { double }
11
+
12
+ context 'when :method_name responds with value' do
13
+ before do
14
+ allow(object).to receive(:breadcrumby_options) do
15
+ {
16
+ i18n_key: :i18n_key,
17
+ method_name: :custom_method_name
18
+ }
19
+ end
20
+
21
+ allow(I18n).to receive(:t).with(:edit, default: 'Edition') { 'edit || Edition' }
22
+
23
+ allow(I18n).to receive(:t).with(
24
+ :name, scope: %i[breadcrumby i18n_key], default: :custom_method_name
25
+ ) { 'translation' }
26
+ end
27
+
28
+ it 'uses the returned value as the object name' do
29
+ expect(subject.i18n_name(object)).to eq 'translation'
30
+ end
31
+ end
32
+
33
+ context 'when :method_name does not respond with value' do
34
+ before do
35
+ allow(object).to receive(:breadcrumby_options) do
36
+ {
37
+ i18n_key: :i18n_key,
38
+ method_name: :custom_method_name_nil
39
+ }
40
+ end
41
+
42
+ allow(I18n).to receive(:t).with(:edit, default: 'Edition') { 'edit || Edition' }
43
+
44
+ allow(I18n).to receive(:t).with(
45
+ :name, scope: %i[breadcrumby i18n_key], default: '--'
46
+ ) { 'translation' }
47
+ end
48
+
49
+ it 'uses a default name as fallback' do
50
+ expect(subject.i18n_name(object)).to eq 'translation'
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.item_options' do
6
+ subject { described_class.new object }
7
+
8
+ let!(:object) { build :school }
9
+
10
+ it 'returns the options used on list element' do
11
+ expect(subject.item_options).to eq(
12
+ itemprop: :itemListElement,
13
+ itemscope: true,
14
+ itemtype: 'http://schema.org/ListItem'
15
+ )
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.item' do
6
+ subject { described_class.new object }
7
+
8
+ let!(:content) { :content }
9
+ let!(:object) { build :school }
10
+
11
+ it 'returns a item element as node of the list' do
12
+ expect(subject.item(content)).to have_tag :li, with: {
13
+ itemprop: :itemListElement,
14
+ itemscope: :itemscope,
15
+ itemtype: 'http://schema.org/ListItem'
16
+ } do
17
+ with_text :content
18
+ end
19
+ end
20
+
21
+ context 'when options is given' do
22
+ let!(:options) { { alt: :custom } }
23
+
24
+ it 'is used' do
25
+ expect(subject.item(content, options)).to have_tag :li, with: { alt: :custom } do
26
+ with_text :content
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.link_action' do
6
+ subject { described_class.new object, options }
7
+
8
+ let!(:action) { :edit }
9
+ let!(:object) { build :school }
10
+ let!(:options) { {} }
11
+
12
+ context 'when action is not given' do
13
+ it 'returns the object show route' do
14
+ expect(subject.link_action(object, nil)).to eq object.show_path
15
+ end
16
+ end
17
+
18
+ context 'when action is given' do
19
+ it 'returns an avoid link' do
20
+ expect(subject.link_action(object, action)).to eq 'javascript:void(0);'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.link_options' do
6
+ subject { described_class.new object }
7
+
8
+ let!(:object) { build :school }
9
+
10
+ before do
11
+ allow(subject).to receive(:i18n_name).with(object) { :i18n_name }
12
+ end
13
+
14
+ context 'when action is not given' do
15
+ let!(:action) { nil }
16
+
17
+ before do
18
+ allow(I18n).to receive(:t).with(:title, scope: [:breadcrumby, 'school'], name: :i18n_name, default: 'title') { 'breadcrumby.school.title' }
19
+ allow(I18n).to receive(:t).with(:title, scope: [:breadcrumby]) { 'title' }
20
+ end
21
+
22
+ it 'returns the link options' do
23
+ expect(subject.link_options(object, action)).to eq(
24
+ itemprop: :item,
25
+ itemscope: true,
26
+ itemtype: 'http://schema.org/Thing',
27
+ title: 'breadcrumby.school.title'
28
+ )
29
+ end
30
+ end
31
+
32
+ context 'when action is given' do
33
+ let!(:action) { :edit }
34
+
35
+ before do
36
+ allow(I18n).to receive(:t).with('actions.edit.title', scope: [:breadcrumby, 'school'], name: :i18n_name, default: 'breadcrumby.actions.edit.title') { 'breadcrumby.school.actions.edit.title' }
37
+ allow(I18n).to receive(:t).with('actions.edit.title', scope: [:breadcrumby]) { 'breadcrumby.actions.edit.title' }
38
+ end
39
+
40
+ it 'returns the link options with title scoped by action fetched from i18n with root fallback' do
41
+ expect(subject.link_options(object, action)).to eq(
42
+ itemprop: :item,
43
+ itemscope: true,
44
+ itemtype: 'http://schema.org/Thing',
45
+ title: 'breadcrumby.school.actions.edit.title'
46
+ )
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.link' do
6
+ subject { described_class.new object, options }
7
+
8
+ let!(:action) { :edit }
9
+ let!(:object) { build :school }
10
+ let!(:options) { {} }
11
+
12
+ context 'when action is not given' do
13
+ before do
14
+ allow(subject).to receive(:i18n_name).with(object) { :i18n_name }
15
+ allow(subject).to receive(:link_options).with(object, nil) { { class: :custom } }
16
+ end
17
+
18
+ it 'build a link with object properties' do
19
+ expect(subject.link(object)).to have_tag(:a, with: { href: 'school.show.path' }) do
20
+ with_tag(:span, with: { itemprop: 'name' }) do
21
+ with_text 'i18n_name'
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ context 'when action is given' do
28
+ before do
29
+ allow(subject).to receive(:i18n_action_name).with(object, action) { :i18n_action_name }
30
+ end
31
+
32
+ it 'build a link with object and action properties' do
33
+ expect(subject.link(object, action: action)).to have_tag(:a, with: { itemprop: 'item', itemscope: 'itemscope', itemtype: 'http://schema.org/Thing', title: 'translation missing: en.breadcrumby.actions.edit.title', href: 'javascript:void(0);' }) do
34
+ with_tag(:span, with: { itemprop: 'name' }) do
35
+ with_text 'i18n_action_name'
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.link_tag_name_options' do
6
+ subject { described_class.new object }
7
+
8
+ let!(:object) { build :school }
9
+
10
+ it 'returns options used on link' do
11
+ expect(subject.link_tag_name_options).to eq(itemprop: :name)
12
+ end
13
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.link_tag_name' do
6
+ subject { described_class.new object, options }
7
+
8
+ let!(:action) { :edit }
9
+ let!(:object) { build :school }
10
+ let!(:options) { {} }
11
+
12
+ context 'when action is not given' do
13
+ before do
14
+ allow(subject).to receive(:i18n_name).with(object) { :i18n_name }
15
+ end
16
+
17
+ it 'build a ta name with object properties' do
18
+ expect(subject.link_tag_name(object, nil)).to have_tag(:span, with: { itemprop: 'name' }) do
19
+ with_text 'i18n_name'
20
+ end
21
+ end
22
+ end
23
+
24
+ context 'when action is given' do
25
+ before do
26
+ allow(subject).to receive(:i18n_action_name).with(object, action) { :i18n_action_name }
27
+ end
28
+
29
+ it 'build a ta name with object and action properties' do
30
+ expect(subject.link_tag_name(object, action)).to have_tag(:span, with: { itemprop: 'name' }) do
31
+ with_text 'i18n_action_name'
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.list_options' do
6
+ subject { described_class.new object }
7
+
8
+ let!(:object) { build :school }
9
+
10
+ it 'returns the options used on list element' do
11
+ expect(subject.list_options).to eq(
12
+ class: :breadcrumby,
13
+ itemscope: true,
14
+ itemtype: 'http://schema.org/BreadcrumbList'
15
+ )
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.meta' do
6
+ subject { described_class.new object }
7
+
8
+ let!(:index) { 7 }
9
+ let!(:object) { build :school }
10
+
11
+ it 'returns a meta element used to count the crumbs' do
12
+ expect(subject.meta(index)).to have_tag :meta, with: { content: 7, itemprop: :position }
13
+ end
14
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.object_extra(0)' do
6
+ context 'when :action is empty' do
7
+ subject { described_class.new object, options }
8
+
9
+ let!(:object) { {} }
10
+ let!(:options) { {} }
11
+
12
+ it 'returns an empty array' do
13
+ expect(subject.object_extra(0)).to eq []
14
+ end
15
+ end
16
+
17
+ context 'when :action is given' do
18
+ subject { described_class.new object, options }
19
+
20
+ let!(:object) { create :unit }
21
+
22
+ context 'with normal relationship' do
23
+ let!(:options) { { action: :edit } }
24
+
25
+ before { Unit.class_eval { breadcrumby } }
26
+
27
+ it 'builds the :action crumb' do
28
+ result = subject.object_extra(0)
29
+
30
+ expect(result.size).to eq 1
31
+
32
+ expect(result[0]).to have_tag(:li, with: { itemprop: 'itemListElement', itemscope: 'itemscope', itemtype: 'http://schema.org/ListItem' }) do
33
+ with_tag(:a, with: { itemprop: 'item', itemscope: 'itemscope', itemtype: 'http://schema.org/Thing', title: 'translation missing: en.breadcrumby.actions.edit.title', href: 'javascript:void(0);' }) do
34
+ with_tag(:span, with: { itemprop: 'name' }) do
35
+ with_text 'translation missing: en.edit'
36
+ end
37
+ end
38
+
39
+ with_tag(:meta, with: { content: '1', itemprop: 'position' })
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'with no relationship as a new record' do
45
+ let!(:options) { { action: :new } }
46
+
47
+ before do
48
+ Unit.class_eval do
49
+ breadcrumby actions: { new: ->(_view) { School.last } }
50
+ end
51
+ end
52
+
53
+ it 'builds the :action crumb' do
54
+ result = subject.object_extra(0)
55
+
56
+ expect(result.size).to eq 2
57
+
58
+ expect(result[0]).to have_tag(:li, with: { itemprop: 'itemListElement', itemscope: 'itemscope', itemtype: 'http://schema.org/ListItem' }) do
59
+ with_tag(:a, with: { itemprop: 'item', itemscope: 'itemscope', itemtype: 'http://schema.org/Thing', title: 'translation missing: en.breadcrumby.actions.index.title', href: 'unit.index.path' }) do
60
+ with_tag(:span, with: { itemprop: 'name' }) do
61
+ with_text 'translation missing: en.index'
62
+ end
63
+ end
64
+
65
+ with_tag(:meta, with: { content: '1', itemprop: 'position' })
66
+ end
67
+
68
+ expect(result[1]).to have_tag(:li, with: { itemprop: 'itemListElement', itemscope: 'itemscope', itemtype: 'http://schema.org/ListItem' }) do
69
+ with_tag(:a, with: { itemprop: 'item', itemscope: 'itemscope', itemtype: 'http://schema.org/Thing', title: 'translation missing: en.breadcrumby.actions.new.title', href: 'javascript:void(0);' }) do
70
+ with_tag(:span, with: { itemprop: 'name' }) do
71
+ with_text 'translation missing: en.new'
72
+ end
73
+ end
74
+
75
+ with_tag(:meta, with: { content: '2', itemprop: 'position' })
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe Breadcrumby::Viewer, '.scope' do
6
+ subject { described_class.new object }
7
+
8
+ let!(:object) { build :school }
9
+
10
+ context 'with default :i18n_key' do
11
+ it 'returns a i18n scope path based on class name' do
12
+ expect(subject.scope(object)).to eq [:breadcrumby, 'school']
13
+ end
14
+ end
15
+
16
+ context 'with custom :i18n_key' do
17
+ before do
18
+ allow(object).to receive(:breadcrumby_options) { { i18n_key: :custom } }
19
+ end
20
+
21
+ it 'returns a i18n scope path based on given name' do
22
+ expect(subject.scope(object)).to eq %i[breadcrumby custom]
23
+ end
24
+ end
25
+
26
+ context 'when :include_model is false' do
27
+ before do
28
+ allow(object).to receive(:breadcrumby_options) { { i18n_key: :custom } }
29
+ end
30
+
31
+ it 'returns a i18n scope path with only root key' do
32
+ expect(subject.scope(object, include_model: false)).to eq %i[breadcrumby]
33
+ end
34
+ end
35
+ end