hanami 2.0.3 → 2.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +25 -9
  5. data/hanami.gemspec +2 -2
  6. data/lib/hanami/config/actions.rb +0 -4
  7. data/lib/hanami/config/views.rb +0 -4
  8. data/lib/hanami/config.rb +54 -0
  9. data/lib/hanami/extensions/action/slice_configured_action.rb +15 -7
  10. data/lib/hanami/extensions/action.rb +4 -4
  11. data/lib/hanami/extensions/router/errors.rb +58 -0
  12. data/lib/hanami/extensions/view/context.rb +129 -60
  13. data/lib/hanami/extensions/view/part.rb +26 -0
  14. data/lib/hanami/extensions/view/scope.rb +26 -0
  15. data/lib/hanami/extensions/view/slice_configured_context.rb +0 -2
  16. data/lib/hanami/extensions/view/slice_configured_helpers.rb +44 -0
  17. data/lib/hanami/extensions/view/slice_configured_view.rb +106 -21
  18. data/lib/hanami/extensions/view/standard_helpers.rb +14 -0
  19. data/lib/hanami/extensions.rb +10 -3
  20. data/lib/hanami/helpers/form_helper/form_builder.rb +1391 -0
  21. data/lib/hanami/helpers/form_helper/values.rb +75 -0
  22. data/lib/hanami/helpers/form_helper.rb +213 -0
  23. data/lib/hanami/middleware/public_errors_app.rb +75 -0
  24. data/lib/hanami/middleware/render_errors.rb +93 -0
  25. data/lib/hanami/slice.rb +27 -2
  26. data/lib/hanami/slice_configurable.rb +3 -2
  27. data/lib/hanami/version.rb +1 -1
  28. data/lib/hanami/web/rack_logger.rb +1 -1
  29. data/lib/hanami.rb +1 -1
  30. data/spec/integration/action/view_rendering/view_context_spec.rb +221 -0
  31. data/spec/integration/action/view_rendering_spec.rb +0 -18
  32. data/spec/integration/rack_app/middleware_spec.rb +23 -23
  33. data/spec/integration/rack_app/rack_app_spec.rb +5 -1
  34. data/spec/integration/view/config/default_context_spec.rb +149 -0
  35. data/spec/integration/view/{inflector_spec.rb → config/inflector_spec.rb} +1 -1
  36. data/spec/integration/view/config/part_class_spec.rb +147 -0
  37. data/spec/integration/view/config/part_namespace_spec.rb +103 -0
  38. data/spec/integration/view/config/paths_spec.rb +119 -0
  39. data/spec/integration/view/config/scope_class_spec.rb +147 -0
  40. data/spec/integration/view/config/scope_namespace_spec.rb +103 -0
  41. data/spec/integration/view/config/template_spec.rb +38 -0
  42. data/spec/integration/view/context/request_spec.rb +3 -7
  43. data/spec/integration/view/helpers/form_helper_spec.rb +174 -0
  44. data/spec/integration/view/helpers/part_helpers_spec.rb +124 -0
  45. data/spec/integration/view/helpers/scope_helpers_spec.rb +84 -0
  46. data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +162 -0
  47. data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +119 -0
  48. data/spec/integration/view/slice_configuration_spec.rb +9 -9
  49. data/spec/integration/web/render_detailed_errors_spec.rb +90 -0
  50. data/spec/integration/web/render_errors_spec.rb +240 -0
  51. data/spec/spec_helper.rb +1 -1
  52. data/spec/support/matchers.rb +32 -0
  53. data/spec/unit/hanami/config/actions/default_values_spec.rb +0 -4
  54. data/spec/unit/hanami/config/render_detailed_errors_spec.rb +25 -0
  55. data/spec/unit/hanami/config/render_errors_spec.rb +25 -0
  56. data/spec/unit/hanami/config/views_spec.rb +0 -18
  57. data/spec/unit/hanami/extensions/view/context_spec.rb +59 -0
  58. data/spec/unit/hanami/helpers/form_helper_spec.rb +2826 -0
  59. data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +27 -0
  60. data/spec/unit/hanami/router/errors/not_found_error_spec.rb +22 -0
  61. data/spec/unit/hanami/slice_configurable_spec.rb +18 -0
  62. data/spec/unit/hanami/version_spec.rb +1 -1
  63. data/spec/unit/hanami/web/rack_logger_spec.rb +1 -1
  64. metadata +65 -33
  65. data/spec/integration/action/view_integration_spec.rb +0 -165
  66. data/spec/integration/view/part_namespace_spec.rb +0 -96
  67. data/spec/integration/view/path_spec.rb +0 -56
  68. data/spec/integration/view/template_spec.rb +0 -68
  69. data/spec/isolation/hanami/application/already_configured_spec.rb +0 -19
  70. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +0 -10
  71. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +0 -14
  72. data/spec/isolation/hanami/application/not_configured_spec.rb +0 -9
  73. data/spec/isolation/hanami/application/routes/configured_spec.rb +0 -44
  74. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +0 -16
  75. data/spec/isolation/hanami/boot/success_spec.rb +0 -50
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "App action / View rendering / View context", :app_integration do
4
+ subject(:context) {
5
+ # We capture the context during rendering via our view spies; see the view classes below
6
+ action.call("REQUEST_METHOD" => "GET", "QUERY_STRING" => "/mock_request")
7
+ action.view.called_with[:context]
8
+ }
9
+
10
+ before do
11
+ with_directory(make_tmp_directory) do
12
+ write "config/app.rb", <<~RUBY
13
+ module TestApp
14
+ class App < Hanami::App
15
+ end
16
+ end
17
+ RUBY
18
+
19
+ write "app/action.rb", <<~RUBY
20
+ # auto_register: false
21
+
22
+ require "hanami/view"
23
+
24
+ module TestApp
25
+ class Action < Hanami::Action
26
+ end
27
+ end
28
+ RUBY
29
+
30
+ before_prepare if respond_to?(:before_prepare)
31
+ require "hanami/prepare"
32
+ end
33
+ end
34
+
35
+ describe "app action" do
36
+ let(:action) { TestApp::App["actions.posts.show"] }
37
+
38
+ def before_prepare
39
+ write "app/actions/posts/show.rb", <<~RUBY
40
+ module TestApp
41
+ module Actions
42
+ module Posts
43
+ class Show < TestApp::Action
44
+ end
45
+ end
46
+ end
47
+ end
48
+ RUBY
49
+
50
+ # Custom view class as a spy for `#call` args
51
+ write "app/views/posts/show.rb", <<~RUBY
52
+ module TestApp
53
+ module Views
54
+ module Posts
55
+ class Show
56
+ attr_reader :called_with
57
+
58
+ def call(**args)
59
+ @called_with = args
60
+ ""
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ RUBY
67
+ end
68
+
69
+ context "no context class defined" do
70
+ it "defines and uses a context class" do
71
+ expect(context).to be_an_instance_of TestApp::Views::Context
72
+ expect(context.class).to be < Hanami::View::Context
73
+ end
74
+
75
+ it "includes the request" do
76
+ expect(context.request).to be_an_instance_of Hanami::Action::Request
77
+ expect(context.request.env["QUERY_STRING"]).to eq "/mock_request"
78
+ end
79
+ end
80
+
81
+ context "context class defined" do
82
+ def before_prepare
83
+ super()
84
+
85
+ write "app/views/context.rb", <<~RUBY
86
+ # auto_register: false
87
+
88
+ module TestApp
89
+ module Views
90
+ class Context < Hanami::View::Context
91
+ def concrete_app_context?
92
+ true
93
+ end
94
+ end
95
+ end
96
+ end
97
+ RUBY
98
+ end
99
+
100
+ it "uses the defined context class" do
101
+ expect(context).to be_an_instance_of TestApp::Views::Context
102
+ expect(context).to be_a_concrete_app_context
103
+ end
104
+ end
105
+
106
+ context "hanami-view not bundled" do
107
+ before do
108
+ allow(Hanami).to receive(:bundled?).and_call_original
109
+ expect(Hanami).to receive(:bundled?).with("hanami-view").and_return false
110
+ end
111
+
112
+ it "does not provide a context" do
113
+ expect(context).to be nil
114
+ end
115
+
116
+ context "context class defined" do
117
+ def before_prepare
118
+ super()
119
+
120
+ write "app/views/context.rb", <<~RUBY
121
+ module TestApp
122
+ module Views
123
+ class Context
124
+ def initialize(**)
125
+ end
126
+
127
+ def with(**)
128
+ self
129
+ end
130
+
131
+ def concrete_app_context?
132
+ true
133
+ end
134
+ end
135
+ end
136
+ end
137
+ RUBY
138
+ end
139
+
140
+ it "uses the defined context class" do
141
+ expect(context).to be_an_instance_of TestApp::Views::Context
142
+ expect(context).to be_a_concrete_app_context
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ describe "slice action" do
149
+ let(:action) { Main::Slice["actions.posts.show"] }
150
+
151
+ def before_prepare
152
+ write "slices/main/action.rb", <<~RUBY
153
+ module Main
154
+ class Action < TestApp::Action
155
+ end
156
+ end
157
+ RUBY
158
+
159
+ write "slices/main/actions/posts/show.rb", <<~RUBY
160
+ module Main
161
+ module Actions
162
+ module Posts
163
+ class Show < Main::Action
164
+ end
165
+ end
166
+ end
167
+ end
168
+ RUBY
169
+
170
+ # Custom view class as a spy for `#call` args
171
+ write "slices/main/views/posts/show.rb", <<~RUBY
172
+ module Main
173
+ module Views
174
+ module Posts
175
+ class Show
176
+ attr_reader :called_with
177
+
178
+ def call(**args)
179
+ @called_with = args
180
+ ""
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ RUBY
187
+ end
188
+
189
+ context "no context class defined" do
190
+ it "defines and uses a context class" do
191
+ expect(context).to be_an_instance_of Main::Views::Context
192
+ expect(context.class).to be < Hanami::View::Context
193
+ end
194
+ end
195
+
196
+ context "context class defined" do
197
+ def before_prepare
198
+ super()
199
+
200
+ write "slices/main/views/context.rb", <<~RUBY
201
+ # auto_register: false
202
+
203
+ module Main
204
+ module Views
205
+ class Context < Hanami::View::Context
206
+ def concrete_slice_context?
207
+ true
208
+ end
209
+ end
210
+ end
211
+ end
212
+ RUBY
213
+ end
214
+
215
+ it "uses the defined context class" do
216
+ expect(context).to be_an_instance_of Main::Views::Context
217
+ expect(context).to be_a_concrete_slice_context
218
+ end
219
+ end
220
+ end
221
+ end
@@ -32,24 +32,6 @@ RSpec.describe "App action / View rendering", :app_integration do
32
32
  end
33
33
  RUBY
34
34
 
35
- write "app/views/context.rb", <<~RUBY
36
- require "hanami/view/context"
37
-
38
- module TestApp
39
- module Views
40
- class Context < Hanami::View::Context
41
- def request
42
- _options.fetch(:request)
43
- end
44
-
45
- def response
46
- _options.fetch(:response)
47
- end
48
- end
49
- end
50
- end
51
- RUBY
52
-
53
35
  write "app/actions/users/show.rb", <<~RUBY
54
36
  module TestApp
55
37
  module Actions
@@ -244,6 +244,7 @@ RSpec.describe "Hanami web app", :app_integration do
244
244
  module TestApp
245
245
  class App < Hanami::App
246
246
  config.logger.stream = File.new("/dev/null", "w")
247
+ config.render_errors = true
247
248
  end
248
249
  end
249
250
  RUBY
@@ -316,8 +317,7 @@ RSpec.describe "Hanami web app", :app_integration do
316
317
  it "excludes not found routes in root scope" do
317
318
  get "/foo"
318
319
 
319
- expect(last_response.status).to eq 404
320
- expect(last_response.body).to eq "Not Found"
320
+ expect(last_response.status).to eq 500
321
321
  expect(last_response.headers).to_not have_key("X-Auth-User-ID")
322
322
  end
323
323
 
@@ -330,12 +330,11 @@ RSpec.describe "Hanami web app", :app_integration do
330
330
  expect(last_response.headers).to have_key("X-Auth-User-ID")
331
331
  end
332
332
 
333
- it "uses Rack middleware for not found paths" do
333
+ it "does not uses the Rack middleware for not found paths" do
334
334
  get "/admin/users"
335
335
 
336
- expect(last_response.status).to be(404)
337
- expect(last_response.body).to eq "Not Found"
338
- expect(last_response.headers).to have_key("X-Auth-User-ID")
336
+ expect(last_response.status).to eq 500
337
+ expect(last_response.headers).not_to have_key("X-Auth-User-ID")
339
338
  end
340
339
  end
341
340
  end
@@ -350,6 +349,7 @@ RSpec.describe "Hanami web app", :app_integration do
350
349
  module TestApp
351
350
  class App < Hanami::App
352
351
  config.logger.stream = File.new("/dev/null", "w")
352
+ config.render_errors = true
353
353
  end
354
354
  end
355
355
  RUBY
@@ -597,15 +597,15 @@ RSpec.describe "Hanami web app", :app_integration do
597
597
  expect(last_response.headers).to_not have_key("X-API-Version")
598
598
  end
599
599
 
600
- it "uses Rack middleware for other paths" do
601
- get "/foo"
600
+ it "does not use Rack middleware for other paths" do
601
+ get "/__not_found__"
602
602
 
603
- expect(last_response.status).to be(404)
604
- expect(last_response.headers["X-Identifier-Root"]).to eq("true")
605
- expect(last_response.headers).to have_key("X-Elapsed")
606
- expect(last_response.headers).to_not have_key("X-Auth-User-ID")
607
- expect(last_response.headers).to_not have_key("X-API-Rate-Limit-Quota")
608
- expect(last_response.headers).to_not have_key("X-API-Version")
603
+ expect(last_response.status).to eq 500
604
+ expect(last_response.headers).not_to have_key("X-Identifier-Root")
605
+ expect(last_response.headers).not_to have_key("X-Elapsed")
606
+ expect(last_response.headers).not_to have_key("X-Auth-User-ID")
607
+ expect(last_response.headers).not_to have_key("X-API-Rate-Limit-Quota")
608
+ expect(last_response.headers).not_to have_key("X-API-Version")
609
609
  end
610
610
 
611
611
  context "scoped" do
@@ -621,15 +621,15 @@ RSpec.describe "Hanami web app", :app_integration do
621
621
  end
622
622
 
623
623
  it "uses Rack middleware for other paths" do
624
- get "/admin/users"
625
-
626
- expect(last_response.status).to be(404)
627
- expect(last_response.headers["X-Identifier-Admin"]).to eq("true")
628
- expect(last_response.headers).to have_key("X-Elapsed")
629
- expect(last_response.headers).to have_key("X-Elapsed")
630
- expect(last_response.headers).to have_key("X-Auth-User-ID")
631
- expect(last_response.headers).to_not have_key("X-API-Rate-Limit-Quota")
632
- expect(last_response.headers).to_not have_key("X-API-Version")
624
+ get "/admin/__not_found__"
625
+
626
+ expect(last_response.status).to eq 500
627
+ expect(last_response.headers).not_to have_key("X-Identifier-Admin")
628
+ expect(last_response.headers).not_to have_key("X-Elapsed")
629
+ expect(last_response.headers).not_to have_key("X-Elapsed")
630
+ expect(last_response.headers).not_to have_key("X-Auth-User-ID")
631
+ expect(last_response.headers).not_to have_key("X-API-Rate-Limit-Quota")
632
+ expect(last_response.headers).not_to have_key("X-API-Version")
633
633
  end
634
634
 
635
635
  # See: https://github.com/hanami/api/issues/8
@@ -210,10 +210,11 @@ RSpec.describe "Hanami web app", :app_integration do
210
210
  let(:app) { Main::Slice.rack_app }
211
211
 
212
212
  around do |example|
213
+ @prev_hanami_env = ENV["HANAMI_ENV"]
213
214
  ENV["HANAMI_ENV"] = "production"
214
215
  example.run
215
216
  ensure
216
- ENV["HANAMI_ENV"] = "test"
217
+ ENV["HANAMI_ENV"] = @prev_hanami_env
217
218
  end
218
219
 
219
220
  specify "Has rack monitor preconfigured with default request logging (when used via a slice)" do
@@ -569,6 +570,7 @@ RSpec.describe "Hanami web app", :app_integration do
569
570
 
570
571
  module TestApp
571
572
  class App < Hanami::App
573
+ config.render_detailed_errors = false
572
574
  end
573
575
  end
574
576
  RUBY
@@ -600,6 +602,8 @@ RSpec.describe "Hanami web app", :app_integration do
600
602
 
601
603
  module TestApp
602
604
  class App < Hanami::App
605
+ config.render_detailed_errors = false
606
+
603
607
  register_slice :admin
604
608
  end
605
609
  end
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "App view / Config / Default context", :app_integration do
4
+ before do
5
+ with_directory(@dir = make_tmp_directory) do
6
+ write "config/app.rb", <<~RUBY
7
+ module TestApp
8
+ class App < Hanami::App
9
+ end
10
+ end
11
+ RUBY
12
+
13
+ write "app/view.rb", <<~RUBY
14
+ # auto_register: false
15
+
16
+ require "hanami/view"
17
+
18
+ module TestApp
19
+ class View < Hanami::View
20
+ end
21
+ end
22
+ RUBY
23
+
24
+ before_prepare if respond_to?(:before_prepare)
25
+ require "hanami/prepare"
26
+ end
27
+ end
28
+
29
+ subject(:default_context) { view_class.config.default_context }
30
+
31
+ describe "app view" do
32
+ let(:view_class) { TestApp::View }
33
+
34
+ describe "no concrete context class defined" do
35
+ it "generates an app context class and configures it as the view's default_context" do
36
+ expect(default_context).to be_an_instance_of TestApp::Views::Context
37
+ expect(default_context.class.superclass).to be Hanami::View::Context
38
+ end
39
+ end
40
+
41
+ describe "concrete context class defined" do
42
+ def before_prepare
43
+ write "app/views/context.rb", <<~RUBY
44
+ # auto_register: false
45
+
46
+ module TestApp
47
+ module Views
48
+ class Context < Hanami::View::Context
49
+ def concrete?
50
+ true
51
+ end
52
+ end
53
+ end
54
+ end
55
+ RUBY
56
+ end
57
+
58
+ it "configures the app scope class as the view's scope_class" do
59
+ expect(default_context).to be_an_instance_of TestApp::Views::Context
60
+ expect(default_context).to be_concrete
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "slice view" do
66
+ let(:view_class) { Main::View }
67
+
68
+ def before_prepare
69
+ write "slices/main/view.rb", <<~RUBY
70
+ # auto_register: false
71
+
72
+ module Main
73
+ class View < TestApp::View
74
+ end
75
+ end
76
+ RUBY
77
+ end
78
+
79
+ describe "no concrete slice context class defined" do
80
+ it "generates an app context class and configures it as the view's default_context" do
81
+ expect(default_context).to be_an_instance_of Main::Views::Context
82
+ expect(default_context.class.superclass).to be TestApp::Views::Context
83
+ end
84
+ end
85
+
86
+ describe "concrete slice context class defined" do
87
+ def before_prepare
88
+ super
89
+
90
+ write "slices/main/views/context.rb", <<~RUBY
91
+ # auto_register: false
92
+
93
+ module Main
94
+ module Views
95
+ class Context < Hanami::View::Context
96
+ def concrete?
97
+ true
98
+ end
99
+ end
100
+ end
101
+ end
102
+ RUBY
103
+ end
104
+
105
+ it "configures the slice context as the view's default_context" do
106
+ expect(default_context).to be_an_instance_of Main::Views::Context
107
+ expect(default_context).to be_concrete
108
+ end
109
+ end
110
+
111
+ describe "view not inheriting from app view, no concrete context class defined" do
112
+ def before_prepare
113
+ write "slices/main/view.rb", <<~RUBY
114
+ # auto_register: false
115
+
116
+ module Main
117
+ class View < Hanami::View
118
+ end
119
+ end
120
+ RUBY
121
+ end
122
+
123
+ it "generates a slice context class, inheriting from the app context class, and configures it as the view's default_context" do
124
+ expect(default_context).to be_an_instance_of Main::Views::Context
125
+ expect(default_context.class.superclass).to be TestApp::Views::Context
126
+ end
127
+ end
128
+
129
+ describe "no app view class defined" do
130
+ def before_prepare
131
+ FileUtils.rm "app/view.rb"
132
+
133
+ write "slices/main/view.rb", <<~RUBY
134
+ # auto_register: false
135
+
136
+ module Main
137
+ class View < Hanami::View
138
+ end
139
+ end
140
+ RUBY
141
+ end
142
+
143
+ it "generates a slice context class, inheriting from the app context class, and configures it as the view's default_context" do
144
+ expect(default_context).to be_an_instance_of Main::Views::Context
145
+ expect(default_context.class.superclass).to be Hanami::View::Context
146
+ end
147
+ end
148
+ end
149
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "hanami"
4
4
 
5
- RSpec.describe "App view / Inflector", :app_integration do
5
+ RSpec.describe "App view / Config / Inflector", :app_integration do
6
6
  before do
7
7
  module TestApp
8
8
  class App < Hanami::App
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "App view / Config / Part class", :app_integration do
4
+ before do
5
+ with_directory(make_tmp_directory) do
6
+ write "config/app.rb", <<~RUBY
7
+ module TestApp
8
+ class App < Hanami::App
9
+ end
10
+ end
11
+ RUBY
12
+
13
+ write "app/view.rb", <<~RUBY
14
+ # auto_register: false
15
+
16
+ require "hanami/view"
17
+
18
+ module TestApp
19
+ class View < Hanami::View
20
+ end
21
+ end
22
+ RUBY
23
+
24
+ before_prepare if respond_to?(:before_prepare)
25
+ require "hanami/prepare"
26
+ end
27
+ end
28
+
29
+ describe "app view" do
30
+ let(:view_class) { TestApp::View }
31
+
32
+ context "no concrete app part class defined" do
33
+ it "generates an app part class and configures it as the view's part_class" do
34
+ expect(view_class.config.part_class).to be TestApp::Views::Part
35
+ expect(view_class.config.part_class.superclass).to be Hanami::View::Part
36
+ end
37
+ end
38
+
39
+ context "concrete app part class defined" do
40
+ def before_prepare
41
+ write "app/views/part.rb", <<~RUBY
42
+ # auto_register: false
43
+
44
+ module TestApp
45
+ module Views
46
+ class Part < Hanami::View::Part
47
+ def self.concrete?
48
+ true
49
+ end
50
+ end
51
+ end
52
+ end
53
+ RUBY
54
+ end
55
+
56
+ it "configures the app part class as the view's part_class" do
57
+ expect(view_class.config.part_class).to be TestApp::Views::Part
58
+ expect(view_class.config.part_class).to be_concrete
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "slice view" do
64
+ let(:view_class) { Main::View }
65
+
66
+ def before_prepare
67
+ write "slices/main/view.rb", <<~RUBY
68
+ # auto_register: false
69
+
70
+ module Main
71
+ class View < TestApp::View
72
+ end
73
+ end
74
+ RUBY
75
+ end
76
+
77
+ context "no concrete slice part class defined" do
78
+ it "generates a slice part class, inheriting from the app part class, and configures it as the view's part_class" do
79
+ expect(view_class.config.part_class).to be Main::Views::Part
80
+ expect(view_class.config.part_class.superclass).to be TestApp::Views::Part
81
+ end
82
+ end
83
+
84
+ context "concrete slice part class defined" do
85
+ def before_prepare
86
+ super
87
+
88
+ write "slices/main/views/part.rb", <<~RUBY
89
+ # auto_register: false
90
+
91
+ module Main
92
+ module Views
93
+ class Part < TestApp::Views::Part
94
+ def self.concrete?
95
+ true
96
+ end
97
+ end
98
+ end
99
+ end
100
+ RUBY
101
+ end
102
+
103
+ it "configures the slice part class as the view's part_class" do
104
+ expect(view_class.config.part_class).to be Main::Views::Part
105
+ expect(view_class.config.part_class).to be_concrete
106
+ end
107
+ end
108
+
109
+ context "view not inheriting from app view, no concrete part class" do
110
+ def before_prepare
111
+ write "slices/main/view.rb", <<~RUBY
112
+ # auto_register: false
113
+
114
+ module Main
115
+ class View < Hanami::View
116
+ end
117
+ end
118
+ RUBY
119
+ end
120
+
121
+ it "generates a slice part class, inheriting from the app part class, and configures it as the view's part_class" do
122
+ expect(view_class.config.part_class).to be Main::Views::Part
123
+ expect(view_class.config.part_class.superclass).to be TestApp::Views::Part
124
+ end
125
+ end
126
+
127
+ context "no app view class defined" do
128
+ def before_prepare
129
+ FileUtils.rm "app/view.rb"
130
+
131
+ write "slices/main/view.rb", <<~RUBY
132
+ # auto_register: false
133
+
134
+ module Main
135
+ class View < Hanami::View
136
+ end
137
+ end
138
+ RUBY
139
+ end
140
+
141
+ it "generates a slice part class, inheriting from Hanami::View::Part, and configures it as the view's part_class" do
142
+ expect(view_class.config.part_class).to be Main::Views::Part
143
+ expect(view_class.config.part_class.superclass).to be Hanami::View::Part
144
+ end
145
+ end
146
+ end
147
+ end