draper 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/CHANGELOG.md +3 -0
  2. data/CONTRIBUTING.md +5 -1
  3. data/Gemfile +23 -9
  4. data/README.md +144 -52
  5. data/Rakefile +1 -0
  6. data/draper.gemspec +1 -1
  7. data/lib/draper.rb +9 -6
  8. data/lib/draper/decoratable.rb +3 -7
  9. data/lib/draper/decoratable/equality.rb +14 -0
  10. data/lib/draper/decorator.rb +4 -7
  11. data/lib/draper/helper_proxy.rb +22 -3
  12. data/lib/draper/test/devise_helper.rb +18 -22
  13. data/lib/draper/test/rspec_integration.rb +4 -0
  14. data/lib/draper/test_case.rb +20 -0
  15. data/lib/draper/version.rb +1 -1
  16. data/lib/draper/view_context.rb +75 -13
  17. data/lib/draper/view_context/build_strategy.rb +48 -0
  18. data/lib/draper/view_helpers.rb +2 -2
  19. data/spec/draper/collection_decorator_spec.rb +169 -196
  20. data/spec/draper/decoratable/equality_spec.rb +10 -0
  21. data/spec/draper/decoratable_spec.rb +107 -132
  22. data/spec/draper/decorated_association_spec.rb +99 -96
  23. data/spec/draper/decorator_spec.rb +408 -434
  24. data/spec/draper/finders_spec.rb +160 -126
  25. data/spec/draper/helper_proxy_spec.rb +38 -8
  26. data/spec/draper/view_context/build_strategy_spec.rb +116 -0
  27. data/spec/draper/view_context_spec.rb +154 -0
  28. data/spec/draper/view_helpers_spec.rb +4 -37
  29. data/spec/dummy/app/controllers/posts_controller.rb +7 -0
  30. data/spec/dummy/app/decorators/post_decorator.rb +26 -2
  31. data/spec/dummy/app/helpers/application_helper.rb +3 -0
  32. data/spec/dummy/app/mailers/post_mailer.rb +10 -0
  33. data/spec/dummy/app/models/admin.rb +5 -0
  34. data/spec/dummy/app/models/mongoid_post.rb +5 -0
  35. data/spec/dummy/app/models/user.rb +5 -0
  36. data/spec/dummy/app/views/posts/_post.html.erb +15 -0
  37. data/spec/dummy/bin/rails +4 -0
  38. data/spec/dummy/config/application.rb +9 -3
  39. data/spec/dummy/config/boot.rb +2 -7
  40. data/spec/dummy/config/environments/development.rb +2 -3
  41. data/spec/dummy/config/environments/production.rb +2 -0
  42. data/spec/dummy/config/environments/test.rb +3 -4
  43. data/spec/dummy/config/initializers/secret_token.rb +1 -0
  44. data/spec/dummy/config/mongoid.yml +80 -0
  45. data/spec/dummy/config/routes.rb +2 -0
  46. data/spec/dummy/fast_spec/post_decorator_spec.rb +38 -0
  47. data/spec/dummy/lib/tasks/test.rake +11 -5
  48. data/spec/dummy/spec/decorators/devise_spec.rb +64 -0
  49. data/spec/dummy/spec/decorators/helpers_spec.rb +21 -0
  50. data/spec/dummy/spec/decorators/post_decorator_spec.rb +26 -6
  51. data/spec/dummy/spec/decorators/spec_type_spec.rb +7 -0
  52. data/spec/dummy/spec/decorators/view_context_spec.rb +22 -0
  53. data/spec/dummy/spec/mailers/post_mailer_spec.rb +10 -6
  54. data/spec/dummy/spec/models/mongoid_post_spec.rb +10 -0
  55. data/spec/dummy/spec/models/post_spec.rb +5 -5
  56. data/spec/dummy/spec/spec_helper.rb +1 -0
  57. data/spec/dummy/test/decorators/minitest/devise_test.rb +64 -0
  58. data/spec/dummy/test/decorators/minitest/helpers_test.rb +21 -0
  59. data/spec/dummy/{mini_test/mini_test_integration_test.rb → test/decorators/minitest/spec_type_test.rb} +9 -3
  60. data/spec/dummy/test/decorators/minitest/view_context_test.rb +24 -0
  61. data/spec/dummy/test/decorators/test_unit/devise_test.rb +64 -0
  62. data/spec/dummy/test/decorators/test_unit/helpers_test.rb +21 -0
  63. data/spec/dummy/test/decorators/test_unit/view_context_test.rb +24 -0
  64. data/spec/dummy/test/minitest_helper.rb +4 -0
  65. data/spec/dummy/test/test_helper.rb +3 -0
  66. data/spec/generators/decorator/decorator_generator_spec.rb +1 -0
  67. data/spec/integration/integration_spec.rb +31 -6
  68. data/spec/spec_helper.rb +32 -25
  69. data/spec/support/shared_examples/decoratable_equality.rb +40 -0
  70. data/spec/support/shared_examples/view_helpers.rb +39 -0
  71. metadata +56 -44
  72. data/spec/dummy/README.rdoc +0 -261
  73. data/spec/dummy/spec/decorators/rspec_integration_spec.rb +0 -19
  74. data/spec/support/action_controller.rb +0 -12
  75. data/spec/support/active_model.rb +0 -7
  76. data/spec/support/active_record.rb +0 -9
  77. data/spec/support/decorators/decorator_with_application_helper.rb +0 -25
  78. data/spec/support/decorators/namespaced_product_decorator.rb +0 -5
  79. data/spec/support/decorators/non_active_model_product_decorator.rb +0 -2
  80. data/spec/support/decorators/product_decorator.rb +0 -23
  81. data/spec/support/decorators/products_decorator.rb +0 -10
  82. data/spec/support/decorators/some_thing_decorator.rb +0 -2
  83. data/spec/support/decorators/specific_product_decorator.rb +0 -2
  84. data/spec/support/decorators/widget_decorator.rb +0 -2
  85. data/spec/support/models/namespaced_product.rb +0 -49
  86. data/spec/support/models/non_active_model_product.rb +0 -3
  87. data/spec/support/models/product.rb +0 -95
  88. data/spec/support/models/some_thing.rb +0 -5
  89. data/spec/support/models/uninferrable_decorator_model.rb +0 -3
  90. data/spec/support/models/widget.rb +0 -2
@@ -1,132 +1,166 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Draper::Finders do
4
- describe ".find" do
5
- it "proxies to the model class" do
6
- Product.should_receive(:find).with(1)
7
- ProductDecorator.find(1)
3
+ module Draper
4
+ describe Finders do
5
+ protect_class ProductDecorator
6
+ before { ProductDecorator.decorates_finders }
7
+
8
+ describe ".find" do
9
+ it "proxies to the model class" do
10
+ Product.should_receive(:find).with(1)
11
+ ProductDecorator.find(1)
12
+ end
13
+
14
+ it "decorates the result" do
15
+ found = Product.new
16
+ Product.stub(:find).and_return(found)
17
+ decorator = ProductDecorator.find(1)
18
+ expect(decorator).to be_a ProductDecorator
19
+ expect(decorator.source).to be found
20
+ end
21
+
22
+ it "passes context to the decorator" do
23
+ Product.stub(:find)
24
+ context = {some: "context"}
25
+ decorator = ProductDecorator.find(1, context: context)
26
+
27
+ expect(decorator.context).to be context
28
+ end
29
+ end
30
+
31
+ describe ".find_by_(x)" do
32
+ it "proxies to the model class" do
33
+ Product.should_receive(:find_by_name).with("apples")
34
+ ProductDecorator.find_by_name("apples")
35
+ end
36
+
37
+ it "decorates the result" do
38
+ found = Product.new
39
+ Product.stub(:find_by_name).and_return(found)
40
+ decorator = ProductDecorator.find_by_name("apples")
41
+ expect(decorator).to be_a ProductDecorator
42
+ expect(decorator.source).to be found
43
+ end
44
+
45
+ it "proxies complex ProductDecorators" do
46
+ Product.should_receive(:find_by_name_and_size).with("apples", "large")
47
+ ProductDecorator.find_by_name_and_size("apples", "large")
48
+ end
49
+
50
+ it "proxies find_last_by_(x) ProductDecorators" do
51
+ Product.should_receive(:find_last_by_name_and_size).with("apples", "large")
52
+ ProductDecorator.find_last_by_name_and_size("apples", "large")
53
+ end
54
+
55
+ it "proxies find_or_initialize_by_(x) ProductDecorators" do
56
+ Product.should_receive(:find_or_initialize_by_name_and_size).with("apples", "large")
57
+ ProductDecorator.find_or_initialize_by_name_and_size("apples", "large")
58
+ end
59
+
60
+ it "proxies find_or_create_by_(x) ProductDecorators" do
61
+ Product.should_receive(:find_or_create_by_name_and_size).with("apples", "large")
62
+ ProductDecorator.find_or_create_by_name_and_size("apples", "large")
63
+ end
64
+
65
+ it "passes context to the decorator" do
66
+ Product.stub(:find_by_name_and_size)
67
+ context = {some: "context"}
68
+ decorator = ProductDecorator.find_by_name_and_size("apples", "large", context: context)
69
+
70
+ expect(decorator.context).to be context
71
+ end
72
+ end
73
+
74
+ describe ".find_all_by_" do
75
+ it "proxies to the model class" do
76
+ Product.should_receive(:find_all_by_name_and_size).with("apples", "large").and_return([])
77
+ ProductDecorator.find_all_by_name_and_size("apples", "large")
78
+ end
79
+
80
+ it "decorates the result" do
81
+ found = [Product.new, Product.new]
82
+ Product.stub(:find_all_by_name).and_return(found)
83
+ decorator = ProductDecorator.find_all_by_name("apples")
84
+
85
+ expect(decorator).to be_a Draper::CollectionDecorator
86
+ expect(decorator.decorator_class).to be ProductDecorator
87
+ expect(decorator).to eq found
88
+ end
89
+
90
+ it "passes context to the decorator" do
91
+ Product.stub(:find_all_by_name)
92
+ context = {some: "context"}
93
+ decorator = ProductDecorator.find_all_by_name("apples", context: context)
94
+
95
+ expect(decorator.context).to be context
96
+ end
97
+ end
98
+
99
+ describe ".all" do
100
+ it "returns a decorated collection" do
101
+ found = [Product.new, Product.new]
102
+ Product.stub all: found
103
+ decorator = ProductDecorator.all
104
+
105
+ expect(decorator).to be_a Draper::CollectionDecorator
106
+ expect(decorator.decorator_class).to be ProductDecorator
107
+ expect(decorator).to eq found
108
+ end
109
+
110
+ it "passes context to the decorator" do
111
+ Product.stub(:all)
112
+ context = {some: "context"}
113
+ decorator = ProductDecorator.all(context: context)
114
+
115
+ expect(decorator.context).to be context
116
+ end
117
+ end
118
+
119
+ describe ".first" do
120
+ it "proxies to the model class" do
121
+ Product.should_receive(:first)
122
+ ProductDecorator.first
123
+ end
124
+
125
+ it "decorates the result" do
126
+ first = Product.new
127
+ Product.stub(:first).and_return(first)
128
+ decorator = ProductDecorator.first
129
+ expect(decorator).to be_a ProductDecorator
130
+ expect(decorator.source).to be first
131
+ end
132
+
133
+ it "passes context to the decorator" do
134
+ Product.stub(:first)
135
+ context = {some: "context"}
136
+ decorator = ProductDecorator.first(context: context)
137
+
138
+ expect(decorator.context).to be context
139
+ end
140
+ end
141
+
142
+ describe ".last" do
143
+ it "proxies to the model class" do
144
+ Product.should_receive(:last)
145
+ ProductDecorator.last
146
+ end
147
+
148
+ it "decorates the result" do
149
+ last = Product.new
150
+ Product.stub(:last).and_return(last)
151
+ decorator = ProductDecorator.last
152
+ expect(decorator).to be_a ProductDecorator
153
+ expect(decorator.source).to be last
154
+ end
155
+
156
+ it "passes context to the decorator" do
157
+ Product.stub(:last)
158
+ context = {some: "context"}
159
+ decorator = ProductDecorator.last(context: context)
160
+
161
+ expect(decorator.context).to be context
162
+ end
8
163
  end
9
164
 
10
- it "decorates the result" do
11
- found = Product.new
12
- Product.stub(:find).and_return(found)
13
- decorator = ProductDecorator.find(1)
14
- decorator.should be_a ProductDecorator
15
- decorator.source.should be found
16
- end
17
-
18
- it "passes context to the decorator" do
19
- decorator = ProductDecorator.find(1, context: {some: 'context'})
20
- decorator.context.should == {some: 'context'}
21
- end
22
- end
23
-
24
- describe ".find_by_(x)" do
25
- it "proxies to the model class" do
26
- Product.should_receive(:find_by_name).with("apples")
27
- ProductDecorator.find_by_name("apples")
28
- end
29
-
30
- it "decorates the result" do
31
- found = Product.new
32
- Product.stub(:find_by_name).and_return(found)
33
- decorator = ProductDecorator.find_by_name("apples")
34
- decorator.should be_a ProductDecorator
35
- decorator.source.should be found
36
- end
37
-
38
- it "proxies complex finders" do
39
- Product.should_receive(:find_by_name_and_size).with("apples", "large")
40
- ProductDecorator.find_by_name_and_size("apples", "large")
41
- end
42
-
43
- it "proxies find_last_by_(x) finders" do
44
- Product.should_receive(:find_last_by_name_and_size).with("apples", "large")
45
- ProductDecorator.find_last_by_name_and_size("apples", "large")
46
- end
47
-
48
- it "proxies find_or_initialize_by_(x) finders" do
49
- Product.should_receive(:find_or_initialize_by_name_and_size).with("apples", "large")
50
- ProductDecorator.find_or_initialize_by_name_and_size("apples", "large")
51
- end
52
-
53
- it "proxies find_or_create_by_(x) finders" do
54
- Product.should_receive(:find_or_create_by_name_and_size).with("apples", "large")
55
- ProductDecorator.find_or_create_by_name_and_size("apples", "large")
56
- end
57
-
58
- it "passes context to the decorator" do
59
- Product.should_receive(:find_by_name_and_size).with("apples", "large", context: {some: 'context'})
60
- decorator = ProductDecorator.find_by_name_and_size("apples", "large", context: {some: 'context'})
61
- decorator.context.should == {some: 'context'}
62
- end
63
- end
64
-
65
- describe ".find_all_by_" do
66
- it "proxies to the model class" do
67
- Product.should_receive(:find_all_by_name_and_size).with("apples", "large").and_return([])
68
- ProductDecorator.find_all_by_name_and_size("apples", "large")
69
- end
70
-
71
- it "decorates the result" do
72
- found = [Product.new, Product.new]
73
- Product.stub(:find_all_by_name).and_return(found)
74
- decorator = ProductDecorator.find_all_by_name("apples")
75
- decorator.should be_a Draper::CollectionDecorator
76
- decorator.should == found
77
- end
78
- end
79
-
80
- describe ".all" do
81
- it "returns a decorated collection" do
82
- collection = ProductDecorator.all
83
- collection.should be_a Draper::CollectionDecorator
84
- collection.first.should be_a ProductDecorator
85
- end
86
-
87
- it "passes context to the collection decorator" do
88
- collection = ProductDecorator.all(context: {some: 'context'})
89
- collection.context.should == {some: 'context'}
90
- end
91
- end
92
-
93
- describe ".first" do
94
- it "proxies to the model class" do
95
- Product.should_receive(:first)
96
- ProductDecorator.first
97
- end
98
-
99
- it "decorates the result" do
100
- first = Product.new
101
- Product.stub(:first).and_return(first)
102
- decorator = ProductDecorator.first
103
- decorator.should be_a ProductDecorator
104
- decorator.source.should be first
105
- end
106
-
107
- it "passes context to the decorator" do
108
- decorator = ProductDecorator.first(context: {some: 'context'})
109
- decorator.context.should == {some: 'context'}
110
- end
111
- end
112
-
113
- describe ".last" do
114
- it "proxies to the model class" do
115
- Product.should_receive(:last)
116
- ProductDecorator.last
117
- end
118
-
119
- it "decorates the result" do
120
- last = Product.new
121
- Product.stub(:last).and_return(last)
122
- decorator = ProductDecorator.last
123
- decorator.should be_a ProductDecorator
124
- decorator.source.should be last
125
- end
126
-
127
- it "passes context to the decorator" do
128
- decorator = ProductDecorator.last(context: {some: 'context'})
129
- decorator.context.should == {some: 'context'}
130
- end
131
165
  end
132
166
  end
@@ -1,12 +1,42 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Draper::HelperProxy do
4
- subject(:helper_proxy) { Draper::HelperProxy.new }
5
- let(:view_context) { Object.new }
6
- before { helper_proxy.stub(:view_context).and_return(view_context) }
7
-
8
- it "proxies methods to the view context" do
9
- view_context.should_receive(:foo).with("bar")
10
- helper_proxy.foo("bar")
3
+ module Draper
4
+ describe HelperProxy do
5
+ describe "#initialize" do
6
+ it "sets the view context" do
7
+ view_context = double
8
+ helper_proxy = HelperProxy.new(view_context)
9
+
10
+ expect(helper_proxy.send(:view_context)).to be view_context
11
+ end
12
+ end
13
+
14
+ describe "#method_missing" do
15
+ protect_class HelperProxy
16
+
17
+ it "proxies methods to the view context" do
18
+ view_context = double
19
+ helper_proxy = HelperProxy.new(view_context)
20
+
21
+ view_context.stub(:foo).and_return{|arg| arg}
22
+ expect(helper_proxy.foo(:passed)).to be :passed
23
+ end
24
+
25
+ it "passes blocks" do
26
+ view_context = double
27
+ helper_proxy = HelperProxy.new(view_context)
28
+
29
+ view_context.stub(:foo).and_return{|&block| block.call}
30
+ expect(helper_proxy.foo{:yielded}).to be :yielded
31
+ end
32
+
33
+ it "defines the method for better performance" do
34
+ helper_proxy = HelperProxy.new(double(foo: "bar"))
35
+
36
+ expect(HelperProxy.instance_methods).not_to include :foo
37
+ helper_proxy.foo
38
+ expect(HelperProxy.instance_methods).to include :foo
39
+ end
40
+ end
11
41
  end
12
42
  end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ def fake_view_context
4
+ double("ViewContext")
5
+ end
6
+
7
+ def fake_controller(view_context = fake_view_context)
8
+ double("Controller", view_context: view_context, request: double("Request"))
9
+ end
10
+
11
+ module Draper
12
+ describe ViewContext::BuildStrategy::Full do
13
+ describe "#call" do
14
+ context "when a current controller is set" do
15
+ it "returns the controller's view context" do
16
+ view_context = fake_view_context
17
+ ViewContext.stub controller: fake_controller(view_context)
18
+ strategy = ViewContext::BuildStrategy::Full.new
19
+
20
+ expect(strategy.call).to be view_context
21
+ end
22
+ end
23
+
24
+ context "when a current controller is not set" do
25
+ it "uses ApplicationController" do
26
+ view_context = fake_view_context
27
+ stub_const "ApplicationController", double(new: fake_controller(view_context))
28
+ strategy = ViewContext::BuildStrategy::Full.new
29
+
30
+ expect(strategy.call).to be view_context
31
+ end
32
+ end
33
+
34
+ it "adds a request if one is not defined" do
35
+ controller = Class.new(ActionController::Base).new
36
+ ViewContext.stub controller: controller
37
+ strategy = ViewContext::BuildStrategy::Full.new
38
+
39
+ expect(controller.request).to be_nil
40
+ strategy.call
41
+ expect(controller.request).to be_an ActionController::TestRequest
42
+ expect(controller.params).to eq({})
43
+
44
+ # sanity checks
45
+ expect(controller.view_context.request).to be controller.request
46
+ expect(controller.view_context.params).to be controller.params
47
+ end
48
+
49
+ it "adds methods to the view context from the constructor block" do
50
+ ViewContext.stub controller: fake_controller
51
+ strategy = ViewContext::BuildStrategy::Full.new do
52
+ def a_helper_method; end
53
+ end
54
+
55
+ expect(strategy.call).to respond_to :a_helper_method
56
+ end
57
+
58
+ it "includes modules into the view context from the constructor block" do
59
+ view_context = Object.new
60
+ ViewContext.stub controller: fake_controller(view_context)
61
+ helpers = Module.new do
62
+ def a_helper_method; end
63
+ end
64
+ strategy = ViewContext::BuildStrategy::Full.new do
65
+ include helpers
66
+ end
67
+
68
+ expect(strategy.call).to respond_to :a_helper_method
69
+ end
70
+ end
71
+ end
72
+
73
+ describe ViewContext::BuildStrategy::Fast do
74
+ describe "#call" do
75
+ it "returns an instance of a subclass of ActionView::Base" do
76
+ strategy = ViewContext::BuildStrategy::Fast.new
77
+
78
+ returned = strategy.call
79
+
80
+ expect(returned).to be_an ActionView::Base
81
+ expect(returned.class).not_to be ActionView::Base
82
+ end
83
+
84
+ it "returns different instances each time" do
85
+ strategy = ViewContext::BuildStrategy::Fast.new
86
+
87
+ expect(strategy.call).not_to be strategy.call
88
+ end
89
+
90
+ it "returns the same subclass each time" do
91
+ strategy = ViewContext::BuildStrategy::Fast.new
92
+
93
+ expect(strategy.call.class).to be strategy.call.class
94
+ end
95
+
96
+ it "adds methods to the view context from the constructor block" do
97
+ strategy = ViewContext::BuildStrategy::Fast.new do
98
+ def a_helper_method; end
99
+ end
100
+
101
+ expect(strategy.call).to respond_to :a_helper_method
102
+ end
103
+
104
+ it "includes modules into the view context from the constructor block" do
105
+ helpers = Module.new do
106
+ def a_helper_method; end
107
+ end
108
+ strategy = ViewContext::BuildStrategy::Fast.new do
109
+ include helpers
110
+ end
111
+
112
+ expect(strategy.call).to respond_to :a_helper_method
113
+ end
114
+ end
115
+ end
116
+ end