strong_presenter 0.0.1 → 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 (132) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -2
  3. data/.rspec +2 -0
  4. data/.travis.yml +18 -0
  5. data/.yardopts +1 -0
  6. data/CHANGELOG.md +31 -0
  7. data/Gemfile +22 -2
  8. data/Guardfile +26 -0
  9. data/README.md +210 -52
  10. data/Rakefile +77 -1
  11. data/gemfiles/3.0.gemfile +2 -0
  12. data/gemfiles/3.1.gemfile +2 -0
  13. data/gemfiles/3.2.gemfile +2 -0
  14. data/gemfiles/4.0.gemfile +2 -0
  15. data/gemfiles/4.1.gemfile +2 -0
  16. data/lib/generators/controller_override.rb +15 -0
  17. data/lib/generators/mini_test/presenter_generator.rb +20 -0
  18. data/lib/generators/mini_test/templates/presenter_spec.rb +4 -0
  19. data/lib/generators/mini_test/templates/presenter_test.rb +4 -0
  20. data/lib/generators/rails/presenter_generator.rb +36 -0
  21. data/lib/generators/rails/templates/presenter.rb +19 -0
  22. data/lib/generators/rspec/presenter_generator.rb +9 -0
  23. data/lib/generators/rspec/templates/presenter_spec.rb +4 -0
  24. data/lib/generators/test_unit/presenter_generator.rb +9 -0
  25. data/lib/generators/test_unit/templates/presenter_test.rb +4 -0
  26. data/lib/strong_presenter/associable.rb +78 -0
  27. data/lib/strong_presenter/collection_presenter.rb +90 -0
  28. data/lib/strong_presenter/controller_additions.rb +50 -0
  29. data/lib/strong_presenter/delegation.rb +18 -0
  30. data/lib/strong_presenter/factory.rb +74 -0
  31. data/lib/strong_presenter/helper_proxy.rb +29 -11
  32. data/lib/strong_presenter/inferrer.rb +54 -0
  33. data/lib/strong_presenter/permissible.rb +73 -0
  34. data/lib/strong_presenter/permissions.rb +138 -0
  35. data/lib/strong_presenter/presenter.rb +191 -0
  36. data/lib/strong_presenter/presenter_association.rb +29 -0
  37. data/lib/strong_presenter/presenter_helper_constructor.rb +60 -0
  38. data/lib/strong_presenter/railtie.rb +27 -3
  39. data/lib/strong_presenter/tasks/test.rake +22 -0
  40. data/lib/strong_presenter/test/devise_helper.rb +30 -0
  41. data/lib/strong_presenter/test/minitest_integration.rb +6 -0
  42. data/lib/strong_presenter/test/rspec_integration.rb +16 -0
  43. data/lib/strong_presenter/test_case.rb +53 -0
  44. data/lib/strong_presenter/version.rb +1 -1
  45. data/lib/strong_presenter/view_context/build_strategy.rb +48 -0
  46. data/lib/strong_presenter/view_context.rb +84 -0
  47. data/lib/strong_presenter/view_helpers.rb +39 -0
  48. data/lib/strong_presenter.rb +64 -2
  49. data/spec/dummy/.rspec +2 -0
  50. data/spec/dummy/Rakefile +7 -0
  51. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  52. data/spec/dummy/app/controllers/localized_urls.rb +5 -0
  53. data/spec/dummy/app/controllers/posts_controller.rb +25 -0
  54. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  55. data/spec/dummy/app/mailers/application_mailer.rb +3 -0
  56. data/spec/dummy/app/mailers/post_mailer.rb +19 -0
  57. data/spec/dummy/app/models/admin.rb +5 -0
  58. data/spec/dummy/app/models/post.rb +3 -0
  59. data/spec/dummy/app/models/user.rb +5 -0
  60. data/spec/dummy/app/presenters/post_presenter.rb +69 -0
  61. data/spec/dummy/app/presenters/special_post_presenter.rb +5 -0
  62. data/spec/dummy/app/presenters/special_posts_presenter.rb +5 -0
  63. data/spec/dummy/app/views/layouts/application.html.erb +11 -0
  64. data/spec/dummy/app/views/post_mailer/presented_email.html.erb +1 -0
  65. data/spec/dummy/app/views/posts/_post.html.erb +50 -0
  66. data/spec/dummy/app/views/posts/show.html.erb +1 -0
  67. data/spec/dummy/bin/rails +4 -0
  68. data/spec/dummy/config/application.rb +70 -0
  69. data/spec/dummy/config/boot.rb +5 -0
  70. data/spec/dummy/config/database.yml +25 -0
  71. data/spec/dummy/config/environment.rb +5 -0
  72. data/spec/dummy/config/environments/development.rb +33 -0
  73. data/spec/dummy/config/environments/production.rb +57 -0
  74. data/spec/dummy/config/environments/test.rb +31 -0
  75. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  76. data/spec/dummy/config/initializers/inflections.rb +15 -0
  77. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  78. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  79. data/spec/dummy/config/initializers/session_store.rb +8 -0
  80. data/spec/dummy/config/locales/en.yml +5 -0
  81. data/spec/dummy/config/routes.rb +9 -0
  82. data/spec/dummy/config.ru +4 -0
  83. data/spec/dummy/db/migrate/20121019115657_create_posts.rb +8 -0
  84. data/spec/dummy/db/schema.rb +21 -0
  85. data/spec/dummy/db/seeds.rb +2 -0
  86. data/spec/dummy/fast_spec/post_presenter_spec.rb +37 -0
  87. data/spec/dummy/lib/tasks/test.rake +16 -0
  88. data/spec/dummy/log/.gitkeep +0 -0
  89. data/spec/dummy/public/404.html +26 -0
  90. data/spec/dummy/public/422.html +26 -0
  91. data/spec/dummy/public/500.html +25 -0
  92. data/spec/dummy/public/favicon.ico +0 -0
  93. data/spec/dummy/script/rails +6 -0
  94. data/spec/dummy/spec/fast_spec_helper.rb +13 -0
  95. data/spec/dummy/spec/mailers/post_mailer_spec.rb +33 -0
  96. data/spec/dummy/spec/models/post_spec.rb +4 -0
  97. data/spec/dummy/spec/presenters/active_model_serializers_spec.rb +11 -0
  98. data/spec/dummy/spec/presenters/devise_spec.rb +64 -0
  99. data/spec/dummy/spec/presenters/helpers_spec.rb +21 -0
  100. data/spec/dummy/spec/presenters/post_presenter_spec.rb +66 -0
  101. data/spec/dummy/spec/presenters/spec_type_spec.rb +7 -0
  102. data/spec/dummy/spec/presenters/special_post_presenter_spec.rb +11 -0
  103. data/spec/dummy/spec/presenters/view_context_spec.rb +22 -0
  104. data/spec/dummy/spec/spec_helper.rb +19 -0
  105. data/spec/dummy/test/minitest_helper.rb +2 -0
  106. data/spec/dummy/test/presenters/minitest/devise_test.rb +64 -0
  107. data/spec/dummy/test/presenters/minitest/helpers_test.rb +21 -0
  108. data/spec/dummy/test/presenters/minitest/spec_type_test.rb +52 -0
  109. data/spec/dummy/test/presenters/minitest/view_context_test.rb +24 -0
  110. data/spec/dummy/test/presenters/test_unit/devise_test.rb +64 -0
  111. data/spec/dummy/test/presenters/test_unit/helpers_test.rb +21 -0
  112. data/spec/dummy/test/presenters/test_unit/view_context_test.rb +24 -0
  113. data/spec/dummy/test/test_helper.rb +13 -0
  114. data/spec/generators/presenters/presenter_generator_spec.rb +131 -0
  115. data/spec/generators/simplecov_spec.rb +5 -0
  116. data/spec/integration/integration_spec.rb +81 -0
  117. data/spec/integration/simplecov_spec.rb +4 -0
  118. data/spec/spec_helper.rb +47 -0
  119. data/spec/strong_presenter/associable_spec.rb +122 -0
  120. data/spec/strong_presenter/collection_presenter_spec.rb +34 -0
  121. data/spec/strong_presenter/delegation_spec.rb +20 -0
  122. data/spec/strong_presenter/permissible_spec.rb +24 -0
  123. data/spec/strong_presenter/permissions_spec.rb +188 -0
  124. data/spec/strong_presenter/presenter_spec.rb +43 -0
  125. data/spec/strong_presenter/simplecov_spec.rb +4 -0
  126. data/spec/support/dummy_app.rb +85 -0
  127. data/spec/support/matchers/have_text.rb +50 -0
  128. data/spec/support/models.rb +14 -0
  129. data/spec/support/schema.rb +12 -0
  130. data/strong_presenter.gemspec +15 -0
  131. metadata +392 -13
  132. data/lib/strong_presenter/base.rb +0 -217
@@ -0,0 +1,52 @@
1
+ require 'minitest_helper'
2
+
3
+ def it_is_a_presenter_test
4
+ it "is a presenter test" do
5
+ assert_kind_of StrongPresenter::TestCase, self
6
+ end
7
+ end
8
+
9
+ def it_is_not_a_presenter_test
10
+ it "is not a presenter test" do
11
+ refute_kind_of StrongPresenter::TestCase, self
12
+ end
13
+ end
14
+
15
+ ProductPresenter = Class.new(StrongPresenter::Presenter)
16
+ ProductsPresenter = Class.new(StrongPresenter::CollectionPresenter)
17
+
18
+ describe ProductPresenter do
19
+ it_is_a_presenter_test
20
+ end
21
+
22
+ describe ProductsPresenter do
23
+ it_is_a_presenter_test
24
+ end
25
+
26
+ describe "ProductPresenter" do
27
+ it_is_a_presenter_test
28
+ end
29
+
30
+ describe "AnyPresenter" do
31
+ it_is_a_presenter_test
32
+ end
33
+
34
+ describe "Any presenter" do
35
+ it_is_a_presenter_test
36
+ end
37
+
38
+ describe "AnyPresenterTest" do
39
+ it_is_a_presenter_test
40
+ end
41
+
42
+ describe "Any presenter test" do
43
+ it_is_a_presenter_test
44
+ end
45
+
46
+ describe Object do
47
+ it_is_not_a_presenter_test
48
+ end
49
+
50
+ describe "Nope" do
51
+ it_is_not_a_presenter_test
52
+ end
@@ -0,0 +1,24 @@
1
+ require 'minitest_helper'
2
+
3
+ def it_does_not_leak_view_context
4
+ 2.times do
5
+ it "has an independent view context" do
6
+ refute_equal :leaked, StrongPresenter::ViewContext.current
7
+ StrongPresenter::ViewContext.current = :leaked
8
+ end
9
+ end
10
+ end
11
+
12
+ describe "A presenter test" do
13
+ it_does_not_leak_view_context
14
+ end
15
+
16
+ describe "A controller test" do
17
+ tests Class.new(ActionController::Base)
18
+
19
+ it_does_not_leak_view_context
20
+ end
21
+
22
+ describe "A mailer test" do
23
+ it_does_not_leak_view_context
24
+ end
@@ -0,0 +1,64 @@
1
+ require 'test_helper'
2
+
3
+ if defined?(Devise)
4
+ class DeviseTest < StrongPresenter::TestCase
5
+ def test_sign_in_a_real_user
6
+ user = User.new
7
+ sign_in user
8
+
9
+ assert_same user, helper.current_user
10
+ end
11
+
12
+ def test_sign_in_a_mock_user
13
+ user = Object.new
14
+ sign_in :user, user
15
+
16
+ assert_same user, helper.current_user
17
+ end
18
+
19
+ def test_sign_in_a_real_admin
20
+ admin = Admin.new
21
+ sign_in admin
22
+
23
+ assert_same admin, helper.current_admin
24
+ end
25
+
26
+ def test_sign_in_a_mock_admin
27
+ admin = Object.new
28
+ sign_in :admin, admin
29
+
30
+ assert_same admin, helper.current_admin
31
+ end
32
+
33
+ def test_sign_out_a_real_user
34
+ user = User.new
35
+ sign_in user
36
+ sign_out user
37
+
38
+ assert helper.current_user.nil?
39
+ end
40
+
41
+ def test_sign_out_a_mock_user
42
+ user = Object.new
43
+ sign_in :user, user
44
+ sign_out :user
45
+
46
+ assert helper.current_user.nil?
47
+ end
48
+
49
+ def test_sign_out_without_a_user
50
+ sign_out :user
51
+
52
+ assert helper.current_user.nil?
53
+ end
54
+
55
+ def test_backwards_compatibility
56
+ user = Object.new
57
+ ActiveSupport::Deprecation.silence do
58
+ sign_in user
59
+ end
60
+
61
+ assert_same user, helper.current_user
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+
3
+ class HelpersTest < StrongPresenter::TestCase
4
+ def test_access_helpers_through_helper
5
+ assert_equal "<p>Help!</p>", helper.content_tag(:p, "Help!")
6
+ end
7
+
8
+ def test_access_helpers_through_helpers
9
+ assert_equal "<p>Help!</p>", helpers.content_tag(:p, "Help!")
10
+ end
11
+
12
+ def test_access_helpers_through_h
13
+ assert_equal "<p>Help!</p>", h.content_tag(:p, "Help!")
14
+ end
15
+
16
+ def test_same_helper_object_as_presenters
17
+ presenter = StrongPresenter::Presenter.new(Object.new)
18
+
19
+ assert_same presenter.helpers, helpers
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ def it_does_not_leak_view_context
4
+ 2.times do |n|
5
+ define_method("test_has_independent_view_context_#{n}") do
6
+ #refute_equal :leaked, StrongPresenter::ViewContext.current
7
+ #StrongPresenter::ViewContext.current = :leaked
8
+ end
9
+ end
10
+ end
11
+
12
+ class PresenterTest < StrongPresenter::TestCase
13
+ #it_does_not_leak_view_context
14
+ end
15
+
16
+ class ControllerTest < ActionController::TestCase
17
+ tests Class.new(ActionController::Base)
18
+
19
+ #it_does_not_leak_view_context
20
+ end
21
+
22
+ class MailerTest < ActionMailer::TestCase
23
+ #it_does_not_leak_view_context
24
+ end
@@ -0,0 +1,13 @@
1
+ begin
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ root '../../'
5
+ command_name 'spec:integration:test:test'
6
+ add_filter 'spec'
7
+ end
8
+ rescue LoadError
9
+ end
10
+
11
+ ENV['RAILS_ENV'] ||= 'test'
12
+ require File.expand_path('../../config/environment', __FILE__)
13
+ require 'rails/test_help'
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+ require 'rails'
3
+ require 'ammeter/init'
4
+ require 'generators/rails/presenter_generator'
5
+
6
+ describe Rails::Generators::PresenterGenerator do
7
+ destination File.expand_path("../tmp", __FILE__)
8
+
9
+ before { prepare_destination }
10
+ after(:all) { FileUtils.rm_rf destination_root }
11
+
12
+ describe "the generated presenter" do
13
+ subject { file("app/presenters/your_model_presenter.rb") }
14
+
15
+ describe "naming" do
16
+ before { run_generator %w(YourModel) }
17
+
18
+ it { should contain "class YourModelPresenter" }
19
+ end
20
+
21
+ describe "namespacing" do
22
+ subject { file("app/presenters/namespace/your_model_presenter.rb") }
23
+ before { run_generator %w(Namespace::YourModel) }
24
+
25
+ it { should contain "class Namespace::YourModelPresenter" }
26
+ end
27
+
28
+ describe "inheritance" do
29
+ context "by default" do
30
+ before { run_generator %w(YourModel) }
31
+
32
+ it { should contain "class YourModelPresenter < StrongPresenter::Presenter" }
33
+ end
34
+
35
+ context "with the --parent option" do
36
+ before { run_generator %w(YourModel --parent=FooPresenter) }
37
+
38
+ it { should contain "class YourModelPresenter < FooPresenter" }
39
+ end
40
+
41
+ context "with an ApplicationPresenter" do
42
+ before do
43
+ Object.any_instance.stub(:require).with("application_presenter").and_return do
44
+ stub_const "ApplicationPresenter", Class.new
45
+ end
46
+ end
47
+
48
+ before { run_generator %w(YourModel) }
49
+
50
+ it { should contain "class YourModelPresenter < ApplicationPresenter" }
51
+ end
52
+ end
53
+ end
54
+
55
+ context "with -t=rspec" do
56
+ describe "the generated spec" do
57
+ subject { file("spec/presenters/your_model_presenter_spec.rb") }
58
+
59
+ describe "naming" do
60
+ before { run_generator %w(YourModel -t=rspec) }
61
+
62
+ it { should contain "describe YourModelPresenter" }
63
+ end
64
+
65
+ describe "namespacing" do
66
+ subject { file("spec/presenters/namespace/your_model_presenter_spec.rb") }
67
+ before { run_generator %w(Namespace::YourModel -t=rspec) }
68
+
69
+ it { should contain "describe Namespace::YourModelPresenter" }
70
+ end
71
+ end
72
+ end
73
+
74
+ context "with -t=test_unit" do
75
+ describe "the generated test" do
76
+ subject { file("test/presenters/your_model_presenter_test.rb") }
77
+
78
+ describe "naming" do
79
+ before { run_generator %w(YourModel -t=test_unit) }
80
+
81
+ it { should contain "class YourModelPresenterTest < StrongPresenter::TestCase" }
82
+ end
83
+
84
+ describe "namespacing" do
85
+ subject { file("test/presenters/namespace/your_model_presenter_test.rb") }
86
+ before { run_generator %w(Namespace::YourModel -t=test_unit) }
87
+
88
+ it { should contain "class Namespace::YourModelPresenterTest < StrongPresenter::TestCase" }
89
+ end
90
+ end
91
+ end
92
+
93
+ context "with -t=mini_test" do
94
+ describe "the generated test" do
95
+ subject { file("test/presenters/your_model_presenter_test.rb") }
96
+
97
+ describe "naming" do
98
+ before { run_generator %w(YourModel -t=mini_test) }
99
+
100
+ it { should contain "class YourModelPresenterTest < StrongPresenter::TestCase" }
101
+ end
102
+
103
+ describe "namespacing" do
104
+ subject { file("test/presenters/namespace/your_model_presenter_test.rb") }
105
+ before { run_generator %w(Namespace::YourModel -t=mini_test) }
106
+
107
+ it { should contain "class Namespace::YourModelPresenterTest < StrongPresenter::TestCase" }
108
+ end
109
+ end
110
+ end
111
+
112
+ context "with -t=mini_test --spec" do
113
+ describe "the generated test" do
114
+ subject { file("test/presenters/your_model_presenter_test.rb") }
115
+
116
+ describe "naming" do
117
+ before { run_generator %w(YourModel -t=mini_test --spec) }
118
+
119
+ it { should contain "describe YourModelPresenter" }
120
+ end
121
+
122
+ describe "namespacing" do
123
+ subject { file("test/presenters/namespace/your_model_presenter_test.rb") }
124
+ before { run_generator %w(Namespace::YourModel -t=mini_test --spec) }
125
+
126
+ it { should contain "describe Namespace::YourModelPresenter" }
127
+ end
128
+ end
129
+ end
130
+
131
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ SimpleCov.command_name 'spec:generators' if defined? SimpleCov
4
+
5
+
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+ require 'support/dummy_app'
3
+ require 'support/matchers/have_text'
4
+
5
+ app = DummyApp.new(ENV["RAILS_ENV"])
6
+ spec_types = {
7
+ view: ["/posts/1", "PostsController"],
8
+ mailer: ["/posts/1/mail", "PostMailer"]
9
+ }
10
+
11
+ app.start_server do
12
+ spec_types.each do |type, (path, controller)|
13
+ page = app.get(path)
14
+
15
+ describe "in a #{type}" do
16
+ it "runs in the correct environment" do
17
+ expect(page).to have_text(app.environment).in("#environment")
18
+ end
19
+
20
+ it "uses the correct view context controller" do
21
+ expect(page).to have_text(controller).in("#controller")
22
+ end
23
+
24
+ it "can use built-in helpers" do
25
+ expect(page).to have_text("Once upon a...").in("#truncated")
26
+ end
27
+
28
+ it "can use built-in private helpers" do
29
+ # Nokogiri unescapes text!
30
+ expect(page).to have_text("<script>danger</script>").in("#html_escaped")
31
+ end
32
+
33
+ it "can use user-defined helpers from app/helpers" do
34
+ expect(page).to have_text("Hello, world!").in("#hello_world")
35
+ end
36
+
37
+ it "can use user-defined helpers from the controller" do
38
+ expect(page).to have_text("Goodnight, moon!").in("#goodnight_moon")
39
+ end
40
+
41
+ it "can be passed to path helpers" do
42
+ expect(page).to have_text("/en/posts/1").in("#path_with_presenter")
43
+ end
44
+
45
+ it "can use path helpers with a model" do
46
+ expect(page).to have_text("/en/posts/1").in("#path_with_model")
47
+ end
48
+
49
+ it "can use path helpers with an id" do
50
+ expect(page).to have_text("/en/posts/1").in("#path_with_id")
51
+ end
52
+
53
+ it "can be passed to url helpers" do
54
+ expect(page).to have_text("http://www.example.com:12345/en/posts/1").in("#url_with_presenter")
55
+ end
56
+
57
+ it "can use url helpers with a model" do
58
+ expect(page).to have_text("http://www.example.com:12345/en/posts/1").in("#url_with_model")
59
+ end
60
+
61
+ it "can use url helpers with an id" do
62
+ expect(page).to have_text("http://www.example.com:12345/en/posts/1").in("#url_with_id")
63
+ end
64
+
65
+ it "can use presents method" do
66
+ expect(page).to have_text("I am permitted").in("#permit_to_present")
67
+ end
68
+
69
+ it "can use present method" do
70
+ expect(page).to have_text("BOO!").in("#peekaboo")
71
+ end
72
+
73
+ if type != :mailer
74
+ it "does not show unpermitted attributes through presents" do
75
+ expect(page).to_not have_text("Top Secret").in("#unpermitted")
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ SimpleCov.command_name "spec:integration:#{ENV['RAILS_ENV']}" if defined? SimpleCov
4
+
@@ -0,0 +1,47 @@
1
+ begin
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter 'spec'
5
+ end
6
+ rescue LoadError
7
+ end
8
+
9
+ require 'bundler/setup'
10
+ require 'strong_presenter'
11
+ require 'rails/version'
12
+ require 'action_controller'
13
+ require 'action_controller/test_case'
14
+ require 'support/models'
15
+
16
+ RSpec.configure do |config|
17
+ config.treat_symbols_as_metadata_keys_with_true_values = true
18
+ config.expect_with(:rspec) {|c| c.syntax = :expect}
19
+ config.order = :random
20
+ end
21
+
22
+ class Model; end
23
+
24
+ class Product < Model; end
25
+ class ProductPresenter < StrongPresenter::Presenter; end
26
+ class ProductsPresenter < StrongPresenter::CollectionPresenter; end
27
+
28
+ class OtherPresenter < StrongPresenter::Presenter; end
29
+
30
+ module Namespaced
31
+ class Product < Model; end
32
+ class ProductPresenter < StrongPresenter::Presenter; end
33
+
34
+ class OtherPresenter < StrongPresenter::Presenter; end
35
+ end
36
+
37
+ class WheelPresenter < StrongPresenter::Presenter; end
38
+ class CarPresenter < StrongPresenter::Presenter; end
39
+
40
+ # After each example, revert changes made to the class
41
+ def protect_class(klass)
42
+ before { stub_const klass.name, Class.new(klass) }
43
+ end
44
+
45
+ def protect_module(mod)
46
+ before { stub_const mod.name, mod.dup }
47
+ end
@@ -0,0 +1,122 @@
1
+ require 'spec_helper'
2
+
3
+ module StrongPresenter
4
+ describe Associable do
5
+ context 'with Presenter' do
6
+ protect_class Product
7
+ protect_class ProductPresenter
8
+
9
+ before(:each) do
10
+ class Manufacturer < Model
11
+ def name; "Factory"; end
12
+ end
13
+ class ManufacturerPresenter < StrongPresenter::Presenter
14
+ def name(*args); "Presented #{object.name}#{(args+[""])[0]}"; end
15
+ end
16
+ Product.send(:define_method, :manufacturer) { @manufacturer ||= Manufacturer.new }
17
+ Product.send(:define_method, :name) { "Product" }
18
+ ProductPresenter.presents_association :manufacturer
19
+
20
+ @product_presenter = ProductPresenter.new(Product.new)
21
+ end
22
+
23
+ it 'presents association' do
24
+ expect(@product_presenter.manufacturer.class).to be ManufacturerPresenter
25
+ expect(@product_presenter.manufacturer.name).to eq "Presented Factory"
26
+ end
27
+
28
+ it 'does not allow presenting without permit' do
29
+ expect(@product_presenter.presents :manufacturer).to be_empty
30
+ expect(@product_presenter.presents [:manufacturer, :name]).to be_empty
31
+ @product_presenter.permit :name
32
+ expect(@product_presenter.presents [:manufacturer, :name]).to be_empty
33
+ end
34
+
35
+ it 'does not allow presenting from association' do
36
+ expect(@product_presenter.manufacturer.presents :name).to be_empty
37
+ end
38
+
39
+ context 'with association permitted' do
40
+ before(:each) do
41
+ @product_presenter.permit :manufacturer
42
+ end
43
+
44
+ it 'allows presenting association' do
45
+ expect(@product_presenter.present(:manufacturer).class).to be ManufacturerPresenter
46
+ end
47
+
48
+ it 'allows presenting association attributes' do
49
+ expect(@product_presenter.present [:manufacturer, :name]).to eq "Presented Factory"
50
+ end
51
+
52
+ it 'allows presenting association attributes with arguments' do
53
+ expect(@product_presenter.present [:manufacturer, :name, " arg"]).to eq "Presented Factory arg"
54
+ end
55
+
56
+ it 'allows presenting from association' do
57
+ expect(@product_presenter.manufacturer.present :name).to eq "Presented Factory"
58
+ end
59
+ end
60
+
61
+ it 'rejects full path from association' do
62
+ @product_presenter.permit [:manufacturer, :name]
63
+ expect(@product_presenter.manufacturer.presents [:manufacturer, :name]).to be_empty
64
+ end
65
+ end
66
+
67
+ context 'with CollectionPresenter' do
68
+ protect_class Product
69
+ protect_class ProductPresenter
70
+ before(:each) do
71
+ Product.send(:define_method, :initialize) { |name| @name = name }
72
+ Product.send(:attr_reader, :name)
73
+ ProductPresenter.send(:define_method, :name) { object.name }
74
+ class ProductList < Model
75
+ attr_accessor :products
76
+ def initialize; @products = [Product.new("X"), Product.new("Y"), Product.new("Z")]; end
77
+ end
78
+ class ProductListPresenter < StrongPresenter::Presenter
79
+ presents_associations :products
80
+ end
81
+
82
+ @presenter = ProductListPresenter.new(ProductList.new)
83
+ end
84
+
85
+ it 'presents collection' do
86
+ expect(@presenter.products).to be_a StrongPresenter::CollectionPresenter
87
+ end
88
+
89
+ it 'allows accessing collection elements' do
90
+ expect(@presenter.products[2].class).to be ProductPresenter
91
+ expect(@presenter.products[2].name).to eq "Z"
92
+ end
93
+ end
94
+
95
+ describe "with ActiveRecord::Base objects" do
96
+ protect_class WheelPresenter
97
+ protect_class CarPresenter
98
+ it 'infers collection presenter from association class' do
99
+ CarPresenter.presents_association :wheels
100
+
101
+ car = Car.new
102
+ car.wheels << Wheel.new
103
+ presenter = CarPresenter.new(car)
104
+ expect(presenter.wheels.class).to be WheelPresenter::Collection
105
+ end
106
+
107
+ it 'infers presenter of polymorphic association repeatedly' do
108
+ WheelPresenter.presents_association :vehicle
109
+
110
+ wheel = Wheel.new
111
+ wheel.vehicle = Car.new
112
+ presenter = WheelPresenter.new(wheel)
113
+ expect(presenter.vehicle.class).to be CarPresenter
114
+
115
+ # if presenter.vehicle is cached, the next example will be incorrect
116
+ wheel.vehicle = Wheel.new
117
+ expect(presenter.vehicle.class).to be WheelPresenter
118
+ end
119
+ end
120
+ end
121
+ end
122
+
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ module StrongPresenter
4
+ describe CollectionPresenter do
5
+ describe "#initialize" do
6
+ it "sets the collection" do
7
+ collection = [Model.new, Model.new]
8
+ collection_presenter = CollectionPresenter.new(collection, :with => Presenter)
9
+
10
+ expect(collection_presenter.send :object).to be collection
11
+ expect(collection_presenter[0].send :object).to be collection[0]
12
+ end
13
+ it "wraps with given presenter" do
14
+ collection = [Product.new, Product.new]
15
+ products_presenter = CollectionPresenter.new(collection, :with => ProductPresenter)
16
+
17
+ expect(products_presenter[0].class).to be ProductPresenter
18
+ end
19
+ end
20
+ describe "Permissible" do
21
+ it "permits on items" do
22
+ collection = [Model.new, Model.new]
23
+ collection_presenter = CollectionPresenter.new(collection, :with => Presenter)
24
+
25
+ expect(collection_presenter[0].filter :z).to be_empty
26
+
27
+ collection_presenter.permit :a, :b, :c
28
+ permitted = collection_presenter[0].filter :a, :c, :z
29
+ expect(permitted).to include(:a, :c)
30
+ expect(permitted).to_not include(:b, :z)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ module StrongPresenter
4
+ describe Delegation do
5
+ protect_class(Product)
6
+ protect_class(ProductPresenter)
7
+
8
+ it '#delegate to object by default' do
9
+ ProductPresenter.delegate :stuff
10
+ Product.send(:define_method, :stuff) {"stuffed"}
11
+ expect(ProductPresenter.new(Product.new).stuff).to eq "stuffed"
12
+ end
13
+
14
+ it 'can #delegate elsewhere' do
15
+ ProductPresenter.send(:define_method, :elsewhere) {[3,4,5]}
16
+ ProductPresenter.delegate :array, :to => :elsewhere
17
+ expect(ProductPresenter.new(Product.new).elsewhere.size).to eq 3
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module StrongPresenter
4
+ describe Permissible do
5
+ it "filters permitted attributes" do
6
+ object = Model.new
7
+ presenter = Presenter.new(object)
8
+
9
+ presenter.permit :a, :b, :c
10
+ permitted = presenter.filter :a, :c, :z
11
+ expect(permitted).to include(:a, :c)
12
+ expect(permitted).to_not include(:b, :z)
13
+ end
14
+
15
+ it "permits all if permit!" do
16
+ object = Model.new
17
+ presenter = Presenter.new(object)
18
+
19
+ presenter.permit!
20
+ permitted = presenter.filter :a, :b, :c
21
+ expect(permitted).to include(:a, :b, :c)
22
+ end
23
+ end
24
+ end