hanami 2.0.3 → 2.1.0.beta2

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -2
  3. data/LICENSE.md +1 -1
  4. data/README.md +26 -10
  5. data/hanami.gemspec +2 -2
  6. data/lib/hanami/app.rb +5 -0
  7. data/lib/hanami/config/actions.rb +4 -11
  8. data/lib/hanami/config/assets.rb +84 -0
  9. data/lib/hanami/config/null_config.rb +3 -0
  10. data/lib/hanami/config/views.rb +0 -4
  11. data/lib/hanami/config.rb +71 -5
  12. data/lib/hanami/extensions/action/slice_configured_action.rb +15 -7
  13. data/lib/hanami/extensions/action.rb +8 -6
  14. data/lib/hanami/extensions/router/errors.rb +58 -0
  15. data/lib/hanami/extensions/view/context.rb +129 -60
  16. data/lib/hanami/extensions/view/part.rb +26 -0
  17. data/lib/hanami/extensions/view/scope.rb +26 -0
  18. data/lib/hanami/extensions/view/slice_configured_context.rb +0 -2
  19. data/lib/hanami/extensions/view/slice_configured_helpers.rb +44 -0
  20. data/lib/hanami/extensions/view/slice_configured_view.rb +106 -21
  21. data/lib/hanami/extensions/view/standard_helpers.rb +18 -0
  22. data/lib/hanami/extensions.rb +10 -3
  23. data/lib/hanami/helpers/assets_helper.rb +752 -0
  24. data/lib/hanami/helpers/form_helper/form_builder.rb +1391 -0
  25. data/lib/hanami/helpers/form_helper/values.rb +75 -0
  26. data/lib/hanami/helpers/form_helper.rb +213 -0
  27. data/lib/hanami/middleware/assets.rb +21 -0
  28. data/lib/hanami/middleware/public_errors_app.rb +75 -0
  29. data/lib/hanami/middleware/render_errors.rb +90 -0
  30. data/lib/hanami/providers/assets.rb +44 -0
  31. data/lib/hanami/rake_tasks.rb +19 -18
  32. data/lib/hanami/settings.rb +1 -1
  33. data/lib/hanami/slice.rb +48 -2
  34. data/lib/hanami/slice_configurable.rb +3 -2
  35. data/lib/hanami/version.rb +1 -1
  36. data/lib/hanami/web/rack_logger.rb +1 -1
  37. data/lib/hanami.rb +3 -3
  38. data/spec/integration/action/view_rendering/view_context_spec.rb +221 -0
  39. data/spec/integration/action/view_rendering_spec.rb +0 -18
  40. data/spec/integration/assets/assets_spec.rb +101 -0
  41. data/spec/integration/assets/serve_static_assets_spec.rb +152 -0
  42. data/spec/integration/logging/exception_logging_spec.rb +115 -0
  43. data/spec/integration/logging/notifications_spec.rb +68 -0
  44. data/spec/integration/logging/request_logging_spec.rb +128 -0
  45. data/spec/integration/rack_app/middleware_spec.rb +22 -22
  46. data/spec/integration/rack_app/rack_app_spec.rb +3 -220
  47. data/spec/integration/rake_tasks_spec.rb +107 -0
  48. data/spec/integration/view/config/default_context_spec.rb +149 -0
  49. data/spec/integration/view/{inflector_spec.rb → config/inflector_spec.rb} +1 -1
  50. data/spec/integration/view/config/part_class_spec.rb +147 -0
  51. data/spec/integration/view/config/part_namespace_spec.rb +103 -0
  52. data/spec/integration/view/config/paths_spec.rb +119 -0
  53. data/spec/integration/view/config/scope_class_spec.rb +147 -0
  54. data/spec/integration/view/config/scope_namespace_spec.rb +103 -0
  55. data/spec/integration/view/config/template_spec.rb +38 -0
  56. data/spec/integration/view/context/assets_spec.rb +3 -9
  57. data/spec/integration/view/context/request_spec.rb +3 -7
  58. data/spec/integration/view/helpers/form_helper_spec.rb +174 -0
  59. data/spec/integration/view/helpers/part_helpers_spec.rb +124 -0
  60. data/spec/integration/view/helpers/scope_helpers_spec.rb +84 -0
  61. data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +162 -0
  62. data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +119 -0
  63. data/spec/integration/view/slice_configuration_spec.rb +9 -9
  64. data/spec/integration/web/render_detailed_errors_spec.rb +107 -0
  65. data/spec/integration/web/render_errors_spec.rb +242 -0
  66. data/spec/spec_helper.rb +1 -1
  67. data/spec/support/app_integration.rb +46 -2
  68. data/spec/support/matchers.rb +32 -0
  69. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +24 -36
  70. data/spec/unit/hanami/config/actions/csrf_protection_spec.rb +4 -3
  71. data/spec/unit/hanami/config/actions/default_values_spec.rb +3 -6
  72. data/spec/unit/hanami/config/render_detailed_errors_spec.rb +25 -0
  73. data/spec/unit/hanami/config/render_errors_spec.rb +25 -0
  74. data/spec/unit/hanami/config/views_spec.rb +0 -18
  75. data/spec/unit/hanami/env_spec.rb +11 -25
  76. data/spec/unit/hanami/extensions/view/context_spec.rb +59 -0
  77. data/spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb +109 -0
  78. data/spec/unit/hanami/helpers/assets_helper/audio_tag_spec.rb +132 -0
  79. data/spec/unit/hanami/helpers/assets_helper/favicon_link_tag_spec.rb +91 -0
  80. data/spec/unit/hanami/helpers/assets_helper/image_tag_spec.rb +92 -0
  81. data/spec/unit/hanami/helpers/assets_helper/javascript_tag_spec.rb +143 -0
  82. data/spec/unit/hanami/helpers/assets_helper/stylesheet_link_tag_spec.rb +126 -0
  83. data/spec/unit/hanami/helpers/assets_helper/video_tag_spec.rb +132 -0
  84. data/spec/unit/hanami/helpers/form_helper_spec.rb +2826 -0
  85. data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +27 -0
  86. data/spec/unit/hanami/router/errors/not_found_error_spec.rb +22 -0
  87. data/spec/unit/hanami/slice_configurable_spec.rb +18 -0
  88. data/spec/unit/hanami/version_spec.rb +1 -1
  89. data/spec/unit/hanami/web/rack_logger_spec.rb +1 -1
  90. metadata +95 -35
  91. data/lib/hanami/assets/app_config.rb +0 -61
  92. data/lib/hanami/assets/config.rb +0 -53
  93. data/spec/integration/action/view_integration_spec.rb +0 -165
  94. data/spec/integration/view/part_namespace_spec.rb +0 -96
  95. data/spec/integration/view/path_spec.rb +0 -56
  96. data/spec/integration/view/template_spec.rb +0 -68
  97. data/spec/isolation/hanami/application/already_configured_spec.rb +0 -19
  98. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +0 -10
  99. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +0 -14
  100. data/spec/isolation/hanami/application/not_configured_spec.rb +0 -9
  101. data/spec/isolation/hanami/application/routes/configured_spec.rb +0 -44
  102. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +0 -16
  103. data/spec/isolation/hanami/boot/success_spec.rb +0 -50
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/test"
4
+
5
+ RSpec.describe "Logging / Notifications", :app_integration do
6
+ include Rack::Test::Methods
7
+
8
+ let(:app) { Hanami.app }
9
+
10
+ specify "Request logging continues even when notifications bus has already been used" do
11
+ dir = Dir.mktmpdir
12
+
13
+ with_tmp_directory(dir) do
14
+ write "config/app.rb", <<~RUBY
15
+ require "hanami"
16
+
17
+ module TestApp
18
+ class App < Hanami::App
19
+ config.actions.format :json
20
+ config.logger.options = {colorize: true}
21
+ config.logger.stream = config.root.join("test.log")
22
+ end
23
+ end
24
+ RUBY
25
+
26
+ write "config/routes.rb", <<~RUBY
27
+ module TestApp
28
+ class Routes < Hanami::Routes
29
+ post "/users", to: "users.create"
30
+ end
31
+ end
32
+ RUBY
33
+
34
+ write "app/actions/users/create.rb", <<~RUBY
35
+ module TestApp
36
+ module Actions
37
+ module Users
38
+ class Create < Hanami::Action
39
+ def handle(req, resp)
40
+ resp.body = req.params.to_h.keys
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ RUBY
47
+
48
+ require "hanami/prepare"
49
+
50
+ # Simulate any component interacting with the notifications bus such that it creates its
51
+ # internal bus with a duplicate copy of all currently registered events. This means that the
52
+ # class-level Dry::Monitor::Notification events implicitly registered by the
53
+ # Dry::Monitor::Rack::Middleware activated via the rack provider are ignored, unless our
54
+ # provider explicitly re-registers them on _instance_ of the notifications bus.
55
+ #
56
+ # See Hanami::Providers::Rack for more detail.
57
+ Hanami.app["notifications"].instrument(:sql)
58
+
59
+ logs = -> { Pathname(dir).join("test.log").realpath.read }
60
+
61
+ post "/users", JSON.generate(name: "jane", password: "secret"), {"CONTENT_TYPE" => "application/json"}
62
+ expect(logs.()).to match %r{POST 200 \d+(µs|ms) 127.0.0.1 /}
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "rack/test"
5
+ require "stringio"
6
+
7
+ RSpec.describe "Logging / Request logging", :app_integration do
8
+ include Rack::Test::Methods
9
+
10
+ let(:app) { Hanami.app }
11
+
12
+ let(:logger_stream) { StringIO.new }
13
+
14
+ def configure_logger
15
+ Hanami.app.config.logger.stream = logger_stream
16
+ end
17
+
18
+ def logs
19
+ @logs ||= (logger_stream.rewind and logger_stream.read)
20
+ end
21
+
22
+ before do
23
+ with_directory(make_tmp_directory) do
24
+ write "config/app.rb", <<~RUBY
25
+ module TestApp
26
+ class App < Hanami::App
27
+ end
28
+ end
29
+ RUBY
30
+
31
+ require "hanami/setup"
32
+ configure_logger
33
+
34
+ before_prepare if respond_to?(:before_prepare)
35
+ require "hanami/prepare"
36
+ end
37
+ end
38
+
39
+ describe "app router" do
40
+ def before_prepare
41
+ write "config/routes.rb", <<~RUBY
42
+ module TestApp
43
+ class Routes < Hanami::Routes
44
+ root to: ->(env) { [200, {}, ["OK"]] }
45
+ end
46
+ end
47
+ RUBY
48
+ end
49
+
50
+ it "logs the requests" do
51
+ get "/"
52
+
53
+ expect(logs.split("\n").length).to eq 1
54
+ expect(logs).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
55
+ end
56
+
57
+ context "production env" do
58
+ around do |example|
59
+ @prev_hanami_env = ENV["HANAMI_ENV"]
60
+ ENV["HANAMI_ENV"] = "production"
61
+ example.run
62
+ ensure
63
+ ENV["HANAMI_ENV"] = @prev_hanami_env
64
+ end
65
+
66
+ it "logs the requests as JSON" do
67
+ get "/"
68
+
69
+ expect(logs.split("\n").length).to eq 1
70
+
71
+ json = JSON.parse(logs, symbolize_names: true)
72
+ expect(json).to include(
73
+ verb: "GET",
74
+ path: "/",
75
+ ip: "127.0.0.1",
76
+ elapsed: Integer,
77
+ elapsed_unit: a_string_matching(/(µs|ms)/),
78
+ )
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "slice router" do
84
+ let(:app) { Main::Slice.rack_app }
85
+
86
+ def before_prepare
87
+ write "slices/main/config/routes.rb", <<~RUBY
88
+ module Main
89
+ class Routes < Hanami::Routes
90
+ root to: ->(env) { [200, {}, ["OK"]] }
91
+ end
92
+ end
93
+ RUBY
94
+ end
95
+
96
+ it "logs the requests" do
97
+ get "/"
98
+
99
+ expect(logs.split("\n").length).to eq 1
100
+ expect(logs).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
101
+ end
102
+
103
+ context "production env" do
104
+ around do |example|
105
+ @prev_hanami_env = ENV["HANAMI_ENV"]
106
+ ENV["HANAMI_ENV"] = "production"
107
+ example.run
108
+ ensure
109
+ ENV["HANAMI_ENV"] = @prev_hanami_env
110
+ end
111
+
112
+ it "logs the requests as JSON" do
113
+ get "/"
114
+
115
+ expect(logs.split("\n").length).to eq 1
116
+
117
+ json = JSON.parse(logs, symbolize_names: true)
118
+ expect(json).to include(
119
+ verb: "GET",
120
+ path: "/",
121
+ ip: "127.0.0.1",
122
+ elapsed: Integer,
123
+ elapsed_unit: a_string_matching(/(µs|ms)/),
124
+ )
125
+ end
126
+ end
127
+ end
128
+ end
@@ -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
@@ -317,7 +318,6 @@ RSpec.describe "Hanami web app", :app_integration do
317
318
  get "/foo"
318
319
 
319
320
  expect(last_response.status).to eq 404
320
- expect(last_response.body).to eq "Not Found"
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 404
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 404
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 404
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
@@ -33,226 +33,6 @@ RSpec.describe "Hanami web app", :app_integration do
33
33
  end
34
34
  end
35
35
 
36
- specify "Has rack monitor preconfigured with default request logging" do
37
- dir = Dir.mktmpdir
38
-
39
- with_tmp_directory(dir) do
40
- write "config/app.rb", <<~RUBY
41
- require "hanami"
42
-
43
- module TestApp
44
- class App < Hanami::App
45
- config.actions.format :json
46
- config.logger.options = {colorize: true}
47
- config.logger.stream = config.root.join("test.log")
48
- end
49
- end
50
- RUBY
51
-
52
- write "app/actions/users/index.rb", <<~RUBY
53
- module TestApp
54
- module Actions
55
- module Users
56
- class Index < Hanami::Action
57
- def handle(req, _resp)
58
- raise StandardError, "OH NOEZ"
59
- end
60
- end
61
- end
62
- end
63
- end
64
- RUBY
65
-
66
- write "app/actions/users/create.rb", <<~RUBY
67
- module TestApp
68
- module Actions
69
- module Users
70
- class Create < Hanami::Action
71
- def handle(req, resp)
72
- resp.body = req.params.to_h.keys
73
- end
74
- end
75
- end
76
- end
77
- end
78
- RUBY
79
-
80
- write "config/routes.rb", <<~RUBY
81
- module TestApp
82
- class Routes < Hanami::Routes
83
- root to: ->(env) { [200, {}, ["OK"]] }
84
- get "/users", to: "users.index"
85
- post "/users", to: "users.create"
86
- end
87
- end
88
- RUBY
89
-
90
- require "hanami/prepare"
91
-
92
- expect(Hanami.app["rack.monitor"]).to be_instance_of(Dry::Monitor::Rack::Middleware)
93
-
94
- get "/"
95
-
96
- logs = -> { Pathname(dir).join("test.log").realpath.read }
97
-
98
- expect(logs.()).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
99
-
100
- post "/users", JSON.generate(name: "jane", password: "secret"), {"CONTENT_TYPE" => "application/json"}
101
-
102
- expect(logs.()).to match %r{POST 200 \d+(µs|ms) 127.0.0.1 /}
103
-
104
- begin
105
- get "/users"
106
- rescue => e # rubocop:disable Style/RescueStandardError
107
- raise unless e.to_s == "OH NOEZ"
108
- end
109
-
110
- err_log = logs.()
111
-
112
- expect(err_log).to include("OH NOEZ")
113
- expect(err_log).to include("app/actions/users/index.rb:6:in `handle'")
114
- end
115
- end
116
-
117
- specify "Logging via the rack monitor even when notifications bus has already been used" do
118
- dir = Dir.mktmpdir
119
-
120
- with_tmp_directory(dir) do
121
- write "config/app.rb", <<~RUBY
122
- require "hanami"
123
-
124
- module TestApp
125
- class App < Hanami::App
126
- config.actions.format :json
127
- config.logger.options = {colorize: true}
128
- config.logger.stream = config.root.join("test.log")
129
- end
130
- end
131
- RUBY
132
-
133
- write "config/routes.rb", <<~RUBY
134
- module TestApp
135
- class Routes < Hanami::Routes
136
- post "/users", to: "users.create"
137
- end
138
- end
139
- RUBY
140
-
141
- write "app/actions/users/create.rb", <<~RUBY
142
- module TestApp
143
- module Actions
144
- module Users
145
- class Create < Hanami::Action
146
- def handle(req, resp)
147
- resp.body = req.params.to_h.keys
148
- end
149
- end
150
- end
151
- end
152
- end
153
- RUBY
154
-
155
- require "hanami/prepare"
156
-
157
- # Simulate any component interacting with the notifications bus such that it creates its
158
- # internal bus with a duplicate copy of all currently registered events. This means that the
159
- # class-level Dry::Monitor::Notification events implicitly registered by the
160
- # Dry::Monitor::Rack::Middleware activated via the rack provider are ignored, unless our
161
- # provider explicitly re-registers them on _instance_ of the notifications bus.
162
- #
163
- # See Hanami::Providers::Rack for more detail.
164
- Hanami.app["notifications"].instrument(:sql)
165
-
166
- logs = -> { Pathname(dir).join("test.log").realpath.read }
167
-
168
- post "/users", JSON.generate(name: "jane", password: "secret"), {"CONTENT_TYPE" => "application/json"}
169
- expect(logs.()).to match %r{POST 200 \d+(µs|ms) 127.0.0.1 /}
170
- end
171
- end
172
-
173
- describe "Request logging when using slice router" do
174
- let(:app) { Main::Slice.rack_app }
175
-
176
- specify "Has rack monitor preconfigured with default request logging (when used via a slice)" do
177
- dir = Dir.mktmpdir
178
-
179
- with_tmp_directory(dir) do
180
- write "config/app.rb", <<~RUBY
181
- require "hanami"
182
-
183
- module TestApp
184
- class App < Hanami::App
185
- config.logger.stream = config.root.join("test.log")
186
- end
187
- end
188
- RUBY
189
-
190
- write "slices/main/config/routes.rb", <<~RUBY
191
- module Main
192
- class Routes < Hanami::Routes
193
- root to: ->(env) { [200, {}, ["OK"]] }
194
- end
195
- end
196
- RUBY
197
-
198
- require "hanami/prepare"
199
-
200
- get "/"
201
-
202
- logs = -> { Pathname(dir).join("test.log").realpath.read }
203
-
204
- expect(logs.()).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
205
- end
206
- end
207
- end
208
-
209
- describe "Request logging on production" do
210
- let(:app) { Main::Slice.rack_app }
211
-
212
- around do |example|
213
- ENV["HANAMI_ENV"] = "production"
214
- example.run
215
- ensure
216
- ENV["HANAMI_ENV"] = "test"
217
- end
218
-
219
- specify "Has rack monitor preconfigured with default request logging (when used via a slice)" do
220
- dir = Dir.mktmpdir
221
-
222
- with_tmp_directory(dir) do
223
- write "config/app.rb", <<~RUBY
224
- require "hanami"
225
-
226
- module TestApp
227
- class App < Hanami::App
228
- config.logger.stream = config.root.join("test.log")
229
- end
230
- end
231
- RUBY
232
-
233
- write "slices/main/config/routes.rb", <<~RUBY
234
- module Main
235
- class Routes < Hanami::Routes
236
- root to: ->(env) { [200, {}, ["OK"]] }
237
- end
238
- end
239
- RUBY
240
-
241
- require "hanami/boot"
242
-
243
- get "/"
244
-
245
- logs = -> { Pathname(dir).join("test.log").realpath.read }
246
-
247
- log_content = logs.()
248
-
249
- expect(log_content).to match(%r["verb":"GET"])
250
- expect(log_content).to match(%r["path":"/"])
251
- expect(log_content).to match(%r[elapsed":\d+,"elapsed_unit":"µs"])
252
- end
253
- end
254
- end
255
-
256
36
  specify "Routing to actions based on their container identifiers" do
257
37
  with_tmp_directory(Dir.mktmpdir) do
258
38
  write "config/app.rb", <<~RUBY
@@ -569,6 +349,7 @@ RSpec.describe "Hanami web app", :app_integration do
569
349
 
570
350
  module TestApp
571
351
  class App < Hanami::App
352
+ config.render_detailed_errors = false
572
353
  end
573
354
  end
574
355
  RUBY
@@ -600,6 +381,8 @@ RSpec.describe "Hanami web app", :app_integration do
600
381
 
601
382
  module TestApp
602
383
  class App < Hanami::App
384
+ config.render_detailed_errors = false
385
+
603
386
  register_slice :admin
604
387
  end
605
388
  end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rake"
4
+ require "hanami/cli/bundler"
5
+
6
+ RSpec.describe "Rake tasks", :app_integration do
7
+ describe "assets:precompile" do
8
+ before do
9
+ allow(Hanami).to receive(:bundled?)
10
+ allow(Hanami).to receive(:bundled?).with("hanami-assets").and_return(hanami_assets_bundled)
11
+ end
12
+
13
+ context "when hanami-assets is bundled" do
14
+ let(:hanami_assets_bundled) { true }
15
+
16
+ xit "compiles assets" do
17
+ with_tmp_directory(Dir.mktmpdir) do
18
+ write "config/app.rb", <<~'RUBY'
19
+ require "hanami"
20
+
21
+ module TestApp
22
+ class App < Hanami::App
23
+ end
24
+ end
25
+ RUBY
26
+
27
+ write "Rakefile", <<~RUBY
28
+ # frozen_string_literal: true
29
+
30
+ require "hanami/rake_tasks"
31
+ RUBY
32
+
33
+ write "app/assets/js/app.js", <<~JS
34
+ console.log("Hello from index.js");
35
+ JS
36
+
37
+ before_prepare if respond_to?(:before_prepare)
38
+ require "hanami/prepare"
39
+
40
+ expect_any_instance_of(Hanami::CLI::Bundler).to receive(:hanami_exec).with("assets compile").and_return(true)
41
+
42
+ Rake::Task["assets:precompile"].invoke
43
+ end
44
+ end
45
+
46
+ it "doesn't list the task" do
47
+ with_tmp_directory(Dir.mktmpdir) do
48
+ write "config/app.rb", <<~'RUBY'
49
+ require "hanami"
50
+
51
+ module TestApp
52
+ class App < Hanami::App
53
+ end
54
+ end
55
+ RUBY
56
+
57
+ write "Rakefile", <<~RUBY
58
+ # frozen_string_literal: true
59
+
60
+ require "hanami/rake_tasks"
61
+ RUBY
62
+
63
+ before_prepare if respond_to?(:before_prepare)
64
+ require "hanami/prepare"
65
+
66
+ output = `bundle exec rake -T`
67
+ expect(output).to_not include("assets:precompile")
68
+ end
69
+ end
70
+ end
71
+
72
+ context "when hanami-assets is not bundled" do
73
+ let(:hanami_assets_bundled) { false }
74
+
75
+ it "raises error" do
76
+ with_tmp_directory(Dir.mktmpdir) do
77
+ write "config/app.rb", <<~'RUBY'
78
+ require "hanami"
79
+
80
+ module TestApp
81
+ class App < Hanami::App
82
+ end
83
+ end
84
+ RUBY
85
+
86
+ write "Rakefile", <<~RUBY
87
+ # frozen_string_literal: true
88
+
89
+ require "hanami/rake_tasks"
90
+ RUBY
91
+
92
+ write "app/assets/js/app.js", <<~JS
93
+ console.log("Hello from index.js");
94
+ JS
95
+
96
+ before_prepare if respond_to?(:before_prepare)
97
+ require "hanami/prepare"
98
+
99
+ expect { Rake::Task["assets:precompile"].invoke }.to raise_error do |exception|
100
+ expect(exception).to be_a(RuntimeError)
101
+ expect(exception.message).to match(/Don't know how to build task 'assets:precompile'/)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end