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.
- checksums.yaml +7 -0
- data/.gitignore +5 -2
- data/.rspec +2 -0
- data/.travis.yml +18 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile +22 -2
- data/Guardfile +26 -0
- data/README.md +210 -52
- data/Rakefile +77 -1
- data/gemfiles/3.0.gemfile +2 -0
- data/gemfiles/3.1.gemfile +2 -0
- data/gemfiles/3.2.gemfile +2 -0
- data/gemfiles/4.0.gemfile +2 -0
- data/gemfiles/4.1.gemfile +2 -0
- data/lib/generators/controller_override.rb +15 -0
- data/lib/generators/mini_test/presenter_generator.rb +20 -0
- data/lib/generators/mini_test/templates/presenter_spec.rb +4 -0
- data/lib/generators/mini_test/templates/presenter_test.rb +4 -0
- data/lib/generators/rails/presenter_generator.rb +36 -0
- data/lib/generators/rails/templates/presenter.rb +19 -0
- data/lib/generators/rspec/presenter_generator.rb +9 -0
- data/lib/generators/rspec/templates/presenter_spec.rb +4 -0
- data/lib/generators/test_unit/presenter_generator.rb +9 -0
- data/lib/generators/test_unit/templates/presenter_test.rb +4 -0
- data/lib/strong_presenter/associable.rb +78 -0
- data/lib/strong_presenter/collection_presenter.rb +90 -0
- data/lib/strong_presenter/controller_additions.rb +50 -0
- data/lib/strong_presenter/delegation.rb +18 -0
- data/lib/strong_presenter/factory.rb +74 -0
- data/lib/strong_presenter/helper_proxy.rb +29 -11
- data/lib/strong_presenter/inferrer.rb +54 -0
- data/lib/strong_presenter/permissible.rb +73 -0
- data/lib/strong_presenter/permissions.rb +138 -0
- data/lib/strong_presenter/presenter.rb +191 -0
- data/lib/strong_presenter/presenter_association.rb +29 -0
- data/lib/strong_presenter/presenter_helper_constructor.rb +60 -0
- data/lib/strong_presenter/railtie.rb +27 -3
- data/lib/strong_presenter/tasks/test.rake +22 -0
- data/lib/strong_presenter/test/devise_helper.rb +30 -0
- data/lib/strong_presenter/test/minitest_integration.rb +6 -0
- data/lib/strong_presenter/test/rspec_integration.rb +16 -0
- data/lib/strong_presenter/test_case.rb +53 -0
- data/lib/strong_presenter/version.rb +1 -1
- data/lib/strong_presenter/view_context/build_strategy.rb +48 -0
- data/lib/strong_presenter/view_context.rb +84 -0
- data/lib/strong_presenter/view_helpers.rb +39 -0
- data/lib/strong_presenter.rb +64 -2
- data/spec/dummy/.rspec +2 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +4 -0
- data/spec/dummy/app/controllers/localized_urls.rb +5 -0
- data/spec/dummy/app/controllers/posts_controller.rb +25 -0
- data/spec/dummy/app/helpers/application_helper.rb +5 -0
- data/spec/dummy/app/mailers/application_mailer.rb +3 -0
- data/spec/dummy/app/mailers/post_mailer.rb +19 -0
- data/spec/dummy/app/models/admin.rb +5 -0
- data/spec/dummy/app/models/post.rb +3 -0
- data/spec/dummy/app/models/user.rb +5 -0
- data/spec/dummy/app/presenters/post_presenter.rb +69 -0
- data/spec/dummy/app/presenters/special_post_presenter.rb +5 -0
- data/spec/dummy/app/presenters/special_posts_presenter.rb +5 -0
- data/spec/dummy/app/views/layouts/application.html.erb +11 -0
- data/spec/dummy/app/views/post_mailer/presented_email.html.erb +1 -0
- data/spec/dummy/app/views/posts/_post.html.erb +50 -0
- data/spec/dummy/app/views/posts/show.html.erb +1 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/config/application.rb +70 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +33 -0
- data/spec/dummy/config/environments/production.rb +57 -0
- data/spec/dummy/config/environments/test.rb +31 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +8 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +9 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20121019115657_create_posts.rb +8 -0
- data/spec/dummy/db/schema.rb +21 -0
- data/spec/dummy/db/seeds.rb +2 -0
- data/spec/dummy/fast_spec/post_presenter_spec.rb +37 -0
- data/spec/dummy/lib/tasks/test.rake +16 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/fast_spec_helper.rb +13 -0
- data/spec/dummy/spec/mailers/post_mailer_spec.rb +33 -0
- data/spec/dummy/spec/models/post_spec.rb +4 -0
- data/spec/dummy/spec/presenters/active_model_serializers_spec.rb +11 -0
- data/spec/dummy/spec/presenters/devise_spec.rb +64 -0
- data/spec/dummy/spec/presenters/helpers_spec.rb +21 -0
- data/spec/dummy/spec/presenters/post_presenter_spec.rb +66 -0
- data/spec/dummy/spec/presenters/spec_type_spec.rb +7 -0
- data/spec/dummy/spec/presenters/special_post_presenter_spec.rb +11 -0
- data/spec/dummy/spec/presenters/view_context_spec.rb +22 -0
- data/spec/dummy/spec/spec_helper.rb +19 -0
- data/spec/dummy/test/minitest_helper.rb +2 -0
- data/spec/dummy/test/presenters/minitest/devise_test.rb +64 -0
- data/spec/dummy/test/presenters/minitest/helpers_test.rb +21 -0
- data/spec/dummy/test/presenters/minitest/spec_type_test.rb +52 -0
- data/spec/dummy/test/presenters/minitest/view_context_test.rb +24 -0
- data/spec/dummy/test/presenters/test_unit/devise_test.rb +64 -0
- data/spec/dummy/test/presenters/test_unit/helpers_test.rb +21 -0
- data/spec/dummy/test/presenters/test_unit/view_context_test.rb +24 -0
- data/spec/dummy/test/test_helper.rb +13 -0
- data/spec/generators/presenters/presenter_generator_spec.rb +131 -0
- data/spec/generators/simplecov_spec.rb +5 -0
- data/spec/integration/integration_spec.rb +81 -0
- data/spec/integration/simplecov_spec.rb +4 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/strong_presenter/associable_spec.rb +122 -0
- data/spec/strong_presenter/collection_presenter_spec.rb +34 -0
- data/spec/strong_presenter/delegation_spec.rb +20 -0
- data/spec/strong_presenter/permissible_spec.rb +24 -0
- data/spec/strong_presenter/permissions_spec.rb +188 -0
- data/spec/strong_presenter/presenter_spec.rb +43 -0
- data/spec/strong_presenter/simplecov_spec.rb +4 -0
- data/spec/support/dummy_app.rb +85 -0
- data/spec/support/matchers/have_text.rb +50 -0
- data/spec/support/models.rb +14 -0
- data/spec/support/schema.rb +12 -0
- data/strong_presenter.gemspec +15 -0
- metadata +392 -13
- 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,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
|
data/spec/spec_helper.rb
ADDED
|
@@ -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
|